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 StructuralEquivalenceEnumConstantTest : StructuralEquivalenceTest {}; 960 961 TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithSameValues) { 962 auto t = makeNamedDecls("enum foo { foo = 1 };", "enum foo { foo = 1 };", 963 Lang_C89); 964 EXPECT_TRUE(testStructuralMatch(t)); 965 } 966 967 TEST_F(StructuralEquivalenceEnumConstantTest, 968 EnumConstantsWithDifferentValues) { 969 auto t = 970 makeNamedDecls("enum e { foo = 1 };", "enum e { foo = 2 };", Lang_C89); 971 EXPECT_FALSE(testStructuralMatch(t)); 972 } 973 974 TEST_F(StructuralEquivalenceEnumConstantTest, 975 EnumConstantsWithDifferentExprsButSameValues) { 976 auto t = makeNamedDecls("enum e { foo = 1 + 1 };", "enum e { foo = 2 };", 977 Lang_CXX11); 978 EXPECT_FALSE(testStructuralMatch(t)); 979 } 980 981 TEST_F(StructuralEquivalenceEnumConstantTest, 982 EnumConstantsWithDifferentSignedness) { 983 auto t = makeNamedDecls("enum e : unsigned { foo = 1 };", 984 "enum e : int { foo = 1 };", Lang_CXX11); 985 EXPECT_FALSE(testStructuralMatch(t)); 986 } 987 988 TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentWidth) { 989 auto t = makeNamedDecls("enum e : short { foo = 1 };", 990 "enum e : int { foo = 1 };", Lang_CXX11); 991 EXPECT_FALSE(testStructuralMatch(t)); 992 } 993 994 TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentName) { 995 auto t = 996 makeDecls<EnumConstantDecl>("enum e { foo = 1 };", "enum e { bar = 1 };", 997 Lang_CXX11, enumConstantDecl()); 998 EXPECT_FALSE(testStructuralMatch(t)); 999 } 1000 1001 struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {}; 1002 1003 TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) { 1004 auto t = makeNamedDecls("template <class T> struct foo;", 1005 "template <class T> struct foo;", Lang_CXX03); 1006 EXPECT_TRUE(testStructuralMatch(t)); 1007 } 1008 1009 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) { 1010 auto t = makeNamedDecls("template <class T> struct foo;", 1011 "template <class U> struct foo;", Lang_CXX03); 1012 EXPECT_TRUE(testStructuralMatch(t)); 1013 } 1014 1015 TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) { 1016 auto t = makeNamedDecls("template <class T> struct foo;", 1017 "template <int T> struct foo;", Lang_CXX03); 1018 EXPECT_FALSE(testStructuralMatch(t)); 1019 } 1020 1021 TEST_F(StructuralEquivalenceTemplateTest, BitFieldDecl) { 1022 const char *Code = "class foo { int a : 2; };"; 1023 auto t = makeNamedDecls(Code, Code, Lang_CXX03); 1024 EXPECT_TRUE(testStructuralMatch(t)); 1025 } 1026 1027 TEST_F(StructuralEquivalenceTemplateTest, BitFieldDeclDifferentWidth) { 1028 auto t = makeNamedDecls("class foo { int a : 2; };", 1029 "class foo { int a : 4; };", Lang_CXX03); 1030 EXPECT_FALSE(testStructuralMatch(t)); 1031 } 1032 1033 TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDecl) { 1034 const char *Code = "template <class T> class foo { int a : sizeof(T); };"; 1035 auto t = makeNamedDecls(Code, Code, Lang_CXX03); 1036 EXPECT_TRUE(testStructuralMatch(t)); 1037 } 1038 1039 TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal) { 1040 auto t = makeNamedDecls( 1041 "template <class A, class B> class foo { int a : sizeof(A); };", 1042 "template <class A, class B> class foo { int a : sizeof(B); };", 1043 Lang_CXX03); 1044 EXPECT_FALSE(testStructuralMatch(t)); 1045 } 1046 1047 TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal2) { 1048 auto t = makeNamedDecls( 1049 "template <class A> class foo { int a : sizeof(A); };", 1050 "template <class A> class foo { int a : sizeof(A) + 1; };", Lang_CXX03); 1051 EXPECT_FALSE(testStructuralMatch(t)); 1052 } 1053 1054 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) { 1055 auto Decls = makeNamedDecls( 1056 "template <bool b> struct foo {explicit(b) foo(int);};", 1057 "template <bool b> struct foo {explicit(b) foo(int);};", Lang_CXX20); 1058 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match( 1059 get<0>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 1060 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match( 1061 get<1>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 1062 EXPECT_TRUE(testStructuralMatch(First, Second)); 1063 } 1064 1065 TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) { 1066 auto Decls = makeNamedDecls( 1067 "template <bool b> struct foo {explicit(b) foo(int);};", 1068 "template <bool b> struct foo {explicit(!b) foo(int);};", Lang_CXX20); 1069 CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match( 1070 get<0>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 1071 CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match( 1072 get<1>(Decls), cxxConstructorDecl(hasName("foo<b>"))); 1073 EXPECT_FALSE(testStructuralMatch(First, Second)); 1074 } 1075 1076 TEST_F(StructuralEquivalenceTemplateTest, 1077 TemplateVsSubstTemplateTemplateParmInArgEq) { 1078 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1079 R"( 1080 template <typename P1> class Arg { }; 1081 template <template <typename PP1> class P1> class Primary { }; 1082 1083 void f() { 1084 // Make specialization with simple template. 1085 Primary <Arg> A; 1086 } 1087 )", 1088 R"( 1089 template <typename P1> class Arg { }; 1090 template <template <typename PP1> class P1> class Primary { }; 1091 1092 template <template <typename PP1> class P1> class Templ { 1093 void f() { 1094 // Make specialization with substituted template template param. 1095 Primary <P1> A; 1096 }; 1097 }; 1098 1099 // Instantiate with substitution Arg into P1. 1100 template class Templ <Arg>; 1101 )", 1102 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1103 EXPECT_TRUE(testStructuralMatch(t)); 1104 } 1105 1106 TEST_F(StructuralEquivalenceTemplateTest, 1107 TemplateVsSubstTemplateTemplateParmInArgNotEq) { 1108 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1109 R"( 1110 template <typename P1> class Arg { }; 1111 template <template <typename PP1> class P1> class Primary { }; 1112 1113 void f() { 1114 // Make specialization with simple template. 1115 Primary <Arg> A; 1116 } 1117 )", 1118 R"( 1119 // Arg is different from the other, this should cause non-equivalence. 1120 template <typename P1> class Arg { int X; }; 1121 template <template <typename PP1> class P1> class Primary { }; 1122 1123 template <template <typename PP1> class P1> class Templ { 1124 void f() { 1125 // Make specialization with substituted template template param. 1126 Primary <P1> A; 1127 }; 1128 }; 1129 1130 // Instantiate with substitution Arg into P1. 1131 template class Templ <Arg>; 1132 )", 1133 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1134 EXPECT_FALSE(testStructuralMatch(t)); 1135 } 1136 1137 struct StructuralEquivalenceDependentTemplateArgsTest 1138 : StructuralEquivalenceTemplateTest {}; 1139 1140 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1141 SameStructsInDependentArgs) { 1142 std::string Code = 1143 R"( 1144 template <typename> 1145 struct S1; 1146 1147 template <typename> 1148 struct enable_if; 1149 1150 struct S 1151 { 1152 template <typename T, typename enable_if<S1<T>>::type> 1153 void f(); 1154 }; 1155 )"; 1156 auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11, 1157 functionTemplateDecl(hasName("f"))); 1158 EXPECT_TRUE(testStructuralMatch(t)); 1159 } 1160 1161 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1162 DifferentStructsInDependentArgs) { 1163 std::string Code = 1164 R"( 1165 template <typename> 1166 struct S1; 1167 1168 template <typename> 1169 struct S2; 1170 1171 template <typename> 1172 struct enable_if; 1173 )"; 1174 auto t = makeDecls<FunctionTemplateDecl>(Code + R"( 1175 struct S 1176 { 1177 template <typename T, typename enable_if<S1<T>>::type> 1178 void f(); 1179 }; 1180 )", 1181 Code + R"( 1182 struct S 1183 { 1184 template <typename T, typename enable_if<S2<T>>::type> 1185 void f(); 1186 }; 1187 )", 1188 Lang_CXX11, 1189 functionTemplateDecl(hasName("f"))); 1190 EXPECT_FALSE(testStructuralMatch(t)); 1191 } 1192 1193 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1194 SameStructsInDependentScopeDeclRefExpr) { 1195 std::string Code = 1196 R"( 1197 template <typename> 1198 struct S1; 1199 1200 template <bool> 1201 struct enable_if; 1202 1203 struct S 1204 { 1205 template <typename T, typename enable_if<S1<T>::value>::type> 1206 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^ 1207 }; 1208 )"; 1209 auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11, 1210 functionTemplateDecl(hasName("f"))); 1211 EXPECT_TRUE(testStructuralMatch(t)); 1212 } 1213 1214 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1215 DifferentStructsInDependentScopeDeclRefExpr) { 1216 std::string Code = 1217 R"( 1218 template <typename> 1219 struct S1; 1220 1221 template <typename> 1222 struct S2; 1223 1224 template <bool> 1225 struct enable_if; 1226 )"; 1227 auto t = makeDecls<FunctionTemplateDecl>(Code + R"( 1228 struct S 1229 { 1230 template <typename T, typename enable_if<S1<T>::value>::type> 1231 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^ 1232 }; 1233 )", 1234 Code + R"( 1235 struct S 1236 { 1237 template <typename T, typename enable_if<S2<T>::value>::type> 1238 void f(); 1239 }; 1240 )", 1241 Lang_CXX03, 1242 functionTemplateDecl(hasName("f"))); 1243 EXPECT_FALSE(testStructuralMatch(t)); 1244 } 1245 1246 TEST_F(StructuralEquivalenceDependentTemplateArgsTest, 1247 DifferentValueInDependentScopeDeclRefExpr) { 1248 std::string Code = 1249 R"( 1250 template <typename> 1251 struct S1; 1252 1253 template <bool> 1254 struct enable_if; 1255 )"; 1256 auto t = makeDecls<FunctionTemplateDecl>(Code + R"( 1257 struct S 1258 { 1259 template <typename T, typename enable_if<S1<T>::value1>::type> 1260 void f(); // DependentScopeDeclRefExpr:^^^^^^^^^^^^ 1261 }; 1262 )", 1263 Code + R"( 1264 struct S 1265 { 1266 template <typename T, typename enable_if<S1<T>::value2>::type> 1267 void f(); 1268 }; 1269 )", 1270 Lang_CXX03, 1271 functionTemplateDecl(hasName("f"))); 1272 EXPECT_FALSE(testStructuralMatch(t)); 1273 } 1274 1275 TEST_F( 1276 StructuralEquivalenceTemplateTest, 1277 ClassTemplSpecWithQualifiedAndNonQualifiedTypeArgsShouldBeEqual) { 1278 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1279 R"( 1280 template <class T> struct Primary {}; 1281 namespace N { 1282 struct Arg; 1283 } 1284 // Explicit instantiation with qualified name. 1285 template struct Primary<N::Arg>; 1286 )", 1287 R"( 1288 template <class T> struct Primary {}; 1289 namespace N { 1290 struct Arg; 1291 } 1292 using namespace N; 1293 // Explicit instantiation with UNqualified name. 1294 template struct Primary<Arg>; 1295 )", 1296 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1297 EXPECT_TRUE(testStructuralMatch(t)); 1298 } 1299 1300 TEST_F( 1301 StructuralEquivalenceTemplateTest, 1302 ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTypeArgs) { 1303 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1304 R"( 1305 template <class T> struct Primary {}; 1306 namespace N { 1307 struct Arg { int a; }; 1308 } 1309 // Explicit instantiation with qualified name. 1310 template struct Primary<N::Arg>; 1311 )", 1312 R"( 1313 template <class T> struct Primary {}; 1314 namespace N { 1315 // This struct is not equivalent with the other in the prev TU. 1316 struct Arg { double b; }; // -- Field mismatch. 1317 } 1318 using namespace N; 1319 // Explicit instantiation with UNqualified name. 1320 template struct Primary<Arg>; 1321 )", 1322 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1323 EXPECT_FALSE(testStructuralMatch(t)); 1324 } 1325 1326 TEST_F( 1327 StructuralEquivalenceTemplateTest, 1328 ClassTemplSpecWithQualifiedAndNonQualifiedTemplArgsShouldBeEqual) { 1329 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1330 R"( 1331 template <template <class> class T> struct Primary {}; 1332 namespace N { 1333 template <class T> struct Arg; 1334 } 1335 // Explicit instantiation with qualified name. 1336 template struct Primary<N::Arg>; 1337 )", 1338 R"( 1339 template <template <class> class T> struct Primary {}; 1340 namespace N { 1341 template <class T> struct Arg; 1342 } 1343 using namespace N; 1344 // Explicit instantiation with UNqualified name. 1345 template struct Primary<Arg>; 1346 )", 1347 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1348 EXPECT_TRUE(testStructuralMatch(t)); 1349 } 1350 1351 TEST_F( 1352 StructuralEquivalenceTemplateTest, 1353 ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTemplArgs) { 1354 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1355 R"( 1356 template <template <class> class T> struct Primary {}; 1357 namespace N { 1358 template <class T> struct Arg { int a; }; 1359 } 1360 // Explicit instantiation with qualified name. 1361 template struct Primary<N::Arg>; 1362 )", 1363 R"( 1364 template <template <class> class T> struct Primary {}; 1365 namespace N { 1366 // This template is not equivalent with the other in the prev TU. 1367 template <class T> struct Arg { double b; }; // -- Field mismatch. 1368 } 1369 using namespace N; 1370 // Explicit instantiation with UNqualified name. 1371 template struct Primary<Arg>; 1372 )", 1373 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1374 EXPECT_FALSE(testStructuralMatch(t)); 1375 } 1376 1377 TEST_F( 1378 StructuralEquivalenceTemplateTest, 1379 ClassTemplSpecWithInequivalentShadowedTemplArg) { 1380 auto t = makeDecls<ClassTemplateSpecializationDecl>( 1381 R"( 1382 template <template <class> class T> struct Primary {}; 1383 template <class T> struct Arg { int a; }; 1384 // Explicit instantiation with ::Arg 1385 template struct Primary<Arg>; 1386 )", 1387 R"( 1388 template <template <class> class T> struct Primary {}; 1389 template <class T> struct Arg { int a; }; 1390 namespace N { 1391 // This template is not equivalent with the other in the global scope. 1392 template <class T> struct Arg { double b; }; // -- Field mismatch. 1393 // Explicit instantiation with N::Arg which shadows ::Arg 1394 template struct Primary<Arg>; 1395 } 1396 )", 1397 Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary"))); 1398 EXPECT_FALSE(testStructuralMatch(t)); 1399 } 1400 struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest { 1401 llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; 1402 1403 template <typename NodeType, typename MatcherType> 1404 std::pair<NodeType *, NodeType *> 1405 findDeclPair(std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> TU, 1406 MatcherType M) { 1407 NodeType *D0 = FirstDeclMatcher<NodeType>().match(get<0>(TU), M); 1408 NodeType *D1 = FirstDeclMatcher<NodeType>().match(get<1>(TU), M); 1409 return {D0, D1}; 1410 } 1411 1412 template <typename NodeType> 1413 bool isInNonEqCache(std::pair<NodeType *, NodeType *> D) { 1414 return NonEquivalentDecls.count(D) > 0; 1415 } 1416 }; 1417 1418 TEST_F(StructuralEquivalenceCacheTest, SimpleNonEq) { 1419 auto TU = makeTuDecls( 1420 R"( 1421 class A {}; 1422 class B {}; 1423 void x(A, A); 1424 )", 1425 R"( 1426 class A {}; 1427 class B {}; 1428 void x(A, B); 1429 )", 1430 Lang_CXX03); 1431 1432 StructuralEquivalenceContext Ctx( 1433 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), 1434 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); 1435 1436 auto X = findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x"))); 1437 EXPECT_FALSE(Ctx.IsEquivalent(X.first, X.second)); 1438 1439 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1440 TU, cxxRecordDecl(hasName("A"), unless(isImplicit()))))); 1441 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1442 TU, cxxRecordDecl(hasName("B"), unless(isImplicit()))))); 1443 } 1444 1445 TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) { 1446 auto TU = makeTuDecls( 1447 R"( 1448 class A {}; 1449 class B { int i; }; 1450 void x(A *); 1451 void y(A *); 1452 class C { 1453 friend void x(A *); 1454 friend void y(A *); 1455 }; 1456 )", 1457 R"( 1458 class A {}; 1459 class B { int i; }; 1460 void x(A *); 1461 void y(B *); 1462 class C { 1463 friend void x(A *); 1464 friend void y(B *); 1465 }; 1466 )", 1467 Lang_CXX03); 1468 1469 StructuralEquivalenceContext Ctx( 1470 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), 1471 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); 1472 1473 auto C = findDeclPair<CXXRecordDecl>( 1474 TU, cxxRecordDecl(hasName("C"), unless(isImplicit()))); 1475 EXPECT_FALSE(Ctx.IsEquivalent(C.first, C.second)); 1476 1477 EXPECT_FALSE(isInNonEqCache(C)); 1478 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1479 TU, cxxRecordDecl(hasName("A"), unless(isImplicit()))))); 1480 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1481 TU, cxxRecordDecl(hasName("B"), unless(isImplicit()))))); 1482 EXPECT_FALSE(isInNonEqCache( 1483 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x"))))); 1484 EXPECT_FALSE(isInNonEqCache( 1485 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("y"))))); 1486 } 1487 1488 TEST_F(StructuralEquivalenceCacheTest, Cycle) { 1489 auto TU = makeTuDecls( 1490 R"( 1491 class C; 1492 class A { C *c; }; 1493 void x(A *); 1494 class C { 1495 friend void x(A *); 1496 }; 1497 )", 1498 R"( 1499 class C; 1500 class A { C *c; }; 1501 void x(A *); 1502 class C { 1503 friend void x(A *); 1504 }; 1505 )", 1506 Lang_CXX03); 1507 1508 StructuralEquivalenceContext Ctx( 1509 get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), 1510 NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); 1511 1512 auto C = findDeclPair<CXXRecordDecl>( 1513 TU, cxxRecordDecl(hasName("C"), unless(isImplicit()))); 1514 EXPECT_TRUE(Ctx.IsEquivalent(C.first, C.second)); 1515 1516 EXPECT_FALSE(isInNonEqCache(C)); 1517 EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>( 1518 TU, cxxRecordDecl(hasName("A"), unless(isImplicit()))))); 1519 EXPECT_FALSE(isInNonEqCache( 1520 findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x"))))); 1521 } 1522 1523 struct StructuralEquivalenceStmtTest : StructuralEquivalenceTest {}; 1524 1525 /// Fallback matcher to be used only when there is no specific matcher for a 1526 /// Expr subclass. Remove this once all Expr subclasses have their own matcher. 1527 static auto &fallbackExprMatcher = expr; 1528 1529 TEST_F(StructuralEquivalenceStmtTest, AddrLabelExpr) { 1530 auto t = makeWrappedStmts("lbl: &&lbl;", "lbl: &&lbl;", Lang_CXX03, 1531 addrLabelExpr()); 1532 EXPECT_TRUE(testStructuralMatch(t)); 1533 } 1534 1535 TEST_F(StructuralEquivalenceStmtTest, AddrLabelExprDifferentLabel) { 1536 auto t = makeWrappedStmts("lbl1: lbl2: &&lbl1;", "lbl1: lbl2: &&lbl2;", 1537 Lang_CXX03, addrLabelExpr()); 1538 // FIXME: Should be false. LabelDecl are incorrectly matched. 1539 EXPECT_TRUE(testStructuralMatch(t)); 1540 } 1541 1542 static const std::string MemoryOrderSrc = R"( 1543 enum memory_order { 1544 memory_order_relaxed, 1545 memory_order_consume, 1546 memory_order_acquire, 1547 memory_order_release, 1548 memory_order_acq_rel, 1549 memory_order_seq_cst 1550 }; 1551 )"; 1552 1553 TEST_F(StructuralEquivalenceStmtTest, AtomicExpr) { 1554 std::string Prefix = "char a, b; " + MemoryOrderSrc; 1555 auto t = makeStmts( 1556 Prefix + 1557 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }", 1558 Prefix + 1559 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }", 1560 Lang_CXX03, atomicExpr()); 1561 EXPECT_TRUE(testStructuralMatch(t)); 1562 } 1563 1564 TEST_F(StructuralEquivalenceStmtTest, AtomicExprDifferentOp) { 1565 std::string Prefix = "char a, b; " + MemoryOrderSrc; 1566 auto t = makeStmts( 1567 Prefix + 1568 "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }", 1569 Prefix + 1570 "void wrapped() { __atomic_store(&a, &b, memory_order_seq_cst); }", 1571 Lang_CXX03, atomicExpr()); 1572 EXPECT_FALSE(testStructuralMatch(t)); 1573 } 1574 1575 TEST_F(StructuralEquivalenceStmtTest, BinaryOperator) { 1576 auto t = makeWrappedStmts("1 + 1", "1 + 1", Lang_CXX03, binaryOperator()); 1577 EXPECT_TRUE(testStructuralMatch(t)); 1578 } 1579 1580 TEST_F(StructuralEquivalenceStmtTest, BinaryOperatorDifferentOps) { 1581 auto t = makeWrappedStmts("1 + 1", "1 - 1", Lang_CXX03, binaryOperator()); 1582 EXPECT_FALSE(testStructuralMatch(t)); 1583 } 1584 1585 TEST_F(StructuralEquivalenceStmtTest, CallExpr) { 1586 std::string Src = "int call(); int wrapped() { call(); }"; 1587 auto t = makeStmts(Src, Src, Lang_CXX03, callExpr()); 1588 EXPECT_TRUE(testStructuralMatch(t)); 1589 } 1590 1591 TEST_F(StructuralEquivalenceStmtTest, CallExprDifferentCallee) { 1592 std::string FunctionSrc = "int func1(); int func2();\n"; 1593 auto t = makeStmts(FunctionSrc + "void wrapper() { func1(); }", 1594 FunctionSrc + "void wrapper() { func2(); }", Lang_CXX03, 1595 callExpr()); 1596 EXPECT_FALSE(testStructuralMatch(t)); 1597 } 1598 1599 TEST_F(StructuralEquivalenceStmtTest, CharacterLiteral) { 1600 auto t = makeWrappedStmts("'a'", "'a'", Lang_CXX03, characterLiteral()); 1601 EXPECT_TRUE(testStructuralMatch(t)); 1602 } 1603 1604 TEST_F(StructuralEquivalenceStmtTest, CharacterLiteralDifferentValues) { 1605 auto t = makeWrappedStmts("'a'", "'b'", Lang_CXX03, characterLiteral()); 1606 EXPECT_FALSE(testStructuralMatch(t)); 1607 } 1608 1609 TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExpr) { 1610 auto t = makeWrappedStmts("__is_lvalue_expr(1)", "__is_lvalue_expr(1)", 1611 Lang_CXX03, fallbackExprMatcher()); 1612 EXPECT_TRUE(testStructuralMatch(t)); 1613 } 1614 1615 TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExprDifferentKind) { 1616 auto t = makeWrappedStmts("__is_lvalue_expr(1)", "__is_rvalue_expr(1)", 1617 Lang_CXX03, fallbackExprMatcher()); 1618 EXPECT_FALSE(testStructuralMatch(t)); 1619 } 1620 1621 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteral) { 1622 auto t = makeWrappedStmts("1.0", "1.0", Lang_CXX03, fallbackExprMatcher()); 1623 EXPECT_TRUE(testStructuralMatch(t)); 1624 } 1625 1626 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentSpelling) { 1627 auto t = makeWrappedStmts("0x10.1p0", "16.0625", Lang_CXX17, 1628 fallbackExprMatcher()); 1629 // Same value but with different spelling is equivalent. 1630 EXPECT_TRUE(testStructuralMatch(t)); 1631 } 1632 1633 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentType) { 1634 auto t = makeWrappedStmts("1.0", "1.0f", Lang_CXX03, fallbackExprMatcher()); 1635 EXPECT_FALSE(testStructuralMatch(t)); 1636 } 1637 1638 TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentValue) { 1639 auto t = makeWrappedStmts("1.01", "1.0", Lang_CXX03, fallbackExprMatcher()); 1640 EXPECT_FALSE(testStructuralMatch(t)); 1641 } 1642 1643 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSame) { 1644 auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)", 1645 "_Generic(0u, unsigned int: 0, float: 1)", Lang_C99, 1646 genericSelectionExpr()); 1647 EXPECT_TRUE(testStructuralMatch(t)); 1648 } 1649 1650 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSignsDiffer) { 1651 auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)", 1652 "_Generic(0, int: 0, float: 1)", Lang_C99, 1653 genericSelectionExpr()); 1654 EXPECT_FALSE(testStructuralMatch(t)); 1655 } 1656 1657 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprOrderDiffers) { 1658 auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)", 1659 "_Generic(0u, float: 1, unsigned int: 0)", Lang_C99, 1660 genericSelectionExpr()); 1661 EXPECT_FALSE(testStructuralMatch(t)); 1662 } 1663 1664 TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprDependentResultSame) { 1665 auto t = makeStmts( 1666 R"( 1667 template <typename T> 1668 void f() { 1669 T x; 1670 (void)_Generic(x, int: 0, float: 1); 1671 } 1672 void g() { f<int>(); } 1673 )", 1674 R"( 1675 template <typename T> 1676 void f() { 1677 T x; 1678 (void)_Generic(x, int: 0, float: 1); 1679 } 1680 void g() { f<int>(); } 1681 )", 1682 Lang_CXX03, genericSelectionExpr()); 1683 EXPECT_TRUE(testStructuralMatch(t)); 1684 } 1685 1686 TEST_F(StructuralEquivalenceStmtTest, 1687 GenericSelectionExprDependentResultOrderDiffers) { 1688 auto t = makeStmts( 1689 R"( 1690 template <typename T> 1691 void f() { 1692 T x; 1693 (void)_Generic(x, float: 1, int: 0); 1694 } 1695 void g() { f<int>(); } 1696 )", 1697 R"( 1698 template <typename T> 1699 void f() { 1700 T x; 1701 (void)_Generic(x, int: 0, float: 1); 1702 } 1703 void g() { f<int>(); } 1704 )", 1705 Lang_CXX03, genericSelectionExpr()); 1706 1707 EXPECT_FALSE(testStructuralMatch(t)); 1708 } 1709 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteral) { 1710 auto t = makeWrappedStmts("1", "1", Lang_CXX03, integerLiteral()); 1711 EXPECT_TRUE(testStructuralMatch(t)); 1712 } 1713 1714 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentSpelling) { 1715 auto t = makeWrappedStmts("1", "0x1", Lang_CXX03, integerLiteral()); 1716 // Same value but with different spelling is equivalent. 1717 EXPECT_TRUE(testStructuralMatch(t)); 1718 } 1719 1720 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentValue) { 1721 auto t = makeWrappedStmts("1", "2", Lang_CXX03, integerLiteral()); 1722 EXPECT_FALSE(testStructuralMatch(t)); 1723 } 1724 1725 TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentTypes) { 1726 auto t = makeWrappedStmts("1", "1L", Lang_CXX03, integerLiteral()); 1727 EXPECT_FALSE(testStructuralMatch(t)); 1728 } 1729 1730 TEST_F(StructuralEquivalenceStmtTest, MemberExpr) { 1731 std::string ClassSrc = "struct C { int a; int b; };"; 1732 auto t = makeStmts(ClassSrc + "int wrapper() { C c; return c.a; }", 1733 ClassSrc + "int wrapper() { C c; return c.a; }", 1734 Lang_CXX03, memberExpr()); 1735 EXPECT_TRUE(testStructuralMatch(t)); 1736 } 1737 1738 TEST_F(StructuralEquivalenceStmtTest, MemberExprDifferentMember) { 1739 std::string ClassSrc = "struct C { int a; int b; };"; 1740 auto t = makeStmts(ClassSrc + "int wrapper() { C c; return c.a; }", 1741 ClassSrc + "int wrapper() { C c; return c.b; }", 1742 Lang_CXX03, memberExpr()); 1743 EXPECT_FALSE(testStructuralMatch(t)); 1744 } 1745 1746 TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteral) { 1747 auto t = 1748 makeWrappedStmts("@\"a\"", "@\"a\"", Lang_OBJCXX, fallbackExprMatcher()); 1749 EXPECT_TRUE(testStructuralMatch(t)); 1750 } 1751 1752 TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteralDifferentContent) { 1753 auto t = 1754 makeWrappedStmts("@\"a\"", "@\"b\"", Lang_OBJCXX, fallbackExprMatcher()); 1755 EXPECT_FALSE(testStructuralMatch(t)); 1756 } 1757 1758 TEST_F(StructuralEquivalenceStmtTest, StringLiteral) { 1759 auto t = makeWrappedStmts("\"a\"", "\"a\"", Lang_CXX03, stringLiteral()); 1760 EXPECT_TRUE(testStructuralMatch(t)); 1761 } 1762 1763 TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentContent) { 1764 auto t = makeWrappedStmts("\"a\"", "\"b\"", Lang_CXX03, stringLiteral()); 1765 EXPECT_FALSE(testStructuralMatch(t)); 1766 } 1767 1768 TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentLength) { 1769 auto t = makeWrappedStmts("\"a\"", "\"aa\"", Lang_CXX03, stringLiteral()); 1770 EXPECT_FALSE(testStructuralMatch(t)); 1771 } 1772 1773 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExpr) { 1774 auto t = makeWrappedStmts("__is_pod(int)", "__is_pod(int)", Lang_CXX03, 1775 fallbackExprMatcher()); 1776 EXPECT_TRUE(testStructuralMatch(t)); 1777 } 1778 1779 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentType) { 1780 auto t = makeWrappedStmts("__is_pod(int)", "__is_pod(long)", Lang_CXX03, 1781 fallbackExprMatcher()); 1782 EXPECT_FALSE(testStructuralMatch(t)); 1783 } 1784 1785 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTrait) { 1786 auto t = makeWrappedStmts( 1787 "__is_pod(int)", "__is_trivially_constructible(int)", Lang_CXX03, expr()); 1788 EXPECT_FALSE(testStructuralMatch(t)); 1789 } 1790 1791 TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTraits) { 1792 auto t = makeWrappedStmts("__is_constructible(int)", 1793 "__is_constructible(int, int)", Lang_CXX03, expr()); 1794 EXPECT_FALSE(testStructuralMatch(t)); 1795 } 1796 1797 TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExpr) { 1798 auto t = makeWrappedStmts("sizeof(int)", "sizeof(int)", Lang_CXX03, 1799 unaryExprOrTypeTraitExpr()); 1800 EXPECT_TRUE(testStructuralMatch(t)); 1801 } 1802 1803 TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentKind) { 1804 auto t = makeWrappedStmts("sizeof(int)", "alignof(long)", Lang_CXX11, 1805 unaryExprOrTypeTraitExpr()); 1806 EXPECT_FALSE(testStructuralMatch(t)); 1807 } 1808 1809 TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentType) { 1810 auto t = makeWrappedStmts("sizeof(int)", "sizeof(long)", Lang_CXX03, 1811 unaryExprOrTypeTraitExpr()); 1812 EXPECT_FALSE(testStructuralMatch(t)); 1813 } 1814 1815 TEST_F(StructuralEquivalenceStmtTest, UnaryOperator) { 1816 auto t = makeWrappedStmts("+1", "+1", Lang_CXX03, unaryOperator()); 1817 EXPECT_TRUE(testStructuralMatch(t)); 1818 } 1819 1820 TEST_F(StructuralEquivalenceStmtTest, UnaryOperatorDifferentOps) { 1821 auto t = makeWrappedStmts("+1", "-1", Lang_CXX03, unaryOperator()); 1822 EXPECT_FALSE(testStructuralMatch(t)); 1823 } 1824 1825 } // end namespace ast_matchers 1826 } // end namespace clang 1827