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