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