1 #include "clang/AST/ASTContext.h" 2 #include "clang/AST/ASTStructuralEquivalence.h" 3 #include "clang/ASTMatchers/ASTMatchers.h" 4 #include "clang/Frontend/ASTUnit.h" 5 #include "clang/Tooling/Tooling.h" 6 #include "llvm/Support/Host.h" 7 8 #include "Language.h" 9 #include "DeclMatcher.h" 10 11 #include "gtest/gtest.h" 12 13 namespace clang { 14 namespace ast_matchers { 15 16 using std::get; 17 18 struct StructuralEquivalenceTest : ::testing::Test { 19 std::unique_ptr<ASTUnit> AST0, AST1; 20 std::string Code0, Code1; // Buffers for SourceManager 21 22 // Get a pair of node pointers into the synthesized AST from the given code 23 // snippets. To determine the returned node, a separate matcher is specified 24 // for both snippets. The first matching node is returned. 25 template <typename NodeType, typename MatcherType> 26 std::tuple<NodeType *, NodeType *> makeDecls( 27 const std::string &SrcCode0, const std::string &SrcCode1, Language Lang, 28 const MatcherType &Matcher0, const MatcherType &Matcher1) { 29 this->Code0 = SrcCode0; 30 this->Code1 = SrcCode1; 31 ArgVector Args = getBasicRunOptionsForLanguage(Lang); 32 33 const char *const InputFileName = "input.cc"; 34 35 AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName); 36 AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName); 37 38 NodeType *D0 = FirstDeclMatcher<NodeType>().match( 39 AST0->getASTContext().getTranslationUnitDecl(), Matcher0); 40 NodeType *D1 = FirstDeclMatcher<NodeType>().match( 41 AST1->getASTContext().getTranslationUnitDecl(), Matcher1); 42 43 return std::make_tuple(D0, D1); 44 } 45 46 std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> makeTuDecls( 47 const std::string &SrcCode0, const std::string &SrcCode1, Language Lang) { 48 this->Code0 = SrcCode0; 49 this->Code1 = SrcCode1; 50 ArgVector Args = getBasicRunOptionsForLanguage(Lang); 51 52 const char *const InputFileName = "input.cc"; 53 54 AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName); 55 AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName); 56 57 return std::make_tuple(AST0->getASTContext().getTranslationUnitDecl(), 58 AST1->getASTContext().getTranslationUnitDecl()); 59 } 60 61 // Get a pair of node pointers into the synthesized AST from the given code 62 // snippets. The same matcher is used for both snippets. 63 template <typename NodeType, typename MatcherType> 64 std::tuple<NodeType *, NodeType *> makeDecls( 65 const std::string &SrcCode0, const std::string &SrcCode1, Language Lang, 66 const MatcherType &AMatcher) { 67 return makeDecls<NodeType, MatcherType>( 68 SrcCode0, SrcCode1, Lang, AMatcher, AMatcher); 69 } 70 71 // Get a pair of Decl pointers to the synthesized declarations from the given 72 // code snippets. We search for the first NamedDecl with given name in both 73 // snippets. 74 std::tuple<NamedDecl *, NamedDecl *> makeNamedDecls( 75 const std::string &SrcCode0, const std::string &SrcCode1, 76 Language Lang, const char *const Identifier = "foo") { 77 auto Matcher = namedDecl(hasName(Identifier)); 78 return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher); 79 } 80 81 bool testStructuralMatch(Decl *D0, Decl *D1) { 82 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01; 83 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10; 84 StructuralEquivalenceContext Ctx01( 85 D0->getASTContext(), D1->getASTContext(), 86 NonEquivalentDecls01, StructuralEquivalenceKind::Default, false, false); 87 StructuralEquivalenceContext Ctx10( 88 D1->getASTContext(), D0->getASTContext(), 89 NonEquivalentDecls10, StructuralEquivalenceKind::Default, false, false); 90 bool Eq01 = Ctx01.IsEquivalent(D0, D1); 91 bool Eq10 = Ctx10.IsEquivalent(D1, D0); 92 EXPECT_EQ(Eq01, Eq10); 93 return Eq01; 94 } 95 96 bool testStructuralMatch(std::tuple<Decl *, Decl *> t) { 97 return testStructuralMatch(get<0>(t), get<1>(t)); 98 } 99 }; 100 101 TEST_F(StructuralEquivalenceTest, Int) { 102 auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX); 103 EXPECT_TRUE(testStructuralMatch(Decls)); 104 } 105 106 TEST_F(StructuralEquivalenceTest, IntVsSignedInt) { 107 auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX); 108 EXPECT_TRUE(testStructuralMatch(Decls)); 109 } 110 111 TEST_F(StructuralEquivalenceTest, Char) { 112 auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX); 113 EXPECT_TRUE(testStructuralMatch(Decls)); 114 } 115 116 // This test is disabled for now. 117 // FIXME Whether this is equivalent is dependendant on the target. 118 TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) { 119 auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX); 120 EXPECT_FALSE(testStructuralMatch(Decls)); 121 } 122 123 TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) { 124 auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX); 125 EXPECT_TRUE(testStructuralMatch(Decls)); 126 } 127 128 TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) { 129 auto Decls = makeNamedDecls("struct foo { int x; };", 130 "struct foo { signed int x; };", Lang_CXX); 131 EXPECT_TRUE(testStructuralMatch(Decls)); 132 } 133 134 TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) { 135 auto Decls = makeNamedDecls("struct foo { char x; };", 136 "struct foo { signed char x; };", Lang_CXX); 137 EXPECT_FALSE(testStructuralMatch(Decls)); 138 } 139 140 TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) { 141 auto Decls = makeDecls<ClassTemplateSpecializationDecl>( 142 R"(template <class T> struct foo; template<> struct foo<int>{};)", 143 R"(template <class T> struct foo; template<> struct foo<signed int>{};)", 144 Lang_CXX, 145 classTemplateSpecializationDecl()); 146 auto Spec0 = get<0>(Decls); 147 auto Spec1 = get<1>(Decls); 148 EXPECT_TRUE(testStructuralMatch(Spec0, Spec1)); 149 } 150 151 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) { 152 auto Decls = makeDecls<ClassTemplateSpecializationDecl>( 153 R"(template <class T> struct foo; template<> struct foo<char>{};)", 154 R"(template <class T> struct foo; template<> struct foo<signed char>{};)", 155 Lang_CXX, 156 classTemplateSpecializationDecl()); 157 auto Spec0 = get<0>(Decls); 158 auto Spec1 = get<1>(Decls); 159 EXPECT_FALSE(testStructuralMatch(Spec0, Spec1)); 160 } 161 162 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) { 163 auto Decls = makeDecls<ClassTemplateSpecializationDecl>( 164 R"( 165 struct true_type{}; 166 template <class T> struct foo; 167 template<> struct foo<char> : true_type {}; 168 )", 169 R"( 170 struct true_type{}; 171 template <class T> struct foo; 172 template<> struct foo<signed char> : true_type {}; 173 )", 174 Lang_CXX, 175 classTemplateSpecializationDecl()); 176 EXPECT_FALSE(testStructuralMatch(Decls)); 177 } 178 179 // This test is disabled for now. 180 // FIXME Enable it, once the check is implemented. 181 TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) { 182 auto Code = 183 R"( 184 namespace NS { 185 template <class T> class Base { 186 int a; 187 }; 188 class Derived : Base<Derived> { 189 }; 190 } 191 void foo(NS::Derived &); 192 )"; 193 auto Decls = makeNamedDecls(Code, Code, Lang_CXX); 194 195 NamespaceDecl *NS = 196 LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl()); 197 ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match( 198 get<1>(Decls), classTemplateDecl(hasName("Base"))); 199 200 // Reorder the decls, move the TD to the last place in the DC. 201 NS->removeDecl(TD); 202 NS->addDeclInternal(TD); 203 204 EXPECT_FALSE(testStructuralMatch(Decls)); 205 } 206 207 TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) { 208 auto Code = "class X { int a; int b; };"; 209 auto Decls = makeNamedDecls(Code, Code, Lang_CXX, "X"); 210 211 CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match( 212 get<1>(Decls), cxxRecordDecl(hasName("X"))); 213 FieldDecl *FD = 214 FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a"))); 215 216 // Reorder the FieldDecls 217 RD->removeDecl(FD); 218 RD->addDeclInternal(FD); 219 220 EXPECT_FALSE(testStructuralMatch(Decls)); 221 } 222 223 struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest { 224 }; 225 226 TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) { 227 auto t = makeNamedDecls( 228 "void foo();", 229 "template<class T> void foo();", 230 Lang_CXX); 231 EXPECT_FALSE(testStructuralMatch(t)); 232 } 233 234 TEST_F(StructuralEquivalenceFunctionTest, DifferentOperators) { 235 auto t = makeDecls<FunctionDecl>( 236 "struct X{}; bool operator<(X, X);", 237 "struct X{}; bool operator==(X, X);", Lang_CXX, 238 functionDecl(hasOverloadedOperatorName("<")), 239 functionDecl(hasOverloadedOperatorName("=="))); 240 EXPECT_FALSE(testStructuralMatch(t)); 241 } 242 243 TEST_F(StructuralEquivalenceFunctionTest, SameOperators) { 244 auto t = makeDecls<FunctionDecl>( 245 "struct X{}; bool operator<(X, X);", 246 "struct X{}; bool operator<(X, X);", Lang_CXX, 247 functionDecl(hasOverloadedOperatorName("<")), 248 functionDecl(hasOverloadedOperatorName("<"))); 249 EXPECT_TRUE(testStructuralMatch(t)); 250 } 251 252 TEST_F(StructuralEquivalenceFunctionTest, CtorVsDtor) { 253 auto t = makeDecls<FunctionDecl>( 254 "struct X{ X(); };", 255 "struct X{ ~X(); };", Lang_CXX, 256 cxxConstructorDecl(), 257 cxxDestructorDecl()); 258 EXPECT_FALSE(testStructuralMatch(t)); 259 } 260 261 TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) { 262 auto t = makeNamedDecls("void foo(int&);", 263 "void foo(const int&);", Lang_CXX); 264 EXPECT_FALSE(testStructuralMatch(t)); 265 } 266 267 TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) { 268 auto t = makeNamedDecls("void foo(int);", 269 "void foo(const int);", Lang_CXX); 270 EXPECT_TRUE(testStructuralMatch(t)); 271 // consider this OK 272 } 273 274 TEST_F(StructuralEquivalenceFunctionTest, Throw) { 275 auto t = makeNamedDecls("void foo();", 276 "void foo() throw();", Lang_CXX); 277 EXPECT_FALSE(testStructuralMatch(t)); 278 } 279 280 TEST_F(StructuralEquivalenceFunctionTest, Noexcept) { 281 auto t = makeNamedDecls("void foo();", 282 "void foo() noexcept;", Lang_CXX11); 283 EXPECT_FALSE(testStructuralMatch(t)); 284 } 285 286 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) { 287 auto t = makeNamedDecls("void foo() throw();", 288 "void foo() noexcept;", Lang_CXX11); 289 EXPECT_FALSE(testStructuralMatch(t)); 290 } 291 292 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) { 293 auto t = makeNamedDecls("void foo() throw();", 294 "void foo() noexcept(false);", Lang_CXX11); 295 EXPECT_FALSE(testStructuralMatch(t)); 296 } 297 298 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) { 299 auto t = makeNamedDecls("void foo() throw();", 300 "void foo() noexcept(true);", Lang_CXX11); 301 EXPECT_FALSE(testStructuralMatch(t)); 302 } 303 304 TEST_F(StructuralEquivalenceFunctionTest, NoexceptNonMatch) { 305 auto t = makeNamedDecls("void foo() noexcept(false);", 306 "void foo() noexcept(true);", Lang_CXX11); 307 EXPECT_FALSE(testStructuralMatch(t)); 308 } 309 310 TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) { 311 auto t = makeNamedDecls("void foo() noexcept(false);", 312 "void foo() noexcept(false);", Lang_CXX11); 313 EXPECT_TRUE(testStructuralMatch(t)); 314 } 315 316 TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) { 317 auto t = makeNamedDecls("void foo() noexcept;", 318 "void foo() noexcept(false);", Lang_CXX11); 319 EXPECT_FALSE(testStructuralMatch(t)); 320 } 321 322 TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) { 323 auto t = makeNamedDecls("void foo() noexcept;", 324 "void foo() noexcept(true);", Lang_CXX11); 325 EXPECT_FALSE(testStructuralMatch(t)); 326 } 327 328 TEST_F(StructuralEquivalenceFunctionTest, ReturnType) { 329 auto t = makeNamedDecls("char foo();", 330 "int foo();", Lang_CXX); 331 EXPECT_FALSE(testStructuralMatch(t)); 332 } 333 334 TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) { 335 auto t = makeNamedDecls("char foo();", 336 "const char foo();", Lang_CXX); 337 EXPECT_FALSE(testStructuralMatch(t)); 338 } 339 340 TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) { 341 auto t = makeNamedDecls("char &foo();", 342 "char &&foo();", Lang_CXX11); 343 EXPECT_FALSE(testStructuralMatch(t)); 344 } 345 346 TEST_F(StructuralEquivalenceFunctionTest, ParamCount) { 347 auto t = makeNamedDecls("void foo(int);", 348 "void foo(int, int);", Lang_CXX); 349 EXPECT_FALSE(testStructuralMatch(t)); 350 } 351 352 TEST_F(StructuralEquivalenceFunctionTest, ParamType) { 353 auto t = makeNamedDecls("void foo(int);", 354 "void foo(char);", Lang_CXX); 355 EXPECT_FALSE(testStructuralMatch(t)); 356 } 357 358 TEST_F(StructuralEquivalenceFunctionTest, ParamName) { 359 auto t = makeNamedDecls("void foo(int a);", 360 "void foo(int b);", Lang_CXX); 361 EXPECT_TRUE(testStructuralMatch(t)); 362 } 363 364 TEST_F(StructuralEquivalenceFunctionTest, Variadic) { 365 auto t = makeNamedDecls("void foo(int x...);", 366 "void foo(int x);", Lang_CXX); 367 EXPECT_FALSE(testStructuralMatch(t)); 368 } 369 370 TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) { 371 auto t = makeNamedDecls("void foo(int *);", 372 "void foo(int);", Lang_CXX); 373 EXPECT_FALSE(testStructuralMatch(t)); 374 } 375 376 TEST_F(StructuralEquivalenceFunctionTest, NameInParen) { 377 auto t = makeNamedDecls( 378 "void ((foo))();", 379 "void foo();", 380 Lang_CXX); 381 EXPECT_TRUE(testStructuralMatch(t)); 382 } 383 384 TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) { 385 auto t = makeNamedDecls( 386 "void (foo)() throw(int);", 387 "void (foo)() noexcept;", 388 Lang_CXX11); 389 EXPECT_FALSE(testStructuralMatch(t)); 390 } 391 392 TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) { 393 auto t = makeNamedDecls( 394 "struct A { void (foo)() const; };", 395 "struct A { void (foo)(); };", 396 Lang_CXX11); 397 EXPECT_FALSE(testStructuralMatch(t)); 398 } 399 400 TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) { 401 auto t = makeNamedDecls( 402 "__attribute__((noreturn)) void foo();", 403 " void foo();", 404 Lang_C); 405 EXPECT_TRUE(testStructuralMatch(t)); 406 } 407 408 TEST_F(StructuralEquivalenceFunctionTest, 409 FunctionsWithDifferentCallingConventions) { 410 // These attributes may not be available on certain platforms. 411 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() != 412 llvm::Triple::x86_64) 413 return; 414 auto t = makeNamedDecls( 415 "__attribute__((preserve_all)) void foo();", 416 "__attribute__((ms_abi)) void foo();", 417 Lang_C); 418 EXPECT_FALSE(testStructuralMatch(t)); 419 } 420 421 TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) { 422 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() != 423 llvm::Triple::x86_64) 424 return; 425 auto t = makeNamedDecls( 426 "__attribute__((no_caller_saved_registers)) void foo();", 427 " void foo();", 428 Lang_C); 429 EXPECT_FALSE(testStructuralMatch(t)); 430 } 431 432 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest { 433 }; 434 435 TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) { 436 auto t = makeDecls<CXXMethodDecl>( 437 "struct X { void foo(); };", 438 "struct X { virtual void foo(); };", Lang_CXX, 439 cxxMethodDecl(hasName("foo"))); 440 EXPECT_FALSE(testStructuralMatch(t)); 441 } 442 443 TEST_F(StructuralEquivalenceCXXMethodTest, Pure) { 444 auto t = makeNamedDecls("struct X { virtual void foo(); };", 445 "struct X { virtual void foo() = 0; };", Lang_CXX); 446 EXPECT_FALSE(testStructuralMatch(t)); 447 } 448 449 TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) { 450 // The final-ness is not checked yet. 451 auto t = makeNamedDecls("struct X { virtual void foo(); };", 452 "struct X { virtual void foo() final; };", Lang_CXX); 453 EXPECT_FALSE(testStructuralMatch(t)); 454 } 455 456 TEST_F(StructuralEquivalenceCXXMethodTest, Const) { 457 auto t = makeNamedDecls("struct X { void foo(); };", 458 "struct X { void foo() const; };", Lang_CXX); 459 EXPECT_FALSE(testStructuralMatch(t)); 460 } 461 462 TEST_F(StructuralEquivalenceCXXMethodTest, Static) { 463 auto t = makeNamedDecls("struct X { void foo(); };", 464 "struct X { static void foo(); };", Lang_CXX); 465 EXPECT_FALSE(testStructuralMatch(t)); 466 } 467 468 TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) { 469 auto t = makeNamedDecls("struct X { void foo(); };", 470 "struct X { void foo() &&; };", Lang_CXX11); 471 EXPECT_FALSE(testStructuralMatch(t)); 472 } 473 474 TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) { 475 auto t = makeNamedDecls("struct X { void foo() &; };", 476 "struct X { void foo() &&; };", Lang_CXX11); 477 EXPECT_FALSE(testStructuralMatch(t)); 478 } 479 480 TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) { 481 auto t = makeDecls<CXXMethodDecl>( 482 "struct X { public: void foo(); };", 483 "struct X { private: void foo(); };", Lang_CXX, 484 cxxMethodDecl(hasName("foo"))); 485 EXPECT_FALSE(testStructuralMatch(t)); 486 } 487 488 TEST_F(StructuralEquivalenceCXXMethodTest, Delete) { 489 auto t = makeNamedDecls("struct X { void foo(); };", 490 "struct X { void foo() = delete; };", Lang_CXX11); 491 EXPECT_FALSE(testStructuralMatch(t)); 492 } 493 494 TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) { 495 auto t = makeDecls<FunctionDecl>( 496 "void foo();", "struct foo { foo(); };", Lang_CXX, 497 functionDecl(hasName("foo")), cxxConstructorDecl(hasName("foo"))); 498 EXPECT_FALSE(testStructuralMatch(t)); 499 } 500 501 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) { 502 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };", 503 "struct X { X(int); };", Lang_CXX, 504 cxxConstructorDecl(hasName("X"))); 505 EXPECT_FALSE(testStructuralMatch(t)); 506 } 507 508 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) { 509 auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };", 510 "struct X { explicit X(int); };", 511 Lang_CXX11, 512 cxxConstructorDecl(hasName("X"))); 513 EXPECT_FALSE(testStructuralMatch(t)); 514 } 515 516 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) { 517 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };", 518 "struct X { X() = default; };", 519 Lang_CXX11, 520 cxxConstructorDecl(hasName("X"))); 521 EXPECT_FALSE(testStructuralMatch(t)); 522 } 523 524 TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) { 525 auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };", 526 "struct X { operator char(); };", 527 Lang_CXX11, 528 cxxConversionDecl()); 529 EXPECT_FALSE(testStructuralMatch(t)); 530 } 531 532 TEST_F(StructuralEquivalenceCXXMethodTest, Operator) { 533 auto t = makeDecls<FunctionDecl>( 534 "struct X { int operator +(int); };", 535 "struct X { int operator -(int); };", Lang_CXX, 536 functionDecl(hasOverloadedOperatorName("+")), 537 functionDecl(hasOverloadedOperatorName("-"))); 538 EXPECT_FALSE(testStructuralMatch(t)); 539 } 540 541 TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) { 542 auto t = makeDecls<FunctionDecl>( 543 "struct X { virtual void f(); }; void X::f() { }", 544 "struct X { virtual void f() { }; };", 545 Lang_CXX, 546 functionDecl(allOf(hasName("f"), isDefinition()))); 547 EXPECT_TRUE(testStructuralMatch(t)); 548 } 549 550 TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) { 551 auto t = makeDecls<FunctionDecl>( 552 "struct X { virtual void f(); }; void X::f() { }", 553 "struct X { void f(); }; void X::f() { }", 554 Lang_CXX, 555 functionDecl(allOf(hasName("f"), isDefinition()))); 556 EXPECT_FALSE(testStructuralMatch(t)); 557 } 558 559 struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest { 560 // FIXME Use a common getRecordDecl with ASTImporterTest.cpp! 561 RecordDecl *getRecordDecl(FieldDecl *FD) { 562 auto *ET = cast<ElaboratedType>(FD->getType().getTypePtr()); 563 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl(); 564 }; 565 }; 566 567 TEST_F(StructuralEquivalenceRecordTest, Name) { 568 auto t = makeDecls<CXXRecordDecl>( 569 "struct A{ };", 570 "struct B{ };", 571 Lang_CXX, 572 cxxRecordDecl(hasName("A")), 573 cxxRecordDecl(hasName("B"))); 574 EXPECT_FALSE(testStructuralMatch(t)); 575 } 576 577 TEST_F(StructuralEquivalenceRecordTest, Fields) { 578 auto t = makeNamedDecls( 579 "struct foo{ int x; };", 580 "struct foo{ char x; };", 581 Lang_CXX); 582 EXPECT_FALSE(testStructuralMatch(t)); 583 } 584 585 TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) { 586 // Currently, methods of a class are not checked at class equivalence. 587 auto t = makeNamedDecls( 588 "struct foo{ int x(); };", 589 "struct foo{ char x(); };", 590 Lang_CXX); 591 EXPECT_FALSE(testStructuralMatch(t)); 592 } 593 594 TEST_F(StructuralEquivalenceRecordTest, Bases) { 595 auto t = makeNamedDecls( 596 "struct A{ }; struct foo: A { };", 597 "struct B{ }; struct foo: B { };", 598 Lang_CXX); 599 EXPECT_FALSE(testStructuralMatch(t)); 600 } 601 602 TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) { 603 auto t = makeNamedDecls( 604 "struct A{ }; struct foo: A { };", 605 "struct A{ }; struct foo: virtual A { };", 606 Lang_CXX); 607 EXPECT_FALSE(testStructuralMatch(t)); 608 } 609 610 TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) { 611 // Access specifier in inheritance is not checked yet. 612 auto t = makeNamedDecls( 613 "struct A{ }; struct foo: public A { };", 614 "struct A{ }; struct foo: private A { };", 615 Lang_CXX); 616 EXPECT_FALSE(testStructuralMatch(t)); 617 } 618 619 TEST_F(StructuralEquivalenceRecordTest, Match) { 620 auto Code = R"( 621 struct A{ }; 622 struct B{ }; 623 struct foo: A, virtual B { 624 void x(); 625 int a; 626 }; 627 )"; 628 auto t = makeNamedDecls(Code, Code, Lang_CXX); 629 EXPECT_TRUE(testStructuralMatch(t)); 630 } 631 632 TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) { 633 auto t = makeTuDecls( 634 R"( 635 struct A { 636 struct { 637 struct A *next; 638 } entry0; 639 struct { 640 struct A *next; 641 } entry1; 642 }; 643 )", 644 "", Lang_C); 645 auto *TU = get<0>(t); 646 auto *Entry0 = 647 FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0"))); 648 auto *Entry1 = 649 FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1"))); 650 auto *R0 = getRecordDecl(Entry0); 651 auto *R1 = getRecordDecl(Entry1); 652 653 ASSERT_NE(R0, R1); 654 EXPECT_TRUE(testStructuralMatch(R0, R0)); 655 EXPECT_TRUE(testStructuralMatch(R1, R1)); 656 EXPECT_FALSE(testStructuralMatch(R0, R1)); 657 } 658 659 TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) { 660 auto t = makeTuDecls( 661 R"( 662 struct X { 663 struct { 664 int a; 665 }; 666 struct { 667 int b; 668 }; 669 }; 670 )", 671 "", Lang_C); 672 auto *TU = get<0>(t); 673 auto *A = FirstDeclMatcher<IndirectFieldDecl>().match( 674 TU, indirectFieldDecl(hasName("a"))); 675 auto *FA = cast<FieldDecl>(A->chain().front()); 676 RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl(); 677 auto *B = FirstDeclMatcher<IndirectFieldDecl>().match( 678 TU, indirectFieldDecl(hasName("b"))); 679 auto *FB = cast<FieldDecl>(B->chain().front()); 680 RecordDecl *RB = cast<RecordType>(FB->getType().getTypePtr())->getDecl(); 681 682 ASSERT_NE(RA, RB); 683 EXPECT_TRUE(testStructuralMatch(RA, RA)); 684 EXPECT_TRUE(testStructuralMatch(RB, RB)); 685 EXPECT_FALSE(testStructuralMatch(RA, RB)); 686 } 687 688 TEST_F(StructuralEquivalenceRecordTest, 689 RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) { 690 auto t = makeTuDecls( 691 R"( 692 struct X { 693 struct { int a; }; 694 struct { int b; }; 695 }; 696 )", 697 R"( 698 struct X { // The order is reversed. 699 struct { int b; }; 700 struct { int a; }; 701 }; 702 )", 703 Lang_C); 704 705 auto *TU = get<0>(t); 706 auto *A = FirstDeclMatcher<IndirectFieldDecl>().match( 707 TU, indirectFieldDecl(hasName("a"))); 708 auto *FA = cast<FieldDecl>(A->chain().front()); 709 RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl(); 710 711 auto *TU1 = get<1>(t); 712 auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match( 713 TU1, indirectFieldDecl(hasName("a"))); 714 auto *FA1 = cast<FieldDecl>(A1->chain().front()); 715 RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl(); 716 717 RecordDecl *X = 718 FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName("X"))); 719 RecordDecl *X1 = 720 FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName("X"))); 721 ASSERT_NE(X, X1); 722 EXPECT_FALSE(testStructuralMatch(X, X1)); 723 724 ASSERT_NE(RA, RA1); 725 EXPECT_TRUE(testStructuralMatch(RA, RA)); 726 EXPECT_TRUE(testStructuralMatch(RA1, RA1)); 727 EXPECT_FALSE(testStructuralMatch(RA1, RA)); 728 } 729 730 TEST_F(StructuralEquivalenceRecordTest, 731 UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) { 732 auto Code = 733 R"( 734 struct A { 735 struct { 736 struct A *next; 737 } entry0; 738 struct { 739 struct A *next; 740 } entry1; 741 }; 742 )"; 743 auto t = makeTuDecls(Code, Code, Lang_C); 744 745 auto *FromTU = get<0>(t); 746 auto *Entry1 = 747 FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("entry1"))); 748 749 auto *ToTU = get<1>(t); 750 auto *Entry0 = 751 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0"))); 752 auto *A = 753 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A"))); 754 A->startDefinition(); // Set isBeingDefined, getDefinition() will return a 755 // nullptr. This may be the case during ASTImport. 756 757 auto *R0 = getRecordDecl(Entry0); 758 auto *R1 = getRecordDecl(Entry1); 759 760 ASSERT_NE(R0, R1); 761 EXPECT_TRUE(testStructuralMatch(R0, R0)); 762 EXPECT_TRUE(testStructuralMatch(R1, R1)); 763 EXPECT_FALSE(testStructuralMatch(R0, R1)); 764 } 765 766 TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) { 767 auto t = makeDecls<CXXRecordDecl>( 768 "struct A { };", 769 "template<class T> struct A { };", 770 Lang_CXX, 771 cxxRecordDecl(hasName("A"))); 772 EXPECT_FALSE(testStructuralMatch(t)); 773 } 774 775 TEST_F(StructuralEquivalenceRecordTest, 776 FwdDeclRecordShouldBeEqualWithFwdDeclRecord) { 777 auto t = makeNamedDecls("class foo;", "class foo;", Lang_CXX11); 778 EXPECT_TRUE(testStructuralMatch(t)); 779 } 780 781 TEST_F(StructuralEquivalenceRecordTest, 782 FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition) { 783 auto t = 784 makeNamedDecls("class foo;", "class foo { int A; };", Lang_CXX11); 785 EXPECT_TRUE(testStructuralMatch(t)); 786 } 787 788 TEST_F(StructuralEquivalenceRecordTest, 789 RecordShouldBeEqualWithRecordWhichHasDefinition) { 790 auto t = makeNamedDecls("class foo { int A; };", "class foo { int A; };", 791 Lang_CXX11); 792 EXPECT_TRUE(testStructuralMatch(t)); 793 } 794 795 TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) { 796 auto t = makeNamedDecls("class foo { int B; };", "class foo { int A; };", 797 Lang_CXX11); 798 EXPECT_FALSE(testStructuralMatch(t)); 799 } 800 801 struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {}; 802 803 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentMethods) { 804 // Get the LambdaExprs, unfortunately we can't match directly the underlying 805 // implicit CXXRecordDecl of the Lambda classes. 806 auto t = makeDecls<LambdaExpr>( 807 "void f() { auto L0 = [](int){}; }", 808 "void f() { auto L1 = [](){}; }", 809 Lang_CXX11, 810 lambdaExpr(), 811 lambdaExpr()); 812 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); 813 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); 814 EXPECT_FALSE(testStructuralMatch(L0, L1)); 815 } 816 817 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqMethods) { 818 auto t = makeDecls<LambdaExpr>( 819 "void f() { auto L0 = [](int){}; }", 820 "void f() { auto L1 = [](int){}; }", 821 Lang_CXX11, 822 lambdaExpr(), 823 lambdaExpr()); 824 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); 825 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); 826 EXPECT_TRUE(testStructuralMatch(L0, L1)); 827 } 828 829 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentFields) { 830 auto t = makeDecls<LambdaExpr>( 831 "void f() { char* X; auto L0 = [X](){}; }", 832 "void f() { float X; auto L1 = [X](){}; }", 833 Lang_CXX11, 834 lambdaExpr(), 835 lambdaExpr()); 836 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); 837 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); 838 EXPECT_FALSE(testStructuralMatch(L0, L1)); 839 } 840 841 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqFields) { 842 auto t = makeDecls<LambdaExpr>( 843 "void f() { float X; auto L0 = [X](){}; }", 844 "void f() { float X; auto L1 = [X](){}; }", 845 Lang_CXX11, 846 lambdaExpr(), 847 lambdaExpr()); 848 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); 849 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); 850 EXPECT_TRUE(testStructuralMatch(L0, L1)); 851 } 852 853 TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { 854 auto t = makeNamedDecls( 855 "struct A{ }; struct B{ }; void foo(A a, A b);", 856 "struct A{ }; struct B{ }; void foo(A a, B b);", 857 Lang_CXX); 858 EXPECT_FALSE(testStructuralMatch(t)); 859 } 860 861 TEST_F(StructuralEquivalenceTest, ExplicitBoolDifferent) { 862 auto Decls = makeNamedDecls("struct foo {explicit(false) foo(int);};", 863 "struct foo {explicit(true) foo(int);};", Lang_CXX2a); 864 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match( 865 get<0>(Decls), cxxConstructorDecl(hasName("foo"))); 866 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match( 867 get<1>(Decls), cxxConstructorDecl(hasName("foo"))); 868 EXPECT_FALSE(testStructuralMatch(First, Second)); 869 } 870 871 TEST_F(StructuralEquivalenceTest, ExplicitBoolSame) { 872 auto Decls = makeNamedDecls("struct foo {explicit(true) foo(int);};", 873 "struct foo {explicit(true) foo(int);};", Lang_CXX2a); 874 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match( 875 get<0>(Decls), cxxConstructorDecl(hasName("foo"))); 876 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match( 877 get<1>(Decls), cxxConstructorDecl(hasName("foo"))); 878 EXPECT_TRUE(testStructuralMatch(First, Second)); 879 } 880 881 struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {}; 882 883 TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) { 884 auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11); 885 EXPECT_TRUE(testStructuralMatch(t)); 886 } 887 888 TEST_F(StructuralEquivalenceEnumTest, 889 FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) { 890 auto t = 891 makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11); 892 EXPECT_TRUE(testStructuralMatch(t)); 893 } 894 895 TEST_F(StructuralEquivalenceEnumTest, 896 EnumShouldBeEqualWithEnumWhichHasDefinition) { 897 auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };", 898 Lang_CXX11); 899 EXPECT_TRUE(testStructuralMatch(t)); 900 } 901 902 TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) { 903 auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };", 904 Lang_CXX11); 905 EXPECT_FALSE(testStructuralMatch(t)); 906 } 907 908 struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {}; 909 910 TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) { 911 auto t = makeNamedDecls("template <class T> struct foo;", 912 "template <class T> struct foo;", Lang_CXX); 913 EXPECT_TRUE(testStructuralMatch(t)); 914 } 915 916 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) { 917 auto t = makeNamedDecls("template <class T> struct foo;", 918 "template <class U> struct foo;", Lang_CXX); 919 EXPECT_TRUE(testStructuralMatch(t)); 920 } 921 922 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) { 923 auto t = makeNamedDecls("template <class T> struct foo;", 924 "template <int T> struct foo;", Lang_CXX); 925 EXPECT_FALSE(testStructuralMatch(t)); 926 } 927 928 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) { 929 auto Decls = makeNamedDecls("template <bool b> struct foo {explicit(b) foo(int);};", 930 "template <bool b> struct foo {explicit(b) foo(int);};", Lang_CXX2a); 931 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match( 932 get<0>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 933 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match( 934 get<1>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 935 EXPECT_TRUE(testStructuralMatch(First, Second)); 936 } 937 938 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) { 939 auto Decls = makeNamedDecls("template <bool b> struct foo {explicit(b) foo(int);};", 940 "template <bool b> struct foo {explicit(!b) foo(int);};", Lang_CXX2a); 941 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match( 942 get<0>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 943 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match( 944 get<1>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 945 EXPECT_FALSE(testStructuralMatch(First, Second)); 946 } 947 948 TEST_F(StructuralEquivalenceTemplateTest, 949 TemplateVsSubstTemplateTemplateParmInArgEq) { 950 auto t = makeDecls<ClassTemplateSpecializationDecl>( 951 R"( 952 template <typename P1> class Arg { }; 953 template <template <typename PP1> class P1> class Primary { }; 954 955 void f() { 956 // Make specialization with simple template. 957 Primary <Arg> A; 958 } 959 )", 960 R"( 961 template <typename P1> class Arg { }; 962 template <template <typename PP1> class P1> class Primary { }; 963 964 template <template <typename PP1> class P1> class Templ { 965 void f() { 966 // Make specialization with substituted template template param. 967 Primary <P1> A; 968 }; 969 }; 970 971 // Instantiate with substitution Arg into P1. 972 template class Templ <Arg>; 973 )", 974 Lang_CXX, classTemplateSpecializationDecl(hasName("Primary"))); 975 EXPECT_TRUE(testStructuralMatch(t)); 976 } 977 978 TEST_F(StructuralEquivalenceTemplateTest, 979 TemplateVsSubstTemplateTemplateParmInArgNotEq) { 980 auto t = makeDecls<ClassTemplateSpecializationDecl>( 981 R"( 982 template <typename P1> class Arg { }; 983 template <template <typename PP1> class P1> class Primary { }; 984 985 void f() { 986 // Make specialization with simple template. 987 Primary <Arg> A; 988 } 989 )", 990 R"( 991 // Arg is different from the other, this should cause non-equivalence. 992 template <typename P1> class Arg { int X; }; 993 template <template <typename PP1> class P1> class Primary { }; 994 995 template <template <typename PP1> class P1> class Templ { 996 void f() { 997 // Make specialization with substituted template template param. 998 Primary <P1> A; 999 }; 1000 }; 1001 1002 // Instantiate with substitution Arg into P1. 1003 template class Templ <Arg>; 1004 )", 1005 Lang_CXX, classTemplateSpecializationDecl(hasName("Primary"))); 1006 EXPECT_FALSE(testStructuralMatch(t)); 1007 } 1008 1009 struct StructuralEquivalenceDependentTemplateArgsTest 1010 : StructuralEquivalenceTemplateTest {}; 1011 1012 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1013 SameStructsInDependentArgs) { 1014 std::string Code = 1015 R"( 1016 template <typename> 1017 struct S1; 1018 1019 template <typename> 1020 struct enable_if; 1021 1022 struct S 1023 { 1024 template <typename T, typename enable_if<S1<T>>::type> 1025 void f(); 1026 }; 1027 )"; 1028 auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11, 1029 functionTemplateDecl(hasName("f"))); 1030 EXPECT_TRUE(testStructuralMatch(t)); 1031 } 1032 1033 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1034 DifferentStructsInDependentArgs) { 1035 std::string Code = 1036 R"( 1037 template <typename> 1038 struct S1; 1039 1040 template <typename> 1041 struct S2; 1042 1043 template <typename> 1044 struct enable_if; 1045 )"; 1046 auto t = makeDecls<FunctionTemplateDecl>(Code + R"( 1047 struct S 1048 { 1049 template <typename T, typename enable_if<S1<T>>::type> 1050 void f(); 1051 }; 1052 )", 1053 Code + R"( 1054 struct S 1055 { 1056 template <typename T, typename enable_if<S2<T>>::type> 1057 void f(); 1058 }; 1059 )", 1060 Lang_CXX11, 1061 functionTemplateDecl(hasName("f"))); 1062 EXPECT_FALSE(testStructuralMatch(t)); 1063 } 1064 1065 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1066 SameStructsInDependentScopeDeclRefExpr) { 1067 std::string Code = 1068 R"( 1069 template <typename> 1070 struct S1; 1071 1072 template <bool> 1073 struct enable_if; 1074 1075 struct S 1076 { 1077 template <typename T, typename enable_if<S1<T>::value>::type> 1078 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^ 1079 }; 1080 )"; 1081 auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11, 1082 functionTemplateDecl(hasName("f"))); 1083 EXPECT_TRUE(testStructuralMatch(t)); 1084 } 1085 1086 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1087 DifferentStructsInDependentScopeDeclRefExpr) { 1088 std::string Code = 1089 R"( 1090 template <typename> 1091 struct S1; 1092 1093 template <typename> 1094 struct S2; 1095 1096 template <bool> 1097 struct enable_if; 1098 )"; 1099 auto t = makeDecls<FunctionTemplateDecl>(Code + R"( 1100 struct S 1101 { 1102 template <typename T, typename enable_if<S1<T>::value>::type> 1103 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^ 1104 }; 1105 )", 1106 Code + R"( 1107 struct S 1108 { 1109 template <typename T, typename enable_if<S2<T>::value>::type> 1110 void f(); 1111 }; 1112 )", 1113 Lang_CXX, 1114 functionTemplateDecl(hasName("f"))); 1115 EXPECT_FALSE(testStructuralMatch(t)); 1116 } 1117 1118 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1119 DifferentValueInDependentScopeDeclRefExpr) { 1120 std::string Code = 1121 R"( 1122 template <typename> 1123 struct S1; 1124 1125 template <bool> 1126 struct enable_if; 1127 )"; 1128 auto t = makeDecls<FunctionTemplateDecl>(Code + R"( 1129 struct S 1130 { 1131 template <typename T, typename enable_if<S1<T>::value1>::type> 1132 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^ 1133 }; 1134 )", 1135 Code + R"( 1136 struct S 1137 { 1138 template <typename T, typename enable_if<S1<T>::value2>::type> 1139 void f(); 1140 }; 1141 )", 1142 Lang_CXX, 1143 functionTemplateDecl(hasName("f"))); 1144 EXPECT_FALSE(testStructuralMatch(t)); 1145 } 1146 1147 TEST_F( 1148 StructuralEquivalenceTemplateTest, 1149 ClassTemplSpecWithQualifiedAndNonQualifiedTypeArgsShouldBeEqual) { 1150 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1151 R"( 1152 template <class T> struct Primary {}; 1153 namespace N { 1154 struct Arg; 1155 } 1156 // Explicit instantiation with qualified name. 1157 template struct Primary<N::Arg>; 1158 )", 1159 R"( 1160 template <class T> struct Primary {}; 1161 namespace N { 1162 struct Arg; 1163 } 1164 using namespace N; 1165 // Explicit instantiation with UNqualified name. 1166 template struct Primary<Arg>; 1167 )", 1168 Lang_CXX, 1169 classTemplateSpecializationDecl(hasName("Primary"))); 1170 EXPECT_TRUE(testStructuralMatch(t)); 1171 } 1172 1173 TEST_F( 1174 StructuralEquivalenceTemplateTest, 1175 ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTypeArgs) { 1176 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1177 R"( 1178 template <class T> struct Primary {}; 1179 namespace N { 1180 struct Arg { int a; }; 1181 } 1182 // Explicit instantiation with qualified name. 1183 template struct Primary<N::Arg>; 1184 )", 1185 R"( 1186 template <class T> struct Primary {}; 1187 namespace N { 1188 // This struct is not equivalent with the other in the prev TU. 1189 struct Arg { double b; }; // -- Field mismatch. 1190 } 1191 using namespace N; 1192 // Explicit instantiation with UNqualified name. 1193 template struct Primary<Arg>; 1194 )", 1195 Lang_CXX, 1196 classTemplateSpecializationDecl(hasName("Primary"))); 1197 EXPECT_FALSE(testStructuralMatch(t)); 1198 } 1199 1200 TEST_F( 1201 StructuralEquivalenceTemplateTest, 1202 ClassTemplSpecWithQualifiedAndNonQualifiedTemplArgsShouldBeEqual) { 1203 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1204 R"( 1205 template <template <class> class T> struct Primary {}; 1206 namespace N { 1207 template <class T> struct Arg; 1208 } 1209 // Explicit instantiation with qualified name. 1210 template struct Primary<N::Arg>; 1211 )", 1212 R"( 1213 template <template <class> class T> struct Primary {}; 1214 namespace N { 1215 template <class T> struct Arg; 1216 } 1217 using namespace N; 1218 // Explicit instantiation with UNqualified name. 1219 template struct Primary<Arg>; 1220 )", 1221 Lang_CXX, 1222 classTemplateSpecializationDecl(hasName("Primary"))); 1223 EXPECT_TRUE(testStructuralMatch(t)); 1224 } 1225 1226 TEST_F( 1227 StructuralEquivalenceTemplateTest, 1228 ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTemplArgs) { 1229 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1230 R"( 1231 template <template <class> class T> struct Primary {}; 1232 namespace N { 1233 template <class T> struct Arg { int a; }; 1234 } 1235 // Explicit instantiation with qualified name. 1236 template struct Primary<N::Arg>; 1237 )", 1238 R"( 1239 template <template <class> class T> struct Primary {}; 1240 namespace N { 1241 // This template is not equivalent with the other in the prev TU. 1242 template <class T> struct Arg { double b; }; // -- Field mismatch. 1243 } 1244 using namespace N; 1245 // Explicit instantiation with UNqualified name. 1246 template struct Primary<Arg>; 1247 )", 1248 Lang_CXX, 1249 classTemplateSpecializationDecl(hasName("Primary"))); 1250 EXPECT_FALSE(testStructuralMatch(t)); 1251 } 1252 1253 TEST_F( 1254 StructuralEquivalenceTemplateTest, 1255 ClassTemplSpecWithInequivalentShadowedTemplArg) { 1256 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1257 R"( 1258 template <template <class> class T> struct Primary {}; 1259 template <class T> struct Arg { int a; }; 1260 // Explicit instantiation with ::Arg 1261 template struct Primary<Arg>; 1262 )", 1263 R"( 1264 template <template <class> class T> struct Primary {}; 1265 template <class T> struct Arg { int a; }; 1266 namespace N { 1267 // This template is not equivalent with the other in the global scope. 1268 template <class T> struct Arg { double b; }; // -- Field mismatch. 1269 // Explicit instantiation with N::Arg which shadows ::Arg 1270 template struct Primary<Arg>; 1271 } 1272 )", 1273 Lang_CXX, 1274 classTemplateSpecializationDecl(hasName("Primary"))); 1275 EXPECT_FALSE(testStructuralMatch(t)); 1276 } 1277 struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest { 1278 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; 1279 1280 template <typename NodeType, typename MatcherType> 1281 std::pair<NodeType *, NodeType *> 1282 findDeclPair(std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> TU, 1283 MatcherType M) { 1284 NodeType *D0 = FirstDeclMatcher<NodeType>().match(get<0>(TU), M); 1285 NodeType *D1 = FirstDeclMatcher<NodeType>().match(get<1>(TU), M); 1286 return {D0, D1}; 1287 } 1288 1289 template <typename NodeType> 1290 bool isInNonEqCache(std::pair<NodeType *, NodeType *> D) { 1291 return NonEquivalentDecls.count(D) > 0; 1292 } 1293 }; 1294 1295 TEST_F(StructuralEquivalenceCacheTest, SimpleNonEq) { 1296 auto TU = makeTuDecls( 1297 R"( 1298 class A {}; 1299 class B {}; 1300 void x(A, A); 1301 )", 1302 R"( 1303 class A {}; 1304 class B {}; 1305 void x(A, B); 1306 )", 1307 Lang_CXX); 1308 1309 StructuralEquivalenceContext Ctx( 1310 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), 1311 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); 1312 1313 auto X = findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x"))); 1314 EXPECT_FALSE(Ctx.IsEquivalent(X.first, X.second)); 1315 1316 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1317 TU, cxxRecordDecl(hasName("A"), unless(isImplicit()))))); 1318 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1319 TU, cxxRecordDecl(hasName("B"), unless(isImplicit()))))); 1320 } 1321 1322 TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) { 1323 auto TU = makeTuDecls( 1324 R"( 1325 class A {}; 1326 class B { int i; }; 1327 void x(A *); 1328 void y(A *); 1329 class C { 1330 friend void x(A *); 1331 friend void y(A *); 1332 }; 1333 )", 1334 R"( 1335 class A {}; 1336 class B { int i; }; 1337 void x(A *); 1338 void y(B *); 1339 class C { 1340 friend void x(A *); 1341 friend void y(B *); 1342 }; 1343 )", 1344 Lang_CXX); 1345 1346 StructuralEquivalenceContext Ctx( 1347 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), 1348 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); 1349 1350 auto C = findDeclPair<CXXRecordDecl>( 1351 TU, cxxRecordDecl(hasName("C"), unless(isImplicit()))); 1352 EXPECT_FALSE(Ctx.IsEquivalent(C.first, C.second)); 1353 1354 EXPECT_FALSE(isInNonEqCache(C)); 1355 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1356 TU, cxxRecordDecl(hasName("A"), unless(isImplicit()))))); 1357 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1358 TU, cxxRecordDecl(hasName("B"), unless(isImplicit()))))); 1359 EXPECT_FALSE(isInNonEqCache( 1360 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x"))))); 1361 EXPECT_FALSE(isInNonEqCache( 1362 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("y"))))); 1363 } 1364 1365 TEST_F(StructuralEquivalenceCacheTest, Cycle) { 1366 auto TU = makeTuDecls( 1367 R"( 1368 class C; 1369 class A { C *c; }; 1370 void x(A *); 1371 class C { 1372 friend void x(A *); 1373 }; 1374 )", 1375 R"( 1376 class C; 1377 class A { C *c; }; 1378 void x(A *); 1379 class C { 1380 friend void x(A *); 1381 }; 1382 )", 1383 Lang_CXX); 1384 1385 StructuralEquivalenceContext Ctx( 1386 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), 1387 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); 1388 1389 auto C = findDeclPair<CXXRecordDecl>( 1390 TU, cxxRecordDecl(hasName("C"), unless(isImplicit()))); 1391 EXPECT_TRUE(Ctx.IsEquivalent(C.first, C.second)); 1392 1393 EXPECT_FALSE(isInNonEqCache(C)); 1394 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1395 TU, cxxRecordDecl(hasName("A"), unless(isImplicit()))))); 1396 EXPECT_FALSE(isInNonEqCache( 1397 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x"))))); 1398 } 1399 1400 } // end namespace ast_matchers 1401 } // end namespace clang 1402