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, DISABLED_NoexceptNonMatch) { 304 // The expression is not checked yet. 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 TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { 802 auto t = makeNamedDecls( 803 "struct A{ }; struct B{ }; void foo(A a, A b);", 804 "struct A{ }; struct B{ }; void foo(A a, B b);", 805 Lang_CXX); 806 EXPECT_FALSE(testStructuralMatch(t)); 807 } 808 809 struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {}; 810 811 TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) { 812 auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11); 813 EXPECT_TRUE(testStructuralMatch(t)); 814 } 815 816 TEST_F(StructuralEquivalenceEnumTest, 817 FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) { 818 auto t = 819 makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11); 820 EXPECT_TRUE(testStructuralMatch(t)); 821 } 822 823 TEST_F(StructuralEquivalenceEnumTest, 824 EnumShouldBeEqualWithEnumWhichHasDefinition) { 825 auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };", 826 Lang_CXX11); 827 EXPECT_TRUE(testStructuralMatch(t)); 828 } 829 830 TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) { 831 auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };", 832 Lang_CXX11); 833 EXPECT_FALSE(testStructuralMatch(t)); 834 } 835 836 struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {}; 837 838 TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) { 839 auto t = makeNamedDecls("template <class T> struct foo;", 840 "template <class T> struct foo;", Lang_CXX); 841 EXPECT_TRUE(testStructuralMatch(t)); 842 } 843 844 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) { 845 auto t = makeNamedDecls("template <class T> struct foo;", 846 "template <class U> struct foo;", Lang_CXX); 847 EXPECT_TRUE(testStructuralMatch(t)); 848 } 849 850 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) { 851 auto t = makeNamedDecls("template <class T> struct foo;", 852 "template <int T> struct foo;", Lang_CXX); 853 EXPECT_FALSE(testStructuralMatch(t)); 854 } 855 856 } // end namespace ast_matchers 857 } // end namespace clang 858