1 //===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Tests for the correct import of AST nodes from one AST context to another. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ADT/StringMap.h" 14 15 #include "clang/AST/DeclContextInternals.h" 16 17 #include "ASTImporterFixtures.h" 18 #include "MatchVerifier.h" 19 20 namespace clang { 21 namespace ast_matchers { 22 23 using internal::Matcher; 24 using internal::BindableMatcher; 25 using llvm::StringMap; 26 27 // Base class for those tests which use the family of `testImport` functions. 28 class TestImportBase : public CompilerOptionSpecificTest, 29 public ::testing::WithParamInterface<ArgVector> { 30 31 template <typename NodeType> 32 llvm::Expected<NodeType> importNode(ASTUnit *From, ASTUnit *To, 33 ASTImporter &Importer, NodeType Node) { 34 ASTContext &ToCtx = To->getASTContext(); 35 36 // Add 'From' file to virtual file system so importer can 'find' it 37 // while importing SourceLocations. It is safe to add same file multiple 38 // times - it just isn't replaced. 39 StringRef FromFileName = From->getMainFileName(); 40 createVirtualFileIfNeeded(To, FromFileName, 41 From->getBufferForFile(FromFileName)); 42 43 auto Imported = Importer.Import(Node); 44 45 if (Imported) { 46 // This should dump source locations and assert if some source locations 47 // were not imported. 48 SmallString<1024> ImportChecker; 49 llvm::raw_svector_ostream ToNothing(ImportChecker); 50 ToCtx.getTranslationUnitDecl()->print(ToNothing); 51 52 // This traverses the AST to catch certain bugs like poorly or not 53 // implemented subtrees. 54 (*Imported)->dump(ToNothing); 55 } 56 57 return Imported; 58 } 59 60 template <typename NodeType> 61 testing::AssertionResult 62 testImport(const std::string &FromCode, const ArgVector &FromArgs, 63 const std::string &ToCode, const ArgVector &ToArgs, 64 MatchVerifier<NodeType> &Verifier, 65 const BindableMatcher<NodeType> &SearchMatcher, 66 const BindableMatcher<NodeType> &VerificationMatcher) { 67 const char *const InputFileName = "input.cc"; 68 const char *const OutputFileName = "output.cc"; 69 70 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs( 71 FromCode, FromArgs, InputFileName), 72 ToAST = tooling::buildASTFromCodeWithArgs( 73 ToCode, ToArgs, OutputFileName); 74 75 ASTContext &FromCtx = FromAST->getASTContext(), 76 &ToCtx = ToAST->getASTContext(); 77 78 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx, 79 FromAST->getFileManager(), false); 80 81 auto FoundNodes = match(SearchMatcher, FromCtx); 82 if (FoundNodes.size() != 1) 83 return testing::AssertionFailure() 84 << "Multiple potential nodes were found!"; 85 86 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes); 87 if (!ToImport) 88 return testing::AssertionFailure() << "Node type mismatch!"; 89 90 // Sanity check: the node being imported should match in the same way as 91 // the result node. 92 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher); 93 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher)); 94 95 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport); 96 if (!Imported) { 97 std::string ErrorText; 98 handleAllErrors( 99 Imported.takeError(), 100 [&ErrorText](const ImportError &Err) { ErrorText = Err.message(); }); 101 return testing::AssertionFailure() 102 << "Import failed, error: \"" << ErrorText << "\"!"; 103 } 104 105 return Verifier.match(*Imported, WrapperMatcher); 106 } 107 108 template <typename NodeType> 109 testing::AssertionResult 110 testImport(const std::string &FromCode, const ArgVector &FromArgs, 111 const std::string &ToCode, const ArgVector &ToArgs, 112 MatchVerifier<NodeType> &Verifier, 113 const BindableMatcher<NodeType> &VerificationMatcher) { 114 return testImport( 115 FromCode, FromArgs, ToCode, ToArgs, Verifier, 116 translationUnitDecl( 117 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))), 118 VerificationMatcher); 119 } 120 121 protected: 122 ArgVector getExtraArgs() const override { return GetParam(); } 123 124 public: 125 126 /// Test how AST node named "declToImport" located in the translation unit 127 /// of "FromCode" virtual file is imported to "ToCode" virtual file. 128 /// The verification is done by running AMatcher over the imported node. 129 template <typename NodeType, typename MatcherType> 130 void testImport(const std::string &FromCode, Language FromLang, 131 const std::string &ToCode, Language ToLang, 132 MatchVerifier<NodeType> &Verifier, 133 const MatcherType &AMatcher) { 134 ArgVector FromArgs = getArgVectorForLanguage(FromLang), 135 ToArgs = getArgVectorForLanguage(ToLang); 136 EXPECT_TRUE( 137 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher)); 138 } 139 140 struct ImportAction { 141 StringRef FromFilename; 142 StringRef ToFilename; 143 // FIXME: Generalize this to support other node kinds. 144 BindableMatcher<Decl> ImportPredicate; 145 146 ImportAction(StringRef FromFilename, StringRef ToFilename, 147 DeclarationMatcher ImportPredicate) 148 : FromFilename(FromFilename), ToFilename(ToFilename), 149 ImportPredicate(ImportPredicate) {} 150 151 ImportAction(StringRef FromFilename, StringRef ToFilename, 152 const std::string &DeclName) 153 : FromFilename(FromFilename), ToFilename(ToFilename), 154 ImportPredicate(namedDecl(hasName(DeclName))) {} 155 }; 156 157 using SingleASTUnit = std::unique_ptr<ASTUnit>; 158 using AllASTUnits = StringMap<SingleASTUnit>; 159 160 struct CodeEntry { 161 std::string CodeSample; 162 Language Lang; 163 }; 164 165 using CodeFiles = StringMap<CodeEntry>; 166 167 /// Builds an ASTUnit for one potential compile options set. 168 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const { 169 ArgVector Args = getArgVectorForLanguage(CE.Lang); 170 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName); 171 EXPECT_TRUE(AST.get()); 172 return AST; 173 } 174 175 /// Test an arbitrary sequence of imports for a set of given in-memory files. 176 /// The verification is done by running VerificationMatcher against a 177 /// specified AST node inside of one of given files. 178 /// \param CodeSamples Map whose key is the file name and the value is the 179 /// file content. 180 /// \param ImportActions Sequence of imports. Each import in sequence 181 /// specifies "from file" and "to file" and a matcher that is used for 182 /// searching a declaration for import in "from file". 183 /// \param FileForFinalCheck Name of virtual file for which the final check is 184 /// applied. 185 /// \param FinalSelectPredicate Matcher that specifies the AST node in the 186 /// FileForFinalCheck for which the verification will be done. 187 /// \param VerificationMatcher Matcher that will be used for verification 188 /// after all imports in sequence are done. 189 void testImportSequence(const CodeFiles &CodeSamples, 190 const std::vector<ImportAction> &ImportActions, 191 StringRef FileForFinalCheck, 192 BindableMatcher<Decl> FinalSelectPredicate, 193 BindableMatcher<Decl> VerificationMatcher) { 194 AllASTUnits AllASTs; 195 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>; 196 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers; 197 198 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) { 199 if (!AllASTs.count(Filename)) { 200 auto Found = CodeSamples.find(Filename); 201 assert(Found != CodeSamples.end() && "Wrong file for import!"); 202 AllASTs[Filename] = createASTUnit(Filename, Found->getValue()); 203 } 204 }; 205 206 for (const ImportAction &Action : ImportActions) { 207 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename; 208 GenASTsIfNeeded(FromFile); 209 GenASTsIfNeeded(ToFile); 210 211 ASTUnit *From = AllASTs[FromFile].get(); 212 ASTUnit *To = AllASTs[ToFile].get(); 213 214 // Create a new importer if needed. 215 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}]; 216 if (!ImporterRef) 217 ImporterRef.reset(new ASTImporter( 218 To->getASTContext(), To->getFileManager(), From->getASTContext(), 219 From->getFileManager(), false)); 220 221 // Find the declaration and import it. 222 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID), 223 From->getASTContext()); 224 EXPECT_TRUE(FoundDecl.size() == 1); 225 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl); 226 auto Imported = importNode(From, To, *ImporterRef, ToImport); 227 EXPECT_TRUE(static_cast<bool>(Imported)); 228 if (!Imported) 229 llvm::consumeError(Imported.takeError()); 230 } 231 232 // Find the declaration and import it. 233 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID), 234 AllASTs[FileForFinalCheck]->getASTContext()); 235 EXPECT_TRUE(FoundDecl.size() == 1); 236 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl); 237 MatchVerifier<Decl> Verifier; 238 EXPECT_TRUE( 239 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher))); 240 } 241 }; 242 243 template <typename T> RecordDecl *getRecordDecl(T *D) { 244 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr()); 245 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl(); 246 } 247 248 struct ImportExpr : TestImportBase {}; 249 struct ImportType : TestImportBase {}; 250 struct ImportDecl : TestImportBase {}; 251 252 struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {}; 253 254 TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) { 255 Decl *FromTU = getTuDecl("void f();", Lang_CXX); 256 auto Pattern = functionDecl(hasName("f")); 257 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 258 259 auto Redecls = getCanonicalForwardRedeclChain(D0); 260 ASSERT_EQ(Redecls.size(), 1u); 261 EXPECT_EQ(D0, Redecls[0]); 262 } 263 264 TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) { 265 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); 266 auto Pattern = functionDecl(hasName("f")); 267 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 268 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 269 FunctionDecl *D1 = D2->getPreviousDecl(); 270 271 auto Redecls = getCanonicalForwardRedeclChain(D0); 272 ASSERT_EQ(Redecls.size(), 3u); 273 EXPECT_EQ(D0, Redecls[0]); 274 EXPECT_EQ(D1, Redecls[1]); 275 EXPECT_EQ(D2, Redecls[2]); 276 } 277 278 TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) { 279 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); 280 auto Pattern = functionDecl(hasName("f")); 281 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 282 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 283 FunctionDecl *D1 = D2->getPreviousDecl(); 284 285 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0); 286 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1); 287 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2); 288 289 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1)); 290 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2)); 291 } 292 293 namespace { 294 struct RedirectingImporter : public ASTImporter { 295 using ASTImporter::ASTImporter; 296 297 protected: 298 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override { 299 auto *ND = dyn_cast<NamedDecl>(FromD); 300 if (!ND || ND->getName() != "shouldNotBeImported") 301 return ASTImporter::ImportImpl(FromD); 302 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) { 303 if (auto *ND = dyn_cast<NamedDecl>(D)) 304 if (ND->getName() == "realDecl") { 305 RegisterImportedDecl(FromD, ND); 306 return ND; 307 } 308 } 309 return ASTImporter::ImportImpl(FromD); 310 } 311 }; 312 313 } // namespace 314 315 struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase { 316 RedirectingImporterTest() { 317 Creator = [](ASTContext &ToContext, FileManager &ToFileManager, 318 ASTContext &FromContext, FileManager &FromFileManager, 319 bool MinimalImport, 320 const std::shared_ptr<ASTImporterSharedState> &SharedState) { 321 return new RedirectingImporter(ToContext, ToFileManager, FromContext, 322 FromFileManager, MinimalImport, 323 SharedState); 324 }; 325 } 326 }; 327 328 // Test that an ASTImporter subclass can intercept an import call. 329 TEST_P(RedirectingImporterTest, InterceptImport) { 330 Decl *From, *To; 331 std::tie(From, To) = 332 getImportedDecl("class shouldNotBeImported {};", Lang_CXX, 333 "class realDecl {};", Lang_CXX, "shouldNotBeImported"); 334 auto *Imported = cast<CXXRecordDecl>(To); 335 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl"); 336 337 // Make sure our importer prevented the importing of the decl. 338 auto *ToTU = Imported->getTranslationUnitDecl(); 339 auto Pattern = functionDecl(hasName("shouldNotBeImported")); 340 unsigned count = 341 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern); 342 EXPECT_EQ(0U, count); 343 } 344 345 // Test that when we indirectly import a declaration the custom ASTImporter 346 // is still intercepting the import. 347 TEST_P(RedirectingImporterTest, InterceptIndirectImport) { 348 Decl *From, *To; 349 std::tie(From, To) = 350 getImportedDecl("class shouldNotBeImported {};" 351 "class F { shouldNotBeImported f; };", 352 Lang_CXX, "class realDecl {};", Lang_CXX, "F"); 353 354 // Make sure our ASTImporter prevented the importing of the decl. 355 auto *ToTU = To->getTranslationUnitDecl(); 356 auto Pattern = functionDecl(hasName("shouldNotBeImported")); 357 unsigned count = 358 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern); 359 EXPECT_EQ(0U, count); 360 } 361 362 struct ImportPath : ASTImporterOptionSpecificTestBase { 363 Decl *FromTU; 364 FunctionDecl *D0, *D1, *D2; 365 ImportPath() { 366 FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); 367 auto Pattern = functionDecl(hasName("f")); 368 D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 369 D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 370 D1 = D2->getPreviousDecl(); 371 } 372 }; 373 374 TEST_P(ImportPath, Push) { 375 ASTImporter::ImportPathTy path; 376 path.push(D0); 377 EXPECT_FALSE(path.hasCycleAtBack()); 378 } 379 380 TEST_P(ImportPath, SmallCycle) { 381 ASTImporter::ImportPathTy path; 382 path.push(D0); 383 path.push(D0); 384 EXPECT_TRUE(path.hasCycleAtBack()); 385 path.pop(); 386 EXPECT_FALSE(path.hasCycleAtBack()); 387 path.push(D0); 388 EXPECT_TRUE(path.hasCycleAtBack()); 389 } 390 391 TEST_P(ImportPath, GetSmallCycle) { 392 ASTImporter::ImportPathTy path; 393 path.push(D0); 394 path.push(D0); 395 EXPECT_TRUE(path.hasCycleAtBack()); 396 std::array<Decl* ,2> Res; 397 int i = 0; 398 for (Decl *Di : path.getCycleAtBack()) { 399 Res[i++] = Di; 400 } 401 ASSERT_EQ(i, 2); 402 EXPECT_EQ(Res[0], D0); 403 EXPECT_EQ(Res[1], D0); 404 } 405 406 TEST_P(ImportPath, GetCycle) { 407 ASTImporter::ImportPathTy path; 408 path.push(D0); 409 path.push(D1); 410 path.push(D2); 411 path.push(D0); 412 EXPECT_TRUE(path.hasCycleAtBack()); 413 std::array<Decl* ,4> Res; 414 int i = 0; 415 for (Decl *Di : path.getCycleAtBack()) { 416 Res[i++] = Di; 417 } 418 ASSERT_EQ(i, 4); 419 EXPECT_EQ(Res[0], D0); 420 EXPECT_EQ(Res[1], D2); 421 EXPECT_EQ(Res[2], D1); 422 EXPECT_EQ(Res[3], D0); 423 } 424 425 TEST_P(ImportPath, CycleAfterCycle) { 426 ASTImporter::ImportPathTy path; 427 path.push(D0); 428 path.push(D1); 429 path.push(D0); 430 path.push(D1); 431 path.push(D2); 432 path.push(D0); 433 EXPECT_TRUE(path.hasCycleAtBack()); 434 std::array<Decl* ,4> Res; 435 int i = 0; 436 for (Decl *Di : path.getCycleAtBack()) { 437 Res[i++] = Di; 438 } 439 ASSERT_EQ(i, 4); 440 EXPECT_EQ(Res[0], D0); 441 EXPECT_EQ(Res[1], D2); 442 EXPECT_EQ(Res[2], D1); 443 EXPECT_EQ(Res[3], D0); 444 445 path.pop(); 446 path.pop(); 447 path.pop(); 448 EXPECT_TRUE(path.hasCycleAtBack()); 449 i = 0; 450 for (Decl *Di : path.getCycleAtBack()) { 451 Res[i++] = Di; 452 } 453 ASSERT_EQ(i, 3); 454 EXPECT_EQ(Res[0], D0); 455 EXPECT_EQ(Res[1], D1); 456 EXPECT_EQ(Res[2], D0); 457 458 path.pop(); 459 EXPECT_FALSE(path.hasCycleAtBack()); 460 } 461 462 TEST_P(ImportExpr, ImportStringLiteral) { 463 MatchVerifier<Decl> Verifier; 464 testImport( 465 "void declToImport() { (void)\"foo\"; }", 466 Lang_CXX, "", Lang_CXX, Verifier, 467 functionDecl(hasDescendant( 468 stringLiteral(hasType(asString("const char [4]")))))); 469 testImport( 470 "void declToImport() { (void)L\"foo\"; }", 471 Lang_CXX, "", Lang_CXX, Verifier, 472 functionDecl(hasDescendant( 473 stringLiteral(hasType(asString("const wchar_t [4]")))))); 474 testImport( 475 "void declToImport() { (void) \"foo\" \"bar\"; }", 476 Lang_CXX, "", Lang_CXX, Verifier, 477 functionDecl(hasDescendant( 478 stringLiteral(hasType(asString("const char [7]")))))); 479 } 480 481 TEST_P(ImportExpr, ImportChooseExpr) { 482 MatchVerifier<Decl> Verifier; 483 484 // This case tests C code that is not condition-dependent and has a true 485 // condition. 486 testImport( 487 "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }", 488 Lang_C, "", Lang_C, Verifier, 489 functionDecl(hasDescendant(chooseExpr()))); 490 } 491 492 TEST_P(ImportExpr, ImportGNUNullExpr) { 493 MatchVerifier<Decl> Verifier; 494 testImport( 495 "void declToImport() { (void)__null; }", 496 Lang_CXX, "", Lang_CXX, Verifier, 497 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger()))))); 498 } 499 500 TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) { 501 MatchVerifier<Decl> Verifier; 502 testImport( 503 "void declToImport() { (void)nullptr; }", 504 Lang_CXX11, "", Lang_CXX11, Verifier, 505 functionDecl(hasDescendant(cxxNullPtrLiteralExpr()))); 506 } 507 508 509 TEST_P(ImportExpr, ImportFloatinglLiteralExpr) { 510 MatchVerifier<Decl> Verifier; 511 testImport( 512 "void declToImport() { (void)1.0; }", 513 Lang_C, "", Lang_C, Verifier, 514 functionDecl(hasDescendant( 515 floatLiteral(equals(1.0), hasType(asString("double")))))); 516 testImport( 517 "void declToImport() { (void)1.0e-5f; }", 518 Lang_C, "", Lang_C, Verifier, 519 functionDecl(hasDescendant( 520 floatLiteral(equals(1.0e-5f), hasType(asString("float")))))); 521 } 522 523 TEST_P(ImportExpr, ImportImaginaryLiteralExpr) { 524 MatchVerifier<Decl> Verifier; 525 testImport( 526 "void declToImport() { (void)1.0i; }", 527 Lang_CXX14, "", Lang_CXX14, Verifier, 528 functionDecl(hasDescendant(imaginaryLiteral()))); 529 } 530 531 TEST_P(ImportExpr, ImportCompoundLiteralExpr) { 532 MatchVerifier<Decl> Verifier; 533 testImport( 534 "void declToImport() {" 535 " struct s { int x; long y; unsigned z; }; " 536 " (void)(struct s){ 42, 0L, 1U }; }", 537 Lang_CXX, "", Lang_CXX, Verifier, 538 functionDecl(hasDescendant( 539 compoundLiteralExpr( 540 hasType(asString("struct s")), 541 has(initListExpr( 542 hasType(asString("struct s")), 543 has(integerLiteral( 544 equals(42), hasType(asString("int")))), 545 has(integerLiteral( 546 equals(0), hasType(asString("long")))), 547 has(integerLiteral( 548 equals(1), hasType(asString("unsigned int")))))))))); 549 } 550 551 TEST_P(ImportExpr, ImportCXXThisExpr) { 552 MatchVerifier<Decl> Verifier; 553 testImport( 554 "class declToImport { void f() { (void)this; } };", 555 Lang_CXX, "", Lang_CXX, Verifier, 556 cxxRecordDecl( 557 hasMethod( 558 hasDescendant( 559 cxxThisExpr( 560 hasType( 561 asString("class declToImport *"))))))); 562 } 563 564 TEST_P(ImportExpr, ImportAtomicExpr) { 565 MatchVerifier<Decl> Verifier; 566 testImport( 567 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", 568 Lang_C, "", Lang_C, Verifier, 569 functionDecl(hasDescendant( 570 atomicExpr( 571 has(ignoringParenImpCasts( 572 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))), 573 hasType(asString("int *"))))), 574 has(integerLiteral(equals(1), hasType(asString("int")))))))); 575 } 576 577 TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) { 578 MatchVerifier<Decl> Verifier; 579 testImport( 580 "void declToImport() { loop: goto loop; (void)&&loop; }", 581 Lang_C, "", Lang_C, Verifier, 582 functionDecl( 583 hasDescendant( 584 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))), 585 hasDescendant( 586 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop"))))))); 587 } 588 589 AST_MATCHER_P(TemplateDecl, hasTemplateDecl, 590 internal::Matcher<NamedDecl>, InnerMatcher) { 591 const NamedDecl *Template = Node.getTemplatedDecl(); 592 return Template && InnerMatcher.matches(*Template, Finder, Builder); 593 } 594 595 TEST_P(ImportExpr, ImportParenListExpr) { 596 MatchVerifier<Decl> Verifier; 597 testImport( 598 "template<typename T> class dummy { void f() { dummy X(*this); } };" 599 "typedef dummy<int> declToImport;" 600 "template class dummy<int>;", 601 Lang_CXX, "", Lang_CXX, Verifier, 602 typedefDecl(hasType(templateSpecializationType( 603 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate( 604 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf( 605 hasName("f"), 606 hasBody(compoundStmt(has(declStmt(hasSingleDecl( 607 varDecl(hasInitializer(parenListExpr(has(unaryOperator( 608 hasOperatorName("*"), 609 hasUnaryOperand(cxxThisExpr()))))))))))))))))))))))); 610 } 611 612 TEST_P(ImportExpr, ImportSwitch) { 613 MatchVerifier<Decl> Verifier; 614 testImport( 615 "void declToImport() { int b; switch (b) { case 1: break; } }", 616 Lang_C, "", Lang_C, Verifier, 617 functionDecl(hasDescendant( 618 switchStmt(has(compoundStmt(has(caseStmt()))))))); 619 } 620 621 TEST_P(ImportExpr, ImportStmtExpr) { 622 MatchVerifier<Decl> Verifier; 623 testImport( 624 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }", 625 Lang_C, "", Lang_C, Verifier, 626 functionDecl(hasDescendant( 627 varDecl( 628 hasName("C"), 629 hasType(asString("int")), 630 hasInitializer( 631 stmtExpr( 632 hasAnySubstatement(declStmt(hasSingleDecl( 633 varDecl( 634 hasName("X"), 635 hasType(asString("int")), 636 hasInitializer( 637 integerLiteral(equals(4))))))), 638 hasDescendant( 639 implicitCastExpr()))))))); 640 } 641 642 TEST_P(ImportExpr, ImportConditionalOperator) { 643 MatchVerifier<Decl> Verifier; 644 testImport( 645 "void declToImport() { (void)(true ? 1 : -5); }", 646 Lang_CXX, "", Lang_CXX, Verifier, 647 functionDecl(hasDescendant( 648 conditionalOperator( 649 hasCondition(cxxBoolLiteral(equals(true))), 650 hasTrueExpression(integerLiteral(equals(1))), 651 hasFalseExpression( 652 unaryOperator(hasUnaryOperand(integerLiteral(equals(5)))))) 653 ))); 654 } 655 656 TEST_P(ImportExpr, ImportBinaryConditionalOperator) { 657 MatchVerifier<Decl> Verifier; 658 testImport( 659 "void declToImport() { (void)(1 ?: -5); }", 660 Lang_CXX, "", Lang_CXX, Verifier, 661 functionDecl(hasDescendant( 662 binaryConditionalOperator( 663 hasCondition( 664 implicitCastExpr( 665 hasSourceExpression(opaqueValueExpr( 666 hasSourceExpression(integerLiteral(equals(1))))), 667 hasType(booleanType()))), 668 hasTrueExpression( 669 opaqueValueExpr( 670 hasSourceExpression(integerLiteral(equals(1))))), 671 hasFalseExpression( 672 unaryOperator( 673 hasOperatorName("-"), 674 hasUnaryOperand(integerLiteral(equals(5))))))))); 675 } 676 677 TEST_P(ImportExpr, ImportDesignatedInitExpr) { 678 MatchVerifier<Decl> Verifier; 679 testImport( 680 "void declToImport() {" 681 " struct point { double x; double y; };" 682 " struct point ptarray[10] = " 683 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }", 684 Lang_C, "", Lang_C, Verifier, 685 functionDecl(hasDescendant( 686 initListExpr( 687 has(designatedInitExpr( 688 designatorCountIs(2), 689 hasDescendant(floatLiteral(equals(1.0))), 690 hasDescendant(integerLiteral(equals(2))))), 691 has(designatedInitExpr( 692 designatorCountIs(2), 693 hasDescendant(floatLiteral(equals(2.0))), 694 hasDescendant(integerLiteral(equals(2))))), 695 has(designatedInitExpr( 696 designatorCountIs(2), 697 hasDescendant(floatLiteral(equals(1.0))), 698 hasDescendant(integerLiteral(equals(0))))))))); 699 } 700 701 TEST_P(ImportExpr, ImportPredefinedExpr) { 702 MatchVerifier<Decl> Verifier; 703 // __func__ expands as StringLiteral("declToImport") 704 testImport( 705 "void declToImport() { (void)__func__; }", 706 Lang_CXX, "", Lang_CXX, Verifier, 707 functionDecl(hasDescendant( 708 predefinedExpr( 709 hasType( 710 asString("const char [13]")), 711 has(stringLiteral(hasType( 712 asString("const char [13]")))))))); 713 } 714 715 TEST_P(ImportExpr, ImportInitListExpr) { 716 MatchVerifier<Decl> Verifier; 717 testImport( 718 "void declToImport() {" 719 " struct point { double x; double y; };" 720 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0," 721 " [0].x = 1.0 }; }", 722 Lang_CXX, "", Lang_CXX, Verifier, 723 functionDecl(hasDescendant( 724 initListExpr( 725 has( 726 cxxConstructExpr( 727 requiresZeroInitialization())), 728 has( 729 initListExpr( 730 hasType(asString("struct point")), 731 has(floatLiteral(equals(1.0))), 732 has(implicitValueInitExpr( 733 hasType(asString("double")))))), 734 has( 735 initListExpr( 736 hasType(asString("struct point")), 737 has(floatLiteral(equals(2.0))), 738 has(floatLiteral(equals(1.0))))))))); 739 } 740 741 742 const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr; 743 744 TEST_P(ImportExpr, ImportVAArgExpr) { 745 MatchVerifier<Decl> Verifier; 746 testImport( 747 "void declToImport(__builtin_va_list list, ...) {" 748 " (void)__builtin_va_arg(list, int); }", 749 Lang_CXX, "", Lang_CXX, Verifier, 750 functionDecl(hasDescendant( 751 cStyleCastExpr(hasSourceExpression(vaArgExpr()))))); 752 } 753 754 TEST_P(ImportExpr, CXXTemporaryObjectExpr) { 755 MatchVerifier<Decl> Verifier; 756 testImport( 757 "struct C {};" 758 "void declToImport() { C c = C(); }", 759 Lang_CXX, "", Lang_CXX, Verifier, 760 functionDecl(hasDescendant( 761 exprWithCleanups(has(cxxConstructExpr( 762 has(materializeTemporaryExpr(has(implicitCastExpr( 763 has(cxxTemporaryObjectExpr()))))))))))); 764 } 765 766 TEST_P(ImportType, ImportAtomicType) { 767 MatchVerifier<Decl> Verifier; 768 testImport( 769 "void declToImport() { typedef _Atomic(int) a_int; }", 770 Lang_CXX11, "", Lang_CXX11, Verifier, 771 functionDecl(hasDescendant(typedefDecl(has(atomicType()))))); 772 } 773 774 TEST_P(ImportDecl, ImportFunctionTemplateDecl) { 775 MatchVerifier<Decl> Verifier; 776 testImport( 777 "template <typename T> void declToImport() { };", 778 Lang_CXX, "", Lang_CXX, Verifier, 779 functionTemplateDecl()); 780 } 781 782 TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) { 783 MatchVerifier<Decl> Verifier; 784 testImport( 785 "template <typename T> struct C { T t; };" 786 "template <typename T> void declToImport() {" 787 " C<T> d;" 788 " (void)d.t;" 789 "}" 790 "void instantiate() { declToImport<int>(); }", 791 Lang_CXX, "", Lang_CXX, Verifier, 792 functionTemplateDecl(hasDescendant( 793 cStyleCastExpr(has(cxxDependentScopeMemberExpr()))))); 794 testImport( 795 "template <typename T> struct C { T t; };" 796 "template <typename T> void declToImport() {" 797 " C<T> d;" 798 " (void)(&d)->t;" 799 "}" 800 "void instantiate() { declToImport<int>(); }", 801 Lang_CXX, "", Lang_CXX, Verifier, 802 functionTemplateDecl(hasDescendant( 803 cStyleCastExpr(has(cxxDependentScopeMemberExpr()))))); 804 } 805 806 TEST_P(ImportType, ImportTypeAliasTemplate) { 807 MatchVerifier<Decl> Verifier; 808 testImport( 809 "template <int K>" 810 "struct dummy { static const int i = K; };" 811 "template <int K> using dummy2 = dummy<K>;" 812 "int declToImport() { return dummy2<3>::i; }", 813 Lang_CXX11, "", Lang_CXX11, Verifier, 814 functionDecl( 815 hasDescendant(implicitCastExpr(has(declRefExpr()))), 816 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl())))))); 817 } 818 819 const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl> 820 varTemplateSpecializationDecl; 821 822 TEST_P(ImportDecl, ImportVarTemplate) { 823 MatchVerifier<Decl> Verifier; 824 testImport( 825 "template <typename T>" 826 "T pi = T(3.1415926535897932385L);" 827 "void declToImport() { (void)pi<int>; }", 828 Lang_CXX14, "", Lang_CXX14, Verifier, 829 functionDecl( 830 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))), 831 unless(hasAncestor(translationUnitDecl(has(varDecl( 832 hasName("pi"), unless(varTemplateSpecializationDecl())))))))); 833 } 834 835 TEST_P(ImportType, ImportPackExpansion) { 836 MatchVerifier<Decl> Verifier; 837 testImport( 838 "template <typename... Args>" 839 "struct dummy {" 840 " dummy(Args... args) {}" 841 " static const int i = 4;" 842 "};" 843 "int declToImport() { return dummy<int>::i; }", 844 Lang_CXX11, "", Lang_CXX11, Verifier, 845 functionDecl(hasDescendant( 846 returnStmt(has(implicitCastExpr(has(declRefExpr()))))))); 847 } 848 849 const internal::VariadicDynCastAllOfMatcher<Type, 850 DependentTemplateSpecializationType> 851 dependentTemplateSpecializationType; 852 853 TEST_P(ImportType, ImportDependentTemplateSpecialization) { 854 MatchVerifier<Decl> Verifier; 855 testImport( 856 "template<typename T>" 857 "struct A;" 858 "template<typename T>" 859 "struct declToImport {" 860 " typename A<T>::template B<T> a;" 861 "};", 862 Lang_CXX, "", Lang_CXX, Verifier, 863 classTemplateDecl(has(cxxRecordDecl(has( 864 fieldDecl(hasType(dependentTemplateSpecializationType()))))))); 865 } 866 867 const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr> 868 sizeOfPackExpr; 869 870 TEST_P(ImportExpr, ImportSizeOfPackExpr) { 871 MatchVerifier<Decl> Verifier; 872 testImport( 873 "template <typename... Ts>" 874 "void declToImport() {" 875 " const int i = sizeof...(Ts);" 876 "};" 877 "void g() { declToImport<int>(); }", 878 Lang_CXX11, "", Lang_CXX11, Verifier, 879 functionTemplateDecl(hasDescendant(sizeOfPackExpr()))); 880 testImport( 881 "template <typename... Ts>" 882 "using X = int[sizeof...(Ts)];" 883 "template <typename... Us>" 884 "struct Y {" 885 " X<Us..., int, double, int, Us...> f;" 886 "};" 887 "Y<float, int> declToImport;", 888 Lang_CXX11, "", Lang_CXX11, Verifier, 889 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType( 890 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7)))))))))); 891 } 892 893 /// \brief Matches __builtin_types_compatible_p: 894 /// GNU extension to check equivalent types 895 /// Given 896 /// \code 897 /// __builtin_types_compatible_p(int, int) 898 /// \endcode 899 // will generate TypeTraitExpr <...> 'int' 900 const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr; 901 902 TEST_P(ImportExpr, ImportTypeTraitExpr) { 903 MatchVerifier<Decl> Verifier; 904 testImport( 905 "void declToImport() { " 906 " (void)__builtin_types_compatible_p(int, int);" 907 "}", 908 Lang_C, "", Lang_C, Verifier, 909 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int")))))); 910 } 911 912 const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr; 913 914 TEST_P(ImportExpr, ImportCXXTypeidExpr) { 915 MatchVerifier<Decl> Verifier; 916 testImport( 917 "namespace std { class type_info {}; }" 918 "void declToImport() {" 919 " int x;" 920 " auto a = typeid(int); auto b = typeid(x);" 921 "}", 922 Lang_CXX11, "", Lang_CXX11, Verifier, 923 functionDecl( 924 hasDescendant(varDecl( 925 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))), 926 hasDescendant(varDecl( 927 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr())))))); 928 } 929 930 TEST_P(ImportExpr, ImportTypeTraitExprValDep) { 931 MatchVerifier<Decl> Verifier; 932 testImport( 933 "template<typename T> struct declToImport {" 934 " void m() { (void)__is_pod(T); }" 935 "};" 936 "void f() { declToImport<int>().m(); }", 937 Lang_CXX11, "", Lang_CXX11, Verifier, 938 classTemplateDecl(has(cxxRecordDecl(has( 939 functionDecl(hasDescendant( 940 typeTraitExpr(hasType(booleanType()))))))))); 941 } 942 943 TEST_P(ImportDecl, ImportRecordDeclInFunc) { 944 MatchVerifier<Decl> Verifier; 945 testImport("int declToImport() { " 946 " struct data_t {int a;int b;};" 947 " struct data_t d;" 948 " return 0;" 949 "}", 950 Lang_C, "", Lang_C, Verifier, 951 functionDecl(hasBody(compoundStmt( 952 has(declStmt(hasSingleDecl(varDecl(hasName("d"))))))))); 953 } 954 955 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) { 956 Decl *FromTU = getTuDecl("int declToImport() { " 957 " struct data_t {int a;int b;};" 958 " struct data_t d;" 959 " return 0;" 960 "}", 961 Lang_C, "input.c"); 962 auto *FromVar = 963 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d"))); 964 ASSERT_TRUE(FromVar); 965 auto ToType = 966 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C); 967 EXPECT_FALSE(ToType.isNull()); 968 } 969 970 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) { 971 // This construct is not supported by ASTImporter. 972 Decl *FromTU = getTuDecl( 973 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }", 974 Lang_C, "input.c"); 975 auto *From = FirstDeclMatcher<FunctionDecl>().match( 976 FromTU, functionDecl(hasName("declToImport"))); 977 ASSERT_TRUE(From); 978 auto *To = Import(From, Lang_C); 979 EXPECT_EQ(To, nullptr); 980 } 981 982 TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) { 983 Decl *FromTU = getTuDecl( 984 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n" 985 "int declToImport(){ return NONAME_SIZEOF(int); }", 986 Lang_C, "input.c"); 987 auto *From = FirstDeclMatcher<FunctionDecl>().match( 988 FromTU, functionDecl(hasName("declToImport"))); 989 ASSERT_TRUE(From); 990 auto *To = Import(From, Lang_C); 991 ASSERT_TRUE(To); 992 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match( 993 To, functionDecl(hasName("declToImport"), 994 hasDescendant(unaryExprOrTypeTraitExpr())))); 995 } 996 997 TEST_P(ASTImporterOptionSpecificTestBase, 998 ImportRecordDeclInFuncParamsFromMacro) { 999 // This construct is not supported by ASTImporter. 1000 Decl *FromTU = getTuDecl( 1001 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n" 1002 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }", 1003 Lang_C, "input.c"); 1004 auto *From = FirstDeclMatcher<FunctionDecl>().match( 1005 FromTU, functionDecl(hasName("declToImport"))); 1006 ASSERT_TRUE(From); 1007 auto *To = Import(From, Lang_C); 1008 EXPECT_EQ(To, nullptr); 1009 } 1010 1011 const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr> 1012 cxxPseudoDestructorExpr; 1013 1014 TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) { 1015 MatchVerifier<Decl> Verifier; 1016 testImport( 1017 "typedef int T;" 1018 "void declToImport(int *p) {" 1019 " T t;" 1020 " p->T::~T();" 1021 "}", 1022 Lang_CXX, "", Lang_CXX, Verifier, 1023 functionDecl(hasDescendant( 1024 callExpr(has(cxxPseudoDestructorExpr()))))); 1025 } 1026 1027 TEST_P(ImportDecl, ImportUsingDecl) { 1028 MatchVerifier<Decl> Verifier; 1029 testImport( 1030 "namespace foo { int bar; }" 1031 "void declToImport() { using foo::bar; }", 1032 Lang_CXX, "", Lang_CXX, Verifier, 1033 functionDecl(hasDescendant(usingDecl()))); 1034 } 1035 1036 /// \brief Matches shadow declarations introduced into a scope by a 1037 /// (resolved) using declaration. 1038 /// 1039 /// Given 1040 /// \code 1041 /// namespace n { int f; } 1042 /// namespace declToImport { using n::f; } 1043 /// \endcode 1044 /// usingShadowDecl() 1045 /// matches \code f \endcode 1046 const internal::VariadicDynCastAllOfMatcher<Decl, 1047 UsingShadowDecl> usingShadowDecl; 1048 1049 TEST_P(ImportDecl, ImportUsingShadowDecl) { 1050 MatchVerifier<Decl> Verifier; 1051 testImport( 1052 "namespace foo { int bar; }" 1053 "namespace declToImport { using foo::bar; }", 1054 Lang_CXX, "", Lang_CXX, Verifier, 1055 namespaceDecl(has(usingShadowDecl()))); 1056 } 1057 1058 TEST_P(ImportExpr, ImportUnresolvedLookupExpr) { 1059 MatchVerifier<Decl> Verifier; 1060 testImport( 1061 "template<typename T> int foo();" 1062 "template <typename T> void declToImport() {" 1063 " (void)::foo<T>;" 1064 " (void)::template foo<T>;" 1065 "}" 1066 "void instantiate() { declToImport<int>(); }", 1067 Lang_CXX, "", Lang_CXX, Verifier, 1068 functionTemplateDecl(hasDescendant(unresolvedLookupExpr()))); 1069 } 1070 1071 TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) { 1072 MatchVerifier<Decl> Verifier; 1073 testImport( 1074 "template <typename T> struct C { T t; };" 1075 "template <typename T> void declToImport() {" 1076 " C<T> d;" 1077 " d.t = T();" 1078 "}" 1079 "void instantiate() { declToImport<int>(); }", 1080 Lang_CXX, "", Lang_CXX, Verifier, 1081 functionTemplateDecl(hasDescendant( 1082 binaryOperator(has(cxxUnresolvedConstructExpr()))))); 1083 testImport( 1084 "template <typename T> struct C { T t; };" 1085 "template <typename T> void declToImport() {" 1086 " C<T> d;" 1087 " (&d)->t = T();" 1088 "}" 1089 "void instantiate() { declToImport<int>(); }", 1090 Lang_CXX, "", Lang_CXX, Verifier, 1091 functionTemplateDecl(hasDescendant( 1092 binaryOperator(has(cxxUnresolvedConstructExpr()))))); 1093 } 1094 1095 /// Check that function "declToImport()" (which is the templated function 1096 /// for corresponding FunctionTemplateDecl) is not added into DeclContext. 1097 /// Same for class template declarations. 1098 TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) { 1099 MatchVerifier<Decl> Verifier; 1100 testImport( 1101 "template <typename T> void declToImport() { T a = 1; }" 1102 "void instantiate() { declToImport<int>(); }", 1103 Lang_CXX, "", Lang_CXX, Verifier, 1104 functionTemplateDecl(hasAncestor(translationUnitDecl( 1105 unless(has(functionDecl(hasName("declToImport")))))))); 1106 testImport( 1107 "template <typename T> struct declToImport { T t; };" 1108 "void instantiate() { declToImport<int>(); }", 1109 Lang_CXX, "", Lang_CXX, Verifier, 1110 classTemplateDecl(hasAncestor(translationUnitDecl( 1111 unless(has(cxxRecordDecl(hasName("declToImport")))))))); 1112 } 1113 1114 TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) { 1115 MatchVerifier<Decl> Verifier; 1116 auto Code = 1117 R"s( 1118 struct declToImport { 1119 template <typename T0> struct X; 1120 template <typename T0> struct X<T0 *> {}; 1121 }; 1122 )s"; 1123 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier, 1124 recordDecl(has(classTemplateDecl()), 1125 has(classTemplateSpecializationDecl()))); 1126 } 1127 1128 TEST_P(ImportExpr, CXXOperatorCallExpr) { 1129 MatchVerifier<Decl> Verifier; 1130 testImport( 1131 "class declToImport {" 1132 " void f() { *this = declToImport(); }" 1133 "};", 1134 Lang_CXX, "", Lang_CXX, Verifier, 1135 cxxRecordDecl(has(cxxMethodDecl(hasDescendant( 1136 cxxOperatorCallExpr()))))); 1137 } 1138 1139 TEST_P(ImportExpr, DependentSizedArrayType) { 1140 MatchVerifier<Decl> Verifier; 1141 testImport( 1142 "template<typename T, int Size> class declToImport {" 1143 " T data[Size];" 1144 "};", 1145 Lang_CXX, "", Lang_CXX, Verifier, 1146 classTemplateDecl(has(cxxRecordDecl( 1147 has(fieldDecl(hasType(dependentSizedArrayType()))))))); 1148 } 1149 1150 TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) { 1151 Decl *FromTU = getTuDecl( 1152 "class A { public: static int X; }; void f() { (void)A::X; }", Lang_CXX); 1153 auto From = FirstDeclMatcher<FunctionDecl>().match( 1154 FromTU, functionDecl(hasName("f"))); 1155 ASSERT_TRUE(From); 1156 ASSERT_TRUE( 1157 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front()) 1158 ->getSubExpr() 1159 ->getBeginLoc() 1160 .isValid()); 1161 FunctionDecl *To = Import(From, Lang_CXX); 1162 ASSERT_TRUE(To); 1163 ASSERT_TRUE( 1164 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front()) 1165 ->getSubExpr() 1166 ->getBeginLoc() 1167 .isValid()); 1168 } 1169 1170 TEST_P(ASTImporterOptionSpecificTestBase, 1171 ImportOfTemplatedDeclOfClassTemplateDecl) { 1172 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX); 1173 auto From = 1174 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl()); 1175 ASSERT_TRUE(From); 1176 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX)); 1177 ASSERT_TRUE(To); 1178 Decl *ToTemplated = To->getTemplatedDecl(); 1179 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX); 1180 EXPECT_TRUE(ToTemplated1); 1181 EXPECT_EQ(ToTemplated1, ToTemplated); 1182 } 1183 1184 TEST_P(ASTImporterOptionSpecificTestBase, 1185 ImportOfTemplatedDeclOfFunctionTemplateDecl) { 1186 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX); 1187 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match( 1188 FromTU, functionTemplateDecl()); 1189 ASSERT_TRUE(From); 1190 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX)); 1191 ASSERT_TRUE(To); 1192 Decl *ToTemplated = To->getTemplatedDecl(); 1193 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX); 1194 EXPECT_TRUE(ToTemplated1); 1195 EXPECT_EQ(ToTemplated1, ToTemplated); 1196 } 1197 1198 TEST_P(ASTImporterOptionSpecificTestBase, 1199 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) { 1200 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX); 1201 auto FromFT = 1202 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl()); 1203 ASSERT_TRUE(FromFT); 1204 1205 auto ToTemplated = 1206 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX)); 1207 EXPECT_TRUE(ToTemplated); 1208 auto ToTU = ToTemplated->getTranslationUnitDecl(); 1209 auto ToFT = 1210 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl()); 1211 EXPECT_TRUE(ToFT); 1212 } 1213 1214 TEST_P(ASTImporterOptionSpecificTestBase, 1215 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) { 1216 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX); 1217 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match( 1218 FromTU, functionTemplateDecl()); 1219 ASSERT_TRUE(FromFT); 1220 1221 auto ToTemplated = 1222 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX)); 1223 EXPECT_TRUE(ToTemplated); 1224 auto ToTU = ToTemplated->getTranslationUnitDecl(); 1225 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match( 1226 ToTU, functionTemplateDecl()); 1227 EXPECT_TRUE(ToFT); 1228 } 1229 1230 TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) { 1231 auto Code = 1232 R"( 1233 namespace x { 1234 template<class X> struct S1{}; 1235 template<class X> struct S2{}; 1236 template<class X> struct S3{}; 1237 } 1238 )"; 1239 Decl *FromTU = getTuDecl(Code, Lang_CXX); 1240 auto FromNs = 1241 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl()); 1242 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX)); 1243 ASSERT_TRUE(ToNs); 1244 auto From = 1245 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, 1246 classTemplateDecl( 1247 hasName("S2"))); 1248 auto To = 1249 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs, 1250 classTemplateDecl( 1251 hasName("S2"))); 1252 ASSERT_TRUE(From); 1253 ASSERT_TRUE(To); 1254 auto ToTemplated = To->getTemplatedDecl(); 1255 auto ToTemplated1 = 1256 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX)); 1257 EXPECT_TRUE(ToTemplated1); 1258 ASSERT_EQ(ToTemplated1, ToTemplated); 1259 } 1260 1261 TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) { 1262 // This tests the import of isConditionTrue directly to make sure the importer 1263 // gets it right. 1264 Decl *From, *To; 1265 std::tie(From, To) = getImportedDecl( 1266 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }", 1267 Lang_C, "", Lang_C); 1268 1269 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext()); 1270 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext()); 1271 1272 const ChooseExpr *FromChooseExpr = 1273 selectFirst<ChooseExpr>("choose", FromResults); 1274 ASSERT_TRUE(FromChooseExpr); 1275 1276 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults); 1277 ASSERT_TRUE(ToChooseExpr); 1278 1279 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue()); 1280 EXPECT_EQ(FromChooseExpr->isConditionDependent(), 1281 ToChooseExpr->isConditionDependent()); 1282 } 1283 1284 TEST_P(ASTImporterOptionSpecificTestBase, 1285 ImportFunctionWithBackReferringParameter) { 1286 Decl *From, *To; 1287 std::tie(From, To) = getImportedDecl( 1288 R"( 1289 template <typename T> struct X {}; 1290 1291 void declToImport(int y, X<int> &x) {} 1292 1293 template <> struct X<int> { 1294 void g() { 1295 X<int> x; 1296 declToImport(0, x); 1297 } 1298 }; 1299 )", 1300 Lang_CXX, "", Lang_CXX); 1301 1302 MatchVerifier<Decl> Verifier; 1303 auto Matcher = functionDecl(hasName("declToImport"), 1304 parameterCountIs(2), 1305 hasParameter(0, hasName("y")), 1306 hasParameter(1, hasName("x")), 1307 hasParameter(1, hasType(asString("X<int> &")))); 1308 ASSERT_TRUE(Verifier.match(From, Matcher)); 1309 EXPECT_TRUE(Verifier.match(To, Matcher)); 1310 } 1311 1312 TEST_P(ASTImporterOptionSpecificTestBase, 1313 TUshouldNotContainTemplatedDeclOfFunctionTemplates) { 1314 Decl *From, *To; 1315 std::tie(From, To) = 1316 getImportedDecl("template <typename T> void declToImport() { T a = 1; }" 1317 "void instantiate() { declToImport<int>(); }", 1318 Lang_CXX, "", Lang_CXX); 1319 1320 auto Check = [](Decl *D) -> bool { 1321 auto TU = D->getTranslationUnitDecl(); 1322 for (auto Child : TU->decls()) { 1323 if (auto *FD = dyn_cast<FunctionDecl>(Child)) { 1324 if (FD->getNameAsString() == "declToImport") { 1325 GTEST_NONFATAL_FAILURE_( 1326 "TU should not contain any FunctionDecl with name declToImport"); 1327 return false; 1328 } 1329 } 1330 } 1331 return true; 1332 }; 1333 1334 ASSERT_TRUE(Check(From)); 1335 EXPECT_TRUE(Check(To)); 1336 } 1337 1338 TEST_P(ASTImporterOptionSpecificTestBase, 1339 TUshouldNotContainTemplatedDeclOfClassTemplates) { 1340 Decl *From, *To; 1341 std::tie(From, To) = 1342 getImportedDecl("template <typename T> struct declToImport { T t; };" 1343 "void instantiate() { declToImport<int>(); }", 1344 Lang_CXX, "", Lang_CXX); 1345 1346 auto Check = [](Decl *D) -> bool { 1347 auto TU = D->getTranslationUnitDecl(); 1348 for (auto Child : TU->decls()) { 1349 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) { 1350 if (RD->getNameAsString() == "declToImport") { 1351 GTEST_NONFATAL_FAILURE_( 1352 "TU should not contain any CXXRecordDecl with name declToImport"); 1353 return false; 1354 } 1355 } 1356 } 1357 return true; 1358 }; 1359 1360 ASSERT_TRUE(Check(From)); 1361 EXPECT_TRUE(Check(To)); 1362 } 1363 1364 TEST_P(ASTImporterOptionSpecificTestBase, 1365 TUshouldNotContainTemplatedDeclOfTypeAlias) { 1366 Decl *From, *To; 1367 std::tie(From, To) = 1368 getImportedDecl( 1369 "template <typename T> struct X {};" 1370 "template <typename T> using declToImport = X<T>;" 1371 "void instantiate() { declToImport<int> a; }", 1372 Lang_CXX11, "", Lang_CXX11); 1373 1374 auto Check = [](Decl *D) -> bool { 1375 auto TU = D->getTranslationUnitDecl(); 1376 for (auto Child : TU->decls()) { 1377 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) { 1378 if (AD->getNameAsString() == "declToImport") { 1379 GTEST_NONFATAL_FAILURE_( 1380 "TU should not contain any TypeAliasDecl with name declToImport"); 1381 return false; 1382 } 1383 } 1384 } 1385 return true; 1386 }; 1387 1388 ASSERT_TRUE(Check(From)); 1389 EXPECT_TRUE(Check(To)); 1390 } 1391 1392 TEST_P(ASTImporterOptionSpecificTestBase, 1393 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) { 1394 1395 Decl *From, *To; 1396 std::tie(From, To) = getImportedDecl( 1397 R"( 1398 template<class T> 1399 class Base {}; 1400 class declToImport : public Base<declToImport> {}; 1401 )", 1402 Lang_CXX, "", Lang_CXX); 1403 1404 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU. 1405 auto Pattern = 1406 translationUnitDecl(unless(has(classTemplateSpecializationDecl()))); 1407 ASSERT_TRUE( 1408 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern)); 1409 EXPECT_TRUE( 1410 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern)); 1411 1412 // Check that the ClassTemplateSpecializationDecl is the child of the 1413 // ClassTemplateDecl. 1414 Pattern = translationUnitDecl(has(classTemplateDecl( 1415 hasName("Base"), has(classTemplateSpecializationDecl())))); 1416 ASSERT_TRUE( 1417 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern)); 1418 EXPECT_TRUE( 1419 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern)); 1420 } 1421 1422 AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) { 1423 size_t Index = 0; 1424 for (Decl *D : Node.decls()) { 1425 if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) { 1426 auto *ND = cast<NamedDecl>(D); 1427 if (Index == Order.size()) 1428 return false; 1429 if (ND->getName() != Order[Index]) 1430 return false; 1431 ++Index; 1432 } 1433 } 1434 return Index == Order.size(); 1435 } 1436 1437 TEST_P(ASTImporterOptionSpecificTestBase, 1438 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) { 1439 Decl *From, *To; 1440 std::tie(From, To) = getImportedDecl( 1441 R"( 1442 namespace NS { 1443 template<class T> 1444 class X {}; 1445 template class X<int>; 1446 } 1447 )", 1448 Lang_CXX, "", Lang_CXX, "NS"); 1449 1450 // Check that the ClassTemplateSpecializationDecl is NOT the child of the 1451 // ClassTemplateDecl. 1452 auto Pattern = namespaceDecl(has(classTemplateDecl( 1453 hasName("X"), unless(has(classTemplateSpecializationDecl()))))); 1454 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern)); 1455 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern)); 1456 1457 // Check that the ClassTemplateSpecializationDecl is the child of the 1458 // NamespaceDecl. 1459 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X")))); 1460 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern)); 1461 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern)); 1462 } 1463 1464 TEST_P(ASTImporterOptionSpecificTestBase, 1465 CXXRecordDeclFieldsShouldBeInCorrectOrder) { 1466 Decl *From, *To; 1467 std::tie(From, To) = 1468 getImportedDecl( 1469 "struct declToImport { int a; int b; };", 1470 Lang_CXX11, "", Lang_CXX11); 1471 1472 MatchVerifier<Decl> Verifier; 1473 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"})))); 1474 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"})))); 1475 } 1476 1477 TEST_P(ASTImporterOptionSpecificTestBase, 1478 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) { 1479 Decl *From, *To; 1480 std::tie(From, To) = getImportedDecl( 1481 // The original recursive algorithm of ASTImporter first imports 'c' then 1482 // 'b' and lastly 'a'. Therefore we must restore the order somehow. 1483 R"s( 1484 struct declToImport { 1485 int a = c + b; 1486 int b = 1; 1487 int c = 2; 1488 }; 1489 )s", 1490 Lang_CXX11, "", Lang_CXX11); 1491 1492 MatchVerifier<Decl> Verifier; 1493 ASSERT_TRUE( 1494 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"})))); 1495 EXPECT_TRUE( 1496 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"})))); 1497 } 1498 1499 TEST_P(ASTImporterOptionSpecificTestBase, 1500 CXXRecordDeclFieldAndIndirectFieldOrder) { 1501 Decl *From, *To; 1502 std::tie(From, To) = getImportedDecl( 1503 // First field is "a", then the field for unnamed union, then "b" and "c" 1504 // from it (indirect fields), then "d". 1505 R"s( 1506 struct declToImport { 1507 int a = d; 1508 union { 1509 int b; 1510 int c; 1511 }; 1512 int d; 1513 }; 1514 )s", 1515 Lang_CXX11, "", Lang_CXX11); 1516 1517 MatchVerifier<Decl> Verifier; 1518 ASSERT_TRUE(Verifier.match( 1519 From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"})))); 1520 EXPECT_TRUE(Verifier.match( 1521 To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"})))); 1522 } 1523 1524 TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) { 1525 Decl *From, *To; 1526 std::tie(From, To) = getImportedDecl( 1527 R"( 1528 struct declToImport { 1529 }; 1530 )", 1531 Lang_CXX, "", Lang_CXX); 1532 1533 MatchVerifier<Decl> Verifier; 1534 // Match the implicit Decl. 1535 auto Matcher = cxxRecordDecl(has(cxxRecordDecl())); 1536 ASSERT_TRUE(Verifier.match(From, Matcher)); 1537 EXPECT_TRUE(Verifier.match(To, Matcher)); 1538 } 1539 1540 TEST_P(ASTImporterOptionSpecificTestBase, 1541 ShouldImportImplicitCXXRecordDeclOfClassTemplate) { 1542 Decl *From, *To; 1543 std::tie(From, To) = getImportedDecl( 1544 R"( 1545 template <typename U> 1546 struct declToImport { 1547 }; 1548 )", 1549 Lang_CXX, "", Lang_CXX); 1550 1551 MatchVerifier<Decl> Verifier; 1552 // Match the implicit Decl. 1553 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl())))); 1554 ASSERT_TRUE(Verifier.match(From, Matcher)); 1555 EXPECT_TRUE(Verifier.match(To, Matcher)); 1556 } 1557 1558 TEST_P(ASTImporterOptionSpecificTestBase, 1559 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) { 1560 Decl *From, *To; 1561 std::tie(From, To) = getImportedDecl( 1562 R"( 1563 template<class T> 1564 class Base {}; 1565 class declToImport : public Base<declToImport> {}; 1566 )", 1567 Lang_CXX, "", Lang_CXX); 1568 1569 auto hasImplicitClass = has(cxxRecordDecl()); 1570 auto Pattern = translationUnitDecl(has(classTemplateDecl( 1571 hasName("Base"), 1572 has(classTemplateSpecializationDecl(hasImplicitClass))))); 1573 ASSERT_TRUE( 1574 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern)); 1575 EXPECT_TRUE( 1576 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern)); 1577 } 1578 1579 TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) { 1580 Decl *From, *To; 1581 std::tie(From, To) = 1582 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX); 1583 1584 MatchVerifier<Decl> Verifier; 1585 auto Matcher = functionDecl(); 1586 ASSERT_TRUE(Verifier.match(From, Matcher)); 1587 EXPECT_TRUE(Verifier.match(To, Matcher)); 1588 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace()); 1589 } 1590 1591 TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) { 1592 Decl *FromTU = getTuDecl( 1593 R"( 1594 struct X {}; 1595 void operator<<(int, X); 1596 )", 1597 Lang_CXX); 1598 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl()); 1599 const Decl *To = Import(From, Lang_CXX); 1600 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace()); 1601 } 1602 1603 TEST_P(ASTImporterOptionSpecificTestBase, 1604 ShouldImportMembersOfClassTemplateSpecializationDecl) { 1605 Decl *From, *To; 1606 std::tie(From, To) = getImportedDecl( 1607 R"( 1608 template<class T> 1609 class Base { int a; }; 1610 class declToImport : Base<declToImport> {}; 1611 )", 1612 Lang_CXX, "", Lang_CXX); 1613 1614 auto Pattern = translationUnitDecl(has(classTemplateDecl( 1615 hasName("Base"), 1616 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a")))))))); 1617 ASSERT_TRUE( 1618 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern)); 1619 EXPECT_TRUE( 1620 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern)); 1621 } 1622 1623 TEST_P(ASTImporterOptionSpecificTestBase, 1624 ImportDefinitionOfClassTemplateAfterFwdDecl) { 1625 { 1626 Decl *FromTU = getTuDecl( 1627 R"( 1628 template <typename T> 1629 struct B; 1630 )", 1631 Lang_CXX, "input0.cc"); 1632 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match( 1633 FromTU, classTemplateDecl(hasName("B"))); 1634 1635 Import(FromD, Lang_CXX); 1636 } 1637 1638 { 1639 Decl *FromTU = getTuDecl( 1640 R"( 1641 template <typename T> 1642 struct B { 1643 void f(); 1644 }; 1645 )", 1646 Lang_CXX, "input1.cc"); 1647 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match( 1648 FromTU, functionDecl(hasName("f"))); 1649 Import(FromD, Lang_CXX); 1650 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match( 1651 FromTU, classTemplateDecl(hasName("B"))); 1652 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX)); 1653 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition()); 1654 } 1655 } 1656 1657 TEST_P(ASTImporterOptionSpecificTestBase, 1658 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) { 1659 Decl *ToTU = getToTuDecl( 1660 R"( 1661 template <typename T> 1662 struct B { 1663 void f(); 1664 }; 1665 1666 template <typename T> 1667 struct B; 1668 )", 1669 Lang_CXX); 1670 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>( 1671 [](const ClassTemplateDecl *T) { 1672 return T->isThisDeclarationADefinition(); 1673 }) 1674 .match(ToTU, classTemplateDecl())); 1675 1676 Decl *FromTU = getTuDecl( 1677 R"( 1678 template <typename T> 1679 struct B { 1680 void f(); 1681 }; 1682 )", 1683 Lang_CXX, "input1.cc"); 1684 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match( 1685 FromTU, classTemplateDecl(hasName("B"))); 1686 1687 Import(FromD, Lang_CXX); 1688 1689 // We should have only one definition. 1690 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>( 1691 [](const ClassTemplateDecl *T) { 1692 return T->isThisDeclarationADefinition(); 1693 }) 1694 .match(ToTU, classTemplateDecl())); 1695 } 1696 1697 TEST_P(ASTImporterOptionSpecificTestBase, 1698 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) { 1699 Decl *ToTU = getToTuDecl( 1700 R"( 1701 struct B { 1702 void f(); 1703 }; 1704 1705 struct B; 1706 )", 1707 Lang_CXX); 1708 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match( 1709 ToTU, cxxRecordDecl(unless(isImplicit())))); 1710 1711 Decl *FromTU = getTuDecl( 1712 R"( 1713 struct B { 1714 void f(); 1715 }; 1716 )", 1717 Lang_CXX, "input1.cc"); 1718 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match( 1719 FromTU, cxxRecordDecl(hasName("B"))); 1720 1721 Import(FromD, Lang_CXX); 1722 1723 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match( 1724 ToTU, cxxRecordDecl(unless(isImplicit())))); 1725 } 1726 1727 static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) { 1728 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber()); 1729 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber()); 1730 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber()); 1731 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber()); 1732 } 1733 static void CompareSourceRanges(SourceRange Range1, SourceRange Range2, 1734 SourceManager &SM1, SourceManager &SM2) { 1735 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 }, 1736 FullSourceLoc{ Range2.getBegin(), SM2 }); 1737 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 }, 1738 FullSourceLoc{ Range2.getEnd(), SM2 }); 1739 } 1740 TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) { 1741 Decl *FromTU = getTuDecl( 1742 R"( 1743 #define MFOO(arg) arg = arg + 1 1744 1745 void foo() { 1746 int a = 5; 1747 MFOO(a); 1748 } 1749 )", 1750 Lang_CXX); 1751 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl()); 1752 auto ToD = Import(FromD, Lang_CXX); 1753 1754 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr()); 1755 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr()); 1756 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral()); 1757 auto FromRHS = 1758 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral()); 1759 1760 SourceManager &ToSM = ToAST->getASTContext().getSourceManager(); 1761 SourceManager &FromSM = FromD->getASTContext().getSourceManager(); 1762 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM, 1763 FromSM); 1764 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM, 1765 FromSM); 1766 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM, 1767 FromSM); 1768 } 1769 1770 TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) { 1771 Decl *FromTU = getTuDecl( 1772 R"( 1773 #define FUNC_INT void declToImport 1774 #define FUNC FUNC_INT 1775 FUNC(int a); 1776 )", 1777 Lang_CXX); 1778 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl()); 1779 auto ToD = Import(FromD, Lang_CXX); 1780 1781 SourceManager &ToSM = ToAST->getASTContext().getSourceManager(); 1782 SourceManager &FromSM = FromD->getASTContext().getSourceManager(); 1783 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM, 1784 FromSM); 1785 } 1786 1787 TEST_P( 1788 ASTImporterOptionSpecificTestBase, 1789 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) { 1790 Decl *ToTU = getToTuDecl( 1791 R"( 1792 template <typename T> 1793 struct B; 1794 1795 template <> 1796 struct B<int> {}; 1797 1798 template <> 1799 struct B<int>; 1800 )", 1801 Lang_CXX); 1802 // We should have only one definition. 1803 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>( 1804 [](const ClassTemplateSpecializationDecl *T) { 1805 return T->isThisDeclarationADefinition(); 1806 }) 1807 .match(ToTU, classTemplateSpecializationDecl())); 1808 1809 Decl *FromTU = getTuDecl( 1810 R"( 1811 template <typename T> 1812 struct B; 1813 1814 template <> 1815 struct B<int> {}; 1816 )", 1817 Lang_CXX, "input1.cc"); 1818 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 1819 FromTU, classTemplateSpecializationDecl(hasName("B"))); 1820 1821 Import(FromD, Lang_CXX); 1822 1823 // We should have only one definition. 1824 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>( 1825 [](const ClassTemplateSpecializationDecl *T) { 1826 return T->isThisDeclarationADefinition(); 1827 }) 1828 .match(ToTU, classTemplateSpecializationDecl())); 1829 } 1830 1831 TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) { 1832 Decl *FromTU = getTuDecl( 1833 R"( 1834 struct { int a; int b; } object0 = { 2, 3 }; 1835 struct { int x; int y; int z; } object1; 1836 )", 1837 Lang_CXX, "input0.cc"); 1838 1839 auto *Obj0 = 1840 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0"))); 1841 auto *From0 = getRecordDecl(Obj0); 1842 auto *Obj1 = 1843 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1"))); 1844 auto *From1 = getRecordDecl(Obj1); 1845 1846 auto *To0 = Import(From0, Lang_CXX); 1847 auto *To1 = Import(From1, Lang_CXX); 1848 1849 EXPECT_TRUE(To0); 1850 EXPECT_TRUE(To1); 1851 EXPECT_NE(To0, To1); 1852 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl()); 1853 } 1854 1855 TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) { 1856 auto *Code = 1857 R"( 1858 struct X { 1859 struct { int a; }; 1860 struct { int b; }; 1861 }; 1862 )"; 1863 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c"); 1864 1865 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c"); 1866 1867 auto *X0 = 1868 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X"))); 1869 auto *X1 = 1870 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X"))); 1871 Import(X0, Lang_C); 1872 Import(X1, Lang_C); 1873 1874 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 1875 // We expect no (ODR) warning during the import. 1876 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings()); 1877 EXPECT_EQ(1u, 1878 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X")))); 1879 } 1880 1881 TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) { 1882 Decl *FromTU0 = getTuDecl( 1883 R"( 1884 struct X { 1885 struct { int a; }; 1886 struct { int b; }; 1887 }; 1888 )", 1889 Lang_C, "input0.c"); 1890 1891 Decl *FromTU1 = getTuDecl( 1892 R"( 1893 struct X { // reversed order 1894 struct { int b; }; 1895 struct { int a; }; 1896 }; 1897 )", 1898 Lang_C, "input1.c"); 1899 1900 auto *X0 = 1901 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X"))); 1902 auto *X1 = 1903 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X"))); 1904 Import(X0, Lang_C); 1905 Import(X1, Lang_C); 1906 1907 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 1908 // We expect one (ODR) warning during the import. 1909 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings()); 1910 EXPECT_EQ(1u, 1911 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X")))); 1912 } 1913 1914 TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) { 1915 auto Pattern = varDecl(hasName("x")); 1916 VarDecl *Imported1; 1917 { 1918 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc"); 1919 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); 1920 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX)); 1921 } 1922 VarDecl *Imported2; 1923 { 1924 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc"); 1925 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); 1926 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX)); 1927 } 1928 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl()); 1929 EXPECT_FALSE(Imported2->isUsed(false)); 1930 { 1931 Decl *FromTU = 1932 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc"); 1933 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 1934 FromTU, functionDecl(hasName("f"))); 1935 Import(FromD, Lang_CXX); 1936 } 1937 EXPECT_TRUE(Imported2->isUsed(false)); 1938 } 1939 1940 TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) { 1941 auto Pattern = varDecl(hasName("x")); 1942 VarDecl *ExistingD; 1943 { 1944 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX); 1945 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern); 1946 } 1947 EXPECT_FALSE(ExistingD->isUsed(false)); 1948 { 1949 Decl *FromTU = getTuDecl( 1950 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc"); 1951 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 1952 FromTU, functionDecl(hasName("f"))); 1953 Import(FromD, Lang_CXX); 1954 } 1955 EXPECT_TRUE(ExistingD->isUsed(false)); 1956 } 1957 1958 TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) { 1959 auto Pattern = varDecl(hasName("a")); 1960 VarDecl *ExistingD; 1961 { 1962 Decl *ToTU = getToTuDecl( 1963 R"( 1964 struct A { 1965 static const int a = 1; 1966 }; 1967 )", Lang_CXX); 1968 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern); 1969 } 1970 EXPECT_FALSE(ExistingD->isUsed(false)); 1971 { 1972 Decl *FromTU = getTuDecl( 1973 R"( 1974 struct A { 1975 static const int a = 1; 1976 }; 1977 const int *f() { return &A::a; } // requires storage, 1978 // thus used flag will be set 1979 )", Lang_CXX, "input1.cc"); 1980 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match( 1981 FromTU, functionDecl(hasName("f"))); 1982 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); 1983 ASSERT_TRUE(FromD->isUsed(false)); 1984 Import(FromFunD, Lang_CXX); 1985 } 1986 EXPECT_TRUE(ExistingD->isUsed(false)); 1987 } 1988 1989 TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) { 1990 auto Pattern = varDecl(hasName("x")); 1991 1992 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc"); 1993 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); 1994 1995 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX)); 1996 1997 ASSERT_FALSE(Imported1->isUsed(false)); 1998 1999 FromD->setIsUsed(); 2000 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX)); 2001 2002 EXPECT_EQ(Imported1, Imported2); 2003 EXPECT_TRUE(Imported2->isUsed(false)); 2004 } 2005 2006 struct ImportFunctions : ASTImporterOptionSpecificTestBase {}; 2007 2008 TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) { 2009 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); 2010 auto Pattern = functionDecl(hasName("f")); 2011 auto *From = 2012 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto 2013 2014 Decl *ImportedD = Import(From, Lang_CXX); 2015 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 2016 2017 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2018 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2019 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2020 EXPECT_TRUE(ImportedD == To0); 2021 EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); 2022 EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); 2023 EXPECT_EQ(To1->getPreviousDecl(), To0); 2024 } 2025 2026 TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) { 2027 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); 2028 auto Pattern = functionDecl(hasName("f")); 2029 auto *From = 2030 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def 2031 2032 Decl *ImportedD = Import(From, Lang_CXX); 2033 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 2034 2035 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2036 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2037 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2038 EXPECT_TRUE(ImportedD == To1); 2039 EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); 2040 EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); 2041 EXPECT_EQ(To1->getPreviousDecl(), To0); 2042 } 2043 2044 TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) { 2045 auto Code = 2046 R"( 2047 struct B { virtual void f(); }; 2048 void B::f() {} 2049 struct D : B { void f(); }; 2050 )"; 2051 auto Pattern = 2052 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D")))); 2053 Decl *FromTU = getTuDecl(Code, Lang_CXX); 2054 CXXMethodDecl *Proto = 2055 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern); 2056 2057 ASSERT_EQ(Proto->size_overridden_methods(), 1u); 2058 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX)); 2059 EXPECT_EQ(To->size_overridden_methods(), 1u); 2060 } 2061 2062 TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) { 2063 auto Code = 2064 R"( 2065 struct B { virtual void f(); }; 2066 void B::f() {} 2067 )"; 2068 auto Pattern = 2069 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B")))); 2070 Decl *FromTU = getTuDecl(Code, Lang_CXX); 2071 CXXMethodDecl *Proto = 2072 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern); 2073 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern); 2074 2075 ASSERT_TRUE(Proto->isVirtual()); 2076 ASSERT_TRUE(Def->isVirtual()); 2077 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX)); 2078 EXPECT_TRUE(To->isVirtual()); 2079 } 2080 2081 TEST_P(ImportFunctions, 2082 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) { 2083 Decl *ToTU = getToTuDecl( 2084 R"( 2085 void f() {} 2086 void f(); 2087 )", 2088 Lang_CXX); 2089 ASSERT_EQ(1u, 2090 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) { 2091 return FD->doesThisDeclarationHaveABody(); 2092 }).match(ToTU, functionDecl())); 2093 2094 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc"); 2095 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl()); 2096 2097 Import(FromD, Lang_CXX); 2098 2099 EXPECT_EQ(1u, 2100 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) { 2101 return FD->doesThisDeclarationHaveABody(); 2102 }).match(ToTU, functionDecl())); 2103 } 2104 2105 TEST_P(ImportFunctions, ImportOverriddenMethodTwice) { 2106 auto Code = 2107 R"( 2108 struct B { virtual void f(); }; 2109 struct D:B { void f(); }; 2110 )"; 2111 auto BFP = 2112 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B")))); 2113 auto DFP = 2114 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D")))); 2115 2116 Decl *FromTU0 = getTuDecl(Code, Lang_CXX); 2117 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP); 2118 Import(DF, Lang_CXX); 2119 2120 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc"); 2121 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP); 2122 Import(BF, Lang_CXX); 2123 2124 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2125 2126 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u); 2127 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u); 2128 } 2129 2130 TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) { 2131 auto CodeWithoutDef = 2132 R"( 2133 struct B { virtual void f(); }; 2134 struct D:B { void f(); }; 2135 )"; 2136 auto CodeWithDef = 2137 R"( 2138 struct B { virtual void f(){}; }; 2139 struct D:B { void f(){}; }; 2140 )"; 2141 auto BFP = 2142 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B")))); 2143 auto DFP = 2144 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D")))); 2145 auto BFDefP = cxxMethodDecl( 2146 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition()); 2147 auto DFDefP = cxxMethodDecl( 2148 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition()); 2149 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition()); 2150 2151 { 2152 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc"); 2153 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP); 2154 Import(FromD, Lang_CXX); 2155 } 2156 { 2157 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc"); 2158 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP); 2159 Import(FromB, Lang_CXX); 2160 } 2161 2162 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2163 2164 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u); 2165 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u); 2166 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u); 2167 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u); 2168 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u); 2169 } 2170 2171 TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) { 2172 auto Code = 2173 R"( 2174 struct B { virtual void f(); }; 2175 struct D:B { void f(); }; 2176 void B::f(){}; 2177 )"; 2178 2179 auto BFP = 2180 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B")))); 2181 auto BFDefP = cxxMethodDecl( 2182 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition()); 2183 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), 2184 unless(isDefinition())); 2185 2186 Decl *FromTU0 = getTuDecl(Code, Lang_CXX); 2187 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP); 2188 Import(D, Lang_CXX); 2189 2190 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc"); 2191 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP); 2192 Import(B, Lang_CXX); 2193 2194 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2195 2196 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u); 2197 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u); 2198 2199 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match( 2200 ToTU, cxxRecordDecl(hasName("B"))); 2201 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP); 2202 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match( 2203 ToTU, cxxMethodDecl(hasName("f"), isDefinition())); 2204 2205 // The definition should be out-of-class. 2206 EXPECT_NE(ToBFInClass, ToBFOutOfClass); 2207 EXPECT_NE(ToBFInClass->getLexicalDeclContext(), 2208 ToBFOutOfClass->getLexicalDeclContext()); 2209 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB); 2210 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU); 2211 2212 // Check that the redecl chain is intact. 2213 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass); 2214 } 2215 2216 TEST_P(ImportFunctions, 2217 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) { 2218 auto CodeTU0 = 2219 R"( 2220 struct B { virtual void f(); }; 2221 struct D:B { void f(); }; 2222 )"; 2223 auto CodeTU1 = 2224 R"( 2225 struct B { virtual void f(); }; 2226 struct D:B { void f(); }; 2227 void B::f(){} 2228 void D::f(){} 2229 void foo(B &b, D &d) { b.f(); d.f(); } 2230 )"; 2231 2232 auto BFP = 2233 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B")))); 2234 auto BFDefP = cxxMethodDecl( 2235 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition()); 2236 auto DFP = 2237 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D")))); 2238 auto DFDefP = cxxMethodDecl( 2239 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition()); 2240 auto FooDef = functionDecl(hasName("foo")); 2241 2242 { 2243 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc"); 2244 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP); 2245 Import(D, Lang_CXX); 2246 } 2247 2248 { 2249 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc"); 2250 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef); 2251 Import(Foo, Lang_CXX); 2252 } 2253 2254 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2255 2256 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u); 2257 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u); 2258 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u); 2259 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u); 2260 2261 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match( 2262 ToTU, cxxRecordDecl(hasName("B"))); 2263 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match( 2264 ToTU, cxxRecordDecl(hasName("D"))); 2265 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP); 2266 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match( 2267 ToTU, cxxMethodDecl(hasName("f"), isDefinition())); 2268 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP); 2269 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match( 2270 ToTU, cxxMethodDecl(hasName("f"), isDefinition())); 2271 2272 // The definition should be out-of-class. 2273 EXPECT_NE(ToBFInClass, ToBFOutOfClass); 2274 EXPECT_NE(ToBFInClass->getLexicalDeclContext(), 2275 ToBFOutOfClass->getLexicalDeclContext()); 2276 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB); 2277 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU); 2278 2279 EXPECT_NE(ToDFInClass, ToDFOutOfClass); 2280 EXPECT_NE(ToDFInClass->getLexicalDeclContext(), 2281 ToDFOutOfClass->getLexicalDeclContext()); 2282 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD); 2283 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU); 2284 2285 // Check that the redecl chain is intact. 2286 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass); 2287 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass); 2288 } 2289 2290 TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) { 2291 std::string Code = "static int v; static int v = 0;"; 2292 auto Pattern = varDecl(hasName("v")); 2293 2294 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c"); 2295 2296 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern); 2297 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern); 2298 2299 auto *To0 = Import(From0, Lang_C); 2300 auto *To1 = Import(From1, Lang_C); 2301 2302 EXPECT_TRUE(To0); 2303 ASSERT_TRUE(To1); 2304 EXPECT_NE(To0, To1); 2305 EXPECT_EQ(To1->getPreviousDecl(), To0); 2306 } 2307 2308 TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) { 2309 TranslationUnitDecl *FromTu = getTuDecl( 2310 "namespace NS0 { namespace { void f(); } }" 2311 "namespace NS1 { namespace { void f(); } }", 2312 Lang_CXX, "input0.cc"); 2313 auto Pattern = functionDecl(hasName("f")); 2314 2315 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern); 2316 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern); 2317 2318 auto *ToF0 = Import(FromF0, Lang_CXX); 2319 auto *ToF1 = Import(FromF1, Lang_CXX); 2320 2321 EXPECT_TRUE(ToF0); 2322 ASSERT_TRUE(ToF1); 2323 EXPECT_NE(ToF0, ToF1); 2324 EXPECT_FALSE(ToF1->getPreviousDecl()); 2325 } 2326 2327 TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) { 2328 { 2329 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }", 2330 Lang_CXX, "input0.cc"); 2331 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 2332 FromTU, functionDecl(hasName("g0"))); 2333 2334 Import(FromD, Lang_CXX); 2335 } 2336 { 2337 Decl *FromTU = 2338 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }", 2339 Lang_CXX, "input1.cc"); 2340 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 2341 FromTU, functionDecl(hasName("g1"))); 2342 Import(FromD, Lang_CXX); 2343 } 2344 2345 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2346 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))), 2347 2u); 2348 } 2349 2350 TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) { 2351 Decl *FromTU = getTuDecl( 2352 R"( 2353 void foo() { 2354 (void)[]() { ; }; 2355 } 2356 )", 2357 Lang_CXX11); 2358 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 2359 FromTU, functionDecl(hasName("foo"))); 2360 auto *ToD = Import(FromD, Lang_CXX); 2361 EXPECT_TRUE(ToD); 2362 CXXRecordDecl *LambdaRec = 2363 cast<LambdaExpr>(cast<CStyleCastExpr>( 2364 *cast<CompoundStmt>(ToD->getBody())->body_begin()) 2365 ->getSubExpr()) 2366 ->getLambdaClass(); 2367 EXPECT_TRUE(LambdaRec->getDestructor()); 2368 } 2369 2370 TEST_P(ImportFunctions, 2371 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) { 2372 Decl *FromTU = getTuDecl( 2373 R"( 2374 struct X { 2375 template <typename T> 2376 void foo(){} 2377 }; 2378 void f() { 2379 X x; 2380 x.foo<int>(); 2381 } 2382 )", 2383 Lang_CXX); 2384 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 2385 FromTU, functionDecl(hasName("f"))); 2386 auto *ToD = Import(FromD, Lang_CXX); 2387 EXPECT_TRUE(ToD); 2388 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match( 2389 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr())))); 2390 } 2391 2392 TEST_P(ImportFunctions, 2393 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) { 2394 Decl *FromTU = getTuDecl( 2395 R"( 2396 struct X { 2397 template <typename T> 2398 void foo(){} 2399 }; 2400 template <typename T> 2401 void f() { 2402 X x; 2403 x.foo<T>(); 2404 } 2405 void g() { 2406 f<int>(); 2407 } 2408 )", 2409 Lang_CXX); 2410 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 2411 FromTU, functionDecl(hasName("g"))); 2412 auto *ToD = Import(FromD, Lang_CXX); 2413 EXPECT_TRUE(ToD); 2414 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2415 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match( 2416 ToTU, translationUnitDecl(hasDescendant( 2417 functionDecl(hasName("f"), hasDescendant(declRefExpr())))))); 2418 } 2419 2420 struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {}; 2421 2422 TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) { 2423 auto Code = 2424 R"( 2425 class X { 2426 template <class T> 2427 void f(T t); 2428 }; 2429 )"; 2430 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc"); 2431 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match( 2432 FromTU1, functionTemplateDecl(hasName("f"))); 2433 auto *ToD1 = Import(FromD1, Lang_CXX); 2434 Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc"); 2435 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match( 2436 FromTU2, functionTemplateDecl(hasName("f"))); 2437 auto *ToD2 = Import(FromD2, Lang_CXX); 2438 EXPECT_EQ(ToD1, ToD2); 2439 } 2440 2441 TEST_P(ImportFunctionTemplates, 2442 ImportFunctionTemplateWithDefInRecordDeclTwice) { 2443 auto Code = 2444 R"( 2445 class X { 2446 template <class T> 2447 void f(T t); 2448 }; 2449 template <class T> 2450 void X::f(T t) {}; 2451 )"; 2452 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc"); 2453 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match( 2454 FromTU1, functionTemplateDecl(hasName("f"))); 2455 auto *ToD1 = Import(FromD1, Lang_CXX); 2456 Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc"); 2457 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match( 2458 FromTU2, functionTemplateDecl(hasName("f"))); 2459 auto *ToD2 = Import(FromD2, Lang_CXX); 2460 EXPECT_EQ(ToD1, ToD2); 2461 } 2462 2463 TEST_P(ImportFunctionTemplates, 2464 ImportFunctionWhenThereIsAFunTemplateWithSameName) { 2465 getToTuDecl( 2466 R"( 2467 template <typename T> 2468 void foo(T) {} 2469 void foo(); 2470 )", 2471 Lang_CXX); 2472 Decl *FromTU = getTuDecl("void foo();", Lang_CXX); 2473 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 2474 FromTU, functionDecl(hasName("foo"))); 2475 auto *ImportedD = Import(FromD, Lang_CXX); 2476 EXPECT_TRUE(ImportedD); 2477 } 2478 2479 TEST_P(ImportFunctionTemplates, 2480 ImportConstructorWhenThereIsAFunTemplateWithSameName) { 2481 auto Code = 2482 R"( 2483 struct Foo { 2484 template <typename T> 2485 Foo(T) {} 2486 Foo(); 2487 }; 2488 )"; 2489 getToTuDecl(Code, Lang_CXX); 2490 Decl *FromTU = getTuDecl(Code, Lang_CXX); 2491 auto *FromD = 2492 LastDeclMatcher<CXXConstructorDecl>().match(FromTU, cxxConstructorDecl()); 2493 auto *ImportedD = Import(FromD, Lang_CXX); 2494 EXPECT_TRUE(ImportedD); 2495 } 2496 2497 TEST_P(ImportFunctionTemplates, 2498 ImportOperatorWhenThereIsAFunTemplateWithSameName) { 2499 getToTuDecl( 2500 R"( 2501 template <typename T> 2502 void operator<(T,T) {} 2503 struct X{}; 2504 void operator<(X, X); 2505 )", 2506 Lang_CXX); 2507 Decl *FromTU = getTuDecl( 2508 R"( 2509 struct X{}; 2510 void operator<(X, X); 2511 )", 2512 Lang_CXX); 2513 auto *FromD = LastDeclMatcher<FunctionDecl>().match( 2514 FromTU, functionDecl(hasOverloadedOperatorName("<"))); 2515 auto *ImportedD = Import(FromD, Lang_CXX); 2516 EXPECT_TRUE(ImportedD); 2517 } 2518 2519 struct ImportFriendFunctions : ImportFunctions {}; 2520 2521 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) { 2522 auto Pattern = functionDecl(hasName("f")); 2523 2524 Decl *FromTU = getTuDecl("struct X { friend void f(); };" 2525 "void f();", 2526 Lang_CXX, 2527 "input0.cc"); 2528 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2529 2530 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2531 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2532 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2533 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); 2534 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2535 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); 2536 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); 2537 } 2538 2539 TEST_P(ImportFriendFunctions, 2540 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) { 2541 auto Pattern = functionDecl(hasName("f")); 2542 2543 Decl *FromTU = getTuDecl("void f();" 2544 "struct X { friend void f(); };", 2545 Lang_CXX, "input0.cc"); 2546 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2547 2548 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2549 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2550 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2551 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); 2552 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2553 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); 2554 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); 2555 } 2556 2557 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) { 2558 auto Pattern = functionDecl(hasName("f")); 2559 2560 Decl *FromTU = getTuDecl("struct X { friend void f(){} };" 2561 "void f();", 2562 Lang_CXX, 2563 "input0.cc"); 2564 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2565 2566 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2567 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2568 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2569 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); 2570 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2571 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); 2572 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); 2573 } 2574 2575 TEST_P(ImportFriendFunctions, 2576 ImportFriendFunctionRedeclChainDef_OutOfClassDef) { 2577 auto Pattern = functionDecl(hasName("f")); 2578 2579 Decl *FromTU = getTuDecl("struct X { friend void f(); };" 2580 "void f(){}", 2581 Lang_CXX, "input0.cc"); 2582 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2583 2584 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2585 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2586 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2587 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); 2588 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2589 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody()); 2590 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); 2591 } 2592 2593 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) { 2594 auto Pattern = functionDecl(hasName("f")); 2595 2596 Decl *FromTU = getTuDecl( 2597 R"( 2598 class X; 2599 void f(X *x){} 2600 class X{ 2601 friend void f(X *x); 2602 }; 2603 )", 2604 Lang_CXX, "input0.cc"); 2605 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2606 2607 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2608 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2609 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2610 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); 2611 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>() 2612 .match(ToTU, friendDecl()) 2613 ->getFriendDecl()); 2614 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody()); 2615 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD); 2616 // The parameters must refer the same type 2617 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(), 2618 (*ImportedD->param_begin())->getOriginalType()); 2619 } 2620 2621 TEST_P(ImportFriendFunctions, 2622 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) { 2623 auto Pattern = functionDecl(hasName("f")); 2624 2625 Decl *FromTU = getTuDecl( 2626 R"( 2627 class X; 2628 void f(X *x){} 2629 class X{ 2630 friend void f(X *x); 2631 }; 2632 )", 2633 Lang_CXX, "input0.cc"); 2634 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2635 2636 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2637 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2638 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2639 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); 2640 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match( 2641 ToTU, functionDecl(unless(hasParent(friendDecl())))); 2642 2643 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody()); 2644 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD); 2645 // The parameters must refer the same type 2646 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(), 2647 (*ImportedD->param_begin())->getOriginalType()); 2648 } 2649 2650 TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) { 2651 auto Pattern = functionDecl(hasName("f")); 2652 2653 FunctionDecl *ImportedD; 2654 { 2655 Decl *FromTU = 2656 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc"); 2657 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2658 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2659 } 2660 FunctionDecl *ImportedD1; 2661 { 2662 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); 2663 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2664 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2665 } 2666 2667 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2668 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2669 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); 2670 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody()); 2671 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD); 2672 } 2673 2674 TEST_P(ImportFriendFunctions, Lookup) { 2675 auto FunctionPattern = functionDecl(hasName("f")); 2676 auto ClassPattern = cxxRecordDecl(hasName("X")); 2677 2678 TranslationUnitDecl *FromTU = 2679 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc"); 2680 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern); 2681 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2682 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2683 { 2684 auto FromName = FromD->getDeclName(); 2685 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern); 2686 auto LookupRes = Class->noload_lookup(FromName); 2687 ASSERT_EQ(LookupRes.size(), 0u); 2688 LookupRes = FromTU->noload_lookup(FromName); 2689 ASSERT_EQ(LookupRes.size(), 1u); 2690 } 2691 2692 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2693 auto ToName = ToD->getDeclName(); 2694 2695 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2696 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern); 2697 auto LookupRes = Class->noload_lookup(ToName); 2698 EXPECT_EQ(LookupRes.size(), 0u); 2699 LookupRes = ToTU->noload_lookup(ToName); 2700 EXPECT_EQ(LookupRes.size(), 1u); 2701 2702 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u); 2703 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern); 2704 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2705 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2706 } 2707 2708 TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) { 2709 auto FunctionPattern = functionDecl(hasName("f")); 2710 auto ClassPattern = cxxRecordDecl(hasName("X")); 2711 2712 TranslationUnitDecl *FromTU = getTuDecl( 2713 "struct X { friend void f(); };" 2714 // This proto decl makes f available to normal 2715 // lookup, otherwise it is hidden. 2716 // Normal C++ lookup (implemented in 2717 // `clang::Sema::CppLookupName()` and in `LookupDirect()`) 2718 // returns the found `NamedDecl` only if the set IDNS is matched 2719 "void f();", 2720 Lang_CXX, "input0.cc"); 2721 auto *FromFriend = 2722 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern); 2723 auto *FromNormal = 2724 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern); 2725 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2726 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2727 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2728 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2729 2730 auto FromName = FromFriend->getDeclName(); 2731 auto *FromClass = 2732 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern); 2733 auto LookupRes = FromClass->noload_lookup(FromName); 2734 ASSERT_EQ(LookupRes.size(), 0u); 2735 LookupRes = FromTU->noload_lookup(FromName); 2736 ASSERT_EQ(LookupRes.size(), 1u); 2737 2738 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX)); 2739 auto ToName = ToFriend->getDeclName(); 2740 2741 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2742 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern); 2743 LookupRes = ToClass->noload_lookup(ToName); 2744 EXPECT_EQ(LookupRes.size(), 0u); 2745 LookupRes = ToTU->noload_lookup(ToName); 2746 // Test is disabled because this result is 2. 2747 EXPECT_EQ(LookupRes.size(), 1u); 2748 2749 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u); 2750 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern); 2751 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern); 2752 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2753 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2754 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2755 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2756 } 2757 2758 TEST_P(ImportFriendFunctions, LookupWithProtoBefore) { 2759 auto FunctionPattern = functionDecl(hasName("f")); 2760 auto ClassPattern = cxxRecordDecl(hasName("X")); 2761 2762 TranslationUnitDecl *FromTU = getTuDecl( 2763 "void f();" 2764 "struct X { friend void f(); };", 2765 Lang_CXX, "input0.cc"); 2766 auto *FromNormal = 2767 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern); 2768 auto *FromFriend = 2769 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern); 2770 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2771 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2772 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2773 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2774 2775 auto FromName = FromNormal->getDeclName(); 2776 auto *FromClass = 2777 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern); 2778 auto LookupRes = FromClass->noload_lookup(FromName); 2779 ASSERT_EQ(LookupRes.size(), 0u); 2780 LookupRes = FromTU->noload_lookup(FromName); 2781 ASSERT_EQ(LookupRes.size(), 1u); 2782 2783 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX)); 2784 auto ToName = ToNormal->getDeclName(); 2785 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2786 2787 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern); 2788 LookupRes = ToClass->noload_lookup(ToName); 2789 EXPECT_EQ(LookupRes.size(), 0u); 2790 LookupRes = ToTU->noload_lookup(ToName); 2791 EXPECT_EQ(LookupRes.size(), 1u); 2792 2793 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u); 2794 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern); 2795 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern); 2796 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2797 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2798 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2799 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2800 } 2801 2802 TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) { 2803 auto Pattern = functionDecl(hasName("f")); 2804 2805 TranslationUnitDecl *FromNormalTU = 2806 getTuDecl("void f();", Lang_CXX, "input0.cc"); 2807 auto *FromNormalF = 2808 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern); 2809 TranslationUnitDecl *FromFriendTU = 2810 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc"); 2811 auto *FromFriendF = 2812 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern); 2813 auto FromNormalName = FromNormalF->getDeclName(); 2814 auto FromFriendName = FromFriendF->getDeclName(); 2815 2816 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2817 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2818 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2819 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2820 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName); 2821 ASSERT_EQ(LookupRes.size(), 1u); 2822 LookupRes = FromFriendTU->noload_lookup(FromFriendName); 2823 ASSERT_EQ(LookupRes.size(), 1u); 2824 2825 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX)); 2826 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2827 auto ToName = ToNormalF->getDeclName(); 2828 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2829 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2830 LookupRes = ToTU->noload_lookup(ToName); 2831 EXPECT_EQ(LookupRes.size(), 1u); 2832 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); 2833 2834 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX)); 2835 LookupRes = ToTU->noload_lookup(ToName); 2836 EXPECT_EQ(LookupRes.size(), 1u); 2837 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2838 2839 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2840 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2841 2842 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2843 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2844 } 2845 2846 TEST_P(ImportFriendFunctions, ImportFriendList) { 2847 TranslationUnitDecl *FromTU = getTuDecl( 2848 "struct X { friend void f(); };" 2849 "void f();", 2850 Lang_CXX, "input0.cc"); 2851 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match( 2852 FromTU, functionDecl(hasName("f"))); 2853 2854 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match( 2855 FromTU, cxxRecordDecl(hasName("X"))); 2856 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl()); 2857 auto FromFriends = FromClass->friends(); 2858 unsigned int FrN = 0; 2859 for (auto Fr : FromFriends) { 2860 ASSERT_EQ(Fr, FromFriend); 2861 ++FrN; 2862 } 2863 ASSERT_EQ(FrN, 1u); 2864 2865 Import(FromFriendF, Lang_CXX); 2866 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2867 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match( 2868 ToTU, cxxRecordDecl(hasName("X"))); 2869 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl()); 2870 auto ToFriends = ToClass->friends(); 2871 FrN = 0; 2872 for (auto Fr : ToFriends) { 2873 EXPECT_EQ(Fr, ToFriend); 2874 ++FrN; 2875 } 2876 EXPECT_EQ(FrN, 1u); 2877 } 2878 2879 AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>, 2880 InnerMatcher) { 2881 if (auto *Typedef = Node.getTypedefNameForAnonDecl()) 2882 return InnerMatcher.matches(*Typedef, Finder, Builder); 2883 return false; 2884 } 2885 2886 TEST_P(ImportDecl, ImportEnumSequential) { 2887 CodeFiles Samples{{"main.c", 2888 {"void foo();" 2889 "void moo();" 2890 "int main() { foo(); moo(); }", 2891 Lang_C}}, 2892 2893 {"foo.c", 2894 {"typedef enum { THING_VALUE } thing_t;" 2895 "void conflict(thing_t type);" 2896 "void foo() { (void)THING_VALUE; }" 2897 "void conflict(thing_t type) {}", 2898 Lang_C}}, 2899 2900 {"moo.c", 2901 {"typedef enum { THING_VALUE } thing_t;" 2902 "void conflict(thing_t type);" 2903 "void moo() { conflict(THING_VALUE); }", 2904 Lang_C}}}; 2905 2906 auto VerificationMatcher = 2907 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))), 2908 hasTypedefForAnonDecl(hasName("thing_t"))); 2909 2910 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))}, 2911 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))}; 2912 2913 testImportSequence( 2914 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo". 2915 // Just check that there is only one enum decl in the result AST. 2916 "main.c", enumDecl(), VerificationMatcher); 2917 2918 // For different import order, result should be the same. 2919 testImportSequence( 2920 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo". 2921 // Check that there is only one enum decl in the result AST. 2922 "main.c", enumDecl(), VerificationMatcher); 2923 } 2924 2925 TEST_P(ImportDecl, ImportFieldOrder) { 2926 MatchVerifier<Decl> Verifier; 2927 testImport("struct declToImport {" 2928 " int b = a + 2;" 2929 " int a = 5;" 2930 "};", 2931 Lang_CXX11, "", Lang_CXX11, Verifier, 2932 recordDecl(hasFieldOrder({"b", "a"}))); 2933 } 2934 2935 const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr> 2936 dependentScopeDeclRefExpr; 2937 2938 TEST_P(ImportExpr, DependentScopeDeclRefExpr) { 2939 MatchVerifier<Decl> Verifier; 2940 testImport("template <typename T> struct S { static T foo; };" 2941 "template <typename T> void declToImport() {" 2942 " (void) S<T>::foo;" 2943 "}" 2944 "void instantiate() { declToImport<int>(); }" 2945 "template <typename T> T S<T>::foo;", 2946 Lang_CXX11, "", Lang_CXX11, Verifier, 2947 functionTemplateDecl(has(functionDecl(has(compoundStmt( 2948 has(cStyleCastExpr(has(dependentScopeDeclRefExpr()))))))))); 2949 2950 testImport("template <typename T> struct S {" 2951 "template<typename S> static void foo(){};" 2952 "};" 2953 "template <typename T> void declToImport() {" 2954 " S<T>::template foo<T>();" 2955 "}" 2956 "void instantiate() { declToImport<int>(); }", 2957 Lang_CXX11, "", Lang_CXX11, Verifier, 2958 functionTemplateDecl(has(functionDecl(has(compoundStmt( 2959 has(callExpr(has(dependentScopeDeclRefExpr()))))))))); 2960 } 2961 2962 const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType> 2963 dependentNameType; 2964 2965 TEST_P(ImportExpr, DependentNameType) { 2966 MatchVerifier<Decl> Verifier; 2967 testImport("template <typename T> struct declToImport {" 2968 " typedef typename T::type dependent_name;" 2969 "};", 2970 Lang_CXX11, "", Lang_CXX11, Verifier, 2971 classTemplateDecl(has( 2972 cxxRecordDecl(has(typedefDecl(has(dependentNameType()))))))); 2973 } 2974 2975 TEST_P(ImportExpr, UnresolvedMemberExpr) { 2976 MatchVerifier<Decl> Verifier; 2977 testImport("struct S { template <typename T> void mem(); };" 2978 "template <typename U> void declToImport() {" 2979 " S s;" 2980 " s.mem<U>();" 2981 "}" 2982 "void instantiate() { declToImport<int>(); }", 2983 Lang_CXX11, "", Lang_CXX11, Verifier, 2984 functionTemplateDecl(has(functionDecl(has( 2985 compoundStmt(has(callExpr(has(unresolvedMemberExpr()))))))))); 2986 } 2987 2988 class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase { 2989 public: 2990 static constexpr auto DefaultCode = R"( 2991 struct A { int x; }; 2992 void f() { 2993 A a; 2994 A a1(a); 2995 A a2(A{}); 2996 a = a1; 2997 a = A{}; 2998 a.~A(); 2999 })"; 3000 3001 template <typename MatcherType> 3002 void testImportOf( 3003 const MatcherType &MethodMatcher, const char *Code = DefaultCode) { 3004 test(MethodMatcher, Code, /*ExpectedCount=*/1u); 3005 } 3006 3007 template <typename MatcherType> 3008 void testNoImportOf( 3009 const MatcherType &MethodMatcher, const char *Code = DefaultCode) { 3010 test(MethodMatcher, Code, /*ExpectedCount=*/0u); 3011 } 3012 3013 private: 3014 template <typename MatcherType> 3015 void test(const MatcherType &MethodMatcher, 3016 const char *Code, unsigned int ExpectedCount) { 3017 auto ClassMatcher = cxxRecordDecl(unless(isImplicit())); 3018 3019 Decl *ToTU = getToTuDecl(Code, Lang_CXX11); 3020 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match( 3021 ToTU, ClassMatcher); 3022 3023 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u); 3024 3025 { 3026 CXXMethodDecl *Method = 3027 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher); 3028 ToClass->removeDecl(Method); 3029 SharedStatePtr->getLookupTable()->remove(Method); 3030 } 3031 3032 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u); 3033 3034 Decl *ImportedClass = nullptr; 3035 { 3036 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc"); 3037 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match( 3038 FromTU, ClassMatcher); 3039 ImportedClass = Import(FromClass, Lang_CXX11); 3040 } 3041 3042 EXPECT_EQ(ToClass, ImportedClass); 3043 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 3044 ExpectedCount); 3045 } 3046 }; 3047 3048 TEST_P(ImportImplicitMethods, DefaultConstructor) { 3049 testImportOf(cxxConstructorDecl(isDefaultConstructor())); 3050 } 3051 3052 TEST_P(ImportImplicitMethods, CopyConstructor) { 3053 testImportOf(cxxConstructorDecl(isCopyConstructor())); 3054 } 3055 3056 TEST_P(ImportImplicitMethods, MoveConstructor) { 3057 testImportOf(cxxConstructorDecl(isMoveConstructor())); 3058 } 3059 3060 TEST_P(ImportImplicitMethods, Destructor) { 3061 testImportOf(cxxDestructorDecl()); 3062 } 3063 3064 TEST_P(ImportImplicitMethods, CopyAssignment) { 3065 testImportOf(cxxMethodDecl(isCopyAssignmentOperator())); 3066 } 3067 3068 TEST_P(ImportImplicitMethods, MoveAssignment) { 3069 testImportOf(cxxMethodDecl(isMoveAssignmentOperator())); 3070 } 3071 3072 TEST_P(ImportImplicitMethods, DoNotImportUserProvided) { 3073 auto Code = R"( 3074 struct A { A() { int x; } }; 3075 )"; 3076 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code); 3077 } 3078 3079 TEST_P(ImportImplicitMethods, DoNotImportDefault) { 3080 auto Code = R"( 3081 struct A { A() = default; }; 3082 )"; 3083 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code); 3084 } 3085 3086 TEST_P(ImportImplicitMethods, DoNotImportDeleted) { 3087 auto Code = R"( 3088 struct A { A() = delete; }; 3089 )"; 3090 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code); 3091 } 3092 3093 TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) { 3094 auto Code = R"( 3095 struct A { void f() { } }; 3096 )"; 3097 testNoImportOf(cxxMethodDecl(hasName("f")), Code); 3098 } 3099 3100 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) { 3101 Decl *ToR1; 3102 { 3103 Decl *FromTU = getTuDecl( 3104 "struct A { };", Lang_CXX, "input0.cc"); 3105 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( 3106 FromTU, cxxRecordDecl(hasName("A"))); 3107 3108 ToR1 = Import(FromR, Lang_CXX); 3109 } 3110 3111 Decl *ToR2; 3112 { 3113 Decl *FromTU = getTuDecl( 3114 "struct A { };", Lang_CXX, "input1.cc"); 3115 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( 3116 FromTU, cxxRecordDecl(hasName("A"))); 3117 3118 ToR2 = Import(FromR, Lang_CXX); 3119 } 3120 3121 EXPECT_EQ(ToR1, ToR2); 3122 } 3123 3124 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) { 3125 Decl *ToR1; 3126 { 3127 Decl *FromTU = getTuDecl( 3128 "struct A { int x; };", Lang_CXX, "input0.cc"); 3129 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( 3130 FromTU, cxxRecordDecl(hasName("A"))); 3131 ToR1 = Import(FromR, Lang_CXX); 3132 } 3133 Decl *ToR2; 3134 { 3135 Decl *FromTU = getTuDecl( 3136 "struct A { unsigned x; };", Lang_CXX, "input1.cc"); 3137 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( 3138 FromTU, cxxRecordDecl(hasName("A"))); 3139 ToR2 = Import(FromR, Lang_CXX); 3140 } 3141 EXPECT_NE(ToR1, ToR2); 3142 } 3143 3144 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) { 3145 Decl *ToF1; 3146 { 3147 Decl *FromTU = getTuDecl( 3148 "struct A { int x; };", Lang_CXX, "input0.cc"); 3149 auto *FromF = FirstDeclMatcher<FieldDecl>().match( 3150 FromTU, fieldDecl(hasName("x"))); 3151 ToF1 = Import(FromF, Lang_CXX); 3152 } 3153 Decl *ToF2; 3154 { 3155 Decl *FromTU = getTuDecl( 3156 "struct A { int x; };", Lang_CXX, "input1.cc"); 3157 auto *FromF = FirstDeclMatcher<FieldDecl>().match( 3158 FromTU, fieldDecl(hasName("x"))); 3159 ToF2 = Import(FromF, Lang_CXX); 3160 } 3161 EXPECT_EQ(ToF1, ToF2); 3162 } 3163 3164 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) { 3165 Decl *ToF1; 3166 { 3167 Decl *FromTU = getTuDecl( 3168 "struct A { int x; };", Lang_CXX, "input0.cc"); 3169 auto *FromF = FirstDeclMatcher<FieldDecl>().match( 3170 FromTU, fieldDecl(hasName("x"))); 3171 ToF1 = Import(FromF, Lang_CXX); 3172 } 3173 Decl *ToF2; 3174 { 3175 Decl *FromTU = getTuDecl( 3176 "struct A { unsigned x; };", Lang_CXX, "input1.cc"); 3177 auto *FromF = FirstDeclMatcher<FieldDecl>().match( 3178 FromTU, fieldDecl(hasName("x"))); 3179 ToF2 = Import(FromF, Lang_CXX); 3180 } 3181 EXPECT_NE(ToF1, ToF2); 3182 } 3183 3184 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) { 3185 Decl *ToM1; 3186 { 3187 Decl *FromTU = getTuDecl( 3188 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc"); 3189 auto *FromM = FirstDeclMatcher<FunctionDecl>().match( 3190 FromTU, functionDecl(hasName("x"), isDefinition())); 3191 ToM1 = Import(FromM, Lang_CXX); 3192 } 3193 Decl *ToM2; 3194 { 3195 Decl *FromTU = getTuDecl( 3196 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc"); 3197 auto *FromM = FirstDeclMatcher<FunctionDecl>().match( 3198 FromTU, functionDecl(hasName("x"), isDefinition())); 3199 ToM2 = Import(FromM, Lang_CXX); 3200 } 3201 EXPECT_EQ(ToM1, ToM2); 3202 } 3203 3204 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) { 3205 Decl *ToM1; 3206 { 3207 Decl *FromTU = getTuDecl( 3208 "struct A { void x(); }; void A::x() { }", 3209 Lang_CXX, "input0.cc"); 3210 auto *FromM = FirstDeclMatcher<FunctionDecl>().match( 3211 FromTU, functionDecl(hasName("x"), isDefinition())); 3212 ToM1 = Import(FromM, Lang_CXX); 3213 } 3214 Decl *ToM2; 3215 { 3216 Decl *FromTU = getTuDecl( 3217 "struct A { void x() const; }; void A::x() const { }", 3218 Lang_CXX, "input1.cc"); 3219 auto *FromM = FirstDeclMatcher<FunctionDecl>().match( 3220 FromTU, functionDecl(hasName("x"), isDefinition())); 3221 ToM2 = Import(FromM, Lang_CXX); 3222 } 3223 EXPECT_NE(ToM1, ToM2); 3224 } 3225 3226 TEST_P(ASTImporterOptionSpecificTestBase, 3227 ImportUnnamedStructsWithRecursingField) { 3228 Decl *FromTU = getTuDecl( 3229 R"( 3230 struct A { 3231 struct { 3232 struct A *next; 3233 } entry0; 3234 struct { 3235 struct A *next; 3236 } entry1; 3237 }; 3238 )", 3239 Lang_C, "input0.cc"); 3240 auto *From = 3241 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A"))); 3242 3243 Import(From, Lang_C); 3244 3245 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 3246 auto *Entry0 = 3247 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0"))); 3248 auto *Entry1 = 3249 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1"))); 3250 auto *R0 = getRecordDecl(Entry0); 3251 auto *R1 = getRecordDecl(Entry1); 3252 EXPECT_NE(R0, R1); 3253 EXPECT_TRUE(MatchVerifier<RecordDecl>().match( 3254 R0, recordDecl(has(fieldDecl(hasName("next")))))); 3255 EXPECT_TRUE(MatchVerifier<RecordDecl>().match( 3256 R1, recordDecl(has(fieldDecl(hasName("next")))))); 3257 } 3258 3259 TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) { 3260 Decl *FromTU = getTuDecl( 3261 R"( 3262 void f(int X, int Y, bool Z) { 3263 (void)[X, Y, Z] { (void)Z; }; 3264 } 3265 )", 3266 Lang_CXX11, "input0.cc"); 3267 auto *FromF = FirstDeclMatcher<FunctionDecl>().match( 3268 FromTU, functionDecl(hasName("f"))); 3269 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11)); 3270 EXPECT_TRUE(ToF); 3271 3272 CXXRecordDecl *FromLambda = 3273 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>( 3274 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass(); 3275 3276 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11)); 3277 EXPECT_TRUE(ToLambda); 3278 3279 // Check if the fields of the lambda class are imported in correct order. 3280 unsigned FromIndex = 0u; 3281 for (auto *FromField : FromLambda->fields()) { 3282 ASSERT_FALSE(FromField->getDeclName()); 3283 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11)); 3284 EXPECT_TRUE(ToField); 3285 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField); 3286 EXPECT_TRUE(ToIndex); 3287 EXPECT_EQ(*ToIndex, FromIndex); 3288 ++FromIndex; 3289 } 3290 3291 EXPECT_EQ(FromIndex, 3u); 3292 } 3293 3294 TEST_P(ASTImporterOptionSpecificTestBase, 3295 MergeFieldDeclsOfClassTemplateSpecialization) { 3296 std::string ClassTemplate = 3297 R"( 3298 template <typename T> 3299 struct X { 3300 int a{0}; // FieldDecl with InitListExpr 3301 X(char) : a(3) {} // (1) 3302 X(int) {} // (2) 3303 }; 3304 )"; 3305 Decl *ToTU = getToTuDecl(ClassTemplate + 3306 R"( 3307 void foo() { 3308 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr 3309 X<char> xc('c'); 3310 } 3311 )", Lang_CXX11); 3312 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3313 ToTU, classTemplateSpecializationDecl(hasName("X"))); 3314 // FieldDecl without InitlistExpr: 3315 auto *ToField = *ToSpec->field_begin(); 3316 ASSERT_TRUE(ToField); 3317 ASSERT_FALSE(ToField->getInClassInitializer()); 3318 Decl *FromTU = getTuDecl(ClassTemplate + 3319 R"( 3320 void bar() { 3321 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr 3322 X<char> xc(1); 3323 } 3324 )", Lang_CXX11); 3325 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3326 FromTU, classTemplateSpecializationDecl(hasName("X"))); 3327 // FieldDecl with InitlistExpr: 3328 auto *FromField = *FromSpec->field_begin(); 3329 ASSERT_TRUE(FromField); 3330 ASSERT_TRUE(FromField->getInClassInitializer()); 3331 3332 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3333 ASSERT_TRUE(ImportedSpec); 3334 EXPECT_EQ(ImportedSpec, ToSpec); 3335 // After the import, the FieldDecl has to be merged, thus it should have the 3336 // InitListExpr. 3337 EXPECT_TRUE(ToField->getInClassInitializer()); 3338 } 3339 3340 TEST_P(ASTImporterOptionSpecificTestBase, 3341 MergeFunctionOfClassTemplateSpecialization) { 3342 std::string ClassTemplate = 3343 R"( 3344 template <typename T> 3345 struct X { 3346 void f() {} 3347 void g() {} 3348 }; 3349 )"; 3350 Decl *ToTU = getToTuDecl(ClassTemplate + 3351 R"( 3352 void foo() { 3353 X<char> x; 3354 x.f(); 3355 } 3356 )", Lang_CXX11); 3357 Decl *FromTU = getTuDecl(ClassTemplate + 3358 R"( 3359 void bar() { 3360 X<char> x; 3361 x.g(); 3362 } 3363 )", Lang_CXX11); 3364 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3365 FromTU, classTemplateSpecializationDecl(hasName("X"))); 3366 auto FunPattern = functionDecl(hasName("g"), 3367 hasParent(classTemplateSpecializationDecl())); 3368 auto *FromFun = 3369 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern); 3370 auto *ToFun = 3371 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern); 3372 ASSERT_TRUE(FromFun->hasBody()); 3373 ASSERT_FALSE(ToFun->hasBody()); 3374 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3375 ASSERT_TRUE(ImportedSpec); 3376 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3377 ToTU, classTemplateSpecializationDecl(hasName("X"))); 3378 EXPECT_EQ(ImportedSpec, ToSpec); 3379 EXPECT_TRUE(ToFun->hasBody()); 3380 } 3381 3382 TEST_P(ASTImporterOptionSpecificTestBase, 3383 ODRViolationOfClassTemplateSpecializationsShouldBeReported) { 3384 std::string ClassTemplate = 3385 R"( 3386 template <typename T> 3387 struct X {}; 3388 )"; 3389 Decl *ToTU = getToTuDecl(ClassTemplate + 3390 R"( 3391 template <> 3392 struct X<char> { 3393 int a; 3394 }; 3395 void foo() { 3396 X<char> x; 3397 } 3398 )", 3399 Lang_CXX11); 3400 Decl *FromTU = getTuDecl(ClassTemplate + 3401 R"( 3402 template <> 3403 struct X<char> { 3404 int b; 3405 }; 3406 void foo() { 3407 X<char> x; 3408 } 3409 )", 3410 Lang_CXX11); 3411 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3412 FromTU, classTemplateSpecializationDecl(hasName("X"))); 3413 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3414 3415 // We expect one (ODR) warning during the import. 3416 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings()); 3417 3418 // The second specialization is different from the first, thus it violates 3419 // ODR, consequently we expect to keep the first specialization only, which is 3420 // already in the "To" context. 3421 EXPECT_FALSE(ImportedSpec); 3422 EXPECT_EQ(1u, 3423 DeclCounter<ClassTemplateSpecializationDecl>().match( 3424 ToTU, classTemplateSpecializationDecl(hasName("X")))); 3425 } 3426 3427 TEST_P(ASTImporterOptionSpecificTestBase, 3428 MergeCtorOfClassTemplateSpecialization) { 3429 std::string ClassTemplate = 3430 R"( 3431 template <typename T> 3432 struct X { 3433 X(char) {} 3434 X(int) {} 3435 }; 3436 )"; 3437 Decl *ToTU = getToTuDecl(ClassTemplate + 3438 R"( 3439 void foo() { 3440 X<char> x('c'); 3441 } 3442 )", Lang_CXX11); 3443 Decl *FromTU = getTuDecl(ClassTemplate + 3444 R"( 3445 void bar() { 3446 X<char> x(1); 3447 } 3448 )", Lang_CXX11); 3449 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3450 FromTU, classTemplateSpecializationDecl(hasName("X"))); 3451 // Match the void(int) ctor. 3452 auto CtorPattern = 3453 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))), 3454 hasParent(classTemplateSpecializationDecl())); 3455 auto *FromCtor = 3456 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern); 3457 auto *ToCtor = 3458 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern); 3459 ASSERT_TRUE(FromCtor->hasBody()); 3460 ASSERT_FALSE(ToCtor->hasBody()); 3461 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3462 ASSERT_TRUE(ImportedSpec); 3463 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3464 ToTU, classTemplateSpecializationDecl(hasName("X"))); 3465 EXPECT_EQ(ImportedSpec, ToSpec); 3466 EXPECT_TRUE(ToCtor->hasBody()); 3467 } 3468 3469 TEST_P(ASTImporterOptionSpecificTestBase, 3470 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) { 3471 auto Code = 3472 R"( 3473 // primary template 3474 template<class T1, class T2, int I> 3475 class A {}; 3476 3477 // partial specialization 3478 template<class T, int I> 3479 class A<T, T*, I> {}; 3480 )"; 3481 Decl *ToTU = getToTuDecl(Code, Lang_CXX11); 3482 Decl *FromTU = getTuDecl(Code, Lang_CXX11); 3483 auto *FromSpec = 3484 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match( 3485 FromTU, classTemplatePartialSpecializationDecl()); 3486 auto *ToSpec = 3487 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match( 3488 ToTU, classTemplatePartialSpecializationDecl()); 3489 3490 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3491 EXPECT_EQ(ImportedSpec, ToSpec); 3492 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match( 3493 ToTU, classTemplatePartialSpecializationDecl())); 3494 } 3495 3496 TEST_P(ASTImporterOptionSpecificTestBase, 3497 ClassTemplateSpecializationsShouldNotBeDuplicated) { 3498 auto Code = 3499 R"( 3500 // primary template 3501 template<class T1, class T2, int I> 3502 class A {}; 3503 3504 // full specialization 3505 template<> 3506 class A<int, int, 1> {}; 3507 )"; 3508 Decl *ToTU = getToTuDecl(Code, Lang_CXX11); 3509 Decl *FromTU = getTuDecl(Code, Lang_CXX11); 3510 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3511 FromTU, classTemplateSpecializationDecl()); 3512 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3513 ToTU, classTemplateSpecializationDecl()); 3514 3515 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3516 EXPECT_EQ(ImportedSpec, ToSpec); 3517 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match( 3518 ToTU, classTemplateSpecializationDecl())); 3519 } 3520 3521 TEST_P(ASTImporterOptionSpecificTestBase, 3522 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) { 3523 std::string PrimaryTemplate = 3524 R"( 3525 template<class T1, class T2, int I> 3526 class A {}; 3527 )"; 3528 auto PartialSpec = 3529 R"( 3530 template<class T, int I> 3531 class A<T, T*, I> {}; 3532 )"; 3533 auto FullSpec = 3534 R"( 3535 template<> 3536 class A<int, int, 1> {}; 3537 )"; 3538 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11); 3539 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11); 3540 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3541 FromTU, classTemplateSpecializationDecl()); 3542 3543 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3544 EXPECT_TRUE(ImportedSpec); 3545 // Check the number of partial specializations. 3546 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match( 3547 ToTU, classTemplatePartialSpecializationDecl())); 3548 // Check the number of full specializations. 3549 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match( 3550 ToTU, classTemplateSpecializationDecl( 3551 unless(classTemplatePartialSpecializationDecl())))); 3552 } 3553 3554 TEST_P(ASTImporterOptionSpecificTestBase, 3555 InitListExprValueKindShouldBeImported) { 3556 Decl *TU = getTuDecl( 3557 R"( 3558 const int &init(); 3559 void foo() { const int &a{init()}; } 3560 )", Lang_CXX11, "input0.cc"); 3561 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a"))); 3562 ASSERT_TRUE(FromD->getAnyInitializer()); 3563 auto *InitExpr = FromD->getAnyInitializer(); 3564 ASSERT_TRUE(InitExpr); 3565 ASSERT_TRUE(InitExpr->isGLValue()); 3566 3567 auto *ToD = Import(FromD, Lang_CXX11); 3568 EXPECT_TRUE(ToD); 3569 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer(); 3570 EXPECT_TRUE(ToInitExpr); 3571 EXPECT_TRUE(ToInitExpr->isGLValue()); 3572 } 3573 3574 struct ImportVariables : ASTImporterOptionSpecificTestBase {}; 3575 3576 TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) { 3577 Decl *FromTU = getTuDecl( 3578 R"( 3579 struct A { 3580 static const int a = 1 + 2; 3581 }; 3582 const int A::a; 3583 )", Lang_CXX, "input1.cc"); 3584 3585 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match( 3586 FromTU, varDecl(hasName("a"))); // Decl with init 3587 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match( 3588 FromTU, varDecl(hasName("a"))); // Decl with definition 3589 ASSERT_NE(FromDWithInit, FromDWithDef); 3590 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit); 3591 3592 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11)); 3593 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11)); 3594 ASSERT_TRUE(ToD0); 3595 ASSERT_TRUE(ToD1); 3596 EXPECT_NE(ToD0, ToD1); 3597 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0); 3598 } 3599 3600 TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) { 3601 auto StructA = 3602 R"( 3603 struct A { 3604 static const int a = 1 + 2; 3605 }; 3606 )"; 3607 Decl *ToTU = getToTuDecl(StructA, Lang_CXX); 3608 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX, 3609 "input1.cc"); 3610 3611 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match( 3612 FromTU, varDecl(hasName("a"))); // Decl with init 3613 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match( 3614 FromTU, varDecl(hasName("a"))); // Decl with definition 3615 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl()); 3616 ASSERT_TRUE(FromDWithInit->getInit()); 3617 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition()); 3618 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition()); 3619 ASSERT_FALSE(FromDWithDef->getInit()); 3620 3621 auto *ToD = FirstDeclMatcher<VarDecl>().match( 3622 ToTU, varDecl(hasName("a"))); // Decl with init 3623 ASSERT_TRUE(ToD->getInit()); 3624 ASSERT_FALSE(ToD->getDefinition()); 3625 3626 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11)); 3627 EXPECT_TRUE(ImportedD->getAnyInitializer()); 3628 EXPECT_TRUE(ImportedD->getDefinition()); 3629 } 3630 3631 TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) { 3632 auto StructA = 3633 R"( 3634 struct A { 3635 static const int a; 3636 }; 3637 )"; 3638 Decl *ToTU = getToTuDecl(StructA, Lang_CXX); 3639 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;", 3640 Lang_CXX, "input1.cc"); 3641 3642 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match( 3643 FromTU, varDecl(hasName("a"))); 3644 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match( 3645 FromTU, varDecl(hasName("a"))); // Decl with definition and with init. 3646 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl()); 3647 ASSERT_FALSE(FromDDeclarationOnly->getInit()); 3648 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition()); 3649 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition()); 3650 ASSERT_TRUE(FromDWithDef->getInit()); 3651 3652 auto *ToD = FirstDeclMatcher<VarDecl>().match( 3653 ToTU, varDecl(hasName("a"))); 3654 ASSERT_FALSE(ToD->getInit()); 3655 ASSERT_FALSE(ToD->getDefinition()); 3656 3657 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11)); 3658 EXPECT_TRUE(ImportedD->getAnyInitializer()); 3659 EXPECT_TRUE(ImportedD->getDefinition()); 3660 } 3661 3662 struct ImportClasses : ASTImporterOptionSpecificTestBase {}; 3663 3664 TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) { 3665 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C); 3666 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc"); 3667 auto Pattern = recordDecl(hasName("X"), unless(isImplicit())); 3668 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern); 3669 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern); 3670 3671 Decl *ImportedDef = Import(FromDef, Lang_C); 3672 3673 EXPECT_NE(ImportedDef, ToProto); 3674 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u); 3675 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern); 3676 EXPECT_TRUE(ImportedDef == ToDef); 3677 EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); 3678 EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); 3679 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto); 3680 } 3681 3682 TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) { 3683 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX); 3684 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc"); 3685 auto Pattern = recordDecl(hasName("X"), unless(isImplicit())); 3686 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern); 3687 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern); 3688 3689 Decl *ImportedDef = Import(FromDef, Lang_CXX); 3690 3691 EXPECT_NE(ImportedDef, ToProto); 3692 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u); 3693 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern); 3694 EXPECT_TRUE(ImportedDef == ToDef); 3695 EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); 3696 EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); 3697 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto); 3698 } 3699 3700 TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) { 3701 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc"); 3702 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc"); 3703 auto Pattern = recordDecl(hasName("X"), unless(isImplicit())); 3704 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern); 3705 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern); 3706 3707 Decl *ImportedProto = Import(FromProto, Lang_C); 3708 Decl *ImportedDef = Import(FromDef, Lang_C); 3709 Decl *ToTU = ImportedDef->getTranslationUnitDecl(); 3710 3711 EXPECT_NE(ImportedDef, ImportedProto); 3712 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u); 3713 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern); 3714 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern); 3715 EXPECT_TRUE(ImportedDef == ToDef); 3716 EXPECT_TRUE(ImportedProto == ToProto); 3717 EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); 3718 EXPECT_FALSE(ToProto->isThisDeclarationADefinition()); 3719 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto); 3720 } 3721 3722 3723 struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {}; 3724 3725 TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) { 3726 Decl *FromTU = getTuDecl( 3727 R"( 3728 class A { 3729 template <int I> class F {}; 3730 class X { 3731 template <int I> friend class F; 3732 }; 3733 }; 3734 )", 3735 Lang_CXX, "input0.cc"); 3736 3737 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match( 3738 FromTU, cxxRecordDecl(hasName("F"), isDefinition())); 3739 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match( 3740 FromTU, cxxRecordDecl(hasName("F"))); 3741 3742 ASSERT_TRUE(FromClass); 3743 ASSERT_TRUE(FromFriendClass); 3744 ASSERT_NE(FromClass, FromFriendClass); 3745 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass); 3746 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass); 3747 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(), 3748 FromClass->getDescribedClassTemplate()); 3749 3750 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX)); 3751 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX)); 3752 3753 EXPECT_TRUE(ToClass); 3754 EXPECT_TRUE(ToFriendClass); 3755 EXPECT_NE(ToClass, ToFriendClass); 3756 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass); 3757 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass); 3758 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(), 3759 ToClass->getDescribedClassTemplate()); 3760 } 3761 3762 TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) { 3763 Decl *FromTu = getTuDecl( 3764 R"( 3765 class declToImport { 3766 friend class declToImport; 3767 }; 3768 )", 3769 Lang_CXX, "input.cc"); 3770 3771 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match( 3772 FromTu, cxxRecordDecl(hasName("declToImport"))); 3773 auto *ToD = Import(FromD, Lang_CXX); 3774 auto Pattern = cxxRecordDecl(has(friendDecl())); 3775 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern)); 3776 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern)); 3777 } 3778 3779 TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) { 3780 Decl *FromTu = getTuDecl( 3781 R"( 3782 template<class A> class declToImport { 3783 template<class A1> friend class declToImport; 3784 }; 3785 )", 3786 Lang_CXX, "input.cc"); 3787 3788 auto *FromD = 3789 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl()); 3790 auto *ToD = Import(FromD, Lang_CXX); 3791 3792 auto Pattern = classTemplateDecl( 3793 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl())))))); 3794 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern)); 3795 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern)); 3796 3797 auto *Class = 3798 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl()); 3799 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl()); 3800 EXPECT_NE(Friend->getFriendDecl(), Class); 3801 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class); 3802 } 3803 3804 TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) { 3805 auto Pattern = classTemplateSpecializationDecl(hasName("X")); 3806 3807 ClassTemplateSpecializationDecl *Imported1; 3808 { 3809 Decl *FromTU = getTuDecl("template<class T> class X;" 3810 "struct Y { friend class X<int>; };", 3811 Lang_CXX, "input0.cc"); 3812 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3813 FromTU, Pattern); 3814 3815 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX)); 3816 } 3817 ClassTemplateSpecializationDecl *Imported2; 3818 { 3819 Decl *FromTU = getTuDecl("template<class T> class X;" 3820 "template<> class X<int>{};" 3821 "struct Z { friend class X<int>; };", 3822 Lang_CXX, "input1.cc"); 3823 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3824 FromTU, Pattern); 3825 3826 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX)); 3827 } 3828 3829 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 3830 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern), 3831 2u); 3832 ASSERT_TRUE(Imported2->getPreviousDecl()); 3833 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1); 3834 } 3835 3836 TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) { 3837 Decl *FromTU0 = getTuDecl( 3838 R"( 3839 class X { 3840 class Y; 3841 }; 3842 class X::Y { 3843 template <typename T> 3844 friend class F; // The decl context of F is the global namespace. 3845 }; 3846 )", 3847 Lang_CXX, "input0.cc"); 3848 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match( 3849 FromTU0, classTemplateDecl(hasName("F"))); 3850 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX)); 3851 Decl *FromTU1 = getTuDecl( 3852 R"( 3853 template <typename T> 3854 class F {}; 3855 )", 3856 Lang_CXX, "input1.cc"); 3857 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match( 3858 FromTU1, classTemplateDecl(hasName("F"))); 3859 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX)); 3860 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(), 3861 Imported1->getTemplatedDecl()->getTypeForDecl()); 3862 } 3863 3864 TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) { 3865 Decl *From, *To; 3866 std::tie(From, To) = 3867 getImportedDecl("class declToImport {};", Lang_CXX, 3868 "class Y { friend class declToImport; };", Lang_CXX); 3869 auto *Imported = cast<CXXRecordDecl>(To); 3870 3871 EXPECT_TRUE(Imported->getPreviousDecl()); 3872 } 3873 3874 TEST_P(ImportFriendClasses, 3875 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) { 3876 Decl *ToTU = getToTuDecl( 3877 R"( 3878 class X { 3879 class Y; 3880 }; 3881 class X::Y { 3882 template <typename T> 3883 friend class F; // The decl context of F is the global namespace. 3884 }; 3885 )", 3886 Lang_CXX); 3887 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match( 3888 ToTU, classTemplateDecl(hasName("F"))); 3889 Decl *FromTU = getTuDecl( 3890 R"( 3891 template <typename T> 3892 class F {}; 3893 )", 3894 Lang_CXX, "input0.cc"); 3895 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match( 3896 FromTU, classTemplateDecl(hasName("F"))); 3897 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX)); 3898 EXPECT_TRUE(ImportedDef->getPreviousDecl()); 3899 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl()); 3900 EXPECT_EQ(ToDecl->getTemplatedDecl(), 3901 ImportedDef->getTemplatedDecl()->getPreviousDecl()); 3902 } 3903 3904 TEST_P(ImportFriendClasses, 3905 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) { 3906 Decl *FromTU0 = getTuDecl( 3907 R"( 3908 class X { 3909 class Y; 3910 }; 3911 class X::Y { 3912 template <typename T> 3913 friend class F; // The decl context of F is the global namespace. 3914 }; 3915 )", 3916 Lang_CXX, "input0.cc"); 3917 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match( 3918 FromTU0, classTemplateDecl(hasName("F"))); 3919 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX)); 3920 Decl *FromTU1 = getTuDecl( 3921 R"( 3922 template <typename T> 3923 class F {}; 3924 )", 3925 Lang_CXX, "input1.cc"); 3926 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match( 3927 FromTU1, classTemplateDecl(hasName("F"))); 3928 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX)); 3929 EXPECT_TRUE(ImportedDef->getPreviousDecl()); 3930 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl()); 3931 EXPECT_EQ(ImportedFwd->getTemplatedDecl(), 3932 ImportedDef->getTemplatedDecl()->getPreviousDecl()); 3933 } 3934 3935 TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) { 3936 Decl *FromTU0 = getTuDecl( 3937 R"( 3938 class X { 3939 class Y; 3940 }; 3941 class X::Y { 3942 friend class F; // The decl context of F is the global namespace. 3943 }; 3944 )", 3945 Lang_CXX, "input0.cc"); 3946 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl()); 3947 QualType FT = Friend->getFriendType()->getType(); 3948 FT = FromTU0->getASTContext().getCanonicalType(FT); 3949 auto *Fwd = cast<TagType>(FT)->getDecl(); 3950 auto *ImportedFwd = Import(Fwd, Lang_CXX); 3951 Decl *FromTU1 = getTuDecl( 3952 R"( 3953 class F {}; 3954 )", 3955 Lang_CXX, "input1.cc"); 3956 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match( 3957 FromTU1, cxxRecordDecl(hasName("F"))); 3958 auto *ImportedDef = Import(Definition, Lang_CXX); 3959 EXPECT_TRUE(ImportedDef->getPreviousDecl()); 3960 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl()); 3961 } 3962 3963 TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) { 3964 auto *Code = R"( 3965 template <class T> 3966 struct X { 3967 friend void foo(){} 3968 }; 3969 )"; 3970 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX); 3971 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match( 3972 ToTU, functionDecl(hasName("foo"))); 3973 3974 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc"); 3975 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match( 3976 FromTU, functionDecl(hasName("foo"))); 3977 auto *ImportedFoo = Import(FromFoo, Lang_CXX); 3978 EXPECT_EQ(ImportedFoo, ToFoo); 3979 } 3980 3981 struct DeclContextTest : ASTImporterOptionSpecificTestBase {}; 3982 3983 TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { 3984 Decl *TU = getTuDecl( 3985 R"( 3986 namespace NS { 3987 3988 template <typename T> 3989 struct S {}; 3990 template struct S<int>; 3991 3992 inline namespace INS { 3993 template <typename T> 3994 struct S {}; 3995 template struct S<int>; 3996 } 3997 3998 } 3999 )", Lang_CXX11, "input0.cc"); 4000 auto *NS = FirstDeclMatcher<NamespaceDecl>().match( 4001 TU, namespaceDecl()); 4002 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 4003 TU, classTemplateSpecializationDecl()); 4004 ASSERT_TRUE(NS->containsDecl(Spec)); 4005 4006 NS->removeDecl(Spec); 4007 EXPECT_FALSE(NS->containsDecl(Spec)); 4008 } 4009 4010 TEST_P(DeclContextTest, 4011 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) { 4012 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX); 4013 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A"))); 4014 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A"))); 4015 4016 // Investigate the list. 4017 auto *DC = A0->getDeclContext(); 4018 ASSERT_TRUE(DC->containsDecl(A0)); 4019 ASSERT_TRUE(DC->containsDecl(A1)); 4020 4021 // Investigate the lookup table. 4022 auto *Map = DC->getLookupPtr(); 4023 ASSERT_TRUE(Map); 4024 auto I = Map->find(A0->getDeclName()); 4025 ASSERT_NE(I, Map->end()); 4026 StoredDeclsList &L = I->second; 4027 // The lookup table contains the most recent decl of A. 4028 ASSERT_NE(L.getAsDecl(), A0); 4029 ASSERT_EQ(L.getAsDecl(), A1); 4030 4031 ASSERT_TRUE(L.getAsDecl()); 4032 // Simulate the private function DeclContext::reconcileExternalVisibleStorage. 4033 // The point here is to have a Vec with only one element, which is not the 4034 // one we are going to delete from the DC later. 4035 L.setHasExternalDecls(); 4036 ASSERT_TRUE(L.getAsVector()); 4037 ASSERT_EQ(1u, L.getAsVector()->size()); 4038 4039 // This asserts in the old implementation. 4040 DC->removeDecl(A0); 4041 EXPECT_FALSE(DC->containsDecl(A0)); 4042 } 4043 4044 struct ImportFunctionTemplateSpecializations 4045 : ASTImporterOptionSpecificTestBase {}; 4046 4047 TEST_P(ImportFunctionTemplateSpecializations, 4048 TUshouldNotContainFunctionTemplateImplicitInstantiation) { 4049 4050 Decl *FromTU = getTuDecl( 4051 R"( 4052 template<class T> 4053 int f() { return 0; } 4054 void foo() { f<int>(); } 4055 )", 4056 Lang_CXX, "input0.cc"); 4057 4058 // Check that the function template instantiation is NOT the child of the TU. 4059 auto Pattern = translationUnitDecl( 4060 unless(has(functionDecl(hasName("f"), isTemplateInstantiation())))); 4061 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern)); 4062 4063 auto *Foo = FirstDeclMatcher<FunctionDecl>().match( 4064 FromTU, functionDecl(hasName("foo"))); 4065 ASSERT_TRUE(Import(Foo, Lang_CXX)); 4066 4067 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 4068 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern)); 4069 } 4070 4071 TEST_P(ImportFunctionTemplateSpecializations, 4072 TUshouldNotContainFunctionTemplateExplicitInstantiation) { 4073 4074 Decl *FromTU = getTuDecl( 4075 R"( 4076 template<class T> 4077 int f() { return 0; } 4078 template int f<int>(); 4079 )", 4080 Lang_CXX, "input0.cc"); 4081 4082 // Check that the function template instantiation is NOT the child of the TU. 4083 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation()); 4084 auto Pattern = translationUnitDecl(unless(has(Instantiation))); 4085 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern)); 4086 4087 ASSERT_TRUE( 4088 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX)); 4089 4090 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 4091 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern)); 4092 } 4093 4094 TEST_P(ImportFunctionTemplateSpecializations, 4095 TUshouldContainFunctionTemplateSpecialization) { 4096 4097 Decl *FromTU = getTuDecl( 4098 R"( 4099 template<class T> 4100 int f() { return 0; } 4101 template <> int f<int>() { return 4; } 4102 )", 4103 Lang_CXX, "input0.cc"); 4104 4105 // Check that the function template specialization is the child of the TU. 4106 auto Specialization = 4107 functionDecl(hasName("f"), isExplicitTemplateSpecialization()); 4108 auto Pattern = translationUnitDecl(has(Specialization)); 4109 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern)); 4110 4111 ASSERT_TRUE( 4112 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX)); 4113 4114 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 4115 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern)); 4116 } 4117 4118 TEST_P(ImportFunctionTemplateSpecializations, 4119 FunctionTemplateSpecializationRedeclChain) { 4120 4121 Decl *FromTU = getTuDecl( 4122 R"( 4123 template<class T> 4124 int f() { return 0; } 4125 template <> int f<int>() { return 4; } 4126 )", 4127 Lang_CXX, "input0.cc"); 4128 4129 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(), 4130 hasParent(translationUnitDecl())); 4131 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec); 4132 { 4133 auto *TU = FromTU; 4134 auto *SpecD = FromSpecD; 4135 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match( 4136 TU, functionTemplateDecl()); 4137 auto *FirstSpecD = *(TemplateD->spec_begin()); 4138 ASSERT_EQ(SpecD, FirstSpecD); 4139 ASSERT_TRUE(SpecD->getPreviousDecl()); 4140 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl()) 4141 ->doesThisDeclarationHaveABody()); 4142 } 4143 4144 ASSERT_TRUE(Import(FromSpecD, Lang_CXX)); 4145 4146 { 4147 auto *TU = ToAST->getASTContext().getTranslationUnitDecl(); 4148 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec); 4149 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match( 4150 TU, functionTemplateDecl()); 4151 auto *FirstSpecD = *(TemplateD->spec_begin()); 4152 EXPECT_EQ(SpecD, FirstSpecD); 4153 ASSERT_TRUE(SpecD->getPreviousDecl()); 4154 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl()) 4155 ->doesThisDeclarationHaveABody()); 4156 } 4157 } 4158 4159 TEST_P(ImportFunctionTemplateSpecializations, 4160 MatchNumberOfFunctionTemplateSpecializations) { 4161 4162 Decl *FromTU = getTuDecl( 4163 R"( 4164 template <typename T> constexpr int f() { return 0; } 4165 template <> constexpr int f<int>() { return 4; } 4166 void foo() { 4167 static_assert(f<char>() == 0, ""); 4168 static_assert(f<int>() == 4, ""); 4169 } 4170 )", 4171 Lang_CXX11, "input0.cc"); 4172 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 4173 FromTU, functionDecl(hasName("foo"))); 4174 4175 Import(FromD, Lang_CXX11); 4176 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 4177 EXPECT_EQ( 4178 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))), 4179 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f")))); 4180 } 4181 4182 TEST_P(ASTImporterOptionSpecificTestBase, 4183 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) { 4184 { 4185 Decl *FromTU = getTuDecl( 4186 R"( 4187 template <typename T> 4188 struct B; 4189 )", 4190 Lang_CXX, "input0.cc"); 4191 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match( 4192 FromTU, classTemplateDecl(hasName("B"))); 4193 4194 Import(FromD, Lang_CXX); 4195 } 4196 4197 { 4198 Decl *FromTU = getTuDecl( 4199 R"( 4200 template <typename T> 4201 struct B { 4202 void f(); 4203 B* b; 4204 }; 4205 )", 4206 Lang_CXX, "input1.cc"); 4207 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match( 4208 FromTU, functionDecl(hasName("f"))); 4209 Import(FromD, Lang_CXX); 4210 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match( 4211 FromTU, classTemplateDecl(hasName("B"))); 4212 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX)); 4213 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition()); 4214 4215 // We expect no (ODR) warning during the import. 4216 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 4217 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings()); 4218 } 4219 } 4220 4221 TEST_P(ASTImporterOptionSpecificTestBase, 4222 ImportingTypedefShouldImportTheCompleteType) { 4223 // We already have an incomplete underlying type in the "To" context. 4224 auto Code = 4225 R"( 4226 template <typename T> 4227 struct S { 4228 void foo(); 4229 }; 4230 using U = S<int>; 4231 )"; 4232 Decl *ToTU = getToTuDecl(Code, Lang_CXX11); 4233 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU, 4234 typedefNameDecl(hasName("U"))); 4235 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType()); 4236 4237 // The "From" context has the same typedef, but the underlying type is 4238 // complete this time. 4239 Decl *FromTU = getTuDecl(std::string(Code) + 4240 R"( 4241 void foo(U* u) { 4242 u->foo(); 4243 } 4244 )", Lang_CXX11); 4245 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU, 4246 typedefNameDecl(hasName("U"))); 4247 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType()); 4248 4249 // The imported type should be complete. 4250 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11)); 4251 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType()); 4252 } 4253 4254 TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) { 4255 auto Code = 4256 R"( 4257 template<class T> 4258 int f() { return 0; } 4259 template <> int f<int>() { return 4; } 4260 )"; 4261 4262 Decl *FromTU = getTuDecl(Code, Lang_CXX); 4263 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, 4264 functionDecl(hasName("f"), isExplicitTemplateSpecialization())); 4265 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u); 4266 4267 auto *ToD = Import(FromD, Lang_CXX); 4268 // The template parameter list should exist. 4269 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u); 4270 } 4271 4272 struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {}; 4273 4274 TEST_P(ASTImporterLookupTableTest, OneDecl) { 4275 auto *ToTU = getToTuDecl("int a;", Lang_CXX); 4276 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a"))); 4277 ASTImporterLookupTable LT(*ToTU); 4278 auto Res = LT.lookup(ToTU, D->getDeclName()); 4279 ASSERT_EQ(Res.size(), 1u); 4280 EXPECT_EQ(*Res.begin(), D); 4281 } 4282 4283 static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) { 4284 for (Decl *D : DC->decls()) { 4285 if (auto *ND = dyn_cast<NamedDecl>(D)) 4286 if (ND->getDeclName() == Name) 4287 return ND; 4288 } 4289 return nullptr; 4290 } 4291 4292 TEST_P(ASTImporterLookupTableTest, 4293 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) { 4294 auto *Code = R"( 4295 template <class T> 4296 struct X { 4297 friend void foo(){} 4298 }; 4299 )"; 4300 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX); 4301 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match( 4302 ToTU, classTemplateDecl(hasName("X"))); 4303 auto *Foo = FirstDeclMatcher<FunctionDecl>().match( 4304 ToTU, functionDecl(hasName("foo"))); 4305 DeclContext *FooDC = Foo->getDeclContext(); 4306 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext(); 4307 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl()); 4308 ASSERT_EQ(cast<Decl>(FooDC), ToTU); 4309 DeclarationName FooName = Foo->getDeclName(); 4310 4311 // Cannot find in the LookupTable of its DC (TUDecl) 4312 SmallVector<NamedDecl *, 2> FoundDecls; 4313 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls); 4314 EXPECT_EQ(FoundDecls.size(), 0u); 4315 4316 // Cannot find in the LookupTable of its LexicalDC (X) 4317 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls); 4318 EXPECT_EQ(FoundDecls.size(), 0u); 4319 4320 // Can't find in the list of Decls of the DC. 4321 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr); 4322 4323 // Can't find in the list of Decls of the LexicalDC 4324 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr); 4325 4326 // ASTImporter specific lookup finds it. 4327 ASTImporterLookupTable LT(*ToTU); 4328 auto Res = LT.lookup(FooDC, Foo->getDeclName()); 4329 ASSERT_EQ(Res.size(), 1u); 4330 EXPECT_EQ(*Res.begin(), Foo); 4331 } 4332 4333 TEST_P(ASTImporterLookupTableTest, 4334 FwdDeclStructShouldBeFoundByImporterSpecificLookup) { 4335 TranslationUnitDecl *ToTU = 4336 getToTuDecl("struct A { struct Foo *p; };", Lang_C); 4337 auto *Foo = 4338 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo"))); 4339 auto *A = 4340 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A"))); 4341 DeclContext *FooDC = Foo->getDeclContext(); 4342 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext(); 4343 ASSERT_EQ(cast<Decl>(FooLexicalDC), A); 4344 ASSERT_EQ(cast<Decl>(FooDC), ToTU); 4345 DeclarationName FooName = Foo->getDeclName(); 4346 4347 // Cannot find in the LookupTable of its DC (TUDecl). 4348 SmallVector<NamedDecl *, 2> FoundDecls; 4349 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls); 4350 EXPECT_EQ(FoundDecls.size(), 0u); 4351 4352 // Cannot find in the LookupTable of its LexicalDC (A). 4353 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls); 4354 EXPECT_EQ(FoundDecls.size(), 0u); 4355 4356 // Can't find in the list of Decls of the DC. 4357 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr); 4358 4359 // Can find in the list of Decls of the LexicalDC. 4360 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo); 4361 4362 // ASTImporter specific lookup finds it. 4363 ASTImporterLookupTable LT(*ToTU); 4364 auto Res = LT.lookup(FooDC, Foo->getDeclName()); 4365 ASSERT_EQ(Res.size(), 1u); 4366 EXPECT_EQ(*Res.begin(), Foo); 4367 } 4368 4369 TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) { 4370 TranslationUnitDecl *ToTU = 4371 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C); 4372 DeclarationName VName = FirstDeclMatcher<VarDecl>() 4373 .match(ToTU, varDecl(hasName("V"))) 4374 ->getDeclName(); 4375 auto *A = 4376 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A"))); 4377 auto *B = 4378 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B"))); 4379 4380 ASTImporterLookupTable LT(*ToTU); 4381 4382 auto Res = LT.lookup(cast<DeclContext>(A), VName); 4383 ASSERT_EQ(Res.size(), 1u); 4384 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match( 4385 ToTU, fieldDecl(hasName("V"), 4386 hasParent(recordDecl(hasName("A")))))); 4387 Res = LT.lookup(cast<DeclContext>(B), VName); 4388 ASSERT_EQ(Res.size(), 1u); 4389 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match( 4390 ToTU, fieldDecl(hasName("V"), 4391 hasParent(recordDecl(hasName("B")))))); 4392 Res = LT.lookup(ToTU, VName); 4393 ASSERT_EQ(Res.size(), 1u); 4394 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match( 4395 ToTU, varDecl(hasName("V"), 4396 hasParent(translationUnitDecl())))); 4397 } 4398 4399 TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) { 4400 TranslationUnitDecl *ToTU = getToTuDecl( 4401 R"( 4402 void foo(); 4403 void foo(int); 4404 void foo(int, int); 4405 )", 4406 Lang_CXX); 4407 4408 ASTImporterLookupTable LT(*ToTU); 4409 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl()); 4410 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl()); 4411 DeclarationName Name = F0->getDeclName(); 4412 auto Res = LT.lookup(ToTU, Name); 4413 EXPECT_EQ(Res.size(), 3u); 4414 EXPECT_EQ(Res.count(F0), 1u); 4415 EXPECT_EQ(Res.count(F2), 1u); 4416 } 4417 4418 TEST_P(ASTImporterLookupTableTest, 4419 DifferentOperatorsShouldHaveDifferentResultSet) { 4420 TranslationUnitDecl *ToTU = getToTuDecl( 4421 R"( 4422 struct X{}; 4423 void operator+(X, X); 4424 void operator-(X, X); 4425 )", 4426 Lang_CXX); 4427 4428 ASTImporterLookupTable LT(*ToTU); 4429 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match( 4430 ToTU, functionDecl(hasOverloadedOperatorName("+"))); 4431 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match( 4432 ToTU, functionDecl(hasOverloadedOperatorName("-"))); 4433 DeclarationName NamePlus = FPlus->getDeclName(); 4434 auto ResPlus = LT.lookup(ToTU, NamePlus); 4435 EXPECT_EQ(ResPlus.size(), 1u); 4436 EXPECT_EQ(ResPlus.count(FPlus), 1u); 4437 EXPECT_EQ(ResPlus.count(FMinus), 0u); 4438 DeclarationName NameMinus = FMinus->getDeclName(); 4439 auto ResMinus = LT.lookup(ToTU, NameMinus); 4440 EXPECT_EQ(ResMinus.size(), 1u); 4441 EXPECT_EQ(ResMinus.count(FMinus), 1u); 4442 EXPECT_EQ(ResMinus.count(FPlus), 0u); 4443 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin()); 4444 } 4445 4446 TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) { 4447 TranslationUnitDecl *ToTU = getToTuDecl( 4448 R"( 4449 struct X {}; 4450 void operator+(X, X); 4451 )", 4452 Lang_CXX); 4453 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match( 4454 ToTU, functionDecl(hasOverloadedOperatorName("+"))); 4455 4456 Decl *FromTU = getTuDecl( 4457 R"( 4458 struct X {}; 4459 void operator+(X, X); 4460 )", 4461 Lang_CXX); 4462 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match( 4463 FromTU, functionDecl(hasOverloadedOperatorName("+"))); 4464 4465 // FromPlus have a different TU, thus its DeclarationName is different too. 4466 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName()); 4467 4468 ASTImporterLookupTable LT(*ToTU); 4469 auto Res = LT.lookup(ToTU, ToPlus->getDeclName()); 4470 ASSERT_EQ(Res.size(), 1u); 4471 EXPECT_EQ(*Res.begin(), ToPlus); 4472 4473 // FromPlus have a different TU, thus its DeclarationName is different too. 4474 Res = LT.lookup(ToTU, FromPlus->getDeclName()); 4475 ASSERT_EQ(Res.size(), 0u); 4476 } 4477 4478 static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) { 4479 QualType Ty = FD->getFriendType()->getType().getCanonicalType(); 4480 return cast<RecordType>(Ty)->getDecl(); 4481 } 4482 4483 TEST_P(ASTImporterLookupTableTest, 4484 LookupFindsFwdFriendClassDeclWithElaboratedType) { 4485 TranslationUnitDecl *ToTU = getToTuDecl( 4486 R"( 4487 class Y { friend class F; }; 4488 )", 4489 Lang_CXX); 4490 4491 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent. 4492 // So we must dig up the underlying CXXRecordDecl. 4493 ASTImporterLookupTable LT(*ToTU); 4494 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl()); 4495 const RecordDecl *RD = getRecordDeclOfFriend(FriendD); 4496 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match( 4497 ToTU, cxxRecordDecl(hasName("Y"))); 4498 4499 DeclarationName Name = RD->getDeclName(); 4500 auto Res = LT.lookup(ToTU, Name); 4501 EXPECT_EQ(Res.size(), 1u); 4502 EXPECT_EQ(*Res.begin(), RD); 4503 4504 Res = LT.lookup(Y, Name); 4505 EXPECT_EQ(Res.size(), 0u); 4506 } 4507 4508 TEST_P(ASTImporterLookupTableTest, 4509 LookupFindsFwdFriendClassDeclWithUnelaboratedType) { 4510 TranslationUnitDecl *ToTU = getToTuDecl( 4511 R"( 4512 class F; 4513 class Y { friend F; }; 4514 )", 4515 Lang_CXX11); 4516 4517 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent. 4518 // So we must dig up the underlying CXXRecordDecl. 4519 ASTImporterLookupTable LT(*ToTU); 4520 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl()); 4521 const RecordDecl *RD = getRecordDeclOfFriend(FriendD); 4522 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y"))); 4523 4524 DeclarationName Name = RD->getDeclName(); 4525 auto Res = LT.lookup(ToTU, Name); 4526 EXPECT_EQ(Res.size(), 1u); 4527 EXPECT_EQ(*Res.begin(), RD); 4528 4529 Res = LT.lookup(Y, Name); 4530 EXPECT_EQ(Res.size(), 0u); 4531 } 4532 4533 TEST_P(ASTImporterLookupTableTest, 4534 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) { 4535 TranslationUnitDecl *ToTU = getToTuDecl( 4536 R"( 4537 class F; 4538 using alias_of_f = F; 4539 class Y { friend alias_of_f; }; 4540 )", 4541 Lang_CXX11); 4542 4543 // ASTImporterLookupTable constructor handles using declarations correctly, 4544 // no assert is expected. 4545 ASTImporterLookupTable LT(*ToTU); 4546 4547 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match( 4548 ToTU, typeAliasDecl(hasName("alias_of_f"))); 4549 DeclarationName Name = Alias->getDeclName(); 4550 auto Res = LT.lookup(ToTU, Name); 4551 EXPECT_EQ(Res.count(Alias), 1u); 4552 } 4553 4554 TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) { 4555 TranslationUnitDecl *ToTU = getToTuDecl( 4556 R"( 4557 class Y { template <class T> friend class F; }; 4558 )", 4559 Lang_CXX); 4560 4561 ASTImporterLookupTable LT(*ToTU); 4562 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match( 4563 ToTU, classTemplateDecl(hasName("F"))); 4564 DeclarationName Name = F->getDeclName(); 4565 auto Res = LT.lookup(ToTU, Name); 4566 EXPECT_EQ(Res.size(), 2u); 4567 EXPECT_EQ(Res.count(F), 1u); 4568 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u); 4569 } 4570 4571 TEST_P(ASTImporterLookupTableTest, DependentFriendClass) { 4572 TranslationUnitDecl *ToTU = getToTuDecl( 4573 R"( 4574 template <typename T> 4575 class F; 4576 4577 template <typename T> 4578 class Y { 4579 friend class F<T>; 4580 }; 4581 )", 4582 Lang_CXX); 4583 4584 ASTImporterLookupTable LT(*ToTU); 4585 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match( 4586 ToTU, classTemplateDecl(hasName("F"))); 4587 DeclarationName Name = F->getDeclName(); 4588 auto Res = LT.lookup(ToTU, Name); 4589 EXPECT_EQ(Res.size(), 2u); 4590 EXPECT_EQ(Res.count(F), 1u); 4591 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u); 4592 } 4593 4594 TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) { 4595 TranslationUnitDecl *ToTU = getToTuDecl( 4596 R"( 4597 template <typename T> 4598 class F; 4599 4600 class Y { 4601 friend class F<int>; 4602 }; 4603 )", 4604 Lang_CXX); 4605 4606 ASTImporterLookupTable LT(*ToTU); 4607 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match( 4608 ToTU, classTemplateDecl(hasName("F"))); 4609 DeclarationName Name = F->getDeclName(); 4610 auto Res = LT.lookup(ToTU, Name); 4611 ASSERT_EQ(Res.size(), 3u); 4612 EXPECT_EQ(Res.count(F), 1u); 4613 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u); 4614 EXPECT_EQ(Res.count(*F->spec_begin()), 1u); 4615 } 4616 4617 TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) { 4618 TranslationUnitDecl *ToTU = getToTuDecl( 4619 R"( 4620 class Y { friend void F(); }; 4621 )", 4622 Lang_CXX); 4623 4624 ASTImporterLookupTable LT(*ToTU); 4625 auto *F = 4626 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F"))); 4627 DeclarationName Name = F->getDeclName(); 4628 auto Res = LT.lookup(ToTU, Name); 4629 EXPECT_EQ(Res.size(), 1u); 4630 EXPECT_EQ(*Res.begin(), F); 4631 } 4632 4633 TEST_P(ASTImporterLookupTableTest, 4634 LookupFindsDeclsInClassTemplateSpecialization) { 4635 TranslationUnitDecl *ToTU = getToTuDecl( 4636 R"( 4637 template <typename T> 4638 struct X { 4639 int F; 4640 }; 4641 void foo() { 4642 X<char> xc; 4643 } 4644 )", 4645 Lang_CXX); 4646 4647 ASTImporterLookupTable LT(*ToTU); 4648 4649 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match( 4650 ToTU, classTemplateDecl(hasName("X"))); 4651 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match( 4652 ToTU, 4653 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl()))))); 4654 4655 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 4656 ToTU, classTemplateSpecializationDecl(hasName("X"))); 4657 FieldDecl *FieldInSpec = *Spec->field_begin(); 4658 ASSERT_TRUE(FieldInSpec); 4659 4660 DeclarationName Name = FieldInSpec->getDeclName(); 4661 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl()); 4662 4663 SmallVector<NamedDecl *, 2> FoundDecls; 4664 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); 4665 EXPECT_EQ(FoundDecls.size(), 1u); 4666 EXPECT_EQ(FoundDecls[0], FieldInTemplate); 4667 4668 auto Res = LT.lookup(TemplateDC, Name); 4669 ASSERT_EQ(Res.size(), 1u); 4670 EXPECT_EQ(*Res.begin(), FieldInTemplate); 4671 4672 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name, 4673 FoundDecls); 4674 EXPECT_EQ(FoundDecls.size(), 1u); 4675 EXPECT_EQ(FoundDecls[0], FieldInSpec); 4676 4677 Res = LT.lookup(cast<DeclContext>(Spec), Name); 4678 ASSERT_EQ(Res.size(), 1u); 4679 EXPECT_EQ(*Res.begin(), FieldInSpec); 4680 } 4681 4682 TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) { 4683 TranslationUnitDecl *ToTU = getToTuDecl( 4684 R"( 4685 class Y { template <class T> friend void F(); }; 4686 )", 4687 Lang_CXX); 4688 4689 ASTImporterLookupTable LT(*ToTU); 4690 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match( 4691 ToTU, functionTemplateDecl(hasName("F"))); 4692 DeclarationName Name = F->getDeclName(); 4693 auto Res = LT.lookup(ToTU, Name); 4694 EXPECT_EQ(Res.size(), 2u); 4695 EXPECT_EQ(Res.count(F), 1u); 4696 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u); 4697 } 4698 4699 TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) { 4700 TranslationUnitDecl *ToTU = getToTuDecl( 4701 R"( 4702 struct X; 4703 struct A { 4704 friend struct X; 4705 }; 4706 struct B { 4707 friend struct X; 4708 }; 4709 )", 4710 Lang_CXX); 4711 4712 ASTImporterLookupTable LT(*ToTU); 4713 auto *X = FirstDeclMatcher<CXXRecordDecl>().match( 4714 ToTU, cxxRecordDecl(hasName("X"))); 4715 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl()); 4716 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl()); 4717 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0); 4718 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1); 4719 ASSERT_EQ(RD0, RD1); 4720 ASSERT_EQ(RD1, X); 4721 4722 DeclarationName Name = X->getDeclName(); 4723 auto Res = LT.lookup(ToTU, Name); 4724 EXPECT_EQ(Res.size(), 1u); 4725 EXPECT_EQ(*Res.begin(), X); 4726 } 4727 4728 TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) { 4729 TranslationUnitDecl *ToTU = getToTuDecl( 4730 R"( 4731 enum E { 4732 A, 4733 B 4734 }; 4735 )", 4736 Lang_C); 4737 4738 ASTImporterLookupTable LT(*ToTU); 4739 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E"))); 4740 auto *A = FirstDeclMatcher<EnumConstantDecl>().match( 4741 ToTU, enumConstantDecl(hasName("A"))); 4742 4743 DeclarationName Name = A->getDeclName(); 4744 // Redecl context is the TU. 4745 ASSERT_EQ(E->getRedeclContext(), ToTU); 4746 4747 SmallVector<NamedDecl *, 2> FoundDecls; 4748 // Normal lookup finds in the DC. 4749 E->localUncachedLookup(Name, FoundDecls); 4750 EXPECT_EQ(FoundDecls.size(), 1u); 4751 4752 // Normal lookup finds in the Redecl context. 4753 ToTU->localUncachedLookup(Name, FoundDecls); 4754 EXPECT_EQ(FoundDecls.size(), 1u); 4755 4756 // Import specific lookup finds in the DC. 4757 auto Res = LT.lookup(E, Name); 4758 ASSERT_EQ(Res.size(), 1u); 4759 EXPECT_EQ(*Res.begin(), A); 4760 4761 // Import specific lookup finds in the Redecl context. 4762 Res = LT.lookup(ToTU, Name); 4763 ASSERT_EQ(Res.size(), 1u); 4764 EXPECT_EQ(*Res.begin(), A); 4765 } 4766 4767 TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) { 4768 TranslationUnitDecl *ToTU = getToTuDecl( 4769 R"( 4770 namespace N { 4771 int A; 4772 } 4773 namespace N { 4774 } 4775 )", 4776 Lang_CXX); 4777 auto *N1 = 4778 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N"))); 4779 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A"))); 4780 DeclarationName Name = A->getDeclName(); 4781 4782 ASTImporterLookupTable LT(*ToTU); 4783 auto Res = LT.lookup(N1, Name); 4784 ASSERT_EQ(Res.size(), 1u); 4785 EXPECT_EQ(*Res.begin(), A); 4786 } 4787 4788 TEST_P(ASTImporterOptionSpecificTestBase, 4789 RedeclChainShouldBeCorrectAmongstNamespaces) { 4790 Decl *FromTU = getTuDecl( 4791 R"( 4792 namespace NS { 4793 struct X; 4794 struct Y { 4795 static const int I = 3; 4796 }; 4797 } 4798 namespace NS { 4799 struct X { // <--- To be imported 4800 void method(int i = Y::I) {} 4801 int f; 4802 }; 4803 } 4804 )", 4805 Lang_CXX); 4806 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match( 4807 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit()))); 4808 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match( 4809 FromTU, 4810 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit()))); 4811 ASSERT_NE(FromFwd, FromDef); 4812 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition()); 4813 ASSERT_TRUE(FromDef->isThisDeclarationADefinition()); 4814 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl()); 4815 4816 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX)); 4817 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX)); 4818 EXPECT_NE(ToFwd, ToDef); 4819 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition()); 4820 EXPECT_TRUE(ToDef->isThisDeclarationADefinition()); 4821 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl()); 4822 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 4823 // We expect no (ODR) warning during the import. 4824 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings()); 4825 } 4826 4827 struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {}; 4828 4829 TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) { 4830 Decl *ToTU = getToTuDecl( 4831 R"( 4832 class X { 4833 template <typename T> friend void foo(); 4834 }; 4835 )", 4836 Lang_CXX); 4837 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match( 4838 ToTU, functionTemplateDecl(hasName("foo"))); 4839 4840 Decl *FromTU = getTuDecl( 4841 R"( 4842 template <typename T> void foo(); 4843 )", 4844 Lang_CXX); 4845 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match( 4846 FromTU, functionTemplateDecl(hasName("foo"))); 4847 auto *Imported = Import(FromFoo, Lang_CXX); 4848 4849 EXPECT_EQ(Imported->getPreviousDecl(), Friend); 4850 } 4851 4852 struct ASTImporterWithFakeErrors : ASTImporter { 4853 using ASTImporter::ASTImporter; 4854 bool returnWithErrorInTest() override { return true; } 4855 }; 4856 4857 struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase { 4858 ErrorHandlingTest() { 4859 Creator = [](ASTContext &ToContext, FileManager &ToFileManager, 4860 ASTContext &FromContext, FileManager &FromFileManager, 4861 bool MinimalImport, 4862 const std::shared_ptr<ASTImporterSharedState> &SharedState) { 4863 return new ASTImporterWithFakeErrors(ToContext, ToFileManager, 4864 FromContext, FromFileManager, 4865 MinimalImport, SharedState); 4866 }; 4867 } 4868 // In this test we purposely report an error (UnsupportedConstruct) when 4869 // importing the below stmt. 4870 static constexpr auto* ErroneousStmt = R"( asm(""); )"; 4871 }; 4872 4873 // Check a case when no new AST node is created in the AST before encountering 4874 // the error. 4875 TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) { 4876 TranslationUnitDecl *ToTU = getToTuDecl( 4877 R"( 4878 template <typename T> 4879 class X {}; 4880 template <> 4881 class X<int> { int a; }; 4882 )", 4883 Lang_CXX); 4884 TranslationUnitDecl *FromTU = getTuDecl( 4885 R"( 4886 template <typename T> 4887 class X {}; 4888 template <> 4889 class X<int> { double b; }; 4890 )", 4891 Lang_CXX); 4892 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 4893 FromTU, classTemplateSpecializationDecl(hasName("X"))); 4894 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX); 4895 EXPECT_FALSE(ImportedSpec); 4896 4897 // The original Decl is kept, no new decl is created. 4898 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match( 4899 ToTU, classTemplateSpecializationDecl(hasName("X"))), 4900 1u); 4901 4902 // But an error is set to the counterpart in the "from" context. 4903 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get(); 4904 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromSpec); 4905 ASSERT_TRUE(OptErr); 4906 EXPECT_EQ(OptErr->Error, ImportError::NameConflict); 4907 } 4908 4909 // Check a case when a new AST node is created but not linked to the AST before 4910 // encountering the error. 4911 TEST_P(ErrorHandlingTest, 4912 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) { 4913 TranslationUnitDecl *FromTU = getTuDecl( 4914 std::string("void foo() { ") + ErroneousStmt + " }", 4915 Lang_CXX); 4916 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match( 4917 FromTU, functionDecl(hasName("foo"))); 4918 4919 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX); 4920 EXPECT_FALSE(ImportedFoo); 4921 4922 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 4923 // Created, but not linked. 4924 EXPECT_EQ( 4925 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))), 4926 0u); 4927 4928 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get(); 4929 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFoo); 4930 ASSERT_TRUE(OptErr); 4931 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); 4932 } 4933 4934 // Check a case when a new AST node is created and linked to the AST before 4935 // encountering the error. The error is set for the counterpart of the nodes in 4936 // the "from" context. 4937 TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) { 4938 TranslationUnitDecl *FromTU = getTuDecl( 4939 std::string(R"( 4940 void f(); 4941 void f() { )") + ErroneousStmt + R"( } 4942 )", 4943 Lang_CXX); 4944 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match( 4945 FromTU, functionDecl(hasName("f"))); 4946 auto *FromDef = 4947 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))); 4948 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX); 4949 EXPECT_FALSE(ImportedProto); // Could not import. 4950 // However, we created two nodes in the AST. 1) the fwd decl 2) the 4951 // definition. The definition is not added to its DC, but the fwd decl is 4952 // there. 4953 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 4954 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))), 4955 1u); 4956 // Match the fwd decl. 4957 auto *ToProto = 4958 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))); 4959 EXPECT_TRUE(ToProto); 4960 // An error is set to the counterpart in the "from" context both for the fwd 4961 // decl and the definition. 4962 ASTImporter *Importer = findFromTU(FromProto)->Importer.get(); 4963 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromProto); 4964 ASSERT_TRUE(OptErr); 4965 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); 4966 OptErr = Importer->getImportDeclErrorIfAny(FromDef); 4967 ASSERT_TRUE(OptErr); 4968 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); 4969 } 4970 4971 // An error should be set for a class if we cannot import one member. 4972 TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) { 4973 TranslationUnitDecl *FromTU = getTuDecl( 4974 std::string(R"( 4975 class X { 4976 void f() { )") + ErroneousStmt + R"( } // This member has the error 4977 // during import. 4978 void ok(); // The error should not prevent importing this. 4979 }; // An error will be set for X too. 4980 )", 4981 Lang_CXX); 4982 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match( 4983 FromTU, cxxRecordDecl(hasName("X"))); 4984 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX); 4985 4986 // An error is set for X. 4987 EXPECT_FALSE(ImportedX); 4988 ASTImporter *Importer = findFromTU(FromX)->Importer.get(); 4989 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX); 4990 ASSERT_TRUE(OptErr); 4991 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); 4992 4993 // An error is set for f(). 4994 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match( 4995 FromTU, cxxMethodDecl(hasName("f"))); 4996 OptErr = Importer->getImportDeclErrorIfAny(FromF); 4997 ASSERT_TRUE(OptErr); 4998 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); 4999 // And any subsequent import should fail. 5000 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX); 5001 EXPECT_FALSE(ImportedF); 5002 5003 // There is an error set for the other member too. 5004 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match( 5005 FromTU, cxxMethodDecl(hasName("ok"))); 5006 OptErr = Importer->getImportDeclErrorIfAny(FromOK); 5007 EXPECT_TRUE(OptErr); 5008 // Cannot import the other member. 5009 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX); 5010 EXPECT_FALSE(ImportedOK); 5011 } 5012 5013 // Check that an error propagates to the dependent AST nodes. 5014 // In the below code it means that an error in X should propagate to A. 5015 // And even to F since the containing A is erroneous. 5016 // And to all AST nodes which we visit during the import process which finally 5017 // ends up in a failure (in the error() function). 5018 TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) { 5019 Decl *FromTU = getTuDecl( 5020 std::string(R"( 5021 namespace NS { 5022 class A { 5023 template <int I> class F {}; 5024 class X { 5025 template <int I> friend class F; 5026 void error() { )") + ErroneousStmt + R"( } 5027 }; 5028 }; 5029 5030 class B {}; 5031 } // NS 5032 )", 5033 Lang_CXX, "input0.cc"); 5034 5035 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match( 5036 FromTU, cxxRecordDecl(hasName("F"), isDefinition())); 5037 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match( 5038 FromTU, cxxRecordDecl(hasName("A"), isDefinition())); 5039 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match( 5040 FromTU, cxxRecordDecl(hasName("B"), isDefinition())); 5041 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match( 5042 FromTU, namespaceDecl(hasName("NS"))); 5043 5044 // Start by importing the templated CXXRecordDecl of F. 5045 // Import fails for that. 5046 EXPECT_FALSE(Import(FromFRD, Lang_CXX)); 5047 // Import fails for A. 5048 EXPECT_FALSE(Import(FromA, Lang_CXX)); 5049 // But we should be able to import the independent B. 5050 EXPECT_TRUE(Import(FromB, Lang_CXX)); 5051 // And the namespace. 5052 EXPECT_TRUE(Import(FromNS, Lang_CXX)); 5053 5054 // An error is set to the templated CXXRecordDecl of F. 5055 ASTImporter *Importer = findFromTU(FromFRD)->Importer.get(); 5056 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFRD); 5057 EXPECT_TRUE(OptErr); 5058 5059 // An error is set to A. 5060 OptErr = Importer->getImportDeclErrorIfAny(FromA); 5061 EXPECT_TRUE(OptErr); 5062 5063 // There is no error set to B. 5064 OptErr = Importer->getImportDeclErrorIfAny(FromB); 5065 EXPECT_FALSE(OptErr); 5066 5067 // There is no error set to NS. 5068 OptErr = Importer->getImportDeclErrorIfAny(FromNS); 5069 EXPECT_FALSE(OptErr); 5070 5071 // Check some of those decls whose ancestor is X, they all should have an 5072 // error set if we visited them during an import process which finally failed. 5073 // These decls are part of a cycle in an ImportPath. 5074 // There would not be any error set for these decls if we hadn't follow the 5075 // ImportPaths and the cycles. 5076 OptErr = Importer->getImportDeclErrorIfAny( 5077 FirstDeclMatcher<ClassTemplateDecl>().match( 5078 FromTU, classTemplateDecl(hasName("F")))); 5079 // An error is set to the 'F' ClassTemplateDecl. 5080 EXPECT_TRUE(OptErr); 5081 // An error is set to the FriendDecl. 5082 OptErr = Importer->getImportDeclErrorIfAny( 5083 FirstDeclMatcher<FriendDecl>().match( 5084 FromTU, friendDecl())); 5085 EXPECT_TRUE(OptErr); 5086 // An error is set to the implicit class of A. 5087 OptErr = 5088 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match( 5089 FromTU, cxxRecordDecl(hasName("A"), isImplicit()))); 5090 EXPECT_TRUE(OptErr); 5091 // An error is set to the implicit class of X. 5092 OptErr = 5093 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match( 5094 FromTU, cxxRecordDecl(hasName("X"), isImplicit()))); 5095 EXPECT_TRUE(OptErr); 5096 } 5097 5098 TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) { 5099 TranslationUnitDecl *FromTU = getTuDecl( 5100 std::string(R"( 5101 namespace X { 5102 void f() { )") + ErroneousStmt + R"( } // This member has the error 5103 // during import. 5104 void ok(); // The error should not prevent importing this. 5105 }; // An error will be set for X too. 5106 )", 5107 Lang_CXX); 5108 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match( 5109 FromTU, namespaceDecl(hasName("X"))); 5110 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX); 5111 5112 // There is no error set for X. 5113 EXPECT_TRUE(ImportedX); 5114 ASTImporter *Importer = findFromTU(FromX)->Importer.get(); 5115 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX); 5116 ASSERT_FALSE(OptErr); 5117 5118 // An error is set for f(). 5119 auto *FromF = FirstDeclMatcher<FunctionDecl>().match( 5120 FromTU, functionDecl(hasName("f"))); 5121 OptErr = Importer->getImportDeclErrorIfAny(FromF); 5122 ASSERT_TRUE(OptErr); 5123 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); 5124 // And any subsequent import should fail. 5125 FunctionDecl *ImportedF = Import(FromF, Lang_CXX); 5126 EXPECT_FALSE(ImportedF); 5127 5128 // There is no error set for ok(). 5129 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match( 5130 FromTU, functionDecl(hasName("ok"))); 5131 OptErr = Importer->getImportDeclErrorIfAny(FromOK); 5132 EXPECT_FALSE(OptErr); 5133 // And we should be able to import. 5134 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX); 5135 EXPECT_TRUE(ImportedOK); 5136 } 5137 5138 // An error should be set for a class if it had a previous import with an error 5139 // from another TU. 5140 TEST_P(ErrorHandlingTest, 5141 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) { 5142 // We already have a fwd decl. 5143 TranslationUnitDecl *ToTU = getToTuDecl( 5144 "class X;", Lang_CXX); 5145 // Then we import a definition. 5146 { 5147 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"( 5148 class X { 5149 void f() { )") + ErroneousStmt + R"( } 5150 void ok(); 5151 }; 5152 )", 5153 Lang_CXX); 5154 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match( 5155 FromTU, cxxRecordDecl(hasName("X"))); 5156 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX); 5157 5158 // An error is set for X ... 5159 EXPECT_FALSE(ImportedX); 5160 ASTImporter *Importer = findFromTU(FromX)->Importer.get(); 5161 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX); 5162 ASSERT_TRUE(OptErr); 5163 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); 5164 } 5165 // ... but the node had been created. 5166 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match( 5167 ToTU, cxxRecordDecl(hasName("X"), isDefinition())); 5168 // An error is set for "ToXDef" in the shared state. 5169 Optional<ImportError> OptErr = 5170 SharedStatePtr->getImportDeclErrorIfAny(ToXDef); 5171 ASSERT_TRUE(OptErr); 5172 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); 5173 5174 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match( 5175 ToTU, cxxRecordDecl(hasName("X"), unless(isDefinition()))); 5176 // An error is NOT set for the fwd Decl of X in the shared state. 5177 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToXFwd); 5178 ASSERT_FALSE(OptErr); 5179 5180 // Try to import X again but from another TU. 5181 { 5182 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"( 5183 class X { 5184 void f() { )") + ErroneousStmt + R"( } 5185 void ok(); 5186 }; 5187 )", 5188 Lang_CXX, "input1.cc"); 5189 5190 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match( 5191 FromTU, cxxRecordDecl(hasName("X"))); 5192 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX); 5193 5194 // If we did not save the errors for the "to" context then the below checks 5195 // would fail, because the lookup finds the fwd Decl of the existing 5196 // definition in the "to" context. We can reach the existing definition via 5197 // the found fwd Decl. That existing definition is structurally equivalent 5198 // (we check only the fields) with this one we want to import, so we return 5199 // with the existing definition, which is erroneous (one method is missing). 5200 5201 // The import should fail. 5202 EXPECT_FALSE(ImportedX); 5203 ASTImporter *Importer = findFromTU(FromX)->Importer.get(); 5204 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX); 5205 // And an error is set for this new X in the "from" ctx. 5206 ASSERT_TRUE(OptErr); 5207 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); 5208 } 5209 } 5210 5211 TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) { 5212 auto MatchFooA = 5213 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("A")))); 5214 auto MatchFooB = 5215 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("B")))); 5216 auto MatchFooC = 5217 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("C")))); 5218 5219 // Provoke import of a method that has overridden methods with import error. 5220 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"( 5221 struct C; 5222 struct A { 5223 virtual void foo(); 5224 void f1(C *); 5225 }; 5226 void A::foo() { 5227 )") + ErroneousStmt + R"( 5228 } 5229 struct B : public A { 5230 void foo() override; 5231 }; 5232 struct C : public B { 5233 void foo() override; 5234 }; 5235 )", 5236 Lang_CXX11); 5237 auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooA); 5238 auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooB); 5239 auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooC); 5240 5241 EXPECT_FALSE(Import(FromFooA, Lang_CXX11)); 5242 ASTImporter *Importer = findFromTU(FromFooA)->Importer.get(); 5243 auto CheckError = [&Importer](Decl *FromD) { 5244 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromD); 5245 ASSERT_TRUE(OptErr); 5246 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct); 5247 }; 5248 CheckError(FromFooA); 5249 EXPECT_FALSE(Import(FromFooB, Lang_CXX11)); 5250 CheckError(FromFooB); 5251 EXPECT_FALSE(Import(FromFooC, Lang_CXX11)); 5252 CheckError(FromFooC); 5253 } 5254 5255 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) { 5256 Decl *FromTU = getTuDecl( 5257 R"( 5258 void f() { 5259 auto L = [](){}; 5260 } 5261 )", 5262 Lang_CXX11, "input0.cc"); 5263 auto Pattern = lambdaExpr(); 5264 CXXRecordDecl *FromL = 5265 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass(); 5266 5267 auto ToL = Import(FromL, Lang_CXX11); 5268 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end()); 5269 unsigned FromLSize = 5270 std::distance(FromL->decls().begin(), FromL->decls().end()); 5271 EXPECT_NE(ToLSize, 0u); 5272 EXPECT_EQ(ToLSize, FromLSize); 5273 } 5274 5275 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) { 5276 Decl *FromTU = getTuDecl( 5277 R"( 5278 template <typename F> 5279 void f(F L = [](){}) {} 5280 )", 5281 Lang_CXX11, "input0.cc"); 5282 auto Pattern = lambdaExpr(); 5283 CXXRecordDecl *FromL = 5284 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass(); 5285 5286 auto ToL = Import(FromL, Lang_CXX11); 5287 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end()); 5288 unsigned FromLSize = 5289 std::distance(FromL->decls().begin(), FromL->decls().end()); 5290 EXPECT_NE(ToLSize, 0u); 5291 EXPECT_EQ(ToLSize, FromLSize); 5292 } 5293 5294 TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) { 5295 Decl *FromTU = getTuDecl( 5296 R"( 5297 auto l1 = [](unsigned lp) { return 1; }; 5298 auto l2 = [](int lp) { return 2; }; 5299 int f(int p) { 5300 return l1(p) + l2(p); 5301 } 5302 )", 5303 Lang_CXX11, "input0.cc"); 5304 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match( 5305 FromTU, functionDecl(hasName("f"))); 5306 FunctionDecl *ToF = Import(FromF, Lang_CXX11); 5307 EXPECT_TRUE(ToF); 5308 } 5309 5310 TEST_P(ASTImporterOptionSpecificTestBase, 5311 ImportExistingFriendClassTemplateDef) { 5312 auto Code = 5313 R"( 5314 template <class T1, class T2> 5315 struct Base { 5316 template <class U1, class U2> 5317 friend struct Class; 5318 }; 5319 template <class T1, class T2> 5320 struct Class { }; 5321 )"; 5322 5323 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX); 5324 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc"); 5325 5326 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match( 5327 ToTU, classTemplateDecl(hasName("Class"))); 5328 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match( 5329 ToTU, classTemplateDecl(hasName("Class"))); 5330 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition()); 5331 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition()); 5332 // Previous friend decl is not linked to it! 5333 ASSERT_FALSE(ToClassDef->getPreviousDecl()); 5334 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef); 5335 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto); 5336 5337 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match( 5338 FromTU, classTemplateDecl(hasName("Class"))); 5339 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match( 5340 FromTU, classTemplateDecl(hasName("Class"))); 5341 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition()); 5342 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition()); 5343 ASSERT_FALSE(FromClassDef->getPreviousDecl()); 5344 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef); 5345 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto); 5346 5347 auto *ImportedDef = Import(FromClassDef, Lang_CXX); 5348 // At import we should find the definition for 'Class' even if the 5349 // prototype (inside 'friend') for it comes first in the AST and is not 5350 // linked to the definition. 5351 EXPECT_EQ(ImportedDef, ToClassDef); 5352 } 5353 5354 struct LLDBLookupTest : ASTImporterOptionSpecificTestBase { 5355 LLDBLookupTest() { 5356 Creator = [](ASTContext &ToContext, FileManager &ToFileManager, 5357 ASTContext &FromContext, FileManager &FromFileManager, 5358 bool MinimalImport, 5359 const std::shared_ptr<ASTImporterSharedState> &SharedState) { 5360 return new ASTImporter(ToContext, ToFileManager, FromContext, 5361 FromFileManager, MinimalImport, 5362 // We use the regular lookup. 5363 /*SharedState=*/nullptr); 5364 }; 5365 } 5366 }; 5367 5368 TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) { 5369 TranslationUnitDecl *ToTU = getToTuDecl( 5370 R"( 5371 extern "C" { 5372 class X{}; 5373 }; 5374 )", 5375 Lang_CXX); 5376 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match( 5377 ToTU, cxxRecordDecl(hasName("X"))); 5378 5379 // Set up a stub external storage. 5380 ToTU->setHasExternalLexicalStorage(true); 5381 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true. 5382 ToTU->setMustBuildLookupTable(); 5383 struct TestExternalASTSource : ExternalASTSource {}; 5384 ToTU->getASTContext().setExternalSource(new TestExternalASTSource()); 5385 5386 Decl *FromTU = getTuDecl( 5387 R"( 5388 class X; 5389 )", 5390 Lang_CXX); 5391 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match( 5392 FromTU, cxxRecordDecl(hasName("X"))); 5393 auto *ImportedX = Import(FromX, Lang_CXX); 5394 // The lookup must find the existing class definition in the LinkageSpecDecl. 5395 // Then the importer renders the existing and the new decl into one chain. 5396 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl()); 5397 } 5398 5399 struct SVEBuiltins : ASTImporterOptionSpecificTestBase {}; 5400 5401 TEST_P(SVEBuiltins, ImportTypes) { 5402 static const char *const TypeNames[] = { 5403 "__SVInt8_t", 5404 "__SVInt16_t", 5405 "__SVInt32_t", 5406 "__SVInt64_t", 5407 "__SVUint8_t", 5408 "__SVUint16_t", 5409 "__SVUint32_t", 5410 "__SVUint64_t", 5411 "__SVFloat16_t", 5412 "__SVFloat32_t", 5413 "__SVFloat64_t", 5414 "__SVBool_t" 5415 }; 5416 5417 TranslationUnitDecl *ToTU = getToTuDecl("", Lang_CXX); 5418 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX, "input.cc"); 5419 for (auto *TypeName : TypeNames) { 5420 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match( 5421 ToTU, typedefDecl(hasName(TypeName))); 5422 QualType ToType = ToTypedef->getUnderlyingType(); 5423 5424 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match( 5425 FromTU, typedefDecl(hasName(TypeName))); 5426 QualType FromType = FromTypedef->getUnderlyingType(); 5427 5428 QualType ImportedType = ImportType(FromType, FromTypedef, Lang_CXX); 5429 EXPECT_EQ(ImportedType, ToType); 5430 } 5431 } 5432 5433 TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) { 5434 // Test that import of implicit functions works and the functions 5435 // are merged into one chain. 5436 auto GetDeclToImport = [this](StringRef File) { 5437 Decl *FromTU = getTuDecl( 5438 R"( 5439 struct X { }; 5440 // Force generating some implicit operator definitions for X. 5441 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; } 5442 )", 5443 Lang_CXX11, File); 5444 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match( 5445 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit()))); 5446 // Destructor is picked as one example of implicit function. 5447 return FromD->getDestructor(); 5448 }; 5449 5450 auto *ToD1 = Import(GetDeclToImport("input1.cc"), Lang_CXX11); 5451 ASSERT_TRUE(ToD1); 5452 5453 auto *ToD2 = Import(GetDeclToImport("input2.cc"), Lang_CXX11); 5454 ASSERT_TRUE(ToD2); 5455 5456 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl()); 5457 } 5458 5459 TEST_P(ASTImporterOptionSpecificTestBase, 5460 ImportOfExplicitlyDefaultedOrDeleted) { 5461 Decl *FromTU = getTuDecl( 5462 R"( 5463 struct X { X() = default; X(const X&) = delete; }; 5464 )", 5465 Lang_CXX11); 5466 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match( 5467 FromTU, cxxRecordDecl(hasName("X"))); 5468 auto *ImportedX = Import(FromX, Lang_CXX11); 5469 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match( 5470 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit()))); 5471 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match( 5472 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit()))); 5473 5474 ASSERT_TRUE(ImportedX); 5475 EXPECT_TRUE(Constr1->isDefaulted()); 5476 EXPECT_TRUE(Constr1->isExplicitlyDefaulted()); 5477 EXPECT_TRUE(Constr2->isDeletedAsWritten()); 5478 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate()); 5479 } 5480 5481 INSTANTIATE_TEST_CASE_P(ParameterizedTests, SVEBuiltins, 5482 ::testing::Values(ArgVector{"-target", 5483 "aarch64-linux-gnu"}), ); 5484 5485 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest, 5486 ::testing::Values(ArgVector()), ); 5487 5488 INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain, 5489 ::testing::Values(ArgVector()), ); 5490 5491 TEST_P(ASTImporterOptionSpecificTestBase, LambdasAreDifferentiated) { 5492 Decl *FromTU = getTuDecl( 5493 R"( 5494 void f() { 5495 auto L0 = [](){}; 5496 auto L1 = [](){}; 5497 } 5498 )", 5499 Lang_CXX11, "input0.cc"); 5500 auto Pattern = lambdaExpr(); 5501 CXXRecordDecl *FromL0 = 5502 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass(); 5503 CXXRecordDecl *FromL1 = 5504 LastDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass(); 5505 ASSERT_NE(FromL0, FromL1); 5506 5507 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11); 5508 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11); 5509 EXPECT_NE(ToL0, ToL1); 5510 } 5511 5512 TEST_P(ASTImporterOptionSpecificTestBase, 5513 LambdasInFunctionParamsAreDifferentiated) { 5514 Decl *FromTU = getTuDecl( 5515 R"( 5516 template <typename F0, typename F1> 5517 void f(F0 L0 = [](){}, F1 L1 = [](){}) {} 5518 )", 5519 Lang_CXX11, "input0.cc"); 5520 auto Pattern = cxxRecordDecl(isLambda()); 5521 CXXRecordDecl *FromL0 = 5522 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern); 5523 CXXRecordDecl *FromL1 = 5524 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern); 5525 ASSERT_NE(FromL0, FromL1); 5526 5527 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11); 5528 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11); 5529 ASSERT_NE(ToL0, ToL1); 5530 } 5531 5532 TEST_P(ASTImporterOptionSpecificTestBase, 5533 LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed) { 5534 Decl *FromTU = getTuDecl( 5535 R"( 5536 #define LAMBDA [](){} 5537 template <typename F0, typename F1> 5538 void f(F0 L0 = LAMBDA, F1 L1 = LAMBDA) {} 5539 )", 5540 Lang_CXX11, "input0.cc"); 5541 auto Pattern = cxxRecordDecl(isLambda()); 5542 CXXRecordDecl *FromL0 = 5543 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern); 5544 CXXRecordDecl *FromL1 = 5545 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern); 5546 ASSERT_NE(FromL0, FromL1); 5547 5548 Import(FromL0, Lang_CXX11); 5549 Import(FromL1, Lang_CXX11); 5550 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11); 5551 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11); 5552 ASSERT_NE(ToL0, ToL1); 5553 } 5554 5555 TEST_P(ASTImporterOptionSpecificTestBase, ImportAssignedLambda) { 5556 Decl *FromTU = getTuDecl( 5557 R"( 5558 void f() { 5559 auto x = []{} = {}; auto x2 = x; 5560 } 5561 )", 5562 Lang_CXX2a, "input0.cc"); 5563 auto FromF = FirstDeclMatcher<FunctionDecl>().match( 5564 FromTU, functionDecl(hasName("f"))); 5565 // We have only one lambda class. 5566 ASSERT_EQ( 5567 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())), 5568 1u); 5569 5570 FunctionDecl *ToF = Import(FromF, Lang_CXX2a); 5571 EXPECT_TRUE(ToF); 5572 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 5573 // We have only one lambda class after the import. 5574 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())), 5575 1u); 5576 } 5577 5578 TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) { 5579 Decl *FromTU = getTuDecl( 5580 R"( 5581 void f() { 5582 auto x = []{} = {}; 5583 auto xb = []{} = {}; 5584 } 5585 )", 5586 Lang_CXX2a, "input0.cc"); 5587 auto FromF = FirstDeclMatcher<FunctionDecl>().match( 5588 FromTU, functionDecl(hasName("f"))); 5589 // We have two lambda classes. 5590 ASSERT_EQ( 5591 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())), 5592 2u); 5593 5594 FunctionDecl *ToF = Import(FromF, Lang_CXX2a); 5595 EXPECT_TRUE(ToF); 5596 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 5597 // We have two lambda classes after the import. 5598 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())), 5599 2u); 5600 } 5601 5602 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest, 5603 DefaultTestValuesForRunOptions, ); 5604 5605 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportPath, 5606 ::testing::Values(ArgVector()), ); 5607 5608 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr, 5609 DefaultTestValuesForRunOptions, ); 5610 5611 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType, 5612 DefaultTestValuesForRunOptions, ); 5613 5614 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl, 5615 DefaultTestValuesForRunOptions, ); 5616 5617 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase, 5618 DefaultTestValuesForRunOptions, ); 5619 5620 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest, 5621 DefaultTestValuesForRunOptions, ); 5622 5623 INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest, 5624 DefaultTestValuesForRunOptions, ); 5625 5626 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions, 5627 DefaultTestValuesForRunOptions, ); 5628 5629 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplates, 5630 DefaultTestValuesForRunOptions, ); 5631 5632 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates, 5633 DefaultTestValuesForRunOptions, ); 5634 5635 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses, 5636 DefaultTestValuesForRunOptions, ); 5637 5638 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions, 5639 DefaultTestValuesForRunOptions, ); 5640 5641 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses, 5642 DefaultTestValuesForRunOptions, ); 5643 5644 INSTANTIATE_TEST_CASE_P(ParameterizedTests, 5645 ImportFunctionTemplateSpecializations, 5646 DefaultTestValuesForRunOptions, ); 5647 5648 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods, 5649 DefaultTestValuesForRunOptions, ); 5650 5651 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables, 5652 DefaultTestValuesForRunOptions, ); 5653 5654 INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest, 5655 DefaultTestValuesForRunOptions, ); 5656 5657 } // end namespace ast_matchers 5658 } // end namespace clang 5659