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