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/Testing/CommandLineArgs.h" 6 #include "clang/Tooling/Tooling.h" 7 #include "llvm/Support/Host.h" 8 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 // Parses the source code in the specified language and sets the ASTs of 23 // the current test instance to the parse result. 24 void makeASTUnits(const std::string &SrcCode0, const std::string &SrcCode1, 25 TestLanguage Lang) { 26 this->Code0 = SrcCode0; 27 this->Code1 = SrcCode1; 28 std::vector<std::string> Args = getCommandLineArgsForTesting(Lang); 29 30 const char *const InputFileName = "input.cc"; 31 32 AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName); 33 AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName); 34 } 35 36 // Get a pair of node pointers into the synthesized AST from the given code 37 // snippets. To determine the returned node, a separate matcher is specified 38 // for both snippets. The first matching node is returned. 39 template <typename NodeType, typename MatcherType> 40 std::tuple<NodeType *, NodeType *> 41 makeDecls(const std::string &SrcCode0, const std::string &SrcCode1, 42 TestLanguage Lang, const MatcherType &Matcher0, 43 const MatcherType &Matcher1) { 44 makeASTUnits(SrcCode0, SrcCode1, Lang); 45 46 NodeType *D0 = FirstDeclMatcher<NodeType>().match( 47 AST0->getASTContext().getTranslationUnitDecl(), Matcher0); 48 NodeType *D1 = FirstDeclMatcher<NodeType>().match( 49 AST1->getASTContext().getTranslationUnitDecl(), Matcher1); 50 51 return std::make_tuple(D0, D1); 52 } 53 54 std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> 55 makeTuDecls(const std::string &SrcCode0, const std::string &SrcCode1, 56 TestLanguage Lang) { 57 makeASTUnits(SrcCode0, SrcCode1, Lang); 58 59 return std::make_tuple(AST0->getASTContext().getTranslationUnitDecl(), 60 AST1->getASTContext().getTranslationUnitDecl()); 61 } 62 63 // Get a pair of node pointers into the synthesized AST from the given code 64 // snippets. The same matcher is used for both snippets. 65 template <typename NodeType, typename MatcherType> 66 std::tuple<NodeType *, NodeType *> 67 makeDecls(const std::string &SrcCode0, const std::string &SrcCode1, 68 TestLanguage Lang, const MatcherType &AMatcher) { 69 return makeDecls<NodeType, MatcherType>( 70 SrcCode0, SrcCode1, Lang, AMatcher, AMatcher); 71 } 72 73 // Get a pair of Decl pointers to the synthesized declarations from the given 74 // code snippets. We search for the first NamedDecl with given name in both 75 // snippets. 76 std::tuple<NamedDecl *, NamedDecl *> 77 makeNamedDecls(const std::string &SrcCode0, const std::string &SrcCode1, 78 TestLanguage Lang, const char *const Identifier = "foo") { 79 auto Matcher = namedDecl(hasName(Identifier)); 80 return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher); 81 } 82 83 // Wraps a Stmt and the ASTContext that contains it. 84 struct StmtWithASTContext { 85 Stmt *S; 86 ASTContext *Context; 87 explicit StmtWithASTContext(Stmt &S, ASTContext &Context) 88 : S(&S), Context(&Context) {} 89 explicit StmtWithASTContext(FunctionDecl *FD) 90 : S(FD->getBody()), Context(&FD->getASTContext()) {} 91 }; 92 93 // Get a pair of node pointers into the synthesized AST from the given code 94 // snippets. To determine the returned node, a separate matcher is specified 95 // for both snippets. The first matching node is returned. 96 template <typename MatcherType> 97 std::tuple<StmtWithASTContext, StmtWithASTContext> 98 makeStmts(const std::string &SrcCode0, const std::string &SrcCode1, 99 TestLanguage Lang, const MatcherType &Matcher0, 100 const MatcherType &Matcher1) { 101 makeASTUnits(SrcCode0, SrcCode1, Lang); 102 103 Stmt *S0 = FirstDeclMatcher<Stmt>().match( 104 AST0->getASTContext().getTranslationUnitDecl(), Matcher0); 105 Stmt *S1 = FirstDeclMatcher<Stmt>().match( 106 AST1->getASTContext().getTranslationUnitDecl(), Matcher1); 107 108 return std::make_tuple(StmtWithASTContext(*S0, AST0->getASTContext()), 109 StmtWithASTContext(*S1, AST1->getASTContext())); 110 } 111 112 // Get a pair of node pointers into the synthesized AST from the given code 113 // snippets. The same matcher is used for both snippets. 114 template <typename MatcherType> 115 std::tuple<StmtWithASTContext, StmtWithASTContext> 116 makeStmts(const std::string &SrcCode0, const std::string &SrcCode1, 117 TestLanguage Lang, const MatcherType &AMatcher) { 118 return makeStmts(SrcCode0, SrcCode1, Lang, AMatcher, AMatcher); 119 } 120 121 // Convenience function for makeStmts that wraps the code inside a function 122 // body. 123 template <typename MatcherType> 124 std::tuple<StmtWithASTContext, StmtWithASTContext> 125 makeWrappedStmts(const std::string &SrcCode0, const std::string &SrcCode1, 126 TestLanguage Lang, const MatcherType &AMatcher) { 127 auto Wrap = [](const std::string &Src) { 128 return "void wrapped() {" + Src + ";}"; 129 }; 130 return makeStmts(Wrap(SrcCode0), Wrap(SrcCode1), Lang, AMatcher); 131 } 132 133 bool testStructuralMatch(Decl *D0, Decl *D1) { 134 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01; 135 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10; 136 StructuralEquivalenceContext Ctx01( 137 D0->getASTContext(), D1->getASTContext(), 138 NonEquivalentDecls01, StructuralEquivalenceKind::Default, false, false); 139 StructuralEquivalenceContext Ctx10( 140 D1->getASTContext(), D0->getASTContext(), 141 NonEquivalentDecls10, StructuralEquivalenceKind::Default, false, false); 142 bool Eq01 = Ctx01.IsEquivalent(D0, D1); 143 bool Eq10 = Ctx10.IsEquivalent(D1, D0); 144 EXPECT_EQ(Eq01, Eq10); 145 return Eq01; 146 } 147 148 bool testStructuralMatch(StmtWithASTContext S0, StmtWithASTContext S1) { 149 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls01; 150 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls10; 151 StructuralEquivalenceContext Ctx01( 152 *S0.Context, *S1.Context, NonEquivalentDecls01, 153 StructuralEquivalenceKind::Default, false, false); 154 StructuralEquivalenceContext Ctx10( 155 *S1.Context, *S0.Context, NonEquivalentDecls10, 156 StructuralEquivalenceKind::Default, false, false); 157 bool Eq01 = Ctx01.IsEquivalent(S0.S, S1.S); 158 bool Eq10 = Ctx10.IsEquivalent(S1.S, S0.S); 159 EXPECT_EQ(Eq01, Eq10); 160 return Eq01; 161 } 162 163 bool 164 testStructuralMatch(std::tuple<StmtWithASTContext, StmtWithASTContext> t) { 165 return testStructuralMatch(get<0>(t), get<1>(t)); 166 } 167 168 bool testStructuralMatch(std::tuple<Decl *, Decl *> t) { 169 return testStructuralMatch(get<0>(t), get<1>(t)); 170 } 171 }; 172 173 TEST_F(StructuralEquivalenceTest, Int) { 174 auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX03); 175 EXPECT_TRUE(testStructuralMatch(Decls)); 176 } 177 178 TEST_F(StructuralEquivalenceTest, IntVsSignedInt) { 179 auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX03); 180 EXPECT_TRUE(testStructuralMatch(Decls)); 181 } 182 183 TEST_F(StructuralEquivalenceTest, Char) { 184 auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX03); 185 EXPECT_TRUE(testStructuralMatch(Decls)); 186 } 187 188 // This test is disabled for now. 189 // FIXME Whether this is equivalent is dependendant on the target. 190 TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) { 191 auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX03); 192 EXPECT_FALSE(testStructuralMatch(Decls)); 193 } 194 195 TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) { 196 auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX03); 197 EXPECT_TRUE(testStructuralMatch(Decls)); 198 } 199 200 TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) { 201 auto Decls = makeNamedDecls("struct foo { int x; };", 202 "struct foo { signed int x; };", Lang_CXX03); 203 EXPECT_TRUE(testStructuralMatch(Decls)); 204 } 205 206 TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) { 207 auto Decls = makeNamedDecls("struct foo { char x; };", 208 "struct foo { signed char x; };", Lang_CXX03); 209 EXPECT_FALSE(testStructuralMatch(Decls)); 210 } 211 212 TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) { 213 auto Decls = makeDecls<ClassTemplateSpecializationDecl>( 214 R"(template <class T> struct foo; template<> struct foo<int>{};)", 215 R"(template <class T> struct foo; template<> struct foo<signed int>{};)", 216 Lang_CXX03, classTemplateSpecializationDecl()); 217 auto Spec0 = get<0>(Decls); 218 auto Spec1 = get<1>(Decls); 219 EXPECT_TRUE(testStructuralMatch(Spec0, Spec1)); 220 } 221 222 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) { 223 auto Decls = makeDecls<ClassTemplateSpecializationDecl>( 224 R"(template <class T> struct foo; template<> struct foo<char>{};)", 225 R"(template <class T> struct foo; template<> struct foo<signed char>{};)", 226 Lang_CXX03, classTemplateSpecializationDecl()); 227 auto Spec0 = get<0>(Decls); 228 auto Spec1 = get<1>(Decls); 229 EXPECT_FALSE(testStructuralMatch(Spec0, Spec1)); 230 } 231 232 TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) { 233 auto Decls = makeDecls<ClassTemplateSpecializationDecl>( 234 R"( 235 struct true_type{}; 236 template <class T> struct foo; 237 template<> struct foo<char> : true_type {}; 238 )", 239 R"( 240 struct true_type{}; 241 template <class T> struct foo; 242 template<> struct foo<signed char> : true_type {}; 243 )", 244 Lang_CXX03, classTemplateSpecializationDecl()); 245 EXPECT_FALSE(testStructuralMatch(Decls)); 246 } 247 248 // This test is disabled for now. 249 // FIXME Enable it, once the check is implemented. 250 TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) { 251 auto Code = 252 R"( 253 namespace NS { 254 template <class T> class Base { 255 int a; 256 }; 257 class Derived : Base<Derived> { 258 }; 259 } 260 void foo(NS::Derived &); 261 )"; 262 auto Decls = makeNamedDecls(Code, Code, Lang_CXX03); 263 264 NamespaceDecl *NS = 265 LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl()); 266 ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match( 267 get<1>(Decls), classTemplateDecl(hasName("Base"))); 268 269 // Reorder the decls, move the TD to the last place in the DC. 270 NS->removeDecl(TD); 271 NS->addDeclInternal(TD); 272 273 EXPECT_FALSE(testStructuralMatch(Decls)); 274 } 275 276 TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) { 277 auto Code = "class X { int a; int b; };"; 278 auto Decls = makeNamedDecls(Code, Code, Lang_CXX03, "X"); 279 280 CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match( 281 get<1>(Decls), cxxRecordDecl(hasName("X"))); 282 FieldDecl *FD = 283 FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a"))); 284 285 // Reorder the FieldDecls 286 RD->removeDecl(FD); 287 RD->addDeclInternal(FD); 288 289 EXPECT_FALSE(testStructuralMatch(Decls)); 290 } 291 292 struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest { 293 }; 294 295 TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) { 296 auto t = makeNamedDecls("void foo();", "template<class T> void foo();", 297 Lang_CXX03); 298 EXPECT_FALSE(testStructuralMatch(t)); 299 } 300 301 TEST_F(StructuralEquivalenceFunctionTest, DifferentOperators) { 302 auto t = makeDecls<FunctionDecl>( 303 "struct X{}; bool operator<(X, X);", "struct X{}; bool operator==(X, X);", 304 Lang_CXX03, functionDecl(hasOverloadedOperatorName("<")), 305 functionDecl(hasOverloadedOperatorName("=="))); 306 EXPECT_FALSE(testStructuralMatch(t)); 307 } 308 309 TEST_F(StructuralEquivalenceFunctionTest, SameOperators) { 310 auto t = makeDecls<FunctionDecl>( 311 "struct X{}; bool operator<(X, X);", "struct X{}; bool operator<(X, X);", 312 Lang_CXX03, functionDecl(hasOverloadedOperatorName("<")), 313 functionDecl(hasOverloadedOperatorName("<"))); 314 EXPECT_TRUE(testStructuralMatch(t)); 315 } 316 317 TEST_F(StructuralEquivalenceFunctionTest, CtorVsDtor) { 318 auto t = makeDecls<FunctionDecl>("struct X{ X(); };", "struct X{ ~X(); };", 319 Lang_CXX03, cxxConstructorDecl(), 320 cxxDestructorDecl()); 321 EXPECT_FALSE(testStructuralMatch(t)); 322 } 323 324 TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) { 325 auto t = 326 makeNamedDecls("void foo(int&);", "void foo(const int&);", Lang_CXX03); 327 EXPECT_FALSE(testStructuralMatch(t)); 328 } 329 330 TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) { 331 auto t = makeNamedDecls("void foo(int);", "void foo(const int);", Lang_CXX03); 332 EXPECT_TRUE(testStructuralMatch(t)); 333 // consider this OK 334 } 335 336 TEST_F(StructuralEquivalenceFunctionTest, Throw) { 337 auto t = makeNamedDecls("void foo();", "void foo() throw();", Lang_CXX03); 338 EXPECT_FALSE(testStructuralMatch(t)); 339 } 340 341 TEST_F(StructuralEquivalenceFunctionTest, Noexcept) { 342 auto t = makeNamedDecls("void foo();", 343 "void foo() noexcept;", Lang_CXX11); 344 EXPECT_FALSE(testStructuralMatch(t)); 345 } 346 347 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) { 348 auto t = makeNamedDecls("void foo() throw();", 349 "void foo() noexcept;", Lang_CXX11); 350 EXPECT_FALSE(testStructuralMatch(t)); 351 } 352 353 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) { 354 auto t = makeNamedDecls("void foo() throw();", 355 "void foo() noexcept(false);", Lang_CXX11); 356 EXPECT_FALSE(testStructuralMatch(t)); 357 } 358 359 TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) { 360 auto t = makeNamedDecls("void foo() throw();", 361 "void foo() noexcept(true);", Lang_CXX11); 362 EXPECT_FALSE(testStructuralMatch(t)); 363 } 364 365 TEST_F(StructuralEquivalenceFunctionTest, NoexceptNonMatch) { 366 auto t = makeNamedDecls("void foo() noexcept(false);", 367 "void foo() noexcept(true);", Lang_CXX11); 368 EXPECT_FALSE(testStructuralMatch(t)); 369 } 370 371 TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) { 372 auto t = makeNamedDecls("void foo() noexcept(false);", 373 "void foo() noexcept(false);", Lang_CXX11); 374 EXPECT_TRUE(testStructuralMatch(t)); 375 } 376 377 TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) { 378 auto t = makeNamedDecls("void foo() noexcept;", 379 "void foo() noexcept(false);", Lang_CXX11); 380 EXPECT_FALSE(testStructuralMatch(t)); 381 } 382 383 TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) { 384 auto t = makeNamedDecls("void foo() noexcept;", 385 "void foo() noexcept(true);", Lang_CXX11); 386 EXPECT_FALSE(testStructuralMatch(t)); 387 } 388 389 TEST_F(StructuralEquivalenceFunctionTest, ReturnType) { 390 auto t = makeNamedDecls("char foo();", "int foo();", Lang_CXX03); 391 EXPECT_FALSE(testStructuralMatch(t)); 392 } 393 394 TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) { 395 auto t = makeNamedDecls("char foo();", "const char foo();", Lang_CXX03); 396 EXPECT_FALSE(testStructuralMatch(t)); 397 } 398 399 TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) { 400 auto t = makeNamedDecls("char &foo();", 401 "char &&foo();", Lang_CXX11); 402 EXPECT_FALSE(testStructuralMatch(t)); 403 } 404 405 TEST_F(StructuralEquivalenceFunctionTest, ParamCount) { 406 auto t = makeNamedDecls("void foo(int);", "void foo(int, int);", Lang_CXX03); 407 EXPECT_FALSE(testStructuralMatch(t)); 408 } 409 410 TEST_F(StructuralEquivalenceFunctionTest, ParamType) { 411 auto t = makeNamedDecls("void foo(int);", "void foo(char);", Lang_CXX03); 412 EXPECT_FALSE(testStructuralMatch(t)); 413 } 414 415 TEST_F(StructuralEquivalenceFunctionTest, ParamName) { 416 auto t = makeNamedDecls("void foo(int a);", "void foo(int b);", Lang_CXX03); 417 EXPECT_TRUE(testStructuralMatch(t)); 418 } 419 420 TEST_F(StructuralEquivalenceFunctionTest, Variadic) { 421 auto t = 422 makeNamedDecls("void foo(int x...);", "void foo(int x);", Lang_CXX03); 423 EXPECT_FALSE(testStructuralMatch(t)); 424 } 425 426 TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) { 427 auto t = makeNamedDecls("void foo(int *);", "void foo(int);", Lang_CXX03); 428 EXPECT_FALSE(testStructuralMatch(t)); 429 } 430 431 TEST_F(StructuralEquivalenceFunctionTest, NameInParen) { 432 auto t = makeNamedDecls("void ((foo))();", "void foo();", Lang_CXX03); 433 EXPECT_TRUE(testStructuralMatch(t)); 434 } 435 436 TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) { 437 auto t = makeNamedDecls( 438 "void (foo)() throw(int);", 439 "void (foo)() noexcept;", 440 Lang_CXX11); 441 EXPECT_FALSE(testStructuralMatch(t)); 442 } 443 444 TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) { 445 auto t = makeNamedDecls( 446 "struct A { void (foo)() const; };", 447 "struct A { void (foo)(); };", 448 Lang_CXX11); 449 EXPECT_FALSE(testStructuralMatch(t)); 450 } 451 452 TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) { 453 auto t = makeNamedDecls("__attribute__((noreturn)) void foo();", 454 " void foo();", Lang_C99); 455 EXPECT_TRUE(testStructuralMatch(t)); 456 } 457 458 TEST_F(StructuralEquivalenceFunctionTest, 459 FunctionsWithDifferentCallingConventions) { 460 // These attributes may not be available on certain platforms. 461 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() != 462 llvm::Triple::x86_64) 463 return; 464 auto t = makeNamedDecls("__attribute__((preserve_all)) void foo();", 465 "__attribute__((ms_abi)) void foo();", Lang_C99); 466 EXPECT_FALSE(testStructuralMatch(t)); 467 } 468 469 TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) { 470 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() != 471 llvm::Triple::x86_64) 472 return; 473 auto t = makeNamedDecls( 474 "__attribute__((no_caller_saved_registers)) void foo();", 475 " void foo();", Lang_C99); 476 EXPECT_FALSE(testStructuralMatch(t)); 477 } 478 479 struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest { 480 }; 481 482 TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) { 483 auto t = makeDecls<CXXMethodDecl>("struct X { void foo(); };", 484 "struct X { virtual void foo(); };", 485 Lang_CXX03, cxxMethodDecl(hasName("foo"))); 486 EXPECT_FALSE(testStructuralMatch(t)); 487 } 488 489 TEST_F(StructuralEquivalenceCXXMethodTest, Pure) { 490 auto t = makeNamedDecls("struct X { virtual void foo(); };", 491 "struct X { virtual void foo() = 0; };", Lang_CXX03); 492 EXPECT_FALSE(testStructuralMatch(t)); 493 } 494 495 TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) { 496 // The final-ness is not checked yet. 497 auto t = 498 makeNamedDecls("struct X { virtual void foo(); };", 499 "struct X { virtual void foo() final; };", Lang_CXX03); 500 EXPECT_FALSE(testStructuralMatch(t)); 501 } 502 503 TEST_F(StructuralEquivalenceCXXMethodTest, Const) { 504 auto t = makeNamedDecls("struct X { void foo(); };", 505 "struct X { void foo() const; };", Lang_CXX03); 506 EXPECT_FALSE(testStructuralMatch(t)); 507 } 508 509 TEST_F(StructuralEquivalenceCXXMethodTest, Static) { 510 auto t = makeNamedDecls("struct X { void foo(); };", 511 "struct X { static void foo(); };", Lang_CXX03); 512 EXPECT_FALSE(testStructuralMatch(t)); 513 } 514 515 TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) { 516 auto t = makeNamedDecls("struct X { void foo(); };", 517 "struct X { void foo() &&; };", Lang_CXX11); 518 EXPECT_FALSE(testStructuralMatch(t)); 519 } 520 521 TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) { 522 auto t = makeNamedDecls("struct X { void foo() &; };", 523 "struct X { void foo() &&; };", Lang_CXX11); 524 EXPECT_FALSE(testStructuralMatch(t)); 525 } 526 527 TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) { 528 auto t = makeDecls<CXXMethodDecl>("struct X { public: void foo(); };", 529 "struct X { private: void foo(); };", 530 Lang_CXX03, cxxMethodDecl(hasName("foo"))); 531 EXPECT_FALSE(testStructuralMatch(t)); 532 } 533 534 TEST_F(StructuralEquivalenceCXXMethodTest, Delete) { 535 auto t = makeNamedDecls("struct X { void foo(); };", 536 "struct X { void foo() = delete; };", Lang_CXX11); 537 EXPECT_FALSE(testStructuralMatch(t)); 538 } 539 540 TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) { 541 auto t = makeDecls<FunctionDecl>("void foo();", "struct foo { foo(); };", 542 Lang_CXX03, functionDecl(hasName("foo")), 543 cxxConstructorDecl(hasName("foo"))); 544 EXPECT_FALSE(testStructuralMatch(t)); 545 } 546 547 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) { 548 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };", 549 "struct X { X(int); };", Lang_CXX03, 550 cxxConstructorDecl(hasName("X"))); 551 EXPECT_FALSE(testStructuralMatch(t)); 552 } 553 554 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) { 555 auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };", 556 "struct X { explicit X(int); };", 557 Lang_CXX11, 558 cxxConstructorDecl(hasName("X"))); 559 EXPECT_FALSE(testStructuralMatch(t)); 560 } 561 562 TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) { 563 auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };", 564 "struct X { X() = default; };", 565 Lang_CXX11, 566 cxxConstructorDecl(hasName("X"))); 567 EXPECT_FALSE(testStructuralMatch(t)); 568 } 569 570 TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) { 571 auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };", 572 "struct X { operator char(); };", 573 Lang_CXX11, 574 cxxConversionDecl()); 575 EXPECT_FALSE(testStructuralMatch(t)); 576 } 577 578 TEST_F(StructuralEquivalenceCXXMethodTest, Operator) { 579 auto t = 580 makeDecls<FunctionDecl>("struct X { int operator +(int); };", 581 "struct X { int operator -(int); };", Lang_CXX03, 582 functionDecl(hasOverloadedOperatorName("+")), 583 functionDecl(hasOverloadedOperatorName("-"))); 584 EXPECT_FALSE(testStructuralMatch(t)); 585 } 586 587 TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) { 588 auto t = makeDecls<FunctionDecl>( 589 "struct X { virtual void f(); }; void X::f() { }", 590 "struct X { virtual void f() { }; };", Lang_CXX03, 591 functionDecl(allOf(hasName("f"), isDefinition()))); 592 EXPECT_TRUE(testStructuralMatch(t)); 593 } 594 595 TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) { 596 auto t = makeDecls<FunctionDecl>( 597 "struct X { virtual void f(); }; void X::f() { }", 598 "struct X { void f(); }; void X::f() { }", Lang_CXX03, 599 functionDecl(allOf(hasName("f"), isDefinition()))); 600 EXPECT_FALSE(testStructuralMatch(t)); 601 } 602 603 struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest { 604 // FIXME Use a common getRecordDecl with ASTImporterTest.cpp! 605 RecordDecl *getRecordDecl(FieldDecl *FD) { 606 auto *ET = cast<ElaboratedType>(FD->getType().getTypePtr()); 607 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl(); 608 }; 609 }; 610 611 TEST_F(StructuralEquivalenceRecordTest, Name) { 612 auto t = makeDecls<CXXRecordDecl>("struct A{ };", "struct B{ };", Lang_CXX03, 613 cxxRecordDecl(hasName("A")), 614 cxxRecordDecl(hasName("B"))); 615 EXPECT_FALSE(testStructuralMatch(t)); 616 } 617 618 TEST_F(StructuralEquivalenceRecordTest, Fields) { 619 auto t = makeNamedDecls("struct foo{ int x; };", "struct foo{ char x; };", 620 Lang_CXX03); 621 EXPECT_FALSE(testStructuralMatch(t)); 622 } 623 624 TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) { 625 // Currently, methods of a class are not checked at class equivalence. 626 auto t = makeNamedDecls("struct foo{ int x(); };", "struct foo{ char x(); };", 627 Lang_CXX03); 628 EXPECT_FALSE(testStructuralMatch(t)); 629 } 630 631 TEST_F(StructuralEquivalenceRecordTest, Bases) { 632 auto t = makeNamedDecls("struct A{ }; struct foo: A { };", 633 "struct B{ }; struct foo: B { };", Lang_CXX03); 634 EXPECT_FALSE(testStructuralMatch(t)); 635 } 636 637 TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) { 638 auto t = 639 makeNamedDecls("struct A{ }; struct foo: A { };", 640 "struct A{ }; struct foo: virtual A { };", Lang_CXX03); 641 EXPECT_FALSE(testStructuralMatch(t)); 642 } 643 644 TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) { 645 // Access specifier in inheritance is not checked yet. 646 auto t = 647 makeNamedDecls("struct A{ }; struct foo: public A { };", 648 "struct A{ }; struct foo: private A { };", Lang_CXX03); 649 EXPECT_FALSE(testStructuralMatch(t)); 650 } 651 652 TEST_F(StructuralEquivalenceRecordTest, Match) { 653 auto Code = R"( 654 struct A{ }; 655 struct B{ }; 656 struct foo: A, virtual B { 657 void x(); 658 int a; 659 }; 660 )"; 661 auto t = makeNamedDecls(Code, Code, Lang_CXX03); 662 EXPECT_TRUE(testStructuralMatch(t)); 663 } 664 665 TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) { 666 auto t = makeTuDecls( 667 R"( 668 struct A { 669 struct { 670 struct A *next; 671 } entry0; 672 struct { 673 struct A *next; 674 } entry1; 675 }; 676 )", 677 "", Lang_C99); 678 auto *TU = get<0>(t); 679 auto *Entry0 = 680 FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0"))); 681 auto *Entry1 = 682 FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1"))); 683 auto *R0 = getRecordDecl(Entry0); 684 auto *R1 = getRecordDecl(Entry1); 685 686 ASSERT_NE(R0, R1); 687 EXPECT_TRUE(testStructuralMatch(R0, R0)); 688 EXPECT_TRUE(testStructuralMatch(R1, R1)); 689 EXPECT_FALSE(testStructuralMatch(R0, R1)); 690 } 691 692 TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) { 693 auto t = makeTuDecls( 694 R"( 695 struct X { 696 struct { 697 int a; 698 }; 699 struct { 700 int b; 701 }; 702 }; 703 )", 704 "", Lang_C99); 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 auto *B = FirstDeclMatcher<IndirectFieldDecl>().match( 711 TU, indirectFieldDecl(hasName("b"))); 712 auto *FB = cast<FieldDecl>(B->chain().front()); 713 RecordDecl *RB = cast<RecordType>(FB->getType().getTypePtr())->getDecl(); 714 715 ASSERT_NE(RA, RB); 716 EXPECT_TRUE(testStructuralMatch(RA, RA)); 717 EXPECT_TRUE(testStructuralMatch(RB, RB)); 718 EXPECT_FALSE(testStructuralMatch(RA, RB)); 719 } 720 721 TEST_F(StructuralEquivalenceRecordTest, 722 RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) { 723 auto t = makeTuDecls( 724 R"( 725 struct X { 726 struct { int a; }; 727 struct { int b; }; 728 }; 729 )", 730 R"( 731 struct X { // The order is reversed. 732 struct { int b; }; 733 struct { int a; }; 734 }; 735 )", 736 Lang_C99); 737 738 auto *TU = get<0>(t); 739 auto *A = FirstDeclMatcher<IndirectFieldDecl>().match( 740 TU, indirectFieldDecl(hasName("a"))); 741 auto *FA = cast<FieldDecl>(A->chain().front()); 742 RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl(); 743 744 auto *TU1 = get<1>(t); 745 auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match( 746 TU1, indirectFieldDecl(hasName("a"))); 747 auto *FA1 = cast<FieldDecl>(A1->chain().front()); 748 RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl(); 749 750 RecordDecl *X = 751 FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName("X"))); 752 RecordDecl *X1 = 753 FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName("X"))); 754 ASSERT_NE(X, X1); 755 EXPECT_FALSE(testStructuralMatch(X, X1)); 756 757 ASSERT_NE(RA, RA1); 758 EXPECT_TRUE(testStructuralMatch(RA, RA)); 759 EXPECT_TRUE(testStructuralMatch(RA1, RA1)); 760 EXPECT_FALSE(testStructuralMatch(RA1, RA)); 761 } 762 763 TEST_F(StructuralEquivalenceRecordTest, 764 UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) { 765 auto Code = 766 R"( 767 struct A { 768 struct { 769 struct A *next; 770 } entry0; 771 struct { 772 struct A *next; 773 } entry1; 774 }; 775 )"; 776 auto t = makeTuDecls(Code, Code, Lang_C99); 777 778 auto *FromTU = get<0>(t); 779 auto *Entry1 = 780 FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("entry1"))); 781 782 auto *ToTU = get<1>(t); 783 auto *Entry0 = 784 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0"))); 785 auto *A = 786 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A"))); 787 A->startDefinition(); // Set isBeingDefined, getDefinition() will return a 788 // nullptr. This may be the case during ASTImport. 789 790 auto *R0 = getRecordDecl(Entry0); 791 auto *R1 = getRecordDecl(Entry1); 792 793 ASSERT_NE(R0, R1); 794 EXPECT_TRUE(testStructuralMatch(R0, R0)); 795 EXPECT_TRUE(testStructuralMatch(R1, R1)); 796 EXPECT_FALSE(testStructuralMatch(R0, R1)); 797 } 798 799 TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) { 800 auto t = makeDecls<CXXRecordDecl>("struct A { };", 801 "template<class T> struct A { };", 802 Lang_CXX03, cxxRecordDecl(hasName("A"))); 803 EXPECT_FALSE(testStructuralMatch(t)); 804 } 805 806 TEST_F(StructuralEquivalenceRecordTest, 807 FwdDeclRecordShouldBeEqualWithFwdDeclRecord) { 808 auto t = makeNamedDecls("class foo;", "class foo;", Lang_CXX11); 809 EXPECT_TRUE(testStructuralMatch(t)); 810 } 811 812 TEST_F(StructuralEquivalenceRecordTest, 813 FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition) { 814 auto t = 815 makeNamedDecls("class foo;", "class foo { int A; };", Lang_CXX11); 816 EXPECT_TRUE(testStructuralMatch(t)); 817 } 818 819 TEST_F(StructuralEquivalenceRecordTest, 820 RecordShouldBeEqualWithRecordWhichHasDefinition) { 821 auto t = makeNamedDecls("class foo { int A; };", "class foo { int A; };", 822 Lang_CXX11); 823 EXPECT_TRUE(testStructuralMatch(t)); 824 } 825 826 TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) { 827 auto t = makeNamedDecls("class foo { int B; };", "class foo { int A; };", 828 Lang_CXX11); 829 EXPECT_FALSE(testStructuralMatch(t)); 830 } 831 832 TEST_F(StructuralEquivalenceRecordTest, SameFriendMultipleTimes) { 833 auto t = makeNamedDecls("struct foo { friend class X; };", 834 "struct foo { friend class X; friend class X; };", 835 Lang_CXX11); 836 EXPECT_FALSE(testStructuralMatch(t)); 837 } 838 839 TEST_F(StructuralEquivalenceRecordTest, SameFriendsDifferentOrder) { 840 auto t = makeNamedDecls("struct foo { friend class X; friend class Y; };", 841 "struct foo { friend class Y; friend class X; };", 842 Lang_CXX11); 843 EXPECT_FALSE(testStructuralMatch(t)); 844 } 845 846 TEST_F(StructuralEquivalenceRecordTest, SameFriendsSameOrder) { 847 auto t = makeNamedDecls("struct foo { friend class X; friend class Y; };", 848 "struct foo { friend class X; friend class Y; };", 849 Lang_CXX11); 850 EXPECT_TRUE(testStructuralMatch(t)); 851 } 852 853 struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {}; 854 855 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentMethods) { 856 // Get the LambdaExprs, unfortunately we can't match directly the underlying 857 // implicit CXXRecordDecl of the Lambda classes. 858 auto t = makeDecls<LambdaExpr>( 859 "void f() { auto L0 = [](int){}; }", 860 "void f() { auto L1 = [](){}; }", 861 Lang_CXX11, 862 lambdaExpr(), 863 lambdaExpr()); 864 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); 865 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); 866 EXPECT_FALSE(testStructuralMatch(L0, L1)); 867 } 868 869 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqMethods) { 870 auto t = makeDecls<LambdaExpr>( 871 "void f() { auto L0 = [](int){}; }", 872 "void f() { auto L1 = [](int){}; }", 873 Lang_CXX11, 874 lambdaExpr(), 875 lambdaExpr()); 876 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); 877 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); 878 EXPECT_TRUE(testStructuralMatch(L0, L1)); 879 } 880 881 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentFields) { 882 auto t = makeDecls<LambdaExpr>( 883 "void f() { char* X; auto L0 = [X](){}; }", 884 "void f() { float X; auto L1 = [X](){}; }", 885 Lang_CXX11, 886 lambdaExpr(), 887 lambdaExpr()); 888 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); 889 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); 890 EXPECT_FALSE(testStructuralMatch(L0, L1)); 891 } 892 893 TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqFields) { 894 auto t = makeDecls<LambdaExpr>( 895 "void f() { float X; auto L0 = [X](){}; }", 896 "void f() { float X; auto L1 = [X](){}; }", 897 Lang_CXX11, 898 lambdaExpr(), 899 lambdaExpr()); 900 CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); 901 CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); 902 EXPECT_TRUE(testStructuralMatch(L0, L1)); 903 } 904 905 TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { 906 auto t = makeNamedDecls("struct A{ }; struct B{ }; void foo(A a, A b);", 907 "struct A{ }; struct B{ }; void foo(A a, B b);", 908 Lang_CXX03); 909 EXPECT_FALSE(testStructuralMatch(t)); 910 } 911 912 TEST_F(StructuralEquivalenceTest, ExplicitBoolDifferent) { 913 auto Decls = makeNamedDecls("struct foo {explicit(false) foo(int);};", 914 "struct foo {explicit(true) foo(int);};", Lang_CXX20); 915 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match( 916 get<0>(Decls), cxxConstructorDecl(hasName("foo"))); 917 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match( 918 get<1>(Decls), cxxConstructorDecl(hasName("foo"))); 919 EXPECT_FALSE(testStructuralMatch(First, Second)); 920 } 921 922 TEST_F(StructuralEquivalenceTest, ExplicitBoolSame) { 923 auto Decls = makeNamedDecls("struct foo {explicit(true) foo(int);};", 924 "struct foo {explicit(true) foo(int);};", Lang_CXX20); 925 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match( 926 get<0>(Decls), cxxConstructorDecl(hasName("foo"))); 927 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match( 928 get<1>(Decls), cxxConstructorDecl(hasName("foo"))); 929 EXPECT_TRUE(testStructuralMatch(First, Second)); 930 } 931 932 struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {}; 933 934 TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) { 935 auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11); 936 EXPECT_TRUE(testStructuralMatch(t)); 937 } 938 939 TEST_F(StructuralEquivalenceEnumTest, 940 FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) { 941 auto t = 942 makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11); 943 EXPECT_TRUE(testStructuralMatch(t)); 944 } 945 946 TEST_F(StructuralEquivalenceEnumTest, 947 EnumShouldBeEqualWithEnumWhichHasDefinition) { 948 auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };", 949 Lang_CXX11); 950 EXPECT_TRUE(testStructuralMatch(t)); 951 } 952 953 TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) { 954 auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };", 955 Lang_CXX11); 956 EXPECT_FALSE(testStructuralMatch(t)); 957 } 958 959 struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {}; 960 961 TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) { 962 auto t = makeNamedDecls("template <class T> struct foo;", 963 "template <class T> struct foo;", Lang_CXX03); 964 EXPECT_TRUE(testStructuralMatch(t)); 965 } 966 967 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) { 968 auto t = makeNamedDecls("template <class T> struct foo;", 969 "template <class U> struct foo;", Lang_CXX03); 970 EXPECT_TRUE(testStructuralMatch(t)); 971 } 972 973 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) { 974 auto t = makeNamedDecls("template <class T> struct foo;", 975 "template <int T> struct foo;", Lang_CXX03); 976 EXPECT_FALSE(testStructuralMatch(t)); 977 } 978 979 TEST_F(StructuralEquivalenceTemplateTest, BitFieldDecl) { 980 const char *Code = "class foo { int a : 2; };"; 981 auto t = makeNamedDecls(Code, Code, Lang_CXX03); 982 EXPECT_TRUE(testStructuralMatch(t)); 983 } 984 985 TEST_F(StructuralEquivalenceTemplateTest, BitFieldDeclDifferentWidth) { 986 auto t = makeNamedDecls("class foo { int a : 2; };", 987 "class foo { int a : 4; };", Lang_CXX03); 988 EXPECT_FALSE(testStructuralMatch(t)); 989 } 990 991 TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDecl) { 992 const char *Code = "template <class T> class foo { int a : sizeof(T); };"; 993 auto t = makeNamedDecls(Code, Code, Lang_CXX03); 994 EXPECT_TRUE(testStructuralMatch(t)); 995 } 996 997 TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal) { 998 auto t = makeNamedDecls( 999 "template <class A, class B> class foo { int a : sizeof(A); };", 1000 "template <class A, class B> class foo { int a : sizeof(B); };", 1001 Lang_CXX03); 1002 EXPECT_FALSE(testStructuralMatch(t)); 1003 } 1004 1005 TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal2) { 1006 auto t = makeNamedDecls( 1007 "template <class A> class foo { int a : sizeof(A); };", 1008 "template <class A> class foo { int a : sizeof(A) + 1; };", Lang_CXX03); 1009 EXPECT_FALSE(testStructuralMatch(t)); 1010 } 1011 1012 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) { 1013 auto Decls = makeNamedDecls( 1014 "template <bool b> struct foo {explicit(b) foo(int);};", 1015 "template <bool b> struct foo {explicit(b) foo(int);};", Lang_CXX20); 1016 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match( 1017 get<0>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 1018 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match( 1019 get<1>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 1020 EXPECT_TRUE(testStructuralMatch(First, Second)); 1021 } 1022 1023 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) { 1024 auto Decls = makeNamedDecls( 1025 "template <bool b> struct foo {explicit(b) foo(int);};", 1026 "template <bool b> struct foo {explicit(!b) foo(int);};", Lang_CXX20); 1027 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match( 1028 get<0>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 1029 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match( 1030 get<1>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 1031 EXPECT_FALSE(testStructuralMatch(First, Second)); 1032 } 1033 1034 TEST_F(StructuralEquivalenceTemplateTest, 1035 TemplateVsSubstTemplateTemplateParmInArgEq) { 1036 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1037 R"( 1038 template <typename P1> class Arg { }; 1039 template <template <typename PP1> class P1> class Primary { }; 1040 1041 void f() { 1042 // Make specialization with simple template. 1043 Primary <Arg> A; 1044 } 1045 )", 1046 R"( 1047 template <typename P1> class Arg { }; 1048 template <template <typename PP1> class P1> class Primary { }; 1049 1050 template <template <typename PP1> class P1> class Templ { 1051 void f() { 1052 // Make specialization with substituted template template param. 1053 Primary <P1> A; 1054 }; 1055 }; 1056 1057 // Instantiate with substitution Arg into P1. 1058 template class Templ <Arg>; 1059 )", 1060 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1061 EXPECT_TRUE(testStructuralMatch(t)); 1062 } 1063 1064 TEST_F(StructuralEquivalenceTemplateTest, 1065 TemplateVsSubstTemplateTemplateParmInArgNotEq) { 1066 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1067 R"( 1068 template <typename P1> class Arg { }; 1069 template <template <typename PP1> class P1> class Primary { }; 1070 1071 void f() { 1072 // Make specialization with simple template. 1073 Primary <Arg> A; 1074 } 1075 )", 1076 R"( 1077 // Arg is different from the other, this should cause non-equivalence. 1078 template <typename P1> class Arg { int X; }; 1079 template <template <typename PP1> class P1> class Primary { }; 1080 1081 template <template <typename PP1> class P1> class Templ { 1082 void f() { 1083 // Make specialization with substituted template template param. 1084 Primary <P1> A; 1085 }; 1086 }; 1087 1088 // Instantiate with substitution Arg into P1. 1089 template class Templ <Arg>; 1090 )", 1091 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1092 EXPECT_FALSE(testStructuralMatch(t)); 1093 } 1094 1095 struct StructuralEquivalenceDependentTemplateArgsTest 1096 : StructuralEquivalenceTemplateTest {}; 1097 1098 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1099 SameStructsInDependentArgs) { 1100 std::string Code = 1101 R"( 1102 template <typename> 1103 struct S1; 1104 1105 template <typename> 1106 struct enable_if; 1107 1108 struct S 1109 { 1110 template <typename T, typename enable_if<S1<T>>::type> 1111 void f(); 1112 }; 1113 )"; 1114 auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11, 1115 functionTemplateDecl(hasName("f"))); 1116 EXPECT_TRUE(testStructuralMatch(t)); 1117 } 1118 1119 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1120 DifferentStructsInDependentArgs) { 1121 std::string Code = 1122 R"( 1123 template <typename> 1124 struct S1; 1125 1126 template <typename> 1127 struct S2; 1128 1129 template <typename> 1130 struct enable_if; 1131 )"; 1132 auto t = makeDecls<FunctionTemplateDecl>(Code + R"( 1133 struct S 1134 { 1135 template <typename T, typename enable_if<S1<T>>::type> 1136 void f(); 1137 }; 1138 )", 1139 Code + R"( 1140 struct S 1141 { 1142 template <typename T, typename enable_if<S2<T>>::type> 1143 void f(); 1144 }; 1145 )", 1146 Lang_CXX11, 1147 functionTemplateDecl(hasName("f"))); 1148 EXPECT_FALSE(testStructuralMatch(t)); 1149 } 1150 1151 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1152 SameStructsInDependentScopeDeclRefExpr) { 1153 std::string Code = 1154 R"( 1155 template <typename> 1156 struct S1; 1157 1158 template <bool> 1159 struct enable_if; 1160 1161 struct S 1162 { 1163 template <typename T, typename enable_if<S1<T>::value>::type> 1164 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^ 1165 }; 1166 )"; 1167 auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11, 1168 functionTemplateDecl(hasName("f"))); 1169 EXPECT_TRUE(testStructuralMatch(t)); 1170 } 1171 1172 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1173 DifferentStructsInDependentScopeDeclRefExpr) { 1174 std::string Code = 1175 R"( 1176 template <typename> 1177 struct S1; 1178 1179 template <typename> 1180 struct S2; 1181 1182 template <bool> 1183 struct enable_if; 1184 )"; 1185 auto t = makeDecls<FunctionTemplateDecl>(Code + R"( 1186 struct S 1187 { 1188 template <typename T, typename enable_if<S1<T>::value>::type> 1189 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^ 1190 }; 1191 )", 1192 Code + R"( 1193 struct S 1194 { 1195 template <typename T, typename enable_if<S2<T>::value>::type> 1196 void f(); 1197 }; 1198 )", 1199 Lang_CXX03, 1200 functionTemplateDecl(hasName("f"))); 1201 EXPECT_FALSE(testStructuralMatch(t)); 1202 } 1203 1204 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1205 DifferentValueInDependentScopeDeclRefExpr) { 1206 std::string Code = 1207 R"( 1208 template <typename> 1209 struct S1; 1210 1211 template <bool> 1212 struct enable_if; 1213 )"; 1214 auto t = makeDecls<FunctionTemplateDecl>(Code + R"( 1215 struct S 1216 { 1217 template <typename T, typename enable_if<S1<T>::value1>::type> 1218 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^ 1219 }; 1220 )", 1221 Code + R"( 1222 struct S 1223 { 1224 template <typename T, typename enable_if<S1<T>::value2>::type> 1225 void f(); 1226 }; 1227 )", 1228 Lang_CXX03, 1229 functionTemplateDecl(hasName("f"))); 1230 EXPECT_FALSE(testStructuralMatch(t)); 1231 } 1232 1233 TEST_F( 1234 StructuralEquivalenceTemplateTest, 1235 ClassTemplSpecWithQualifiedAndNonQualifiedTypeArgsShouldBeEqual) { 1236 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1237 R"( 1238 template <class T> struct Primary {}; 1239 namespace N { 1240 struct Arg; 1241 } 1242 // Explicit instantiation with qualified name. 1243 template struct Primary<N::Arg>; 1244 )", 1245 R"( 1246 template <class T> struct Primary {}; 1247 namespace N { 1248 struct Arg; 1249 } 1250 using namespace N; 1251 // Explicit instantiation with UNqualified name. 1252 template struct Primary<Arg>; 1253 )", 1254 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1255 EXPECT_TRUE(testStructuralMatch(t)); 1256 } 1257 1258 TEST_F( 1259 StructuralEquivalenceTemplateTest, 1260 ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTypeArgs) { 1261 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1262 R"( 1263 template <class T> struct Primary {}; 1264 namespace N { 1265 struct Arg { int a; }; 1266 } 1267 // Explicit instantiation with qualified name. 1268 template struct Primary<N::Arg>; 1269 )", 1270 R"( 1271 template <class T> struct Primary {}; 1272 namespace N { 1273 // This struct is not equivalent with the other in the prev TU. 1274 struct Arg { double b; }; // -- Field mismatch. 1275 } 1276 using namespace N; 1277 // Explicit instantiation with UNqualified name. 1278 template struct Primary<Arg>; 1279 )", 1280 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1281 EXPECT_FALSE(testStructuralMatch(t)); 1282 } 1283 1284 TEST_F( 1285 StructuralEquivalenceTemplateTest, 1286 ClassTemplSpecWithQualifiedAndNonQualifiedTemplArgsShouldBeEqual) { 1287 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1288 R"( 1289 template <template <class> class T> struct Primary {}; 1290 namespace N { 1291 template <class T> struct Arg; 1292 } 1293 // Explicit instantiation with qualified name. 1294 template struct Primary<N::Arg>; 1295 )", 1296 R"( 1297 template <template <class> class T> struct Primary {}; 1298 namespace N { 1299 template <class T> struct Arg; 1300 } 1301 using namespace N; 1302 // Explicit instantiation with UNqualified name. 1303 template struct Primary<Arg>; 1304 )", 1305 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1306 EXPECT_TRUE(testStructuralMatch(t)); 1307 } 1308 1309 TEST_F( 1310 StructuralEquivalenceTemplateTest, 1311 ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTemplArgs) { 1312 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1313 R"( 1314 template <template <class> class T> struct Primary {}; 1315 namespace N { 1316 template <class T> struct Arg { int a; }; 1317 } 1318 // Explicit instantiation with qualified name. 1319 template struct Primary<N::Arg>; 1320 )", 1321 R"( 1322 template <template <class> class T> struct Primary {}; 1323 namespace N { 1324 // This template is not equivalent with the other in the prev TU. 1325 template <class T> struct Arg { double b; }; // -- Field mismatch. 1326 } 1327 using namespace N; 1328 // Explicit instantiation with UNqualified name. 1329 template struct Primary<Arg>; 1330 )", 1331 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1332 EXPECT_FALSE(testStructuralMatch(t)); 1333 } 1334 1335 TEST_F( 1336 StructuralEquivalenceTemplateTest, 1337 ClassTemplSpecWithInequivalentShadowedTemplArg) { 1338 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1339 R"( 1340 template <template <class> class T> struct Primary {}; 1341 template <class T> struct Arg { int a; }; 1342 // Explicit instantiation with ::Arg 1343 template struct Primary<Arg>; 1344 )", 1345 R"( 1346 template <template <class> class T> struct Primary {}; 1347 template <class T> struct Arg { int a; }; 1348 namespace N { 1349 // This template is not equivalent with the other in the global scope. 1350 template <class T> struct Arg { double b; }; // -- Field mismatch. 1351 // Explicit instantiation with N::Arg which shadows ::Arg 1352 template struct Primary<Arg>; 1353 } 1354 )", 1355 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1356 EXPECT_FALSE(testStructuralMatch(t)); 1357 } 1358 struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest { 1359 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; 1360 1361 template <typename NodeType, typename MatcherType> 1362 std::pair<NodeType *, NodeType *> 1363 findDeclPair(std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> TU, 1364 MatcherType M) { 1365 NodeType *D0 = FirstDeclMatcher<NodeType>().match(get<0>(TU), M); 1366 NodeType *D1 = FirstDeclMatcher<NodeType>().match(get<1>(TU), M); 1367 return {D0, D1}; 1368 } 1369 1370 template <typename NodeType> 1371 bool isInNonEqCache(std::pair<NodeType *, NodeType *> D) { 1372 return NonEquivalentDecls.count(D) > 0; 1373 } 1374 }; 1375 1376 TEST_F(StructuralEquivalenceCacheTest, SimpleNonEq) { 1377 auto TU = makeTuDecls( 1378 R"( 1379 class A {}; 1380 class B {}; 1381 void x(A, A); 1382 )", 1383 R"( 1384 class A {}; 1385 class B {}; 1386 void x(A, B); 1387 )", 1388 Lang_CXX03); 1389 1390 StructuralEquivalenceContext Ctx( 1391 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), 1392 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); 1393 1394 auto X = findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x"))); 1395 EXPECT_FALSE(Ctx.IsEquivalent(X.first, X.second)); 1396 1397 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1398 TU, cxxRecordDecl(hasName("A"), unless(isImplicit()))))); 1399 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1400 TU, cxxRecordDecl(hasName("B"), unless(isImplicit()))))); 1401 } 1402 1403 TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) { 1404 auto TU = makeTuDecls( 1405 R"( 1406 class A {}; 1407 class B { int i; }; 1408 void x(A *); 1409 void y(A *); 1410 class C { 1411 friend void x(A *); 1412 friend void y(A *); 1413 }; 1414 )", 1415 R"( 1416 class A {}; 1417 class B { int i; }; 1418 void x(A *); 1419 void y(B *); 1420 class C { 1421 friend void x(A *); 1422 friend void y(B *); 1423 }; 1424 )", 1425 Lang_CXX03); 1426 1427 StructuralEquivalenceContext Ctx( 1428 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), 1429 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); 1430 1431 auto C = findDeclPair<CXXRecordDecl>( 1432 TU, cxxRecordDecl(hasName("C"), unless(isImplicit()))); 1433 EXPECT_FALSE(Ctx.IsEquivalent(C.first, C.second)); 1434 1435 EXPECT_FALSE(isInNonEqCache(C)); 1436 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1437 TU, cxxRecordDecl(hasName("A"), unless(isImplicit()))))); 1438 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1439 TU, cxxRecordDecl(hasName("B"), unless(isImplicit()))))); 1440 EXPECT_FALSE(isInNonEqCache( 1441 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x"))))); 1442 EXPECT_FALSE(isInNonEqCache( 1443 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("y"))))); 1444 } 1445 1446 TEST_F(StructuralEquivalenceCacheTest, Cycle) { 1447 auto TU = makeTuDecls( 1448 R"( 1449 class C; 1450 class A { C *c; }; 1451 void x(A *); 1452 class C { 1453 friend void x(A *); 1454 }; 1455 )", 1456 R"( 1457 class C; 1458 class A { C *c; }; 1459 void x(A *); 1460 class C { 1461 friend void x(A *); 1462 }; 1463 )", 1464 Lang_CXX03); 1465 1466 StructuralEquivalenceContext Ctx( 1467 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), 1468 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); 1469 1470 auto C = findDeclPair<CXXRecordDecl>( 1471 TU, cxxRecordDecl(hasName("C"), unless(isImplicit()))); 1472 EXPECT_TRUE(Ctx.IsEquivalent(C.first, C.second)); 1473 1474 EXPECT_FALSE(isInNonEqCache(C)); 1475 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1476 TU, cxxRecordDecl(hasName("A"), unless(isImplicit()))))); 1477 EXPECT_FALSE(isInNonEqCache( 1478 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x"))))); 1479 } 1480 1481 struct StructuralEquivalenceStmtTest : StructuralEquivalenceTest {}; 1482 1483 /// Fallback matcher to be used only when there is no specific matcher for a 1484 /// Expr subclass. Remove this once all Expr subclasses have their own matcher. 1485 static auto &fallbackExprMatcher = expr; 1486 1487 TEST_F(StructuralEquivalenceStmtTest, AddrLabelExpr) { 1488 auto t = makeWrappedStmts("lbl: &&lbl;", "lbl: &&lbl;", Lang_CXX03, 1489 addrLabelExpr()); 1490 EXPECT_TRUE(testStructuralMatch(t)); 1491 } 1492 1493 TEST_F(StructuralEquivalenceStmtTest, AddrLabelExprDifferentLabel) { 1494 auto t = makeWrappedStmts("lbl1: lbl2: &&lbl1;", "lbl1: lbl2: &&lbl2;", 1495 Lang_CXX03, addrLabelExpr()); 1496 // FIXME: Should be false. LabelDecl are incorrectly matched. 1497 EXPECT_TRUE(testStructuralMatch(t)); 1498 } 1499 1500 static const std::string MemoryOrderSrc = R"( 1501 enum memory_order { 1502 memory_order_relaxed, 1503 memory_order_consume, 1504 memory_order_acquire, 1505 memory_order_release, 1506 memory_order_acq_rel, 1507 memory_order_seq_cst 1508 }; 1509 )"; 1510 1511 TEST_F(StructuralEquivalenceStmtTest, AtomicExpr) { 1512 std::string Prefix = "char a, b; " + MemoryOrderSrc; 1513 auto t = makeStmts( 1514 Prefix + 1515 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }", 1516 Prefix + 1517 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }", 1518 Lang_CXX03, atomicExpr()); 1519 EXPECT_TRUE(testStructuralMatch(t)); 1520 } 1521 1522 TEST_F(StructuralEquivalenceStmtTest, AtomicExprDifferentOp) { 1523 std::string Prefix = "char a, b; " + MemoryOrderSrc; 1524 auto t = makeStmts( 1525 Prefix + 1526 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }", 1527 Prefix + 1528 "void wrapped() { __atomic_store(&a, &b, memory_order_seq_cst); }", 1529 Lang_CXX03, atomicExpr()); 1530 EXPECT_FALSE(testStructuralMatch(t)); 1531 } 1532 1533 TEST_F(StructuralEquivalenceStmtTest, BinaryOperator) { 1534 auto t = makeWrappedStmts("1 + 1", "1 + 1", Lang_CXX03, binaryOperator()); 1535 EXPECT_TRUE(testStructuralMatch(t)); 1536 } 1537 1538 TEST_F(StructuralEquivalenceStmtTest, BinaryOperatorDifferentOps) { 1539 auto t = makeWrappedStmts("1 + 1", "1 - 1", Lang_CXX03, binaryOperator()); 1540 EXPECT_FALSE(testStructuralMatch(t)); 1541 } 1542 1543 TEST_F(StructuralEquivalenceStmtTest, CallExpr) { 1544 std::string Src = "int call(); int wrapped() { call(); }"; 1545 auto t = makeStmts(Src, Src, Lang_CXX03, callExpr()); 1546 EXPECT_TRUE(testStructuralMatch(t)); 1547 } 1548 1549 TEST_F(StructuralEquivalenceStmtTest, CallExprDifferentCallee) { 1550 std::string FunctionSrc = "int func1(); int func2();\n"; 1551 auto t = makeStmts(FunctionSrc + "void wrapper() { func1(); }", 1552 FunctionSrc + "void wrapper() { func2(); }", Lang_CXX03, 1553 callExpr()); 1554 EXPECT_FALSE(testStructuralMatch(t)); 1555 } 1556 1557 TEST_F(StructuralEquivalenceStmtTest, CharacterLiteral) { 1558 auto t = makeWrappedStmts("'a'", "'a'", Lang_CXX03, characterLiteral()); 1559 EXPECT_TRUE(testStructuralMatch(t)); 1560 } 1561 1562 TEST_F(StructuralEquivalenceStmtTest, CharacterLiteralDifferentValues) { 1563 auto t = makeWrappedStmts("'a'", "'b'", Lang_CXX03, characterLiteral()); 1564 EXPECT_FALSE(testStructuralMatch(t)); 1565 } 1566 1567 TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExpr) { 1568 auto t = makeWrappedStmts("__is_lvalue_expr(1)", "__is_lvalue_expr(1)", 1569 Lang_CXX03, fallbackExprMatcher()); 1570 EXPECT_TRUE(testStructuralMatch(t)); 1571 } 1572 1573 TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExprDifferentKind) { 1574 auto t = makeWrappedStmts("__is_lvalue_expr(1)", "__is_rvalue_expr(1)", 1575 Lang_CXX03, fallbackExprMatcher()); 1576 EXPECT_FALSE(testStructuralMatch(t)); 1577 } 1578 1579 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteral) { 1580 auto t = makeWrappedStmts("1.0", "1.0", Lang_CXX03, fallbackExprMatcher()); 1581 EXPECT_TRUE(testStructuralMatch(t)); 1582 } 1583 1584 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentSpelling) { 1585 auto t = makeWrappedStmts("0x10.1p0", "16.0625", Lang_CXX17, 1586 fallbackExprMatcher()); 1587 // Same value but with different spelling is equivalent. 1588 EXPECT_TRUE(testStructuralMatch(t)); 1589 } 1590 1591 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentType) { 1592 auto t = makeWrappedStmts("1.0", "1.0f", Lang_CXX03, fallbackExprMatcher()); 1593 EXPECT_FALSE(testStructuralMatch(t)); 1594 } 1595 1596 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentValue) { 1597 auto t = makeWrappedStmts("1.01", "1.0", Lang_CXX03, fallbackExprMatcher()); 1598 EXPECT_FALSE(testStructuralMatch(t)); 1599 } 1600 1601 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSame) { 1602 auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)", 1603 "_Generic(0u, unsigned int: 0, float: 1)", Lang_C99, 1604 genericSelectionExpr()); 1605 EXPECT_TRUE(testStructuralMatch(t)); 1606 } 1607 1608 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSignsDiffer) { 1609 auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)", 1610 "_Generic(0, int: 0, float: 1)", Lang_C99, 1611 genericSelectionExpr()); 1612 EXPECT_FALSE(testStructuralMatch(t)); 1613 } 1614 1615 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprOrderDiffers) { 1616 auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)", 1617 "_Generic(0u, float: 1, unsigned int: 0)", Lang_C99, 1618 genericSelectionExpr()); 1619 EXPECT_FALSE(testStructuralMatch(t)); 1620 } 1621 1622 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprDependentResultSame) { 1623 auto t = makeStmts( 1624 R"( 1625 template <typename T> 1626 void f() { 1627 T x; 1628 (void)_Generic(x, int: 0, float: 1); 1629 } 1630 void g() { f<int>(); } 1631 )", 1632 R"( 1633 template <typename T> 1634 void f() { 1635 T x; 1636 (void)_Generic(x, int: 0, float: 1); 1637 } 1638 void g() { f<int>(); } 1639 )", 1640 Lang_CXX03, genericSelectionExpr()); 1641 EXPECT_TRUE(testStructuralMatch(t)); 1642 } 1643 1644 TEST_F(StructuralEquivalenceStmtTest, 1645 GenericSelectionExprDependentResultOrderDiffers) { 1646 auto t = makeStmts( 1647 R"( 1648 template <typename T> 1649 void f() { 1650 T x; 1651 (void)_Generic(x, float: 1, int: 0); 1652 } 1653 void g() { f<int>(); } 1654 )", 1655 R"( 1656 template <typename T> 1657 void f() { 1658 T x; 1659 (void)_Generic(x, int: 0, float: 1); 1660 } 1661 void g() { f<int>(); } 1662 )", 1663 Lang_CXX03, genericSelectionExpr()); 1664 1665 EXPECT_FALSE(testStructuralMatch(t)); 1666 } 1667 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteral) { 1668 auto t = makeWrappedStmts("1", "1", Lang_CXX03, integerLiteral()); 1669 EXPECT_TRUE(testStructuralMatch(t)); 1670 } 1671 1672 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentSpelling) { 1673 auto t = makeWrappedStmts("1", "0x1", Lang_CXX03, integerLiteral()); 1674 // Same value but with different spelling is equivalent. 1675 EXPECT_TRUE(testStructuralMatch(t)); 1676 } 1677 1678 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentValue) { 1679 auto t = makeWrappedStmts("1", "2", Lang_CXX03, integerLiteral()); 1680 EXPECT_FALSE(testStructuralMatch(t)); 1681 } 1682 1683 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentTypes) { 1684 auto t = makeWrappedStmts("1", "1L", Lang_CXX03, integerLiteral()); 1685 EXPECT_FALSE(testStructuralMatch(t)); 1686 } 1687 1688 TEST_F(StructuralEquivalenceStmtTest, MemberExpr) { 1689 std::string ClassSrc = "struct C { int a; int b; };"; 1690 auto t = makeStmts(ClassSrc + "int wrapper() { C c; return c.a; }", 1691 ClassSrc + "int wrapper() { C c; return c.a; }", 1692 Lang_CXX03, memberExpr()); 1693 EXPECT_TRUE(testStructuralMatch(t)); 1694 } 1695 1696 TEST_F(StructuralEquivalenceStmtTest, MemberExprDifferentMember) { 1697 std::string ClassSrc = "struct C { int a; int b; };"; 1698 auto t = makeStmts(ClassSrc + "int wrapper() { C c; return c.a; }", 1699 ClassSrc + "int wrapper() { C c; return c.b; }", 1700 Lang_CXX03, memberExpr()); 1701 EXPECT_FALSE(testStructuralMatch(t)); 1702 } 1703 1704 TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteral) { 1705 auto t = 1706 makeWrappedStmts("@\"a\"", "@\"a\"", Lang_OBJCXX, fallbackExprMatcher()); 1707 EXPECT_TRUE(testStructuralMatch(t)); 1708 } 1709 1710 TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteralDifferentContent) { 1711 auto t = 1712 makeWrappedStmts("@\"a\"", "@\"b\"", Lang_OBJCXX, fallbackExprMatcher()); 1713 EXPECT_FALSE(testStructuralMatch(t)); 1714 } 1715 1716 TEST_F(StructuralEquivalenceStmtTest, StringLiteral) { 1717 auto t = makeWrappedStmts("\"a\"", "\"a\"", Lang_CXX03, stringLiteral()); 1718 EXPECT_TRUE(testStructuralMatch(t)); 1719 } 1720 1721 TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentContent) { 1722 auto t = makeWrappedStmts("\"a\"", "\"b\"", Lang_CXX03, stringLiteral()); 1723 EXPECT_FALSE(testStructuralMatch(t)); 1724 } 1725 1726 TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentLength) { 1727 auto t = makeWrappedStmts("\"a\"", "\"aa\"", Lang_CXX03, stringLiteral()); 1728 EXPECT_FALSE(testStructuralMatch(t)); 1729 } 1730 1731 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExpr) { 1732 auto t = makeWrappedStmts("__is_pod(int)", "__is_pod(int)", Lang_CXX03, 1733 fallbackExprMatcher()); 1734 EXPECT_TRUE(testStructuralMatch(t)); 1735 } 1736 1737 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentType) { 1738 auto t = makeWrappedStmts("__is_pod(int)", "__is_pod(long)", Lang_CXX03, 1739 fallbackExprMatcher()); 1740 EXPECT_FALSE(testStructuralMatch(t)); 1741 } 1742 1743 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTrait) { 1744 auto t = makeWrappedStmts( 1745 "__is_pod(int)", "__is_trivially_constructible(int)", Lang_CXX03, expr()); 1746 EXPECT_FALSE(testStructuralMatch(t)); 1747 } 1748 1749 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTraits) { 1750 auto t = makeWrappedStmts("__is_constructible(int)", 1751 "__is_constructible(int, int)", Lang_CXX03, expr()); 1752 EXPECT_FALSE(testStructuralMatch(t)); 1753 } 1754 1755 TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExpr) { 1756 auto t = makeWrappedStmts("sizeof(int)", "sizeof(int)", Lang_CXX03, 1757 unaryExprOrTypeTraitExpr()); 1758 EXPECT_TRUE(testStructuralMatch(t)); 1759 } 1760 1761 TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentKind) { 1762 auto t = makeWrappedStmts("sizeof(int)", "alignof(long)", Lang_CXX11, 1763 unaryExprOrTypeTraitExpr()); 1764 EXPECT_FALSE(testStructuralMatch(t)); 1765 } 1766 1767 TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentType) { 1768 auto t = makeWrappedStmts("sizeof(int)", "sizeof(long)", Lang_CXX03, 1769 unaryExprOrTypeTraitExpr()); 1770 EXPECT_FALSE(testStructuralMatch(t)); 1771 } 1772 1773 TEST_F(StructuralEquivalenceStmtTest, UnaryOperator) { 1774 auto t = makeWrappedStmts("+1", "+1", Lang_CXX03, unaryOperator()); 1775 EXPECT_TRUE(testStructuralMatch(t)); 1776 } 1777 1778 TEST_F(StructuralEquivalenceStmtTest, UnaryOperatorDifferentOps) { 1779 auto t = makeWrappedStmts("+1", "-1", Lang_CXX03, unaryOperator()); 1780 EXPECT_FALSE(testStructuralMatch(t)); 1781 } 1782 1783 } // end namespace ast_matchers 1784 } // end namespace clang 1785