llvm-project
2652 строки · 87.7 Кб
1#include "clang/AST/ASTContext.h"2#include "clang/AST/ASTStructuralEquivalence.h"3#include "clang/AST/Decl.h"4#include "clang/AST/DeclTemplate.h"5#include "clang/ASTMatchers/ASTMatchers.h"6#include "clang/Frontend/ASTUnit.h"7#include "clang/Testing/CommandLineArgs.h"8#include "clang/Tooling/Tooling.h"9#include "llvm/TargetParser/Host.h"10
11#include "DeclMatcher.h"12
13#include "gtest/gtest.h"14
15namespace clang {16namespace ast_matchers {17
18using std::get;19
20struct StructuralEquivalenceTest : ::testing::Test {21std::unique_ptr<ASTUnit> AST0, AST1;22std::string Code0, Code1; // Buffers for SourceManager23
24// Parses the source code in the specified language and sets the ASTs of25// the current test instance to the parse result.26void makeASTUnits(const std::string &SrcCode0, const std::string &SrcCode1,27TestLanguage Lang) {28this->Code0 = SrcCode0;29this->Code1 = SrcCode1;30std::vector<std::string> Args = getCommandLineArgsForTesting(Lang);31
32const char *const InputFileName = "input.cc";33
34AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);35AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);36}37
38// Get a pair of node pointers into the synthesized AST from the given code39// snippets. To determine the returned node, a separate matcher is specified40// for both snippets. The first matching node is returned.41template <typename NodeType, typename MatcherType>42std::tuple<NodeType *, NodeType *>43makeDecls(const std::string &SrcCode0, const std::string &SrcCode1,44TestLanguage Lang, const MatcherType &Matcher0,45const MatcherType &Matcher1) {46makeASTUnits(SrcCode0, SrcCode1, Lang);47
48NodeType *D0 = FirstDeclMatcher<NodeType>().match(49AST0->getASTContext().getTranslationUnitDecl(), Matcher0);50NodeType *D1 = FirstDeclMatcher<NodeType>().match(51AST1->getASTContext().getTranslationUnitDecl(), Matcher1);52
53return std::make_tuple(D0, D1);54}55
56std::tuple<TranslationUnitDecl *, TranslationUnitDecl *>57makeTuDecls(const std::string &SrcCode0, const std::string &SrcCode1,58TestLanguage Lang) {59makeASTUnits(SrcCode0, SrcCode1, Lang);60
61return std::make_tuple(AST0->getASTContext().getTranslationUnitDecl(),62AST1->getASTContext().getTranslationUnitDecl());63}64
65// Get a pair of node pointers into the synthesized AST from the given code66// snippets. The same matcher is used for both snippets.67template <typename NodeType, typename MatcherType>68std::tuple<NodeType *, NodeType *>69makeDecls(const std::string &SrcCode0, const std::string &SrcCode1,70TestLanguage Lang, const MatcherType &AMatcher) {71return makeDecls<NodeType, MatcherType>(72SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);73}74
75// Get a pair of Decl pointers to the synthesized declarations from the given76// code snippets. We search for the first NamedDecl with given name in both77// snippets.78std::tuple<NamedDecl *, NamedDecl *>79makeNamedDecls(const std::string &SrcCode0, const std::string &SrcCode1,80TestLanguage Lang, const char *const Identifier = "foo") {81auto Matcher = namedDecl(hasName(Identifier));82return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher);83}84
85// Wraps a Stmt and the ASTContext that contains it.86struct StmtWithASTContext {87Stmt *S;88ASTContext *Context;89explicit StmtWithASTContext(Stmt &S, ASTContext &Context)90: S(&S), Context(&Context) {}91explicit StmtWithASTContext(FunctionDecl *FD)92: S(FD->getBody()), Context(&FD->getASTContext()) {}93};94
95// Get a pair of node pointers into the synthesized AST from the given code96// snippets. To determine the returned node, a separate matcher is specified97// for both snippets. The first matching node is returned.98template <typename MatcherType>99std::tuple<StmtWithASTContext, StmtWithASTContext>100makeStmts(const std::string &SrcCode0, const std::string &SrcCode1,101TestLanguage Lang, const MatcherType &Matcher0,102const MatcherType &Matcher1) {103makeASTUnits(SrcCode0, SrcCode1, Lang);104
105Stmt *S0 = FirstDeclMatcher<Stmt>().match(106AST0->getASTContext().getTranslationUnitDecl(), Matcher0);107Stmt *S1 = FirstDeclMatcher<Stmt>().match(108AST1->getASTContext().getTranslationUnitDecl(), Matcher1);109
110return std::make_tuple(StmtWithASTContext(*S0, AST0->getASTContext()),111StmtWithASTContext(*S1, AST1->getASTContext()));112}113
114// Get a pair of node pointers into the synthesized AST from the given code115// snippets. The same matcher is used for both snippets.116template <typename MatcherType>117std::tuple<StmtWithASTContext, StmtWithASTContext>118makeStmts(const std::string &SrcCode0, const std::string &SrcCode1,119TestLanguage Lang, const MatcherType &AMatcher) {120return makeStmts(SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);121}122
123// Convenience function for makeStmts that wraps the code inside a function124// body.125template <typename MatcherType>126std::tuple<StmtWithASTContext, StmtWithASTContext>127makeWrappedStmts(const std::string &SrcCode0, const std::string &SrcCode1,128TestLanguage Lang, const MatcherType &AMatcher) {129auto Wrap = [](const std::string &Src) {130return "void wrapped() {" + Src + ";}";131};132return makeStmts(Wrap(SrcCode0), Wrap(SrcCode1), Lang, AMatcher);133}134
135bool testStructuralMatch(Decl *D0, Decl *D1,136bool IgnoreTemplateParmDepth = false) {137llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01;138llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10;139StructuralEquivalenceContext Ctx01(140D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls01,141StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,142/*Complain=*/false, /*ErrorOnTagTypeMismatch=*/false,143IgnoreTemplateParmDepth);144StructuralEquivalenceContext Ctx10(145D1->getASTContext(), D0->getASTContext(), NonEquivalentDecls10,146StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,147/*Complain=*/false, /*ErrorOnTagTypeMismatch=*/false,148IgnoreTemplateParmDepth);149bool Eq01 = Ctx01.IsEquivalent(D0, D1);150bool Eq10 = Ctx10.IsEquivalent(D1, D0);151EXPECT_EQ(Eq01, Eq10);152return Eq01;153}154
155bool testStructuralMatch(StmtWithASTContext S0, StmtWithASTContext S1) {156llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01;157llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10;158StructuralEquivalenceContext Ctx01(159*S0.Context, *S1.Context, NonEquivalentDecls01,160StructuralEquivalenceKind::Default, false, false);161StructuralEquivalenceContext Ctx10(162*S1.Context, *S0.Context, NonEquivalentDecls10,163StructuralEquivalenceKind::Default, false, false);164bool Eq01 = Ctx01.IsEquivalent(S0.S, S1.S);165bool Eq10 = Ctx10.IsEquivalent(S1.S, S0.S);166EXPECT_EQ(Eq01, Eq10);167return Eq01;168}169
170bool171testStructuralMatch(std::tuple<StmtWithASTContext, StmtWithASTContext> t) {172return testStructuralMatch(get<0>(t), get<1>(t));173}174
175bool testStructuralMatch(std::tuple<Decl *, Decl *> t,176bool IgnoreTemplateParmDepth = false) {177return testStructuralMatch(get<0>(t), get<1>(t), IgnoreTemplateParmDepth);178}179};180
181TEST_F(StructuralEquivalenceTest, Int) {182auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX03);183EXPECT_TRUE(testStructuralMatch(Decls));184}
185
186TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {187auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX03);188EXPECT_TRUE(testStructuralMatch(Decls));189}
190
191TEST_F(StructuralEquivalenceTest, Char) {192auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX03);193EXPECT_TRUE(testStructuralMatch(Decls));194}
195
196// This test is disabled for now.
197// FIXME Whether this is equivalent is dependent on the target.
198TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {199auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX03);200EXPECT_FALSE(testStructuralMatch(Decls));201}
202
203TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {204auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX03);205EXPECT_TRUE(testStructuralMatch(Decls));206}
207
208TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) {209auto Decls = makeNamedDecls("struct foo { int x; };",210"struct foo { signed int x; };", Lang_CXX03);211EXPECT_TRUE(testStructuralMatch(Decls));212}
213
214TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) {215auto Decls = makeNamedDecls("struct foo { char x; };",216"struct foo { signed char x; };", Lang_CXX03);217EXPECT_FALSE(testStructuralMatch(Decls));218}
219
220TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {221auto Decls = makeDecls<ClassTemplateSpecializationDecl>(222R"(template <class T> struct foo; template<> struct foo<int>{};)",223R"(template <class T> struct foo; template<> struct foo<signed int>{};)",224Lang_CXX03, classTemplateSpecializationDecl());225auto Spec0 = get<0>(Decls);226auto Spec1 = get<1>(Decls);227EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));228}
229
230TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {231auto Decls = makeDecls<ClassTemplateSpecializationDecl>(232R"(template <class T> struct foo; template<> struct foo<char>{};)",233R"(template <class T> struct foo; template<> struct foo<signed char>{};)",234Lang_CXX03, classTemplateSpecializationDecl());235auto Spec0 = get<0>(Decls);236auto Spec1 = get<1>(Decls);237EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));238}
239
240TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {241auto Decls = makeDecls<ClassTemplateSpecializationDecl>(242R"(243struct true_type{};
244template <class T> struct foo;
245template<> struct foo<char> : true_type {};
246)",247R"(248struct true_type{};
249template <class T> struct foo;
250template<> struct foo<signed char> : true_type {};
251)",252Lang_CXX03, classTemplateSpecializationDecl());253EXPECT_FALSE(testStructuralMatch(Decls));254}
255
256// This test is disabled for now.
257// FIXME Enable it, once the check is implemented.
258TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {259auto Code =260R"(261namespace NS {
262template <class T> class Base {
263int a;
264};
265class Derived : Base<Derived> {
266};
267}
268void foo(NS::Derived &);
269)";270auto Decls = makeNamedDecls(Code, Code, Lang_CXX03);271
272NamespaceDecl *NS =273LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl());274ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(275get<1>(Decls), classTemplateDecl(hasName("Base")));276
277// Reorder the decls, move the TD to the last place in the DC.278NS->removeDecl(TD);279NS->addDeclInternal(TD);280
281EXPECT_FALSE(testStructuralMatch(Decls));282}
283
284TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {285auto Code = "class X { int a; int b; };";286auto Decls = makeNamedDecls(Code, Code, Lang_CXX03, "X");287
288CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(289get<1>(Decls), cxxRecordDecl(hasName("X")));290FieldDecl *FD =291FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a")));292
293// Reorder the FieldDecls294RD->removeDecl(FD);295RD->addDeclInternal(FD);296
297EXPECT_FALSE(testStructuralMatch(Decls));298}
299
300struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {301};302
303TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) {304auto t = makeNamedDecls("void foo();", "template<class T> void foo();",305Lang_CXX03);306EXPECT_FALSE(testStructuralMatch(t));307}
308
309TEST_F(StructuralEquivalenceFunctionTest, DifferentOperators) {310auto t = makeDecls<FunctionDecl>(311"struct X{}; bool operator<(X, X);", "struct X{}; bool operator==(X, X);",312Lang_CXX03, functionDecl(hasOverloadedOperatorName("<")),313functionDecl(hasOverloadedOperatorName("==")));314EXPECT_FALSE(testStructuralMatch(t));315}
316
317TEST_F(StructuralEquivalenceFunctionTest, SameOperators) {318auto t = makeDecls<FunctionDecl>(319"struct X{}; bool operator<(X, X);", "struct X{}; bool operator<(X, X);",320Lang_CXX03, functionDecl(hasOverloadedOperatorName("<")),321functionDecl(hasOverloadedOperatorName("<")));322EXPECT_TRUE(testStructuralMatch(t));323}
324
325TEST_F(StructuralEquivalenceFunctionTest, CtorVsDtor) {326auto t = makeDecls<FunctionDecl>("struct X{ X(); };", "struct X{ ~X(); };",327Lang_CXX03, cxxConstructorDecl(),328cxxDestructorDecl());329EXPECT_FALSE(testStructuralMatch(t));330}
331
332TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {333auto t =334makeNamedDecls("void foo(int&);", "void foo(const int&);", Lang_CXX03);335EXPECT_FALSE(testStructuralMatch(t));336}
337
338TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) {339auto t = makeNamedDecls("void foo(int);", "void foo(const int);", Lang_CXX03);340EXPECT_TRUE(testStructuralMatch(t));341// consider this OK342}
343
344TEST_F(StructuralEquivalenceFunctionTest, Throw) {345auto t = makeNamedDecls("void foo();", "void foo() throw();", Lang_CXX03);346EXPECT_FALSE(testStructuralMatch(t));347}
348
349TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {350auto t = makeNamedDecls("void foo();",351"void foo() noexcept;", Lang_CXX11);352EXPECT_FALSE(testStructuralMatch(t));353}
354
355TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {356auto t = makeNamedDecls("void foo() throw();",357"void foo() noexcept;", Lang_CXX11);358EXPECT_FALSE(testStructuralMatch(t));359}
360
361TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {362auto t = makeNamedDecls("void foo() throw();",363"void foo() noexcept(false);", Lang_CXX11);364EXPECT_FALSE(testStructuralMatch(t));365}
366
367TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {368auto t = makeNamedDecls("void foo() throw();",369"void foo() noexcept(true);", Lang_CXX11);370EXPECT_FALSE(testStructuralMatch(t));371}
372
373TEST_F(StructuralEquivalenceFunctionTest, NoexceptNonMatch) {374auto t = makeNamedDecls("void foo() noexcept(false);",375"void foo() noexcept(true);", Lang_CXX11);376EXPECT_FALSE(testStructuralMatch(t));377}
378
379TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) {380auto t = makeNamedDecls("void foo() noexcept(false);",381"void foo() noexcept(false);", Lang_CXX11);382EXPECT_TRUE(testStructuralMatch(t));383}
384
385TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) {386auto t = makeNamedDecls("void foo() noexcept;",387"void foo() noexcept(false);", Lang_CXX11);388EXPECT_FALSE(testStructuralMatch(t));389}
390
391TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) {392auto t = makeNamedDecls("void foo() noexcept;",393"void foo() noexcept(true);", Lang_CXX11);394EXPECT_FALSE(testStructuralMatch(t));395}
396
397TEST_F(StructuralEquivalenceFunctionTest, ReturnType) {398auto t = makeNamedDecls("char foo();", "int foo();", Lang_CXX03);399EXPECT_FALSE(testStructuralMatch(t));400}
401
402TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) {403auto t = makeNamedDecls("char foo();", "const char foo();", Lang_CXX03);404EXPECT_FALSE(testStructuralMatch(t));405}
406
407TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) {408auto t = makeNamedDecls("char &foo();",409"char &&foo();", Lang_CXX11);410EXPECT_FALSE(testStructuralMatch(t));411}
412
413TEST_F(StructuralEquivalenceFunctionTest, ParamCount) {414auto t = makeNamedDecls("void foo(int);", "void foo(int, int);", Lang_CXX03);415EXPECT_FALSE(testStructuralMatch(t));416}
417
418TEST_F(StructuralEquivalenceFunctionTest, ParamType) {419auto t = makeNamedDecls("void foo(int);", "void foo(char);", Lang_CXX03);420EXPECT_FALSE(testStructuralMatch(t));421}
422
423TEST_F(StructuralEquivalenceFunctionTest, ParamName) {424auto t = makeNamedDecls("void foo(int a);", "void foo(int b);", Lang_CXX03);425EXPECT_TRUE(testStructuralMatch(t));426}
427
428TEST_F(StructuralEquivalenceFunctionTest, Variadic) {429auto t =430makeNamedDecls("void foo(int x...);", "void foo(int x);", Lang_CXX03);431EXPECT_FALSE(testStructuralMatch(t));432}
433
434TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) {435auto t = makeNamedDecls("void foo(int *);", "void foo(int);", Lang_CXX03);436EXPECT_FALSE(testStructuralMatch(t));437}
438
439TEST_F(StructuralEquivalenceFunctionTest, NameInParen) {440auto t = makeNamedDecls("void ((foo))();", "void foo();", Lang_CXX03);441EXPECT_TRUE(testStructuralMatch(t));442}
443
444TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) {445auto t = makeNamedDecls(446"void (foo)() throw(int);",447"void (foo)() noexcept;",448Lang_CXX11);449EXPECT_FALSE(testStructuralMatch(t));450}
451
452TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) {453auto t = makeNamedDecls(454"struct A { void (foo)() const; };",455"struct A { void (foo)(); };",456Lang_CXX11);457EXPECT_FALSE(testStructuralMatch(t));458}
459
460TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) {461auto t = makeNamedDecls("__attribute__((noreturn)) void foo();",462" void foo();", Lang_C99);463EXPECT_TRUE(testStructuralMatch(t));464}
465
466TEST_F(StructuralEquivalenceFunctionTest,467FunctionsWithDifferentCallingConventions) {468// These attributes may not be available on certain platforms.469if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=470llvm::Triple::x86_64)471GTEST_SKIP();472auto t = makeNamedDecls("__attribute__((preserve_all)) void foo();",473"__attribute__((ms_abi)) void foo();", Lang_C99);474EXPECT_FALSE(testStructuralMatch(t));475}
476
477TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) {478if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=479llvm::Triple::x86_64)480GTEST_SKIP();481auto t = makeNamedDecls(482"__attribute__((no_caller_saved_registers)) void foo();",483" void foo();", Lang_C99);484EXPECT_FALSE(testStructuralMatch(t));485}
486
487struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {488};489
490TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) {491auto t = makeDecls<CXXMethodDecl>("struct X { void foo(); };",492"struct X { virtual void foo(); };",493Lang_CXX03, cxxMethodDecl(hasName("foo")));494EXPECT_FALSE(testStructuralMatch(t));495}
496
497TEST_F(StructuralEquivalenceCXXMethodTest, Pure) {498auto t = makeNamedDecls("struct X { virtual void foo(); };",499"struct X { virtual void foo() = 0; };", Lang_CXX03);500EXPECT_FALSE(testStructuralMatch(t));501}
502
503TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) {504// The final-ness is not checked yet.505auto t =506makeNamedDecls("struct X { virtual void foo(); };",507"struct X { virtual void foo() final; };", Lang_CXX03);508EXPECT_FALSE(testStructuralMatch(t));509}
510
511TEST_F(StructuralEquivalenceCXXMethodTest, Const) {512auto t = makeNamedDecls("struct X { void foo(); };",513"struct X { void foo() const; };", Lang_CXX03);514EXPECT_FALSE(testStructuralMatch(t));515}
516
517TEST_F(StructuralEquivalenceCXXMethodTest, Static) {518auto t = makeNamedDecls("struct X { void foo(); };",519"struct X { static void foo(); };", Lang_CXX03);520EXPECT_FALSE(testStructuralMatch(t));521}
522
523TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) {524auto t = makeNamedDecls("struct X { void foo(); };",525"struct X { void foo() &&; };", Lang_CXX11);526EXPECT_FALSE(testStructuralMatch(t));527}
528
529TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) {530auto t = makeNamedDecls("struct X { void foo() &; };",531"struct X { void foo() &&; };", Lang_CXX11);532EXPECT_FALSE(testStructuralMatch(t));533}
534
535TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) {536auto t = makeDecls<CXXMethodDecl>("struct X { public: void foo(); };",537"struct X { private: void foo(); };",538Lang_CXX03, cxxMethodDecl(hasName("foo")));539EXPECT_FALSE(testStructuralMatch(t));540}
541
542TEST_F(StructuralEquivalenceCXXMethodTest, Delete) {543auto t = makeNamedDecls("struct X { void foo(); };",544"struct X { void foo() = delete; };", Lang_CXX11);545EXPECT_FALSE(testStructuralMatch(t));546}
547
548TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) {549auto t = makeDecls<FunctionDecl>("void foo();", "struct foo { foo(); };",550Lang_CXX03, functionDecl(hasName("foo")),551cxxConstructorDecl(hasName("foo")));552EXPECT_FALSE(testStructuralMatch(t));553}
554
555TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) {556auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",557"struct X { X(int); };", Lang_CXX03,558cxxConstructorDecl(hasName("X")));559EXPECT_FALSE(testStructuralMatch(t));560}
561
562TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) {563auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };",564"struct X { explicit X(int); };",565Lang_CXX11,566cxxConstructorDecl(hasName("X")));567EXPECT_FALSE(testStructuralMatch(t));568}
569
570TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) {571auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",572"struct X { X() = default; };",573Lang_CXX11,574cxxConstructorDecl(hasName("X")));575EXPECT_FALSE(testStructuralMatch(t));576}
577
578TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) {579auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };",580"struct X { operator char(); };",581Lang_CXX11,582cxxConversionDecl());583EXPECT_FALSE(testStructuralMatch(t));584}
585
586TEST_F(StructuralEquivalenceCXXMethodTest, Operator) {587auto t =588makeDecls<FunctionDecl>("struct X { int operator +(int); };",589"struct X { int operator -(int); };", Lang_CXX03,590functionDecl(hasOverloadedOperatorName("+")),591functionDecl(hasOverloadedOperatorName("-")));592EXPECT_FALSE(testStructuralMatch(t));593}
594
595TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) {596auto t = makeDecls<FunctionDecl>(597"struct X { virtual void f(); }; void X::f() { }",598"struct X { virtual void f() { }; };", Lang_CXX03,599functionDecl(allOf(hasName("f"), isDefinition())));600EXPECT_TRUE(testStructuralMatch(t));601}
602
603TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) {604auto t = makeDecls<FunctionDecl>(605"struct X { virtual void f(); }; void X::f() { }",606"struct X { void f(); }; void X::f() { }", Lang_CXX03,607functionDecl(allOf(hasName("f"), isDefinition())));608EXPECT_FALSE(testStructuralMatch(t));609}
610
611struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {612// FIXME Use a common getRecordDecl with ASTImporterTest.cpp!613RecordDecl *getRecordDecl(FieldDecl *FD) {614auto *ET = cast<ElaboratedType>(FD->getType().getTypePtr());615return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();616};617};618
619TEST_F(StructuralEquivalenceRecordTest, Name) {620auto t = makeDecls<CXXRecordDecl>("struct A{ };", "struct B{ };", Lang_CXX03,621cxxRecordDecl(hasName("A")),622cxxRecordDecl(hasName("B")));623EXPECT_FALSE(testStructuralMatch(t));624}
625
626TEST_F(StructuralEquivalenceRecordTest, Fields) {627auto t = makeNamedDecls("struct foo{ int x; };", "struct foo{ char x; };",628Lang_CXX03);629EXPECT_FALSE(testStructuralMatch(t));630}
631
632TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) {633// Currently, methods of a class are not checked at class equivalence.634auto t = makeNamedDecls("struct foo{ int x(); };", "struct foo{ char x(); };",635Lang_CXX03);636EXPECT_FALSE(testStructuralMatch(t));637}
638
639TEST_F(StructuralEquivalenceRecordTest, Bases) {640auto t = makeNamedDecls("struct A{ }; struct foo: A { };",641"struct B{ }; struct foo: B { };", Lang_CXX03);642EXPECT_FALSE(testStructuralMatch(t));643}
644
645TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) {646auto t =647makeNamedDecls("struct A{ }; struct foo: A { };",648"struct A{ }; struct foo: virtual A { };", Lang_CXX03);649EXPECT_FALSE(testStructuralMatch(t));650}
651
652TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) {653// Access specifier in inheritance is not checked yet.654auto t =655makeNamedDecls("struct A{ }; struct foo: public A { };",656"struct A{ }; struct foo: private A { };", Lang_CXX03);657EXPECT_FALSE(testStructuralMatch(t));658}
659
660TEST_F(StructuralEquivalenceRecordTest, Match) {661auto Code = R"(662struct A{ };
663struct B{ };
664struct foo: A, virtual B {
665void x();
666int a;
667};
668)";669auto t = makeNamedDecls(Code, Code, Lang_CXX03);670EXPECT_TRUE(testStructuralMatch(t));671}
672
673TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) {674auto t = makeTuDecls(675R"(676struct A {
677struct {
678struct A *next;
679} entry0;
680struct {
681struct A *next;
682} entry1;
683};
684)",685"", Lang_C99);686auto *TU = get<0>(t);687auto *Entry0 =688FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0")));689auto *Entry1 =690FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1")));691auto *R0 = getRecordDecl(Entry0);692auto *R1 = getRecordDecl(Entry1);693
694ASSERT_NE(R0, R1);695EXPECT_TRUE(testStructuralMatch(R0, R0));696EXPECT_TRUE(testStructuralMatch(R1, R1));697EXPECT_FALSE(testStructuralMatch(R0, R1));698}
699
700TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) {701auto t = makeTuDecls(702R"(703struct X {
704struct {
705int a;
706};
707struct {
708int b;
709};
710};
711)",712"", Lang_C99);713auto *TU = get<0>(t);714auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(715TU, indirectFieldDecl(hasName("a")));716auto *FA = cast<FieldDecl>(A->chain().front());717RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();718auto *B = FirstDeclMatcher<IndirectFieldDecl>().match(719TU, indirectFieldDecl(hasName("b")));720auto *FB = cast<FieldDecl>(B->chain().front());721RecordDecl *RB = cast<RecordType>(FB->getType().getTypePtr())->getDecl();722
723ASSERT_NE(RA, RB);724EXPECT_TRUE(testStructuralMatch(RA, RA));725EXPECT_TRUE(testStructuralMatch(RB, RB));726EXPECT_FALSE(testStructuralMatch(RA, RB));727}
728
729TEST_F(StructuralEquivalenceRecordTest,730RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) {731auto t = makeTuDecls(732R"(733struct X {
734struct { int a; };
735struct { int b; };
736};
737)",738R"(739struct X { // The order is reversed.
740struct { int b; };
741struct { int a; };
742};
743)",744Lang_C99);745
746auto *TU = get<0>(t);747auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(748TU, indirectFieldDecl(hasName("a")));749auto *FA = cast<FieldDecl>(A->chain().front());750RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();751
752auto *TU1 = get<1>(t);753auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match(754TU1, indirectFieldDecl(hasName("a")));755auto *FA1 = cast<FieldDecl>(A1->chain().front());756RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl();757
758RecordDecl *X =759FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName("X")));760RecordDecl *X1 =761FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName("X")));762ASSERT_NE(X, X1);763EXPECT_FALSE(testStructuralMatch(X, X1));764
765ASSERT_NE(RA, RA1);766EXPECT_TRUE(testStructuralMatch(RA, RA));767EXPECT_TRUE(testStructuralMatch(RA1, RA1));768EXPECT_FALSE(testStructuralMatch(RA1, RA));769}
770
771TEST_F(StructuralEquivalenceRecordTest,772UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {773auto Code =774R"(775struct A {
776struct {
777struct A *next;
778} entry0;
779struct {
780struct A *next;
781} entry1;
782};
783)";784auto t = makeTuDecls(Code, Code, Lang_C99);785
786auto *FromTU = get<0>(t);787auto *Entry1 =788FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("entry1")));789
790auto *ToTU = get<1>(t);791auto *Entry0 =792FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));793auto *A =794FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));795A->startDefinition(); // Set isBeingDefined, getDefinition() will return a796// nullptr. This may be the case during ASTImport.797
798auto *R0 = getRecordDecl(Entry0);799auto *R1 = getRecordDecl(Entry1);800
801ASSERT_NE(R0, R1);802EXPECT_TRUE(testStructuralMatch(R0, R0));803EXPECT_TRUE(testStructuralMatch(R1, R1));804EXPECT_FALSE(testStructuralMatch(R0, R1));805}
806
807TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) {808auto t = makeDecls<CXXRecordDecl>("struct A { };",809"template<class T> struct A { };",810Lang_CXX03, cxxRecordDecl(hasName("A")));811EXPECT_FALSE(testStructuralMatch(t));812}
813
814TEST_F(StructuralEquivalenceRecordTest,815FwdDeclRecordShouldBeEqualWithFwdDeclRecord) {816auto t = makeNamedDecls("class foo;", "class foo;", Lang_CXX11);817EXPECT_TRUE(testStructuralMatch(t));818}
819
820TEST_F(StructuralEquivalenceRecordTest,821FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition) {822auto t =823makeNamedDecls("class foo;", "class foo { int A; };", Lang_CXX11);824EXPECT_TRUE(testStructuralMatch(t));825}
826
827TEST_F(StructuralEquivalenceRecordTest,828RecordShouldBeEqualWithRecordWhichHasDefinition) {829auto t = makeNamedDecls("class foo { int A; };", "class foo { int A; };",830Lang_CXX11);831EXPECT_TRUE(testStructuralMatch(t));832}
833
834TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) {835auto t = makeNamedDecls("class foo { int B; };", "class foo { int A; };",836Lang_CXX11);837EXPECT_FALSE(testStructuralMatch(t));838}
839
840TEST_F(StructuralEquivalenceRecordTest, SameFriendMultipleTimes) {841auto t = makeNamedDecls("struct foo { friend class X; };",842"struct foo { friend class X; friend class X; };",843Lang_CXX11);844EXPECT_FALSE(testStructuralMatch(t));845}
846
847TEST_F(StructuralEquivalenceRecordTest, SameFriendsDifferentOrder) {848auto t = makeNamedDecls("struct foo { friend class X; friend class Y; };",849"struct foo { friend class Y; friend class X; };",850Lang_CXX11);851EXPECT_FALSE(testStructuralMatch(t));852}
853
854TEST_F(StructuralEquivalenceRecordTest, SameFriendsSameOrder) {855auto t = makeNamedDecls("struct foo { friend class X; friend class Y; };",856"struct foo { friend class X; friend class Y; };",857Lang_CXX11);858EXPECT_TRUE(testStructuralMatch(t));859}
860
861struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {};862
863TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentMethods) {864// Get the LambdaExprs, unfortunately we can't match directly the underlying865// implicit CXXRecordDecl of the Lambda classes.866auto t = makeDecls<LambdaExpr>(867"void f() { auto L0 = [](int){}; }",868"void f() { auto L1 = [](){}; }",869Lang_CXX11,870lambdaExpr(),871lambdaExpr());872CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();873CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();874EXPECT_FALSE(testStructuralMatch(L0, L1));875}
876
877TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqMethods) {878auto t = makeDecls<LambdaExpr>(879"void f() { auto L0 = [](int){}; }",880"void f() { auto L1 = [](int){}; }",881Lang_CXX11,882lambdaExpr(),883lambdaExpr());884CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();885CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();886EXPECT_TRUE(testStructuralMatch(L0, L1));887}
888
889TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentFields) {890auto t = makeDecls<LambdaExpr>(891"void f() { char* X; auto L0 = [X](){}; }",892"void f() { float X; auto L1 = [X](){}; }",893Lang_CXX11,894lambdaExpr(),895lambdaExpr());896CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();897CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();898EXPECT_FALSE(testStructuralMatch(L0, L1));899}
900
901TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqFields) {902auto t = makeDecls<LambdaExpr>(903"void f() { float X; auto L0 = [X](){}; }",904"void f() { float X; auto L1 = [X](){}; }",905Lang_CXX11,906lambdaExpr(),907lambdaExpr());908CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();909CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();910EXPECT_TRUE(testStructuralMatch(L0, L1));911}
912
913TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {914auto t = makeNamedDecls("struct A{ }; struct B{ }; void foo(A a, A b);",915"struct A{ }; struct B{ }; void foo(A a, B b);",916Lang_CXX03);917EXPECT_FALSE(testStructuralMatch(t));918}
919
920TEST_F(StructuralEquivalenceTest, ExplicitBoolDifferent) {921auto Decls = makeNamedDecls("struct foo {explicit(false) foo(int);};",922"struct foo {explicit(true) foo(int);};", Lang_CXX20);923CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(924get<0>(Decls), cxxConstructorDecl(hasName("foo")));925CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(926get<1>(Decls), cxxConstructorDecl(hasName("foo")));927EXPECT_FALSE(testStructuralMatch(First, Second));928}
929
930TEST_F(StructuralEquivalenceTest, ExplicitBoolSame) {931auto Decls = makeNamedDecls("struct foo {explicit(true) foo(int);};",932"struct foo {explicit(true) foo(int);};", Lang_CXX20);933CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(934get<0>(Decls), cxxConstructorDecl(hasName("foo")));935CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(936get<1>(Decls), cxxConstructorDecl(hasName("foo")));937EXPECT_TRUE(testStructuralMatch(First, Second));938}
939
940struct StructuralEquivalenceRecordContextTest : StructuralEquivalenceTest {};941
942TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNoVsNamed) {943auto Decls =944makeNamedDecls("class X;", "namespace N { class X; }", Lang_CXX03, "X");945EXPECT_FALSE(testStructuralMatch(Decls));946}
947
948TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNamedVsNamed) {949auto Decls = makeNamedDecls("namespace A { class X; }",950"namespace B { class X; }", Lang_CXX03, "X");951EXPECT_FALSE(testStructuralMatch(Decls));952}
953
954TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsNamed) {955auto Decls = makeNamedDecls("namespace { class X; }",956"namespace N { class X; }", Lang_CXX03, "X");957EXPECT_FALSE(testStructuralMatch(Decls));958}
959
960TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNoVsAnon) {961auto Decls =962makeNamedDecls("class X;", "namespace { class X; }", Lang_CXX03, "X");963EXPECT_FALSE(testStructuralMatch(Decls));964}
965
966TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsAnon) {967auto Decls = makeNamedDecls("namespace { class X; }",968"namespace { class X; }", Lang_CXX03, "X");969EXPECT_TRUE(testStructuralMatch(Decls));970}
971
972TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsAnonAnon) {973auto Decls =974makeNamedDecls("namespace { class X; }",975"namespace { namespace { class X; } }", Lang_CXX03, "X");976EXPECT_FALSE(testStructuralMatch(Decls));977}
978
979TEST_F(StructuralEquivalenceRecordContextTest,980NamespaceNamedNamedVsNamedNamed) {981auto Decls = makeNamedDecls("namespace A { namespace N { class X; } }",982"namespace B { namespace N { class X; } }",983Lang_CXX03, "X");984EXPECT_FALSE(testStructuralMatch(Decls));985}
986
987TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNamedVsInline) {988auto Decls = makeNamedDecls("namespace A { namespace A { class X; } }",989"namespace A { inline namespace A { class X; } }",990Lang_CXX17, "X");991EXPECT_FALSE(testStructuralMatch(Decls));992}
993
994TEST_F(StructuralEquivalenceRecordContextTest, NamespaceInlineVsInline) {995auto Decls = makeNamedDecls("namespace A { inline namespace A { class X; } }",996"namespace A { inline namespace B { class X; } }",997Lang_CXX17, "X");998EXPECT_TRUE(testStructuralMatch(Decls));999}
1000
1001TEST_F(StructuralEquivalenceRecordContextTest, NamespaceInlineTopLevel) {1002auto Decls =1003makeNamedDecls("inline namespace A { class X; }",1004"inline namespace B { class X; }", Lang_CXX17, "X");1005EXPECT_TRUE(testStructuralMatch(Decls));1006}
1007
1008TEST_F(StructuralEquivalenceRecordContextTest, TransparentContext) {1009auto Decls =1010makeNamedDecls("extern \"C\" { class X; }", "class X;", Lang_CXX03, "X");1011EXPECT_TRUE(testStructuralMatch(Decls));1012}
1013
1014TEST_F(StructuralEquivalenceRecordContextTest, TransparentContextNE) {1015auto Decls = makeNamedDecls("extern \"C\" { class X; }",1016"namespace { class X; }", Lang_CXX03, "X");1017EXPECT_FALSE(testStructuralMatch(Decls));1018}
1019
1020TEST_F(StructuralEquivalenceRecordContextTest, TransparentContextInNamespace) {1021auto Decls = makeNamedDecls("extern \"C\" { namespace N { class X; } }",1022"namespace N { extern \"C\" { class X; } }",1023Lang_CXX03, "X");1024EXPECT_TRUE(testStructuralMatch(Decls));1025}
1026
1027TEST_F(StructuralEquivalenceRecordContextTest,1028ClassTemplateSpecializationContext) {1029std::string Code =1030R"(1031template <typename T> struct O {
1032struct M {};
1033};
1034)";1035auto t = makeDecls<VarDecl>(Code + R"(1036typedef O<int>::M MT1;
1037MT1 A;
1038)",1039Code + R"(1040namespace {
1041struct I {};
1042} // namespace
1043typedef O<I>::M MT2;
1044MT2 A;
1045)",1046Lang_CXX11, varDecl(hasName("A")));1047EXPECT_FALSE(testStructuralMatch(t));1048}
1049
1050TEST_F(StructuralEquivalenceTest, NamespaceOfRecordMember) {1051auto Decls = makeNamedDecls(1052R"(1053class X;
1054class Y { X* x; };
1055)",1056R"(1057namespace N { class X; }
1058class Y { N::X* x; };
1059)",1060Lang_CXX03, "Y");1061EXPECT_FALSE(testStructuralMatch(Decls));1062}
1063
1064TEST_F(StructuralEquivalenceTest, StructDefinitionInPrototype) {1065auto Decls =1066makeNamedDecls("struct Param { int a; }; void foo(struct Param *p);",1067"void foo(struct Param { int a; } *p);", Lang_C89);1068EXPECT_TRUE(testStructuralMatch(Decls));1069}
1070
1071TEST_F(StructuralEquivalenceTest, StructDefinitionInPrototypeDifferentName) {1072auto Decls =1073makeNamedDecls("struct Param1 { int a; }; void foo(struct Param1 *p);",1074"void foo(struct Param2 { int a; } *p);", Lang_C89);1075EXPECT_FALSE(testStructuralMatch(Decls));1076}
1077
1078TEST_F(StructuralEquivalenceRecordContextTest, RecordInsideFunction) {1079auto Decls = makeNamedDecls("struct Param { int a; };",1080"void f() { struct Param { int a; }; }", Lang_C89,1081"Param");1082EXPECT_TRUE(testStructuralMatch(Decls));1083}
1084
1085struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {};1086
1087TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) {1088auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11);1089EXPECT_TRUE(testStructuralMatch(t));1090}
1091
1092TEST_F(StructuralEquivalenceEnumTest,1093FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) {1094auto t =1095makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11);1096EXPECT_TRUE(testStructuralMatch(t));1097}
1098
1099TEST_F(StructuralEquivalenceEnumTest,1100EnumShouldBeEqualWithEnumWhichHasDefinition) {1101auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };",1102Lang_CXX11);1103EXPECT_TRUE(testStructuralMatch(t));1104}
1105
1106TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) {1107auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };",1108Lang_CXX11);1109EXPECT_FALSE(testStructuralMatch(t));1110}
1111
1112struct StructuralEquivalenceEnumConstantTest : StructuralEquivalenceTest {};1113
1114TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithSameValues) {1115auto t = makeNamedDecls("enum foo { foo = 1 };", "enum foo { foo = 1 };",1116Lang_C89);1117EXPECT_TRUE(testStructuralMatch(t));1118}
1119
1120TEST_F(StructuralEquivalenceEnumConstantTest,1121EnumConstantsWithDifferentValues) {1122auto t =1123makeNamedDecls("enum e { foo = 1 };", "enum e { foo = 2 };", Lang_C89);1124EXPECT_FALSE(testStructuralMatch(t));1125}
1126
1127TEST_F(StructuralEquivalenceEnumConstantTest,1128EnumConstantsWithDifferentExprsButSameValues) {1129auto t = makeNamedDecls("enum e { foo = 1 + 1 };", "enum e { foo = 2 };",1130Lang_CXX11);1131EXPECT_FALSE(testStructuralMatch(t));1132}
1133
1134TEST_F(StructuralEquivalenceEnumConstantTest,1135EnumConstantsWithDifferentSignedness) {1136auto t = makeNamedDecls("enum e : unsigned { foo = 1 };",1137"enum e : int { foo = 1 };", Lang_CXX11);1138EXPECT_FALSE(testStructuralMatch(t));1139}
1140
1141TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentWidth) {1142auto t = makeNamedDecls("enum e : short { foo = 1 };",1143"enum e : int { foo = 1 };", Lang_CXX11);1144EXPECT_FALSE(testStructuralMatch(t));1145}
1146
1147TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentName) {1148auto t =1149makeDecls<EnumConstantDecl>("enum e { foo = 1 };", "enum e { bar = 1 };",1150Lang_CXX11, enumConstantDecl());1151EXPECT_FALSE(testStructuralMatch(t));1152}
1153
1154struct StructuralEquivalenceObjCCategoryTest : StructuralEquivalenceTest {};1155
1156TEST_F(StructuralEquivalenceObjCCategoryTest, MatchinCategoryNames) {1157auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",1158"@interface A @end @interface A(X) @end",1159Lang_OBJC, objcCategoryDecl());1160EXPECT_TRUE(testStructuralMatch(t));1161}
1162
1163TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesForDifferentClasses) {1164auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",1165"@interface B @end @interface B(X) @end",1166Lang_OBJC, objcCategoryDecl());1167EXPECT_FALSE(testStructuralMatch(t));1168}
1169
1170TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithDifferentNames) {1171auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",1172"@interface A @end @interface A(Y) @end",1173Lang_OBJC, objcCategoryDecl());1174EXPECT_FALSE(testStructuralMatch(t));1175}
1176
1177TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithoutInterfaces) {1178auto t = makeDecls<ObjCCategoryDecl>(" @interface A(X) @end",1179"@interface A @end @interface A(X) @end",1180Lang_OBJC, objcCategoryDecl());1181EXPECT_FALSE(testStructuralMatch(t));1182
1183auto t2 = makeDecls<ObjCCategoryDecl>("@interface A(X) @end",1184"@interface A(X) @end",1185Lang_OBJC, objcCategoryDecl());1186EXPECT_TRUE(testStructuralMatch(t2));1187}
1188
1189TEST_F(StructuralEquivalenceObjCCategoryTest, CategoryAndExtension) {1190auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",1191"@interface A @end @interface A() @end",1192Lang_OBJC, objcCategoryDecl());1193EXPECT_FALSE(testStructuralMatch(t));1194}
1195
1196TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingProtocols) {1197auto t = makeDecls<ObjCCategoryDecl>(1198"@protocol P @end @interface A @end @interface A(X)<P> @end",1199"@protocol P @end @interface A @end @interface A(X)<P> @end", Lang_OBJC,1200objcCategoryDecl());1201EXPECT_TRUE(testStructuralMatch(t));1202}
1203
1204TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentProtocols) {1205auto t = makeDecls<ObjCCategoryDecl>(1206"@protocol P @end @interface A @end @interface A(X)<P> @end",1207"@protocol Q @end @interface A @end @interface A(X)<Q> @end", Lang_OBJC,1208objcCategoryDecl());1209EXPECT_FALSE(testStructuralMatch(t));1210}
1211
1212TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentProtocolsOrder) {1213auto t = makeDecls<ObjCCategoryDecl>(1214"@protocol P @end @protocol Q @end @interface A @end @interface A(X)<P, "1215"Q> @end",1216"@protocol P @end @protocol Q @end @interface A @end @interface A(X)<Q, "1217"P> @end",1218Lang_OBJC, objcCategoryDecl());1219EXPECT_FALSE(testStructuralMatch(t));1220}
1221
1222TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingIvars) {1223auto t = makeDecls<ObjCCategoryDecl>(1224"@interface A @end @interface A() { int x; } @end",1225"@interface A @end @interface A() { int x; } @end", Lang_OBJC,1226objcCategoryDecl());1227EXPECT_TRUE(testStructuralMatch(t));1228}
1229
1230TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarName) {1231auto t = makeDecls<ObjCCategoryDecl>(1232"@interface A @end @interface A() { int x; } @end",1233"@interface A @end @interface A() { int y; } @end", Lang_OBJC,1234objcCategoryDecl());1235EXPECT_FALSE(testStructuralMatch(t));1236}
1237
1238TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarType) {1239auto t = makeDecls<ObjCCategoryDecl>(1240"@interface A @end @interface A() { int x; } @end",1241"@interface A @end @interface A() { float x; } @end", Lang_OBJC,1242objcCategoryDecl());1243EXPECT_FALSE(testStructuralMatch(t));1244}
1245
1246TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarBitfieldWidth) {1247auto t = makeDecls<ObjCCategoryDecl>(1248"@interface A @end @interface A() { int x: 1; } @end",1249"@interface A @end @interface A() { int x: 2; } @end", Lang_OBJC,1250objcCategoryDecl());1251EXPECT_FALSE(testStructuralMatch(t));1252}
1253
1254TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarVisibility) {1255auto t = makeDecls<ObjCCategoryDecl>(1256"@interface A @end @interface A() { @public int x; } @end",1257"@interface A @end @interface A() { @protected int x; } @end", Lang_OBJC,1258objcCategoryDecl());1259EXPECT_FALSE(testStructuralMatch(t));1260}
1261
1262TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarNumber) {1263auto t = makeDecls<ObjCCategoryDecl>(1264"@interface A @end @interface A() { int x; } @end",1265"@interface A @end @interface A() {} @end", Lang_OBJC,1266objcCategoryDecl());1267EXPECT_FALSE(testStructuralMatch(t));1268}
1269
1270TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarOrder) {1271auto t = makeDecls<ObjCCategoryDecl>(1272"@interface A @end @interface A() { int x; int y; } @end",1273"@interface A @end @interface A() { int y; int x; } @end", Lang_OBJC,1274objcCategoryDecl());1275EXPECT_FALSE(testStructuralMatch(t));1276}
1277
1278TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingMethods) {1279auto t = makeDecls<ObjCCategoryDecl>(1280"@interface A @end @interface A(X) -(void)test; @end",1281"@interface A @end @interface A(X) -(void)test; @end", Lang_OBJC,1282objcCategoryDecl());1283EXPECT_TRUE(testStructuralMatch(t));1284}
1285
1286TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodName) {1287auto t = makeDecls<ObjCCategoryDecl>(1288"@interface A @end @interface A(X) -(void)test; @end",1289"@interface A @end @interface A(X) -(void)wasd; @end", Lang_OBJC,1290objcCategoryDecl());1291EXPECT_FALSE(testStructuralMatch(t));1292
1293auto t2 = makeDecls<ObjCCategoryDecl>(1294"@interface A @end @interface A(X) -(void)test:(int)x more:(int)y; @end",1295"@interface A @end @interface A(X) -(void)test:(int)x :(int)y; @end",1296Lang_OBJC, objcCategoryDecl());1297EXPECT_FALSE(testStructuralMatch(t2));1298}
1299
1300TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodClassInstance) {1301auto t = makeDecls<ObjCCategoryDecl>(1302"@interface A @end @interface A(X) -(void)test; @end",1303"@interface A @end @interface A(X) +(void)test; @end", Lang_OBJC,1304objcCategoryDecl());1305EXPECT_FALSE(testStructuralMatch(t));1306}
1307
1308TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodReturnType) {1309auto t = makeDecls<ObjCCategoryDecl>(1310"@interface A @end @interface A(X) -(void)test; @end",1311"@interface A @end @interface A(X) -(int)test; @end", Lang_OBJC,1312objcCategoryDecl());1313EXPECT_FALSE(testStructuralMatch(t));1314}
1315
1316TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodParameterType) {1317auto t = makeDecls<ObjCCategoryDecl>(1318"@interface A @end @interface A(X) -(void)test:(int)x; @end",1319"@interface A @end @interface A(X) -(void)test:(float)x; @end", Lang_OBJC,1320objcCategoryDecl());1321EXPECT_FALSE(testStructuralMatch(t));1322}
1323
1324TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodParameterName) {1325auto t = makeDecls<ObjCCategoryDecl>(1326"@interface A @end @interface A(X) -(void)test:(int)x; @end",1327"@interface A @end @interface A(X) -(void)test:(int)y; @end", Lang_OBJC,1328objcCategoryDecl());1329EXPECT_TRUE(testStructuralMatch(t));1330}
1331
1332TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodNumber) {1333auto t = makeDecls<ObjCCategoryDecl>(1334"@interface A @end @interface A(X) -(void)test; @end",1335"@interface A @end @interface A(X) @end", Lang_OBJC, objcCategoryDecl());1336EXPECT_FALSE(testStructuralMatch(t));1337}
1338
1339TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodOrder) {1340auto t = makeDecls<ObjCCategoryDecl>(1341"@interface A @end @interface A(X) -(void)u; -(void)v; @end",1342"@interface A @end @interface A(X) -(void)v; -(void)u; @end", Lang_OBJC,1343objcCategoryDecl());1344EXPECT_FALSE(testStructuralMatch(t));1345}
1346
1347struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {};1348
1349TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) {1350auto t = makeNamedDecls("template <class T> struct foo;",1351"template <class T> struct foo;", Lang_CXX03);1352EXPECT_TRUE(testStructuralMatch(t));1353}
1354
1355TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) {1356auto t = makeNamedDecls("template <class T> struct foo;",1357"template <class U> struct foo;", Lang_CXX03);1358EXPECT_TRUE(testStructuralMatch(t));1359}
1360
1361TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) {1362auto t = makeNamedDecls("template <class T> struct foo;",1363"template <int T> struct foo;", Lang_CXX03);1364EXPECT_FALSE(testStructuralMatch(t));1365}
1366
1367TEST_F(StructuralEquivalenceTemplateTest, BitFieldDecl) {1368const char *Code = "class foo { int a : 2; };";1369auto t = makeNamedDecls(Code, Code, Lang_CXX03);1370EXPECT_TRUE(testStructuralMatch(t));1371}
1372
1373TEST_F(StructuralEquivalenceTemplateTest, BitFieldDeclDifferentWidth) {1374auto t = makeNamedDecls("class foo { int a : 2; };",1375"class foo { int a : 4; };", Lang_CXX03);1376EXPECT_FALSE(testStructuralMatch(t));1377}
1378
1379TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDecl) {1380const char *Code = "template <class T> class foo { int a : sizeof(T); };";1381auto t = makeNamedDecls(Code, Code, Lang_CXX03);1382EXPECT_TRUE(testStructuralMatch(t));1383}
1384
1385TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal) {1386auto t = makeNamedDecls(1387"template <class A, class B> class foo { int a : sizeof(A); };",1388"template <class A, class B> class foo { int a : sizeof(B); };",1389Lang_CXX03);1390EXPECT_FALSE(testStructuralMatch(t));1391}
1392
1393TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal2) {1394auto t = makeNamedDecls(1395"template <class A> class foo { int a : sizeof(A); };",1396"template <class A> class foo { int a : sizeof(A) + 1; };", Lang_CXX03);1397EXPECT_FALSE(testStructuralMatch(t));1398}
1399
1400TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) {1401auto Decls = makeNamedDecls(1402"template <bool b> struct foo {explicit(b) foo(int);};",1403"template <bool b> struct foo {explicit(b) foo(int);};", Lang_CXX20);1404CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(1405get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));1406CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(1407get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));1408EXPECT_TRUE(testStructuralMatch(First, Second));1409}
1410
1411TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) {1412auto Decls = makeNamedDecls(1413"template <bool b> struct foo {explicit(b) foo(int);};",1414"template <bool b> struct foo {explicit(!b) foo(int);};", Lang_CXX20);1415CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(1416get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));1417CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(1418get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));1419EXPECT_FALSE(testStructuralMatch(First, Second));1420}
1421
1422TEST_F(StructuralEquivalenceTemplateTest,1423TemplateVsSubstTemplateTemplateParmInArgEq) {1424auto t = makeDecls<ClassTemplateSpecializationDecl>(1425R"(1426template <typename P1> class Arg { };
1427template <template <typename PP1> class P1> class Primary { };
1428
1429void f() {
1430// Make specialization with simple template.
1431Primary <Arg> A;
1432}
1433)",1434R"(1435template <typename P1> class Arg { };
1436template <template <typename PP1> class P1> class Primary { };
1437
1438template <template <typename PP1> class P1> class Templ {
1439void f() {
1440// Make specialization with substituted template template param.
1441Primary <P1> A;
1442};
1443};
1444
1445// Instantiate with substitution Arg into P1.
1446template class Templ <Arg>;
1447)",1448Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1449EXPECT_TRUE(testStructuralMatch(t));1450}
1451
1452TEST_F(StructuralEquivalenceTemplateTest,1453TemplateVsSubstTemplateTemplateParmInArgNotEq) {1454auto t = makeDecls<ClassTemplateSpecializationDecl>(1455R"(1456template <typename P1> class Arg { };
1457template <template <typename PP1> class P1> class Primary { };
1458
1459void f() {
1460// Make specialization with simple template.
1461Primary <Arg> A;
1462}
1463)",1464R"(1465// Arg is different from the other, this should cause non-equivalence.
1466template <typename P1> class Arg { int X; };
1467template <template <typename PP1> class P1> class Primary { };
1468
1469template <template <typename PP1> class P1> class Templ {
1470void f() {
1471// Make specialization with substituted template template param.
1472Primary <P1> A;
1473};
1474};
1475
1476// Instantiate with substitution Arg into P1.
1477template class Templ <Arg>;
1478)",1479Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1480EXPECT_FALSE(testStructuralMatch(t));1481}
1482
1483struct StructuralEquivalenceDependentTemplateArgsTest1484: StructuralEquivalenceTemplateTest {};1485
1486TEST_F(StructuralEquivalenceDependentTemplateArgsTest,1487SameStructsInDependentArgs) {1488std::string Code =1489R"(1490template <typename>
1491struct S1;
1492
1493template <typename>
1494struct enable_if;
1495
1496struct S
1497{
1498template <typename T, typename enable_if<S1<T>>::type>
1499void f();
1500};
1501)";1502auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,1503functionTemplateDecl(hasName("f")));1504EXPECT_TRUE(testStructuralMatch(t));1505}
1506
1507TEST_F(StructuralEquivalenceDependentTemplateArgsTest,1508DifferentStructsInDependentArgs) {1509std::string Code =1510R"(1511template <typename>
1512struct S1;
1513
1514template <typename>
1515struct S2;
1516
1517template <typename>
1518struct enable_if;
1519)";1520auto t = makeDecls<FunctionTemplateDecl>(Code + R"(1521struct S
1522{
1523template <typename T, typename enable_if<S1<T>>::type>
1524void f();
1525};
1526)",1527Code + R"(1528struct S
1529{
1530template <typename T, typename enable_if<S2<T>>::type>
1531void f();
1532};
1533)",1534Lang_CXX11,1535functionTemplateDecl(hasName("f")));1536EXPECT_FALSE(testStructuralMatch(t));1537}
1538
1539TEST_F(StructuralEquivalenceDependentTemplateArgsTest,1540SameStructsInDependentScopeDeclRefExpr) {1541std::string Code =1542R"(1543template <typename>
1544struct S1;
1545
1546template <bool>
1547struct enable_if;
1548
1549struct S
1550{
1551template <typename T, typename enable_if<S1<T>::value>::type>
1552void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1553};
1554)";1555auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,1556functionTemplateDecl(hasName("f")));1557EXPECT_TRUE(testStructuralMatch(t));1558}
1559
1560TEST_F(StructuralEquivalenceDependentTemplateArgsTest,1561DifferentStructsInDependentScopeDeclRefExpr) {1562std::string Code =1563R"(1564template <typename>
1565struct S1;
1566
1567template <typename>
1568struct S2;
1569
1570template <bool>
1571struct enable_if;
1572)";1573auto t = makeDecls<FunctionTemplateDecl>(Code + R"(1574struct S
1575{
1576template <typename T, typename enable_if<S1<T>::value>::type>
1577void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1578};
1579)",1580Code + R"(1581struct S
1582{
1583template <typename T, typename enable_if<S2<T>::value>::type>
1584void f();
1585};
1586)",1587Lang_CXX03,1588functionTemplateDecl(hasName("f")));1589EXPECT_FALSE(testStructuralMatch(t));1590}
1591
1592TEST_F(StructuralEquivalenceDependentTemplateArgsTest,1593DifferentValueInDependentScopeDeclRefExpr) {1594std::string Code =1595R"(1596template <typename>
1597struct S1;
1598
1599template <bool>
1600struct enable_if;
1601)";1602auto t = makeDecls<FunctionTemplateDecl>(Code + R"(1603struct S
1604{
1605template <typename T, typename enable_if<S1<T>::value1>::type>
1606void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^
1607};
1608)",1609Code + R"(1610struct S
1611{
1612template <typename T, typename enable_if<S1<T>::value2>::type>
1613void f();
1614};
1615)",1616Lang_CXX03,1617functionTemplateDecl(hasName("f")));1618EXPECT_FALSE(testStructuralMatch(t));1619}
1620
1621TEST_F(1622StructuralEquivalenceTemplateTest,1623ClassTemplSpecWithQualifiedAndNonQualifiedTypeArgsShouldBeEqual) {1624auto t = makeDecls<ClassTemplateSpecializationDecl>(1625R"(1626template <class T> struct Primary {};
1627namespace N {
1628struct Arg;
1629}
1630// Explicit instantiation with qualified name.
1631template struct Primary<N::Arg>;
1632)",1633R"(1634template <class T> struct Primary {};
1635namespace N {
1636struct Arg;
1637}
1638using namespace N;
1639// Explicit instantiation with UNqualified name.
1640template struct Primary<Arg>;
1641)",1642Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1643EXPECT_TRUE(testStructuralMatch(t));1644}
1645
1646TEST_F(1647StructuralEquivalenceTemplateTest,1648ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTypeArgs) {1649auto t = makeDecls<ClassTemplateSpecializationDecl>(1650R"(1651template <class T> struct Primary {};
1652namespace N {
1653struct Arg { int a; };
1654}
1655// Explicit instantiation with qualified name.
1656template struct Primary<N::Arg>;
1657)",1658R"(1659template <class T> struct Primary {};
1660namespace N {
1661// This struct is not equivalent with the other in the prev TU.
1662struct Arg { double b; }; // -- Field mismatch.
1663}
1664using namespace N;
1665// Explicit instantiation with UNqualified name.
1666template struct Primary<Arg>;
1667)",1668Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1669EXPECT_FALSE(testStructuralMatch(t));1670}
1671
1672TEST_F(1673StructuralEquivalenceTemplateTest,1674ClassTemplSpecWithQualifiedAndNonQualifiedTemplArgsShouldBeEqual) {1675auto t = makeDecls<ClassTemplateSpecializationDecl>(1676R"(1677template <template <class> class T> struct Primary {};
1678namespace N {
1679template <class T> struct Arg;
1680}
1681// Explicit instantiation with qualified name.
1682template struct Primary<N::Arg>;
1683)",1684R"(1685template <template <class> class T> struct Primary {};
1686namespace N {
1687template <class T> struct Arg;
1688}
1689using namespace N;
1690// Explicit instantiation with UNqualified name.
1691template struct Primary<Arg>;
1692)",1693Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1694EXPECT_TRUE(testStructuralMatch(t));1695}
1696
1697TEST_F(1698StructuralEquivalenceTemplateTest,1699ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTemplArgs) {1700auto t = makeDecls<ClassTemplateSpecializationDecl>(1701R"(1702template <template <class> class T> struct Primary {};
1703namespace N {
1704template <class T> struct Arg { int a; };
1705}
1706// Explicit instantiation with qualified name.
1707template struct Primary<N::Arg>;
1708)",1709R"(1710template <template <class> class T> struct Primary {};
1711namespace N {
1712// This template is not equivalent with the other in the prev TU.
1713template <class T> struct Arg { double b; }; // -- Field mismatch.
1714}
1715using namespace N;
1716// Explicit instantiation with UNqualified name.
1717template struct Primary<Arg>;
1718)",1719Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1720EXPECT_FALSE(testStructuralMatch(t));1721}
1722
1723TEST_F(StructuralEquivalenceTemplateTest,1724IgnoreTemplateParmDepthAtTemplateTypeParmDecl) {1725auto Decls = makeDecls<ClassTemplateDecl>(1726R"(1727template<class> struct A;
1728)",1729R"(1730template<class> struct S {
1731template<class> friend struct A;
1732};
1733)",1734Lang_CXX03, classTemplateDecl(hasName("A")),1735classTemplateDecl(hasName("A")));1736EXPECT_TRUE(testStructuralMatch(Decls));1737EXPECT_TRUE(testStructuralMatch(Decls, true));1738}
1739
1740TEST_F(StructuralEquivalenceTemplateTest,1741IgnoreTemplateParmDepthAtNonTypeTemplateParmDecl) {1742auto Decls = makeDecls<ClassTemplateDecl>(1743R"(1744template<class T, T U> struct A;
1745)",1746R"(1747template<class T> struct S {
1748template<class P, P Q> friend struct A;
1749};
1750)",1751Lang_CXX03, classTemplateDecl(hasName("A")),1752classTemplateDecl(hasName("A")));1753EXPECT_FALSE(testStructuralMatch(Decls));1754EXPECT_TRUE(testStructuralMatch(Decls, /*IgnoreTemplateParmDepth=*/true));1755}
1756
1757TEST_F(1758StructuralEquivalenceTemplateTest,1759ClassTemplSpecWithInequivalentShadowedTemplArg) {1760auto t = makeDecls<ClassTemplateSpecializationDecl>(1761R"(1762template <template <class> class T> struct Primary {};
1763template <class T> struct Arg { int a; };
1764// Explicit instantiation with ::Arg
1765template struct Primary<Arg>;
1766)",1767R"(1768template <template <class> class T> struct Primary {};
1769template <class T> struct Arg { int a; };
1770namespace N {
1771// This template is not equivalent with the other in the global scope.
1772template <class T> struct Arg { double b; }; // -- Field mismatch.
1773// Explicit instantiation with N::Arg which shadows ::Arg
1774template struct Primary<Arg>;
1775}
1776)",1777Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1778EXPECT_FALSE(testStructuralMatch(t));1779}
1780struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest {1781llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;1782
1783template <typename NodeType, typename MatcherType>1784std::pair<NodeType *, NodeType *>1785findDeclPair(std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> TU,1786MatcherType M) {1787NodeType *D0 = FirstDeclMatcher<NodeType>().match(get<0>(TU), M);1788NodeType *D1 = FirstDeclMatcher<NodeType>().match(get<1>(TU), M);1789return {D0, D1};1790}1791
1792template <typename NodeType>1793bool isInNonEqCache(std::pair<NodeType *, NodeType *> D) {1794return NonEquivalentDecls.count(D) > 0;1795}1796};1797
1798TEST_F(StructuralEquivalenceCacheTest, SimpleNonEq) {1799auto TU = makeTuDecls(1800R"(1801class A {};
1802class B {};
1803void x(A, A);
1804)",1805R"(1806class A {};
1807class B {};
1808void x(A, B);
1809)",1810Lang_CXX03);1811
1812StructuralEquivalenceContext Ctx(1813get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),1814NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);1815
1816auto X = findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")));1817EXPECT_FALSE(Ctx.IsEquivalent(X.first, X.second));1818
1819EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(1820TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));1821EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(1822TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));1823}
1824
1825TEST_F(StructuralEquivalenceCacheTest, ReturnStmtNonEq) {1826auto TU = makeTuDecls(1827R"(1828bool x() { return true; }
1829)",1830R"(1831bool x() { return false; }
1832)",1833Lang_CXX03);1834
1835StructuralEquivalenceContext Ctx(1836get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),1837NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);1838
1839auto X = findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")));1840EXPECT_FALSE(Ctx.IsEquivalent(X.first->getBody(), X.second->getBody()));1841
1842}
1843
1844TEST_F(StructuralEquivalenceCacheTest, VarDeclNoEq) {1845auto TU = makeTuDecls(1846R"(1847int p;
1848)",1849R"(1850int q;
1851)",1852Lang_CXX03);1853
1854StructuralEquivalenceContext Ctx(1855get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),1856NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);1857
1858auto Var = findDeclPair<VarDecl>(TU, varDecl());1859EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));1860}
1861
1862TEST_F(StructuralEquivalenceCacheTest, VarDeclWithDifferentStorageClassNoEq) {1863auto TU = makeTuDecls(1864R"(1865int p;
1866)",1867R"(1868static int p;
1869)",1870Lang_CXX03);1871
1872StructuralEquivalenceContext Ctx(1873get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),1874NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);1875
1876auto Var = findDeclPair<VarDecl>(TU, varDecl());1877EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));1878}
1879
1880TEST_F(StructuralEquivalenceCacheTest,1881NonTypeTemplateParmWithDifferentPositionNoEq) {1882auto TU = makeTuDecls(1883R"(1884template<int T>
1885struct A {
1886template<int U>
1887void foo() {}
1888};
1889)",1890R"(1891template<int U>
1892struct A {
1893template<int V, int T>
1894void foo() {}
1895};
1896)",1897Lang_CXX03);1898
1899StructuralEquivalenceContext Ctx(1900get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),1901NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);1902
1903auto NTTP = findDeclPair<NonTypeTemplateParmDecl>(1904TU, nonTypeTemplateParmDecl(hasName("T")));1905EXPECT_FALSE(Ctx.IsEquivalent(NTTP.first, NTTP.second));1906}
1907
1908TEST_F(StructuralEquivalenceCacheTest, VarDeclWithInitNoEq) {1909auto TU = makeTuDecls(1910R"(1911int p = 1;
1912)",1913R"(1914int p = 2;
1915)",1916Lang_CXX03);1917
1918StructuralEquivalenceContext Ctx(1919get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),1920NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);1921
1922auto Var = findDeclPair<VarDecl>(TU, varDecl());1923EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));1924}
1925
1926TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) {1927auto TU = makeTuDecls(1928R"(1929class A {};
1930class B { int i; };
1931void x(A *);
1932void y(A *);
1933class C {
1934friend void x(A *);
1935friend void y(A *);
1936};
1937)",1938R"(1939class A {};
1940class B { int i; };
1941void x(A *);
1942void y(B *);
1943class C {
1944friend void x(A *);
1945friend void y(B *);
1946};
1947)",1948Lang_CXX03);1949
1950StructuralEquivalenceContext Ctx(1951get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),1952NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);1953
1954auto C = findDeclPair<CXXRecordDecl>(1955TU, cxxRecordDecl(hasName("C"), unless(isImplicit())));1956EXPECT_FALSE(Ctx.IsEquivalent(C.first, C.second));1957
1958EXPECT_FALSE(isInNonEqCache(C));1959EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(1960TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));1961EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(1962TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));1963EXPECT_FALSE(isInNonEqCache(1964findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));1965EXPECT_FALSE(isInNonEqCache(1966findDeclPair<FunctionDecl>(TU, functionDecl(hasName("y")))));1967}
1968
1969TEST_F(StructuralEquivalenceCacheTest, Cycle) {1970auto TU = makeTuDecls(1971R"(1972class C;
1973class A { C *c; };
1974void x(A *);
1975class C {
1976friend void x(A *);
1977};
1978)",1979R"(1980class C;
1981class A { C *c; };
1982void x(A *);
1983class C {
1984friend void x(A *);
1985};
1986)",1987Lang_CXX03);1988
1989StructuralEquivalenceContext Ctx(1990get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(),1991NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false);1992
1993auto C = findDeclPair<CXXRecordDecl>(1994TU, cxxRecordDecl(hasName("C"), unless(isImplicit())));1995EXPECT_TRUE(Ctx.IsEquivalent(C.first, C.second));1996
1997EXPECT_FALSE(isInNonEqCache(C));1998EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(1999TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));2000EXPECT_FALSE(isInNonEqCache(2001findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));2002}
2003
2004struct StructuralEquivalenceStmtTest : StructuralEquivalenceTest {};2005
2006/// Fallback matcher to be used only when there is no specific matcher for a
2007/// Expr subclass. Remove this once all Expr subclasses have their own matcher.
2008static auto &fallbackExprMatcher = expr;2009
2010TEST_F(StructuralEquivalenceStmtTest, AddrLabelExpr) {2011auto t = makeWrappedStmts("lbl: &&lbl;", "lbl: &&lbl;", Lang_CXX03,2012addrLabelExpr());2013EXPECT_TRUE(testStructuralMatch(t));2014}
2015
2016TEST_F(StructuralEquivalenceStmtTest, AddrLabelExprDifferentLabel) {2017auto t = makeWrappedStmts("lbl1: lbl2: &&lbl1;", "lbl1: lbl2: &&lbl2;",2018Lang_CXX03, addrLabelExpr());2019// FIXME: Should be false. LabelDecl are incorrectly matched.2020EXPECT_TRUE(testStructuralMatch(t));2021}
2022
2023static const std::string MemoryOrderSrc = R"(2024enum memory_order {
2025memory_order_relaxed,
2026memory_order_consume,
2027memory_order_acquire,
2028memory_order_release,
2029memory_order_acq_rel,
2030memory_order_seq_cst
2031};
2032)";2033
2034TEST_F(StructuralEquivalenceStmtTest, AtomicExpr) {2035std::string Prefix = "char a, b; " + MemoryOrderSrc;2036auto t = makeStmts(2037Prefix +2038"void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",2039Prefix +2040"void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",2041Lang_CXX03, atomicExpr());2042EXPECT_TRUE(testStructuralMatch(t));2043}
2044
2045TEST_F(StructuralEquivalenceStmtTest, AtomicExprDifferentOp) {2046std::string Prefix = "char a, b; " + MemoryOrderSrc;2047auto t = makeStmts(2048Prefix +2049"void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",2050Prefix +2051"void wrapped() { __atomic_store(&a, &b, memory_order_seq_cst); }",2052Lang_CXX03, atomicExpr());2053EXPECT_FALSE(testStructuralMatch(t));2054}
2055
2056TEST_F(StructuralEquivalenceStmtTest, BinaryOperator) {2057auto t = makeWrappedStmts("1 + 1", "1 + 1", Lang_CXX03, binaryOperator());2058EXPECT_TRUE(testStructuralMatch(t));2059}
2060
2061TEST_F(StructuralEquivalenceStmtTest, BinaryOperatorDifferentOps) {2062auto t = makeWrappedStmts("1 + 1", "1 - 1", Lang_CXX03, binaryOperator());2063EXPECT_FALSE(testStructuralMatch(t));2064}
2065
2066TEST_F(StructuralEquivalenceStmtTest, CallExpr) {2067std::string Src = "int call(); int wrapped() { call(); }";2068auto t = makeStmts(Src, Src, Lang_CXX03, callExpr());2069EXPECT_TRUE(testStructuralMatch(t));2070}
2071
2072TEST_F(StructuralEquivalenceStmtTest, CallExprDifferentCallee) {2073std::string FunctionSrc = "int func1(); int func2();\n";2074auto t = makeStmts(FunctionSrc + "void wrapper() { func1(); }",2075FunctionSrc + "void wrapper() { func2(); }", Lang_CXX03,2076callExpr());2077EXPECT_FALSE(testStructuralMatch(t));2078}
2079
2080TEST_F(StructuralEquivalenceStmtTest, CharacterLiteral) {2081auto t = makeWrappedStmts("'a'", "'a'", Lang_CXX03, characterLiteral());2082EXPECT_TRUE(testStructuralMatch(t));2083}
2084
2085TEST_F(StructuralEquivalenceStmtTest, CharacterLiteralDifferentValues) {2086auto t = makeWrappedStmts("'a'", "'b'", Lang_CXX03, characterLiteral());2087EXPECT_FALSE(testStructuralMatch(t));2088}
2089
2090TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExpr) {2091auto t = makeWrappedStmts("__is_lvalue_expr(1)", "__is_lvalue_expr(1)",2092Lang_CXX03, fallbackExprMatcher());2093EXPECT_TRUE(testStructuralMatch(t));2094}
2095
2096TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExprDifferentKind) {2097auto t = makeWrappedStmts("__is_lvalue_expr(1)", "__is_rvalue_expr(1)",2098Lang_CXX03, fallbackExprMatcher());2099EXPECT_FALSE(testStructuralMatch(t));2100}
2101
2102TEST_F(StructuralEquivalenceStmtTest, FloatingLiteral) {2103auto t = makeWrappedStmts("1.0", "1.0", Lang_CXX03, fallbackExprMatcher());2104EXPECT_TRUE(testStructuralMatch(t));2105}
2106
2107TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentSpelling) {2108auto t = makeWrappedStmts("0x10.1p0", "16.0625", Lang_CXX17,2109fallbackExprMatcher());2110// Same value but with different spelling is equivalent.2111EXPECT_TRUE(testStructuralMatch(t));2112}
2113
2114TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentType) {2115auto t = makeWrappedStmts("1.0", "1.0f", Lang_CXX03, fallbackExprMatcher());2116EXPECT_FALSE(testStructuralMatch(t));2117}
2118
2119TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentValue) {2120auto t = makeWrappedStmts("1.01", "1.0", Lang_CXX03, fallbackExprMatcher());2121EXPECT_FALSE(testStructuralMatch(t));2122}
2123
2124TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSame) {2125auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",2126"_Generic(0u, unsigned int: 0, float: 1)", Lang_C99,2127genericSelectionExpr());2128EXPECT_TRUE(testStructuralMatch(t));2129}
2130
2131TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSignsDiffer) {2132auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",2133"_Generic(0, int: 0, float: 1)", Lang_C99,2134genericSelectionExpr());2135EXPECT_FALSE(testStructuralMatch(t));2136}
2137
2138TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprOrderDiffers) {2139auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",2140"_Generic(0u, float: 1, unsigned int: 0)", Lang_C99,2141genericSelectionExpr());2142EXPECT_FALSE(testStructuralMatch(t));2143}
2144
2145TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprDependentResultSame) {2146auto t = makeStmts(2147R"(2148template <typename T>
2149void f() {
2150T x;
2151(void)_Generic(x, int: 0, float: 1);
2152}
2153void g() { f<int>(); }
2154)",2155R"(2156template <typename T>
2157void f() {
2158T x;
2159(void)_Generic(x, int: 0, float: 1);
2160}
2161void g() { f<int>(); }
2162)",2163Lang_CXX03, genericSelectionExpr());2164EXPECT_TRUE(testStructuralMatch(t));2165}
2166
2167TEST_F(StructuralEquivalenceStmtTest,2168GenericSelectionExprDependentResultOrderDiffers) {2169auto t = makeStmts(2170R"(2171template <typename T>
2172void f() {
2173T x;
2174(void)_Generic(x, float: 1, int: 0);
2175}
2176void g() { f<int>(); }
2177)",2178R"(2179template <typename T>
2180void f() {
2181T x;
2182(void)_Generic(x, int: 0, float: 1);
2183}
2184void g() { f<int>(); }
2185)",2186Lang_CXX03, genericSelectionExpr());2187
2188EXPECT_FALSE(testStructuralMatch(t));2189}
2190TEST_F(StructuralEquivalenceStmtTest, IntegerLiteral) {2191auto t = makeWrappedStmts("1", "1", Lang_CXX03, integerLiteral());2192EXPECT_TRUE(testStructuralMatch(t));2193}
2194
2195TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentSpelling) {2196auto t = makeWrappedStmts("1", "0x1", Lang_CXX03, integerLiteral());2197// Same value but with different spelling is equivalent.2198EXPECT_TRUE(testStructuralMatch(t));2199}
2200
2201TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentValue) {2202auto t = makeWrappedStmts("1", "2", Lang_CXX03, integerLiteral());2203EXPECT_FALSE(testStructuralMatch(t));2204}
2205
2206TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentTypes) {2207auto t = makeWrappedStmts("1", "1L", Lang_CXX03, integerLiteral());2208EXPECT_FALSE(testStructuralMatch(t));2209}
2210
2211TEST_F(StructuralEquivalenceStmtTest, MemberExpr) {2212std::string ClassSrc = "struct C { int a; int b; };";2213auto t = makeStmts(ClassSrc + "int wrapper() { C c; return c.a; }",2214ClassSrc + "int wrapper() { C c; return c.a; }",2215Lang_CXX03, memberExpr());2216EXPECT_TRUE(testStructuralMatch(t));2217}
2218
2219TEST_F(StructuralEquivalenceStmtTest, MemberExprDifferentMember) {2220std::string ClassSrc = "struct C { int a; int b; };";2221auto t = makeStmts(ClassSrc + "int wrapper() { C c; return c.a; }",2222ClassSrc + "int wrapper() { C c; return c.b; }",2223Lang_CXX03, memberExpr());2224EXPECT_FALSE(testStructuralMatch(t));2225}
2226
2227TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteral) {2228auto t =2229makeWrappedStmts("@\"a\"", "@\"a\"", Lang_OBJCXX, fallbackExprMatcher());2230EXPECT_TRUE(testStructuralMatch(t));2231}
2232
2233TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteralDifferentContent) {2234auto t =2235makeWrappedStmts("@\"a\"", "@\"b\"", Lang_OBJCXX, fallbackExprMatcher());2236EXPECT_FALSE(testStructuralMatch(t));2237}
2238
2239TEST_F(StructuralEquivalenceStmtTest, StringLiteral) {2240auto t = makeWrappedStmts("\"a\"", "\"a\"", Lang_CXX03, stringLiteral());2241EXPECT_TRUE(testStructuralMatch(t));2242}
2243
2244TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentContent) {2245auto t = makeWrappedStmts("\"a\"", "\"b\"", Lang_CXX03, stringLiteral());2246EXPECT_FALSE(testStructuralMatch(t));2247}
2248
2249TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentLength) {2250auto t = makeWrappedStmts("\"a\"", "\"aa\"", Lang_CXX03, stringLiteral());2251EXPECT_FALSE(testStructuralMatch(t));2252}
2253
2254TEST_F(StructuralEquivalenceStmtTest, TypeTraitExpr) {2255auto t = makeWrappedStmts("__is_pod(int)", "__is_pod(int)", Lang_CXX03,2256fallbackExprMatcher());2257EXPECT_TRUE(testStructuralMatch(t));2258}
2259
2260TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentType) {2261auto t = makeWrappedStmts("__is_pod(int)", "__is_pod(long)", Lang_CXX03,2262fallbackExprMatcher());2263EXPECT_FALSE(testStructuralMatch(t));2264}
2265
2266TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTrait) {2267auto t = makeWrappedStmts(2268"__is_pod(int)", "__is_trivially_constructible(int)", Lang_CXX03, expr());2269EXPECT_FALSE(testStructuralMatch(t));2270}
2271
2272TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTraits) {2273auto t = makeWrappedStmts("__is_constructible(int)",2274"__is_constructible(int, int)", Lang_CXX03, expr());2275EXPECT_FALSE(testStructuralMatch(t));2276}
2277
2278TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExpr) {2279auto t = makeWrappedStmts("sizeof(int)", "sizeof(int)", Lang_CXX03,2280unaryExprOrTypeTraitExpr());2281EXPECT_TRUE(testStructuralMatch(t));2282}
2283
2284TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentKind) {2285auto t = makeWrappedStmts("sizeof(int)", "alignof(long)", Lang_CXX11,2286unaryExprOrTypeTraitExpr());2287EXPECT_FALSE(testStructuralMatch(t));2288}
2289
2290TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentType) {2291auto t = makeWrappedStmts("sizeof(int)", "sizeof(long)", Lang_CXX03,2292unaryExprOrTypeTraitExpr());2293EXPECT_FALSE(testStructuralMatch(t));2294}
2295
2296TEST_F(StructuralEquivalenceStmtTest, UnaryOperator) {2297auto t = makeWrappedStmts("+1", "+1", Lang_CXX03, unaryOperator());2298EXPECT_TRUE(testStructuralMatch(t));2299}
2300
2301TEST_F(StructuralEquivalenceStmtTest, UnaryOperatorDifferentOps) {2302auto t = makeWrappedStmts("+1", "-1", Lang_CXX03, unaryOperator());2303EXPECT_FALSE(testStructuralMatch(t));2304}
2305
2306TEST_F(StructuralEquivalenceStmtTest,2307CXXOperatorCallExprVsUnaryBinaryOperator) {2308auto t = makeNamedDecls(2309R"(2310template <typename T, T x>
2311class A;
2312template <typename T, T x, T y>
2313void foo(
2314A<T, x + y>,
2315A<T, x - y>,
2316A<T, -x>,
2317A<T, x * y>,
2318A<T, *x>,
2319A<T, x / y>,
2320A<T, x % y>,
2321A<T, x ^ y>,
2322A<T, x & y>,
2323A<T, &x>,
2324A<T, x | y>,
2325A<T, ~x>,
2326A<T, !x>,
2327A<T, x < y>,
2328A<T, (x > y)>,
2329A<T, x << y>,
2330A<T, (x >> y)>,
2331A<T, x == y>,
2332A<T, x != y>,
2333A<T, x <= y>,
2334A<T, x >= y>,
2335A<T, x <=> y>,
2336A<T, x && y>,
2337A<T, x || y>,
2338A<T, ++x>,
2339A<T, --x>,
2340A<T, (x , y)>,
2341A<T, x ->* y>,
2342A<T, x -> y>
2343);
2344)",2345R"(2346struct Bar {
2347Bar& operator=(Bar&);
2348Bar& operator->();
2349};
2350
2351Bar& operator+(Bar&, Bar&);
2352Bar& operator+(Bar&);
2353Bar& operator-(Bar&, Bar&);
2354Bar& operator-(Bar&);
2355Bar& operator*(Bar&, Bar&);
2356Bar& operator*(Bar&);
2357Bar& operator/(Bar&, Bar&);
2358Bar& operator%(Bar&, Bar&);
2359Bar& operator^(Bar&, Bar&);
2360Bar& operator&(Bar&, Bar&);
2361Bar& operator&(Bar&);
2362Bar& operator|(Bar&, Bar&);
2363Bar& operator~(Bar&);
2364Bar& operator!(Bar&);
2365Bar& operator<(Bar&, Bar&);
2366Bar& operator>(Bar&, Bar&);
2367Bar& operator+=(Bar&, Bar&);
2368Bar& operator-=(Bar&, Bar&);
2369Bar& operator*=(Bar&, Bar&);
2370Bar& operator/=(Bar&, Bar&);
2371Bar& operator%=(Bar&, Bar&);
2372Bar& operator^=(Bar&, Bar&);
2373Bar& operator&=(Bar&, Bar&);
2374Bar& operator|=(Bar&, Bar&);
2375Bar& operator<<(Bar&, Bar&);
2376Bar& operator>>(Bar&, Bar&);
2377Bar& operator<<=(Bar&, Bar&);
2378Bar& operator>>=(Bar&, Bar&);
2379Bar& operator==(Bar&, Bar&);
2380Bar& operator!=(Bar&, Bar&);
2381Bar& operator<=(Bar&, Bar&);
2382Bar& operator>=(Bar&, Bar&);
2383Bar& operator<=>(Bar&, Bar&);
2384Bar& operator&&(Bar&, Bar&);
2385Bar& operator||(Bar&, Bar&);
2386Bar& operator++(Bar&);
2387Bar& operator--(Bar&);
2388Bar& operator,(Bar&, Bar&);
2389Bar& operator->*(Bar&, Bar&);
2390
2391template <typename T, T x>
2392class A;
2393template <typename T, T x, T y>
2394void foo(
2395A<T, x + y>,
2396A<T, x - y>,
2397A<T, -x>,
2398A<T, x * y>,
2399A<T, *x>,
2400A<T, x / y>,
2401A<T, x % y>,
2402A<T, x ^ y>,
2403A<T, x & y>,
2404A<T, &x>,
2405A<T, x | y>,
2406A<T, ~x>,
2407A<T, !x>,
2408A<T, x < y>,
2409A<T, (x > y)>,
2410A<T, x << y>,
2411A<T, (x >> y)>,
2412A<T, x == y>,
2413A<T, x != y>,
2414A<T, x <= y>,
2415A<T, x >= y>,
2416A<T, x <=> y>,
2417A<T, x && y>,
2418A<T, x || y>,
2419A<T, ++x>,
2420A<T, --x>,
2421A<T, (x , y)>,
2422A<T, x ->* y>,
2423A<T, x -> y>
2424);
2425)",2426Lang_CXX20);2427EXPECT_TRUE(testStructuralMatch(t));2428}
2429
2430TEST_F(StructuralEquivalenceStmtTest,2431CXXOperatorCallExprVsUnaryBinaryOperatorNe) {2432auto t = makeNamedDecls(2433R"(2434template <typename T, T x>
2435class A;
2436template <typename T, T x, T y>
2437void foo(
2438A<T, x + y>
2439);
2440)",2441R"(2442struct Bar;
2443
2444Bar& operator-(Bar&, Bar&);
2445
2446template <typename T, T x>
2447class A;
2448template <typename T, T x, T y>
2449void foo(
2450A<T, x - y>
2451);
2452)",2453Lang_CXX11);2454EXPECT_FALSE(testStructuralMatch(t));2455}
2456
2457TEST_F(StructuralEquivalenceStmtTest, NonTypeTemplateParm) {2458auto t = makeNamedDecls(2459R"(2460template <typename T, T x>
2461class A;
2462template <typename T, T x, T y>
2463void foo(A<T, x>);
2464)",2465R"(2466template <typename T, T x>
2467class A;
2468template <typename T, T x, T y>
2469void foo(A<T, y>);
2470)",2471Lang_CXX11);2472EXPECT_FALSE(testStructuralMatch(t));2473}
2474
2475TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentName) {2476auto t = makeStmts(2477R"(2478void f1(int);
2479template <typename T>
2480void f(T t) {
2481f1(t);
2482}
2483void g() { f<int>(1); }
2484)",2485R"(2486void f2(int);
2487template <typename T>
2488void f(T t) {
2489f2(t);
2490}
2491void g() { f<int>(1); }
2492)",2493Lang_CXX03, unresolvedLookupExpr());2494EXPECT_FALSE(testStructuralMatch(t));2495}
2496
2497TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentQualifier) {2498auto t = makeStmts(2499R"(2500struct X {
2501static void g(int);
2502static void g(char);
2503};
2504
2505template <typename T>
2506void f(T t) {
2507X::g(t);
2508}
2509
2510void g() { f<int>(1); }
2511)",2512R"(2513struct Y {
2514static void g(int);
2515static void g(char);
2516};
2517
2518template <typename T>
2519void f(T t) {
2520Y::g(t);
2521}
2522
2523void g() { f<int>(1); }
2524)",2525Lang_CXX03, unresolvedLookupExpr());2526EXPECT_FALSE(testStructuralMatch(t));2527}
2528
2529TEST_F(StructuralEquivalenceStmtTest,2530UnresolvedLookupDifferentTemplateArgument) {2531auto t = makeStmts(2532R"(2533struct A {};
2534template<typename T1, typename T2>
2535void g() {}
2536
2537template <typename T>
2538void f() {
2539g<A, T>();
2540}
2541
2542void h() { f<int>(); }
2543)",2544R"(2545struct B {};
2546template<typename T1, typename T2>
2547void g() {}
2548
2549template <typename T>
2550void f() {
2551g<B, T>();
2552}
2553
2554void h() { f<int>(); }
2555)",2556Lang_CXX03, unresolvedLookupExpr());2557EXPECT_FALSE(testStructuralMatch(t));2558}
2559
2560TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookup) {2561auto t = makeStmts(2562R"(2563struct A {};
2564struct B {
2565template<typename T1, typename T2>
2566static void g(int) {};
2567template<typename T1, typename T2>
2568static void g(char) {};
2569};
2570
2571template <typename T1, typename T2>
2572void f(T2 x) {
2573B::g<A, T1>(x);
2574}
2575
2576void g() { f<char, int>(1); }
2577)",2578R"(2579struct A {};
2580struct B {
2581template<typename T1, typename T2>
2582static void g(int) {};
2583template<typename T1, typename T2>
2584static void g(char) {};
2585};
2586
2587template <typename T1, typename T2>
2588void f(T2 x) {
2589B::g<A, T1>(x);
2590}
2591
2592void g() { f<char, int>(1); }
2593)",2594Lang_CXX03, unresolvedLookupExpr());2595EXPECT_TRUE(testStructuralMatch(t));2596}
2597
2598TEST_F(StructuralEquivalenceCacheTest, GotoStmtNoEq) {2599auto S = makeStmts(2600R"(2601void foo() {
2602goto L1;
2603L1: foo();
2604}
2605)",2606R"(2607void foo() {
2608goto L2;
2609L2: foo();
2610}
2611)",2612Lang_CXX03, gotoStmt());2613EXPECT_FALSE(testStructuralMatch(S));2614}
2615
2616TEST_F(StructuralEquivalenceStmtTest, DeclRefExpr) {2617std::string Prefix = "enum Test { AAA, BBB };";2618auto t = makeStmts(2619Prefix + "void foo(int i) {if (i > 0) {i = AAA;} else {i = BBB;}}",2620Prefix + "void foo(int i) {if (i > 0) {i = BBB;} else {i = AAA;}}",2621Lang_CXX03, ifStmt());2622EXPECT_FALSE(testStructuralMatch(t));2623}
2624
2625TEST_F(StructuralEquivalenceCacheTest, CXXDependentScopeMemberExprNoEq) {2626auto S = makeStmts(2627R"(2628template <class T>
2629void foo() {
2630(void)T().x;
2631}
2632struct A { int x; };
2633void bar() {
2634foo<A>();
2635}
2636)",2637R"(2638template <class T>
2639void foo() {
2640(void)T().y;
2641}
2642struct A { int y; };
2643void bar() {
2644foo<A>();
2645}
2646)",2647Lang_CXX11, cxxDependentScopeMemberExpr());2648EXPECT_FALSE(testStructuralMatch(S));2649}
2650
2651} // end namespace ast_matchers2652} // end namespace clang2653