1 //===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Tests for the correct import of AST nodes from one AST context to another. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "MatchVerifier.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/AST/ASTImporter.h" 17 #include "clang/ASTMatchers/ASTMatchFinder.h" 18 #include "clang/ASTMatchers/ASTMatchers.h" 19 #include "clang/Tooling/Tooling.h" 20 21 #include "DeclMatcher.h" 22 #include "Language.h" 23 #include "gmock/gmock.h" 24 #include "llvm/ADT/StringMap.h" 25 26 namespace clang { 27 namespace ast_matchers { 28 29 using internal::Matcher; 30 using internal::BindableMatcher; 31 using llvm::StringMap; 32 33 // Creates a virtual file and assigns that to the context of given AST. If the 34 // file already exists then the file will not be created again as a duplicate. 35 static void 36 createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName, 37 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) { 38 assert(ToAST); 39 ASTContext &ToCtx = ToAST->getASTContext(); 40 auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>( 41 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get()); 42 auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>( 43 OFS->overlays_begin()->get()); 44 MFS->addFile(FileName, 0, std::move(Buffer)); 45 } 46 47 static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName, 48 StringRef Code) { 49 return createVirtualFileIfNeeded(ToAST, FileName, 50 llvm::MemoryBuffer::getMemBuffer(Code)); 51 } 52 53 const StringRef DeclToImportID = "declToImport"; 54 const StringRef DeclToVerifyID = "declToVerify"; 55 56 // Common base for the different families of ASTImporter tests that are 57 // parameterized on the compiler options which may result a different AST. E.g. 58 // -fms-compatibility or -fdelayed-template-parsing. 59 struct ParameterizedTestsFixture : ::testing::TestWithParam<ArgVector> { 60 61 // Returns the argument vector used for a specific language option, this set 62 // can be tweaked by the test parameters. 63 ArgVector getArgVectorForLanguage(Language Lang) const { 64 ArgVector Args = getBasicRunOptionsForLanguage(Lang); 65 ArgVector ExtraArgs = GetParam(); 66 for (const auto &Arg : ExtraArgs) { 67 Args.push_back(Arg); 68 } 69 return Args; 70 } 71 72 }; 73 74 // Base class for those tests which use the family of `testImport` functions. 75 class TestImportBase : public ParameterizedTestsFixture { 76 77 template <typename NodeType> 78 NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer, 79 NodeType Node) { 80 ASTContext &ToCtx = To->getASTContext(); 81 82 // Add 'From' file to virtual file system so importer can 'find' it 83 // while importing SourceLocations. It is safe to add same file multiple 84 // times - it just isn't replaced. 85 StringRef FromFileName = From->getMainFileName(); 86 createVirtualFileIfNeeded(To, FromFileName, 87 From->getBufferForFile(FromFileName)); 88 89 auto Imported = Importer.Import(Node); 90 91 // This should dump source locations and assert if some source locations 92 // were not imported. 93 SmallString<1024> ImportChecker; 94 llvm::raw_svector_ostream ToNothing(ImportChecker); 95 ToCtx.getTranslationUnitDecl()->print(ToNothing); 96 97 // This traverses the AST to catch certain bugs like poorly or not 98 // implemented subtrees. 99 Imported->dump(ToNothing); 100 101 return Imported; 102 } 103 104 template <typename NodeType> 105 testing::AssertionResult 106 testImport(const std::string &FromCode, const ArgVector &FromArgs, 107 const std::string &ToCode, const ArgVector &ToArgs, 108 MatchVerifier<NodeType> &Verifier, 109 const BindableMatcher<NodeType> &SearchMatcher, 110 const BindableMatcher<NodeType> &VerificationMatcher) { 111 const char *const InputFileName = "input.cc"; 112 const char *const OutputFileName = "output.cc"; 113 114 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs( 115 FromCode, FromArgs, InputFileName), 116 ToAST = tooling::buildASTFromCodeWithArgs( 117 ToCode, ToArgs, OutputFileName); 118 119 ASTContext &FromCtx = FromAST->getASTContext(), 120 &ToCtx = ToAST->getASTContext(); 121 122 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx, 123 FromAST->getFileManager(), false); 124 125 auto FoundNodes = match(SearchMatcher, FromCtx); 126 if (FoundNodes.size() != 1) 127 return testing::AssertionFailure() 128 << "Multiple potential nodes were found!"; 129 130 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes); 131 if (!ToImport) 132 return testing::AssertionFailure() << "Node type mismatch!"; 133 134 // Sanity check: the node being imported should match in the same way as 135 // the result node. 136 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher); 137 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher)); 138 139 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport); 140 if (!Imported) 141 return testing::AssertionFailure() << "Import failed, nullptr returned!"; 142 143 return Verifier.match(Imported, WrapperMatcher); 144 } 145 146 template <typename NodeType> 147 testing::AssertionResult 148 testImport(const std::string &FromCode, const ArgVector &FromArgs, 149 const std::string &ToCode, const ArgVector &ToArgs, 150 MatchVerifier<NodeType> &Verifier, 151 const BindableMatcher<NodeType> &VerificationMatcher) { 152 return testImport( 153 FromCode, FromArgs, ToCode, ToArgs, Verifier, 154 translationUnitDecl( 155 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))), 156 VerificationMatcher); 157 } 158 159 public: 160 161 /// Test how AST node named "declToImport" located in the translation unit 162 /// of "FromCode" virtual file is imported to "ToCode" virtual file. 163 /// The verification is done by running AMatcher over the imported node. 164 template <typename NodeType, typename MatcherType> 165 void testImport(const std::string &FromCode, Language FromLang, 166 const std::string &ToCode, Language ToLang, 167 MatchVerifier<NodeType> &Verifier, 168 const MatcherType &AMatcher) { 169 ArgVector FromArgs = getArgVectorForLanguage(FromLang), 170 ToArgs = getArgVectorForLanguage(ToLang); 171 EXPECT_TRUE( 172 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher)); 173 } 174 175 struct ImportAction { 176 StringRef FromFilename; 177 StringRef ToFilename; 178 // FIXME: Generalize this to support other node kinds. 179 BindableMatcher<Decl> ImportPredicate; 180 181 ImportAction(StringRef FromFilename, StringRef ToFilename, 182 DeclarationMatcher ImportPredicate) 183 : FromFilename(FromFilename), ToFilename(ToFilename), 184 ImportPredicate(ImportPredicate) {} 185 186 ImportAction(StringRef FromFilename, StringRef ToFilename, 187 const std::string &DeclName) 188 : FromFilename(FromFilename), ToFilename(ToFilename), 189 ImportPredicate(namedDecl(hasName(DeclName))) {} 190 }; 191 192 using SingleASTUnit = std::unique_ptr<ASTUnit>; 193 using AllASTUnits = StringMap<SingleASTUnit>; 194 195 struct CodeEntry { 196 std::string CodeSample; 197 Language Lang; 198 }; 199 200 using CodeFiles = StringMap<CodeEntry>; 201 202 /// Builds an ASTUnit for one potential compile options set. 203 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const { 204 ArgVector Args = getArgVectorForLanguage(CE.Lang); 205 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName); 206 EXPECT_TRUE(AST.get()); 207 return AST; 208 } 209 210 /// Test an arbitrary sequence of imports for a set of given in-memory files. 211 /// The verification is done by running VerificationMatcher against a 212 /// specified AST node inside of one of given files. 213 /// \param CodeSamples Map whose key is the file name and the value is the 214 /// file content. 215 /// \param ImportActions Sequence of imports. Each import in sequence 216 /// specifies "from file" and "to file" and a matcher that is used for 217 /// searching a declaration for import in "from file". 218 /// \param FileForFinalCheck Name of virtual file for which the final check is 219 /// applied. 220 /// \param FinalSelectPredicate Matcher that specifies the AST node in the 221 /// FileForFinalCheck for which the verification will be done. 222 /// \param VerificationMatcher Matcher that will be used for verification 223 /// after all imports in sequence are done. 224 void testImportSequence(const CodeFiles &CodeSamples, 225 const std::vector<ImportAction> &ImportActions, 226 StringRef FileForFinalCheck, 227 BindableMatcher<Decl> FinalSelectPredicate, 228 BindableMatcher<Decl> VerificationMatcher) { 229 AllASTUnits AllASTs; 230 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>; 231 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers; 232 233 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) { 234 if (!AllASTs.count(Filename)) { 235 auto Found = CodeSamples.find(Filename); 236 assert(Found != CodeSamples.end() && "Wrong file for import!"); 237 AllASTs[Filename] = createASTUnit(Filename, Found->getValue()); 238 } 239 }; 240 241 for (const ImportAction &Action : ImportActions) { 242 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename; 243 GenASTsIfNeeded(FromFile); 244 GenASTsIfNeeded(ToFile); 245 246 ASTUnit *From = AllASTs[FromFile].get(); 247 ASTUnit *To = AllASTs[ToFile].get(); 248 249 // Create a new importer if needed. 250 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}]; 251 if (!ImporterRef) 252 ImporterRef.reset(new ASTImporter( 253 To->getASTContext(), To->getFileManager(), From->getASTContext(), 254 From->getFileManager(), false)); 255 256 // Find the declaration and import it. 257 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID), 258 From->getASTContext()); 259 EXPECT_TRUE(FoundDecl.size() == 1); 260 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl); 261 auto Imported = importNode(From, To, *ImporterRef, ToImport); 262 EXPECT_TRUE(Imported); 263 } 264 265 // Find the declaration and import it. 266 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID), 267 AllASTs[FileForFinalCheck]->getASTContext()); 268 EXPECT_TRUE(FoundDecl.size() == 1); 269 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl); 270 MatchVerifier<Decl> Verifier; 271 EXPECT_TRUE( 272 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher))); 273 } 274 }; 275 276 template <typename T> RecordDecl *getRecordDecl(T *D) { 277 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr()); 278 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl(); 279 } 280 281 // This class provides generic methods to write tests which can check internal 282 // attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also, 283 // this fixture makes it possible to import from several "From" contexts. 284 class ASTImporterTestBase : public ParameterizedTestsFixture { 285 286 const char *const InputFileName = "input.cc"; 287 const char *const OutputFileName = "output.cc"; 288 289 // Buffer for the To context, must live in the test scope. 290 std::string ToCode; 291 292 // Represents a "From" translation unit and holds an importer object which we 293 // use to import from this translation unit. 294 struct TU { 295 // Buffer for the context, must live in the test scope. 296 std::string Code; 297 std::string FileName; 298 std::unique_ptr<ASTUnit> Unit; 299 TranslationUnitDecl *TUDecl = nullptr; 300 std::unique_ptr<ASTImporter> Importer; 301 TU(StringRef Code, StringRef FileName, ArgVector Args) 302 : Code(Code), FileName(FileName), 303 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args, 304 this->FileName)), 305 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) { 306 Unit->enableSourceFileDiagnostics(); 307 } 308 309 void lazyInitImporter(ASTUnit *ToAST) { 310 assert(ToAST); 311 if (!Importer) { 312 Importer.reset(new ASTImporter( 313 ToAST->getASTContext(), ToAST->getFileManager(), 314 Unit->getASTContext(), Unit->getFileManager(), false)); 315 } 316 assert(&ToAST->getASTContext() == &Importer->getToContext()); 317 createVirtualFileIfNeeded(ToAST, FileName, Code); 318 } 319 320 Decl *import(ASTUnit *ToAST, Decl *FromDecl) { 321 lazyInitImporter(ToAST); 322 return Importer->Import(FromDecl); 323 } 324 325 QualType import(ASTUnit *ToAST, QualType FromType) { 326 lazyInitImporter(ToAST); 327 return Importer->Import(FromType); 328 } 329 }; 330 331 // We may have several From contexts and related translation units. In each 332 // AST, the buffers for the source are handled via references and are set 333 // during the creation of the AST. These references must point to a valid 334 // buffer until the AST is alive. Thus, we must use a list in order to avoid 335 // moving of the stored objects because that would mean breaking the 336 // references in the AST. By using a vector a move could happen when the 337 // vector is expanding, with the list we won't have these issues. 338 std::list<TU> FromTUs; 339 340 void lazyInitToAST(Language ToLang) { 341 if (ToAST) 342 return; 343 ArgVector ToArgs = getArgVectorForLanguage(ToLang); 344 // Build the AST from an empty file. 345 ToAST = tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc"); 346 ToAST->enableSourceFileDiagnostics(); 347 } 348 349 TU *findFromTU(Decl *From) { 350 // Create a virtual file in the To Ctx which corresponds to the file from 351 // which we want to import the `From` Decl. Without this source locations 352 // will be invalid in the ToCtx. 353 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) { 354 return E.TUDecl == From->getTranslationUnitDecl(); 355 }); 356 assert(It != FromTUs.end()); 357 return &*It; 358 } 359 360 public: 361 // We may have several From context but only one To context. 362 std::unique_ptr<ASTUnit> ToAST; 363 364 // Creates an AST both for the From and To source code and imports the Decl 365 // of the identifier into the To context. 366 // Must not be called more than once within the same test. 367 std::tuple<Decl *, Decl *> 368 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode, 369 Language ToLang, StringRef Identifier = DeclToImportID) { 370 ArgVector FromArgs = getArgVectorForLanguage(FromLang), 371 ToArgs = getArgVectorForLanguage(ToLang); 372 373 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs); 374 TU &FromTU = FromTUs.back(); 375 376 ToCode = ToSrcCode; 377 assert(!ToAST); 378 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName); 379 ToAST->enableSourceFileDiagnostics(); 380 381 ASTContext &FromCtx = FromTU.Unit->getASTContext(); 382 383 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code); 384 385 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier); 386 assert(ImportedII && "Declaration with the given identifier " 387 "should be specified in test!"); 388 DeclarationName ImportDeclName(ImportedII); 389 SmallVector<NamedDecl *, 4> FoundDecls; 390 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName, 391 FoundDecls); 392 393 assert(FoundDecls.size() == 1); 394 395 Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front()); 396 397 assert(Imported); 398 return std::make_tuple(*FoundDecls.begin(), Imported); 399 } 400 401 // Creates a TU decl for the given source code which can be used as a From 402 // context. May be called several times in a given test (with different file 403 // name). 404 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang, 405 StringRef FileName = "input.cc") { 406 assert( 407 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) { 408 return E.FileName == FileName; 409 }) == FromTUs.end()); 410 411 ArgVector Args = getArgVectorForLanguage(Lang); 412 FromTUs.emplace_back(SrcCode, FileName, Args); 413 TU &Tu = FromTUs.back(); 414 415 return Tu.TUDecl; 416 } 417 418 // Creates the To context with the given source code and returns the TU decl. 419 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) { 420 ArgVector ToArgs = getArgVectorForLanguage(ToLang); 421 ToCode = ToSrcCode; 422 assert(!ToAST); 423 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName); 424 ToAST->enableSourceFileDiagnostics(); 425 426 return ToAST->getASTContext().getTranslationUnitDecl(); 427 } 428 429 // Import the given Decl into the ToCtx. 430 // May be called several times in a given test. 431 // The different instances of the param From may have different ASTContext. 432 Decl *Import(Decl *From, Language ToLang) { 433 lazyInitToAST(ToLang); 434 TU *FromTU = findFromTU(From); 435 return FromTU->import(ToAST.get(), From); 436 } 437 438 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) { 439 lazyInitToAST(ToLang); 440 TU *FromTU = findFromTU(TUDecl); 441 return FromTU->import(ToAST.get(), FromType); 442 } 443 444 ~ASTImporterTestBase() { 445 if (!::testing::Test::HasFailure()) return; 446 447 for (auto &Tu : FromTUs) { 448 assert(Tu.Unit); 449 llvm::errs() << "FromAST:\n"; 450 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump(); 451 llvm::errs() << "\n"; 452 } 453 if (ToAST) { 454 llvm::errs() << "ToAST:\n"; 455 ToAST->getASTContext().getTranslationUnitDecl()->dump(); 456 } 457 } 458 }; 459 460 struct ImportExpr : TestImportBase {}; 461 struct ImportType : TestImportBase {}; 462 struct ImportDecl : TestImportBase {}; 463 464 struct CanonicalRedeclChain : ASTImporterTestBase {}; 465 466 TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) { 467 Decl *FromTU = getTuDecl("void f();", Lang_CXX); 468 auto Pattern = functionDecl(hasName("f")); 469 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 470 471 auto Redecls = getCanonicalForwardRedeclChain(D0); 472 ASSERT_EQ(Redecls.size(), 1u); 473 EXPECT_EQ(D0, Redecls[0]); 474 } 475 476 TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) { 477 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); 478 auto Pattern = functionDecl(hasName("f")); 479 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 480 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 481 FunctionDecl *D1 = D2->getPreviousDecl(); 482 483 auto Redecls = getCanonicalForwardRedeclChain(D0); 484 ASSERT_EQ(Redecls.size(), 3u); 485 EXPECT_EQ(D0, Redecls[0]); 486 EXPECT_EQ(D1, Redecls[1]); 487 EXPECT_EQ(D2, Redecls[2]); 488 } 489 490 TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) { 491 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); 492 auto Pattern = functionDecl(hasName("f")); 493 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 494 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 495 FunctionDecl *D1 = D2->getPreviousDecl(); 496 497 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0); 498 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1); 499 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2); 500 501 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1)); 502 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2)); 503 } 504 505 506 TEST_P(ImportExpr, ImportStringLiteral) { 507 MatchVerifier<Decl> Verifier; 508 testImport( 509 "void declToImport() { (void)\"foo\"; }", 510 Lang_CXX, "", Lang_CXX, Verifier, 511 functionDecl(hasDescendant( 512 stringLiteral(hasType(asString("const char [4]")))))); 513 testImport( 514 "void declToImport() { (void)L\"foo\"; }", 515 Lang_CXX, "", Lang_CXX, Verifier, 516 functionDecl(hasDescendant( 517 stringLiteral(hasType(asString("const wchar_t [4]")))))); 518 testImport( 519 "void declToImport() { (void) \"foo\" \"bar\"; }", 520 Lang_CXX, "", Lang_CXX, Verifier, 521 functionDecl(hasDescendant( 522 stringLiteral(hasType(asString("const char [7]")))))); 523 } 524 525 TEST_P(ImportExpr, ImportGNUNullExpr) { 526 MatchVerifier<Decl> Verifier; 527 testImport( 528 "void declToImport() { (void)__null; }", 529 Lang_CXX, "", Lang_CXX, Verifier, 530 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger()))))); 531 } 532 533 TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) { 534 MatchVerifier<Decl> Verifier; 535 testImport( 536 "void declToImport() { (void)nullptr; }", 537 Lang_CXX11, "", Lang_CXX11, Verifier, 538 functionDecl(hasDescendant(cxxNullPtrLiteralExpr()))); 539 } 540 541 542 TEST_P(ImportExpr, ImportFloatinglLiteralExpr) { 543 MatchVerifier<Decl> Verifier; 544 testImport( 545 "void declToImport() { (void)1.0; }", 546 Lang_C, "", Lang_C, Verifier, 547 functionDecl(hasDescendant( 548 floatLiteral(equals(1.0), hasType(asString("double")))))); 549 testImport( 550 "void declToImport() { (void)1.0e-5f; }", 551 Lang_C, "", Lang_C, Verifier, 552 functionDecl(hasDescendant( 553 floatLiteral(equals(1.0e-5f), hasType(asString("float")))))); 554 } 555 556 TEST_P(ImportExpr, ImportImaginaryLiteralExpr) { 557 MatchVerifier<Decl> Verifier; 558 testImport( 559 "void declToImport() { (void)1.0i; }", 560 Lang_CXX14, "", Lang_CXX14, Verifier, 561 functionDecl(hasDescendant(imaginaryLiteral()))); 562 } 563 564 TEST_P(ImportExpr, ImportCompoundLiteralExpr) { 565 MatchVerifier<Decl> Verifier; 566 testImport( 567 "void declToImport() {" 568 " struct s { int x; long y; unsigned z; }; " 569 " (void)(struct s){ 42, 0L, 1U }; }", 570 Lang_CXX, "", Lang_CXX, Verifier, 571 functionDecl(hasDescendant( 572 compoundLiteralExpr( 573 hasType(asString("struct s")), 574 has(initListExpr( 575 hasType(asString("struct s")), 576 has(integerLiteral( 577 equals(42), hasType(asString("int")))), 578 has(integerLiteral( 579 equals(0), hasType(asString("long")))), 580 has(integerLiteral( 581 equals(1), hasType(asString("unsigned int")))))))))); 582 } 583 584 TEST_P(ImportExpr, ImportCXXThisExpr) { 585 MatchVerifier<Decl> Verifier; 586 testImport( 587 "class declToImport { void f() { (void)this; } };", 588 Lang_CXX, "", Lang_CXX, Verifier, 589 cxxRecordDecl( 590 hasMethod( 591 hasDescendant( 592 cxxThisExpr( 593 hasType( 594 asString("class declToImport *"))))))); 595 } 596 597 TEST_P(ImportExpr, ImportAtomicExpr) { 598 MatchVerifier<Decl> Verifier; 599 testImport( 600 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", 601 Lang_C, "", Lang_C, Verifier, 602 functionDecl(hasDescendant( 603 atomicExpr( 604 has(ignoringParenImpCasts( 605 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))), 606 hasType(asString("int *"))))), 607 has(integerLiteral(equals(1), hasType(asString("int")))))))); 608 } 609 610 TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) { 611 MatchVerifier<Decl> Verifier; 612 testImport( 613 "void declToImport() { loop: goto loop; (void)&&loop; }", 614 Lang_C, "", Lang_C, Verifier, 615 functionDecl( 616 hasDescendant( 617 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))), 618 hasDescendant( 619 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop"))))))); 620 } 621 622 AST_MATCHER_P(TemplateDecl, hasTemplateDecl, 623 internal::Matcher<NamedDecl>, InnerMatcher) { 624 const NamedDecl *Template = Node.getTemplatedDecl(); 625 return Template && InnerMatcher.matches(*Template, Finder, Builder); 626 } 627 628 TEST_P(ImportExpr, ImportParenListExpr) { 629 MatchVerifier<Decl> Verifier; 630 testImport( 631 "template<typename T> class dummy { void f() { dummy X(*this); } };" 632 "typedef dummy<int> declToImport;" 633 "template class dummy<int>;", 634 Lang_CXX, "", Lang_CXX, Verifier, 635 typedefDecl(hasType(templateSpecializationType( 636 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate( 637 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf( 638 hasName("f"), 639 hasBody(compoundStmt(has(declStmt(hasSingleDecl( 640 varDecl(hasInitializer(parenListExpr(has(unaryOperator( 641 hasOperatorName("*"), 642 hasUnaryOperand(cxxThisExpr()))))))))))))))))))))))); 643 } 644 645 TEST_P(ImportExpr, ImportSwitch) { 646 MatchVerifier<Decl> Verifier; 647 testImport( 648 "void declToImport() { int b; switch (b) { case 1: break; } }", 649 Lang_C, "", Lang_C, Verifier, 650 functionDecl(hasDescendant( 651 switchStmt(has(compoundStmt(has(caseStmt()))))))); 652 } 653 654 TEST_P(ImportExpr, ImportStmtExpr) { 655 MatchVerifier<Decl> Verifier; 656 testImport( 657 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }", 658 Lang_C, "", Lang_C, Verifier, 659 functionDecl(hasDescendant( 660 varDecl( 661 hasName("C"), 662 hasType(asString("int")), 663 hasInitializer( 664 stmtExpr( 665 hasAnySubstatement(declStmt(hasSingleDecl( 666 varDecl( 667 hasName("X"), 668 hasType(asString("int")), 669 hasInitializer( 670 integerLiteral(equals(4))))))), 671 hasDescendant( 672 implicitCastExpr()))))))); 673 } 674 675 TEST_P(ImportExpr, ImportConditionalOperator) { 676 MatchVerifier<Decl> Verifier; 677 testImport( 678 "void declToImport() { (void)(true ? 1 : -5); }", 679 Lang_CXX, "", Lang_CXX, Verifier, 680 functionDecl(hasDescendant( 681 conditionalOperator( 682 hasCondition(cxxBoolLiteral(equals(true))), 683 hasTrueExpression(integerLiteral(equals(1))), 684 hasFalseExpression( 685 unaryOperator(hasUnaryOperand(integerLiteral(equals(5)))))) 686 ))); 687 } 688 689 TEST_P(ImportExpr, ImportBinaryConditionalOperator) { 690 MatchVerifier<Decl> Verifier; 691 testImport( 692 "void declToImport() { (void)(1 ?: -5); }", 693 Lang_CXX, "", Lang_CXX, Verifier, 694 functionDecl(hasDescendant( 695 binaryConditionalOperator( 696 hasCondition( 697 implicitCastExpr( 698 hasSourceExpression(opaqueValueExpr( 699 hasSourceExpression(integerLiteral(equals(1))))), 700 hasType(booleanType()))), 701 hasTrueExpression( 702 opaqueValueExpr( 703 hasSourceExpression(integerLiteral(equals(1))))), 704 hasFalseExpression( 705 unaryOperator( 706 hasOperatorName("-"), 707 hasUnaryOperand(integerLiteral(equals(5))))))))); 708 } 709 710 TEST_P(ImportExpr, ImportDesignatedInitExpr) { 711 MatchVerifier<Decl> Verifier; 712 testImport( 713 "void declToImport() {" 714 " struct point { double x; double y; };" 715 " struct point ptarray[10] = " 716 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }", 717 Lang_C, "", Lang_C, Verifier, 718 functionDecl(hasDescendant( 719 initListExpr( 720 has(designatedInitExpr( 721 designatorCountIs(2), 722 has(floatLiteral(equals(1.0))), 723 has(integerLiteral(equals(2))))), 724 has(designatedInitExpr( 725 designatorCountIs(2), 726 has(floatLiteral(equals(2.0))), 727 has(integerLiteral(equals(2))))), 728 has(designatedInitExpr( 729 designatorCountIs(2), 730 has(floatLiteral(equals(1.0))), 731 has(integerLiteral(equals(0))))))))); 732 } 733 734 735 TEST_P(ImportExpr, ImportPredefinedExpr) { 736 MatchVerifier<Decl> Verifier; 737 // __func__ expands as StringLiteral("declToImport") 738 testImport( 739 "void declToImport() { (void)__func__; }", 740 Lang_CXX, "", Lang_CXX, Verifier, 741 functionDecl(hasDescendant( 742 predefinedExpr( 743 hasType( 744 asString("const char [13]")), 745 has(stringLiteral(hasType( 746 asString("const char [13]")))))))); 747 } 748 749 TEST_P(ImportExpr, ImportInitListExpr) { 750 MatchVerifier<Decl> Verifier; 751 testImport( 752 "void declToImport() {" 753 " struct point { double x; double y; };" 754 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0," 755 " [0].x = 1.0 }; }", 756 Lang_CXX, "", Lang_CXX, Verifier, 757 functionDecl(hasDescendant( 758 initListExpr( 759 has( 760 cxxConstructExpr( 761 requiresZeroInitialization())), 762 has( 763 initListExpr( 764 hasType(asString("struct point")), 765 has(floatLiteral(equals(1.0))), 766 has(implicitValueInitExpr( 767 hasType(asString("double")))))), 768 has( 769 initListExpr( 770 hasType(asString("struct point")), 771 has(floatLiteral(equals(2.0))), 772 has(floatLiteral(equals(1.0))))))))); 773 } 774 775 776 const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr; 777 778 TEST_P(ImportExpr, ImportVAArgExpr) { 779 MatchVerifier<Decl> Verifier; 780 testImport( 781 "void declToImport(__builtin_va_list list, ...) {" 782 " (void)__builtin_va_arg(list, int); }", 783 Lang_CXX, "", Lang_CXX, Verifier, 784 functionDecl(hasDescendant( 785 cStyleCastExpr(hasSourceExpression(vaArgExpr()))))); 786 } 787 788 TEST_P(ImportExpr, CXXTemporaryObjectExpr) { 789 MatchVerifier<Decl> Verifier; 790 testImport( 791 "struct C {};" 792 "void declToImport() { C c = C(); }", 793 Lang_CXX, "", Lang_CXX, Verifier, 794 functionDecl(hasDescendant( 795 exprWithCleanups(has(cxxConstructExpr( 796 has(materializeTemporaryExpr(has(implicitCastExpr( 797 has(cxxTemporaryObjectExpr()))))))))))); 798 } 799 800 TEST_P(ImportType, ImportAtomicType) { 801 MatchVerifier<Decl> Verifier; 802 testImport( 803 "void declToImport() { typedef _Atomic(int) a_int; }", 804 Lang_CXX11, "", Lang_CXX11, Verifier, 805 functionDecl(hasDescendant(typedefDecl(has(atomicType()))))); 806 } 807 808 TEST_P(ImportDecl, ImportFunctionTemplateDecl) { 809 MatchVerifier<Decl> Verifier; 810 testImport( 811 "template <typename T> void declToImport() { };", 812 Lang_CXX, "", Lang_CXX, Verifier, 813 functionTemplateDecl()); 814 } 815 816 TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) { 817 MatchVerifier<Decl> Verifier; 818 testImport( 819 "template <typename T> struct C { T t; };" 820 "template <typename T> void declToImport() {" 821 " C<T> d;" 822 " (void)d.t;" 823 "}" 824 "void instantiate() { declToImport<int>(); }", 825 Lang_CXX, "", Lang_CXX, Verifier, 826 functionTemplateDecl(hasDescendant( 827 cStyleCastExpr(has(cxxDependentScopeMemberExpr()))))); 828 testImport( 829 "template <typename T> struct C { T t; };" 830 "template <typename T> void declToImport() {" 831 " C<T> d;" 832 " (void)(&d)->t;" 833 "}" 834 "void instantiate() { declToImport<int>(); }", 835 Lang_CXX, "", Lang_CXX, Verifier, 836 functionTemplateDecl(hasDescendant( 837 cStyleCastExpr(has(cxxDependentScopeMemberExpr()))))); 838 } 839 840 TEST_P(ImportType, ImportTypeAliasTemplate) { 841 MatchVerifier<Decl> Verifier; 842 testImport( 843 "template <int K>" 844 "struct dummy { static const int i = K; };" 845 "template <int K> using dummy2 = dummy<K>;" 846 "int declToImport() { return dummy2<3>::i; }", 847 Lang_CXX11, "", Lang_CXX11, Verifier, 848 functionDecl( 849 hasDescendant(implicitCastExpr(has(declRefExpr()))), 850 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl())))))); 851 } 852 853 const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl> 854 varTemplateSpecializationDecl; 855 856 TEST_P(ImportDecl, ImportVarTemplate) { 857 MatchVerifier<Decl> Verifier; 858 testImport( 859 "template <typename T>" 860 "T pi = T(3.1415926535897932385L);" 861 "void declToImport() { (void)pi<int>; }", 862 Lang_CXX14, "", Lang_CXX14, Verifier, 863 functionDecl( 864 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))), 865 unless(hasAncestor(translationUnitDecl(has(varDecl( 866 hasName("pi"), unless(varTemplateSpecializationDecl())))))))); 867 } 868 869 TEST_P(ImportType, ImportPackExpansion) { 870 MatchVerifier<Decl> Verifier; 871 testImport( 872 "template <typename... Args>" 873 "struct dummy {" 874 " dummy(Args... args) {}" 875 " static const int i = 4;" 876 "};" 877 "int declToImport() { return dummy<int>::i; }", 878 Lang_CXX11, "", Lang_CXX11, Verifier, 879 functionDecl(hasDescendant( 880 returnStmt(has(implicitCastExpr(has(declRefExpr()))))))); 881 } 882 883 const internal::VariadicDynCastAllOfMatcher<Type, 884 DependentTemplateSpecializationType> 885 dependentTemplateSpecializationType; 886 887 TEST_P(ImportType, ImportDependentTemplateSpecialization) { 888 MatchVerifier<Decl> Verifier; 889 testImport( 890 "template<typename T>" 891 "struct A;" 892 "template<typename T>" 893 "struct declToImport {" 894 " typename A<T>::template B<T> a;" 895 "};", 896 Lang_CXX, "", Lang_CXX, Verifier, 897 classTemplateDecl(has(cxxRecordDecl(has( 898 fieldDecl(hasType(dependentTemplateSpecializationType()))))))); 899 } 900 901 const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr> 902 sizeOfPackExpr; 903 904 TEST_P(ImportExpr, ImportSizeOfPackExpr) { 905 MatchVerifier<Decl> Verifier; 906 testImport( 907 "template <typename... Ts>" 908 "void declToImport() {" 909 " const int i = sizeof...(Ts);" 910 "};" 911 "void g() { declToImport<int>(); }", 912 Lang_CXX11, "", Lang_CXX11, Verifier, 913 functionTemplateDecl(hasDescendant(sizeOfPackExpr()))); 914 testImport( 915 "template <typename... Ts>" 916 "using X = int[sizeof...(Ts)];" 917 "template <typename... Us>" 918 "struct Y {" 919 " X<Us..., int, double, int, Us...> f;" 920 "};" 921 "Y<float, int> declToImport;", 922 Lang_CXX11, "", Lang_CXX11, Verifier, 923 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType( 924 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7)))))))))); 925 } 926 927 /// \brief Matches __builtin_types_compatible_p: 928 /// GNU extension to check equivalent types 929 /// Given 930 /// \code 931 /// __builtin_types_compatible_p(int, int) 932 /// \endcode 933 // will generate TypeTraitExpr <...> 'int' 934 const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr; 935 936 TEST_P(ImportExpr, ImportTypeTraitExpr) { 937 MatchVerifier<Decl> Verifier; 938 testImport( 939 "void declToImport() { " 940 " (void)__builtin_types_compatible_p(int, int);" 941 "}", 942 Lang_C, "", Lang_C, Verifier, 943 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int")))))); 944 } 945 946 const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr; 947 948 TEST_P(ImportExpr, ImportCXXTypeidExpr) { 949 MatchVerifier<Decl> Verifier; 950 testImport( 951 "namespace std { class type_info {}; }" 952 "void declToImport() {" 953 " int x;" 954 " auto a = typeid(int); auto b = typeid(x);" 955 "}", 956 Lang_CXX11, "", Lang_CXX11, Verifier, 957 functionDecl( 958 hasDescendant(varDecl( 959 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))), 960 hasDescendant(varDecl( 961 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr())))))); 962 } 963 964 TEST_P(ImportExpr, ImportTypeTraitExprValDep) { 965 MatchVerifier<Decl> Verifier; 966 testImport( 967 "template<typename T> struct declToImport {" 968 " void m() { (void)__is_pod(T); }" 969 "};" 970 "void f() { declToImport<int>().m(); }", 971 Lang_CXX11, "", Lang_CXX11, Verifier, 972 classTemplateDecl(has(cxxRecordDecl(has( 973 functionDecl(hasDescendant( 974 typeTraitExpr(hasType(booleanType()))))))))); 975 } 976 977 TEST_P(ImportDecl, ImportRecordDeclInFunc) { 978 MatchVerifier<Decl> Verifier; 979 testImport("int declToImport() { " 980 " struct data_t {int a;int b;};" 981 " struct data_t d;" 982 " return 0;" 983 "}", 984 Lang_C, "", Lang_C, Verifier, 985 functionDecl(hasBody(compoundStmt( 986 has(declStmt(hasSingleDecl(varDecl(hasName("d"))))))))); 987 } 988 989 TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) { 990 Decl *FromTU = getTuDecl("int declToImport() { " 991 " struct data_t {int a;int b;};" 992 " struct data_t d;" 993 " return 0;" 994 "}", 995 Lang_C, "input.c"); 996 auto *FromVar = 997 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d"))); 998 ASSERT_TRUE(FromVar); 999 auto ToType = 1000 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C); 1001 EXPECT_FALSE(ToType.isNull()); 1002 } 1003 1004 TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) { 1005 // This construct is not supported by ASTImporter. 1006 Decl *FromTU = getTuDecl( 1007 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }", 1008 Lang_C, "input.c"); 1009 auto *From = FirstDeclMatcher<FunctionDecl>().match( 1010 FromTU, functionDecl(hasName("declToImport"))); 1011 ASSERT_TRUE(From); 1012 auto *To = Import(From, Lang_C); 1013 EXPECT_EQ(To, nullptr); 1014 } 1015 1016 TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncFromMacro) { 1017 Decl *FromTU = getTuDecl( 1018 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n" 1019 "int declToImport(){ return NONAME_SIZEOF(int); }", 1020 Lang_C, "input.c"); 1021 auto *From = FirstDeclMatcher<FunctionDecl>().match( 1022 FromTU, functionDecl(hasName("declToImport"))); 1023 ASSERT_TRUE(From); 1024 auto *To = Import(From, Lang_C); 1025 ASSERT_TRUE(To); 1026 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match( 1027 To, functionDecl(hasName("declToImport"), 1028 hasDescendant(unaryExprOrTypeTraitExpr())))); 1029 } 1030 1031 TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParamsFromMacro) { 1032 // This construct is not supported by ASTImporter. 1033 Decl *FromTU = getTuDecl( 1034 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n" 1035 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }", 1036 Lang_C, "input.c"); 1037 auto *From = FirstDeclMatcher<FunctionDecl>().match( 1038 FromTU, functionDecl(hasName("declToImport"))); 1039 ASSERT_TRUE(From); 1040 auto *To = Import(From, Lang_C); 1041 EXPECT_EQ(To, nullptr); 1042 } 1043 1044 const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr> 1045 cxxPseudoDestructorExpr; 1046 1047 TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) { 1048 MatchVerifier<Decl> Verifier; 1049 testImport( 1050 "typedef int T;" 1051 "void declToImport(int *p) {" 1052 " T t;" 1053 " p->T::~T();" 1054 "}", 1055 Lang_CXX, "", Lang_CXX, Verifier, 1056 functionDecl(hasDescendant( 1057 callExpr(has(cxxPseudoDestructorExpr()))))); 1058 } 1059 1060 TEST_P(ImportDecl, ImportUsingDecl) { 1061 MatchVerifier<Decl> Verifier; 1062 testImport( 1063 "namespace foo { int bar; }" 1064 "void declToImport() { using foo::bar; }", 1065 Lang_CXX, "", Lang_CXX, Verifier, 1066 functionDecl(hasDescendant(usingDecl()))); 1067 } 1068 1069 /// \brief Matches shadow declarations introduced into a scope by a 1070 /// (resolved) using declaration. 1071 /// 1072 /// Given 1073 /// \code 1074 /// namespace n { int f; } 1075 /// namespace declToImport { using n::f; } 1076 /// \endcode 1077 /// usingShadowDecl() 1078 /// matches \code f \endcode 1079 const internal::VariadicDynCastAllOfMatcher<Decl, 1080 UsingShadowDecl> usingShadowDecl; 1081 1082 TEST_P(ImportDecl, ImportUsingShadowDecl) { 1083 MatchVerifier<Decl> Verifier; 1084 testImport( 1085 "namespace foo { int bar; }" 1086 "namespace declToImport { using foo::bar; }", 1087 Lang_CXX, "", Lang_CXX, Verifier, 1088 namespaceDecl(has(usingShadowDecl()))); 1089 } 1090 1091 TEST_P(ImportExpr, ImportUnresolvedLookupExpr) { 1092 MatchVerifier<Decl> Verifier; 1093 testImport( 1094 "template<typename T> int foo();" 1095 "template <typename T> void declToImport() {" 1096 " (void)::foo<T>;" 1097 " (void)::template foo<T>;" 1098 "}" 1099 "void instantiate() { declToImport<int>(); }", 1100 Lang_CXX, "", Lang_CXX, Verifier, 1101 functionTemplateDecl(hasDescendant(unresolvedLookupExpr()))); 1102 } 1103 1104 TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) { 1105 MatchVerifier<Decl> Verifier; 1106 testImport( 1107 "template <typename T> struct C { T t; };" 1108 "template <typename T> void declToImport() {" 1109 " C<T> d;" 1110 " d.t = T();" 1111 "}" 1112 "void instantiate() { declToImport<int>(); }", 1113 Lang_CXX, "", Lang_CXX, Verifier, 1114 functionTemplateDecl(hasDescendant( 1115 binaryOperator(has(cxxUnresolvedConstructExpr()))))); 1116 testImport( 1117 "template <typename T> struct C { T t; };" 1118 "template <typename T> void declToImport() {" 1119 " C<T> d;" 1120 " (&d)->t = T();" 1121 "}" 1122 "void instantiate() { declToImport<int>(); }", 1123 Lang_CXX, "", Lang_CXX, Verifier, 1124 functionTemplateDecl(hasDescendant( 1125 binaryOperator(has(cxxUnresolvedConstructExpr()))))); 1126 } 1127 1128 /// Check that function "declToImport()" (which is the templated function 1129 /// for corresponding FunctionTemplateDecl) is not added into DeclContext. 1130 /// Same for class template declarations. 1131 TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) { 1132 MatchVerifier<Decl> Verifier; 1133 testImport( 1134 "template <typename T> void declToImport() { T a = 1; }" 1135 "void instantiate() { declToImport<int>(); }", 1136 Lang_CXX, "", Lang_CXX, Verifier, 1137 functionTemplateDecl(hasAncestor(translationUnitDecl( 1138 unless(has(functionDecl(hasName("declToImport")))))))); 1139 testImport( 1140 "template <typename T> struct declToImport { T t; };" 1141 "void instantiate() { declToImport<int>(); }", 1142 Lang_CXX, "", Lang_CXX, Verifier, 1143 classTemplateDecl(hasAncestor(translationUnitDecl( 1144 unless(has(cxxRecordDecl(hasName("declToImport")))))))); 1145 } 1146 1147 TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) { 1148 MatchVerifier<Decl> Verifier; 1149 auto Code = 1150 R"s( 1151 struct declToImport { 1152 template <typename T0> struct X; 1153 template <typename T0> struct X<T0 *> {}; 1154 }; 1155 )s"; 1156 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier, 1157 recordDecl(has(classTemplateDecl()), 1158 has(classTemplateSpecializationDecl()))); 1159 } 1160 1161 TEST_P(ImportExpr, CXXOperatorCallExpr) { 1162 MatchVerifier<Decl> Verifier; 1163 testImport( 1164 "class declToImport {" 1165 " void f() { *this = declToImport(); }" 1166 "};", 1167 Lang_CXX, "", Lang_CXX, Verifier, 1168 cxxRecordDecl(has(cxxMethodDecl(hasDescendant( 1169 cxxOperatorCallExpr()))))); 1170 } 1171 1172 TEST_P(ImportExpr, DependentSizedArrayType) { 1173 MatchVerifier<Decl> Verifier; 1174 testImport( 1175 "template<typename T, int Size> class declToImport {" 1176 " T data[Size];" 1177 "};", 1178 Lang_CXX, "", Lang_CXX, Verifier, 1179 classTemplateDecl(has(cxxRecordDecl( 1180 has(fieldDecl(hasType(dependentSizedArrayType()))))))); 1181 } 1182 1183 TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) { 1184 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX); 1185 auto From = 1186 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl()); 1187 ASSERT_TRUE(From); 1188 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX)); 1189 ASSERT_TRUE(To); 1190 Decl *ToTemplated = To->getTemplatedDecl(); 1191 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX); 1192 EXPECT_TRUE(ToTemplated1); 1193 EXPECT_EQ(ToTemplated1, ToTemplated); 1194 } 1195 1196 TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) { 1197 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX); 1198 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match( 1199 FromTU, functionTemplateDecl()); 1200 ASSERT_TRUE(From); 1201 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX)); 1202 ASSERT_TRUE(To); 1203 Decl *ToTemplated = To->getTemplatedDecl(); 1204 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX); 1205 EXPECT_TRUE(ToTemplated1); 1206 EXPECT_EQ(ToTemplated1, ToTemplated); 1207 } 1208 1209 TEST_P(ASTImporterTestBase, 1210 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) { 1211 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX); 1212 auto FromFT = 1213 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl()); 1214 ASSERT_TRUE(FromFT); 1215 1216 auto ToTemplated = 1217 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX)); 1218 EXPECT_TRUE(ToTemplated); 1219 auto ToTU = ToTemplated->getTranslationUnitDecl(); 1220 auto ToFT = 1221 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl()); 1222 EXPECT_TRUE(ToFT); 1223 } 1224 1225 TEST_P(ASTImporterTestBase, 1226 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) { 1227 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX); 1228 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match( 1229 FromTU, functionTemplateDecl()); 1230 ASSERT_TRUE(FromFT); 1231 1232 auto ToTemplated = 1233 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX)); 1234 EXPECT_TRUE(ToTemplated); 1235 auto ToTU = ToTemplated->getTranslationUnitDecl(); 1236 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match( 1237 ToTU, functionTemplateDecl()); 1238 EXPECT_TRUE(ToFT); 1239 } 1240 1241 TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) { 1242 auto Code = 1243 R"( 1244 namespace x { 1245 template<class X> struct S1{}; 1246 template<class X> struct S2{}; 1247 template<class X> struct S3{}; 1248 } 1249 )"; 1250 Decl *FromTU = getTuDecl(Code, Lang_CXX); 1251 auto FromNs = 1252 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl()); 1253 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX)); 1254 ASSERT_TRUE(ToNs); 1255 auto From = 1256 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, 1257 classTemplateDecl( 1258 hasName("S2"))); 1259 auto To = 1260 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs, 1261 classTemplateDecl( 1262 hasName("S2"))); 1263 ASSERT_TRUE(From); 1264 ASSERT_TRUE(To); 1265 auto ToTemplated = To->getTemplatedDecl(); 1266 auto ToTemplated1 = 1267 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX)); 1268 EXPECT_TRUE(ToTemplated1); 1269 ASSERT_EQ(ToTemplated1, ToTemplated); 1270 } 1271 1272 TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) { 1273 Decl *From, *To; 1274 std::tie(From, To) = getImportedDecl( 1275 R"( 1276 template <typename T> struct X {}; 1277 1278 void declToImport(int y, X<int> &x) {} 1279 1280 template <> struct X<int> { 1281 void g() { 1282 X<int> x; 1283 declToImport(0, x); 1284 } 1285 }; 1286 )", 1287 Lang_CXX, "", Lang_CXX); 1288 1289 MatchVerifier<Decl> Verifier; 1290 auto Matcher = functionDecl(hasName("declToImport"), 1291 parameterCountIs(2), 1292 hasParameter(0, hasName("y")), 1293 hasParameter(1, hasName("x")), 1294 hasParameter(1, hasType(asString("X<int> &")))); 1295 ASSERT_TRUE(Verifier.match(From, Matcher)); 1296 EXPECT_TRUE(Verifier.match(To, Matcher)); 1297 } 1298 1299 TEST_P(ASTImporterTestBase, 1300 TUshouldNotContainTemplatedDeclOfFunctionTemplates) { 1301 Decl *From, *To; 1302 std::tie(From, To) = 1303 getImportedDecl("template <typename T> void declToImport() { T a = 1; }" 1304 "void instantiate() { declToImport<int>(); }", 1305 Lang_CXX, "", Lang_CXX); 1306 1307 auto Check = [](Decl *D) -> bool { 1308 auto TU = D->getTranslationUnitDecl(); 1309 for (auto Child : TU->decls()) { 1310 if (auto *FD = dyn_cast<FunctionDecl>(Child)) { 1311 if (FD->getNameAsString() == "declToImport") { 1312 GTEST_NONFATAL_FAILURE_( 1313 "TU should not contain any FunctionDecl with name declToImport"); 1314 return false; 1315 } 1316 } 1317 } 1318 return true; 1319 }; 1320 1321 ASSERT_TRUE(Check(From)); 1322 EXPECT_TRUE(Check(To)); 1323 } 1324 1325 TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) { 1326 Decl *From, *To; 1327 std::tie(From, To) = 1328 getImportedDecl("template <typename T> struct declToImport { T t; };" 1329 "void instantiate() { declToImport<int>(); }", 1330 Lang_CXX, "", Lang_CXX); 1331 1332 auto Check = [](Decl *D) -> bool { 1333 auto TU = D->getTranslationUnitDecl(); 1334 for (auto Child : TU->decls()) { 1335 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) { 1336 if (RD->getNameAsString() == "declToImport") { 1337 GTEST_NONFATAL_FAILURE_( 1338 "TU should not contain any CXXRecordDecl with name declToImport"); 1339 return false; 1340 } 1341 } 1342 } 1343 return true; 1344 }; 1345 1346 ASSERT_TRUE(Check(From)); 1347 EXPECT_TRUE(Check(To)); 1348 } 1349 1350 TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) { 1351 Decl *From, *To; 1352 std::tie(From, To) = 1353 getImportedDecl( 1354 "template <typename T> struct X {};" 1355 "template <typename T> using declToImport = X<T>;" 1356 "void instantiate() { declToImport<int> a; }", 1357 Lang_CXX11, "", Lang_CXX11); 1358 1359 auto Check = [](Decl *D) -> bool { 1360 auto TU = D->getTranslationUnitDecl(); 1361 for (auto Child : TU->decls()) { 1362 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) { 1363 if (AD->getNameAsString() == "declToImport") { 1364 GTEST_NONFATAL_FAILURE_( 1365 "TU should not contain any TypeAliasDecl with name declToImport"); 1366 return false; 1367 } 1368 } 1369 } 1370 return true; 1371 }; 1372 1373 ASSERT_TRUE(Check(From)); 1374 EXPECT_TRUE(Check(To)); 1375 } 1376 1377 TEST_P( 1378 ASTImporterTestBase, 1379 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) { 1380 1381 Decl *From, *To; 1382 std::tie(From, To) = getImportedDecl( 1383 R"( 1384 template<class T> 1385 class Base {}; 1386 class declToImport : public Base<declToImport> {}; 1387 )", 1388 Lang_CXX, "", Lang_CXX); 1389 1390 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU. 1391 auto Pattern = 1392 translationUnitDecl(unless(has(classTemplateSpecializationDecl()))); 1393 ASSERT_TRUE( 1394 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern)); 1395 EXPECT_TRUE( 1396 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern)); 1397 1398 // Check that the ClassTemplateSpecializationDecl is the child of the 1399 // ClassTemplateDecl. 1400 Pattern = translationUnitDecl(has(classTemplateDecl( 1401 hasName("Base"), has(classTemplateSpecializationDecl())))); 1402 ASSERT_TRUE( 1403 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern)); 1404 EXPECT_TRUE( 1405 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern)); 1406 } 1407 1408 AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) { 1409 size_t Index = 0; 1410 for (FieldDecl *Field : Node.fields()) { 1411 if (Index == Order.size()) 1412 return false; 1413 if (Field->getName() != Order[Index]) 1414 return false; 1415 ++Index; 1416 } 1417 return Index == Order.size(); 1418 } 1419 1420 TEST_P(ASTImporterTestBase, 1421 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) { 1422 Decl *From, *To; 1423 std::tie(From, To) = getImportedDecl( 1424 R"( 1425 namespace NS { 1426 template<class T> 1427 class X {}; 1428 template class X<int>; 1429 } 1430 )", 1431 Lang_CXX, "", Lang_CXX, "NS"); 1432 1433 // Check that the ClassTemplateSpecializationDecl is NOT the child of the 1434 // ClassTemplateDecl. 1435 auto Pattern = namespaceDecl(has(classTemplateDecl( 1436 hasName("X"), unless(has(classTemplateSpecializationDecl()))))); 1437 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern)); 1438 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern)); 1439 1440 // Check that the ClassTemplateSpecializationDecl is the child of the 1441 // NamespaceDecl. 1442 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X")))); 1443 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern)); 1444 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern)); 1445 } 1446 1447 TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) { 1448 Decl *From, *To; 1449 std::tie(From, To) = 1450 getImportedDecl( 1451 "struct declToImport { int a; int b; };", 1452 Lang_CXX11, "", Lang_CXX11); 1453 1454 MatchVerifier<Decl> Verifier; 1455 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"})))); 1456 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"})))); 1457 } 1458 1459 TEST_P(ASTImporterTestBase, 1460 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) { 1461 Decl *From, *To; 1462 std::tie(From, To) = getImportedDecl( 1463 // The original recursive algorithm of ASTImporter first imports 'c' then 1464 // 'b' and lastly 'a'. Therefore we must restore the order somehow. 1465 R"s( 1466 struct declToImport { 1467 int a = c + b; 1468 int b = 1; 1469 int c = 2; 1470 }; 1471 )s", 1472 Lang_CXX11, "", Lang_CXX11); 1473 1474 MatchVerifier<Decl> Verifier; 1475 ASSERT_TRUE( 1476 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"})))); 1477 EXPECT_TRUE( 1478 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"})))); 1479 } 1480 1481 TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) { 1482 Decl *From, *To; 1483 std::tie(From, To) = getImportedDecl( 1484 R"( 1485 struct declToImport { 1486 }; 1487 )", 1488 Lang_CXX, "", Lang_CXX); 1489 1490 MatchVerifier<Decl> Verifier; 1491 // Match the implicit Decl. 1492 auto Matcher = cxxRecordDecl(has(cxxRecordDecl())); 1493 ASSERT_TRUE(Verifier.match(From, Matcher)); 1494 EXPECT_TRUE(Verifier.match(To, Matcher)); 1495 } 1496 1497 TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) { 1498 Decl *From, *To; 1499 std::tie(From, To) = getImportedDecl( 1500 R"( 1501 template <typename U> 1502 struct declToImport { 1503 }; 1504 )", 1505 Lang_CXX, "", Lang_CXX); 1506 1507 MatchVerifier<Decl> Verifier; 1508 // Match the implicit Decl. 1509 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl())))); 1510 ASSERT_TRUE(Verifier.match(From, Matcher)); 1511 EXPECT_TRUE(Verifier.match(To, Matcher)); 1512 } 1513 1514 TEST_P( 1515 ASTImporterTestBase, 1516 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) { 1517 Decl *From, *To; 1518 std::tie(From, To) = getImportedDecl( 1519 R"( 1520 template<class T> 1521 class Base {}; 1522 class declToImport : public Base<declToImport> {}; 1523 )", 1524 Lang_CXX, "", Lang_CXX); 1525 1526 auto hasImplicitClass = has(cxxRecordDecl()); 1527 auto Pattern = translationUnitDecl(has(classTemplateDecl( 1528 hasName("Base"), 1529 has(classTemplateSpecializationDecl(hasImplicitClass))))); 1530 ASSERT_TRUE( 1531 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern)); 1532 EXPECT_TRUE( 1533 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern)); 1534 } 1535 1536 TEST_P(ASTImporterTestBase, IDNSOrdinary) { 1537 Decl *From, *To; 1538 std::tie(From, To) = 1539 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX); 1540 1541 MatchVerifier<Decl> Verifier; 1542 auto Matcher = functionDecl(); 1543 ASSERT_TRUE(Verifier.match(From, Matcher)); 1544 EXPECT_TRUE(Verifier.match(To, Matcher)); 1545 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace()); 1546 } 1547 1548 TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) { 1549 Decl *FromTU = getTuDecl( 1550 R"( 1551 struct X {}; 1552 void operator<<(int, X); 1553 )", 1554 Lang_CXX); 1555 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl()); 1556 const Decl *To = Import(From, Lang_CXX); 1557 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace()); 1558 } 1559 1560 TEST_P(ASTImporterTestBase, 1561 ShouldImportMembersOfClassTemplateSpecializationDecl) { 1562 Decl *From, *To; 1563 std::tie(From, To) = getImportedDecl( 1564 R"( 1565 template<class T> 1566 class Base { int a; }; 1567 class declToImport : Base<declToImport> {}; 1568 )", 1569 Lang_CXX, "", Lang_CXX); 1570 1571 auto Pattern = translationUnitDecl(has(classTemplateDecl( 1572 hasName("Base"), 1573 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a")))))))); 1574 ASSERT_TRUE( 1575 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern)); 1576 EXPECT_TRUE( 1577 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern)); 1578 } 1579 1580 TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) { 1581 { 1582 Decl *FromTU = getTuDecl( 1583 R"( 1584 template <typename T> 1585 struct B; 1586 )", 1587 Lang_CXX, "input0.cc"); 1588 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match( 1589 FromTU, classTemplateDecl(hasName("B"))); 1590 1591 Import(FromD, Lang_CXX); 1592 } 1593 1594 { 1595 Decl *FromTU = getTuDecl( 1596 R"( 1597 template <typename T> 1598 struct B { 1599 void f(); 1600 }; 1601 )", 1602 Lang_CXX, "input1.cc"); 1603 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match( 1604 FromTU, functionDecl(hasName("f"))); 1605 Import(FromD, Lang_CXX); 1606 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match( 1607 FromTU, classTemplateDecl(hasName("B"))); 1608 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX)); 1609 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition()); 1610 } 1611 } 1612 1613 TEST_P(ASTImporterTestBase, 1614 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) { 1615 Decl *ToTU = getToTuDecl( 1616 R"( 1617 template <typename T> 1618 struct B { 1619 void f(); 1620 }; 1621 1622 template <typename T> 1623 struct B; 1624 )", 1625 Lang_CXX); 1626 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>( 1627 [](const ClassTemplateDecl *T) { 1628 return T->isThisDeclarationADefinition(); 1629 }) 1630 .match(ToTU, classTemplateDecl())); 1631 1632 Decl *FromTU = getTuDecl( 1633 R"( 1634 template <typename T> 1635 struct B { 1636 void f(); 1637 }; 1638 )", 1639 Lang_CXX, "input1.cc"); 1640 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match( 1641 FromTU, classTemplateDecl(hasName("B"))); 1642 1643 Import(FromD, Lang_CXX); 1644 1645 // We should have only one definition. 1646 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>( 1647 [](const ClassTemplateDecl *T) { 1648 return T->isThisDeclarationADefinition(); 1649 }) 1650 .match(ToTU, classTemplateDecl())); 1651 } 1652 1653 TEST_P(ASTImporterTestBase, 1654 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) { 1655 Decl *ToTU = getToTuDecl( 1656 R"( 1657 struct B { 1658 void f(); 1659 }; 1660 1661 struct B; 1662 )", 1663 Lang_CXX); 1664 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match( 1665 ToTU, cxxRecordDecl(unless(isImplicit())))); 1666 1667 Decl *FromTU = getTuDecl( 1668 R"( 1669 struct B { 1670 void f(); 1671 }; 1672 )", 1673 Lang_CXX, "input1.cc"); 1674 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match( 1675 FromTU, cxxRecordDecl(hasName("B"))); 1676 1677 Import(FromD, Lang_CXX); 1678 1679 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match( 1680 ToTU, cxxRecordDecl(unless(isImplicit())))); 1681 } 1682 1683 static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) { 1684 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber()); 1685 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber()); 1686 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber()); 1687 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber()); 1688 } 1689 static void CompareSourceRanges(SourceRange Range1, SourceRange Range2, 1690 SourceManager &SM1, SourceManager &SM2) { 1691 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 }, 1692 FullSourceLoc{ Range2.getBegin(), SM2 }); 1693 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 }, 1694 FullSourceLoc{ Range2.getEnd(), SM2 }); 1695 } 1696 TEST_P(ASTImporterTestBase, ImportSourceLocs) { 1697 Decl *FromTU = getTuDecl( 1698 R"( 1699 #define MFOO(arg) arg = arg + 1 1700 1701 void foo() { 1702 int a = 5; 1703 MFOO(a); 1704 } 1705 )", 1706 Lang_CXX); 1707 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl()); 1708 auto ToD = Import(FromD, Lang_CXX); 1709 1710 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr()); 1711 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr()); 1712 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral()); 1713 auto FromRHS = 1714 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral()); 1715 1716 SourceManager &ToSM = ToAST->getASTContext().getSourceManager(); 1717 SourceManager &FromSM = FromD->getASTContext().getSourceManager(); 1718 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM, 1719 FromSM); 1720 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM, 1721 FromSM); 1722 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM, 1723 FromSM); 1724 } 1725 1726 TEST_P(ASTImporterTestBase, ImportNestedMacro) { 1727 Decl *FromTU = getTuDecl( 1728 R"( 1729 #define FUNC_INT void declToImport 1730 #define FUNC FUNC_INT 1731 FUNC(int a); 1732 )", 1733 Lang_CXX); 1734 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl()); 1735 auto ToD = Import(FromD, Lang_CXX); 1736 1737 SourceManager &ToSM = ToAST->getASTContext().getSourceManager(); 1738 SourceManager &FromSM = FromD->getASTContext().getSourceManager(); 1739 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM, 1740 FromSM); 1741 } 1742 1743 TEST_P( 1744 ASTImporterTestBase, 1745 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) 1746 { 1747 Decl *ToTU = getToTuDecl( 1748 R"( 1749 template <typename T> 1750 struct B; 1751 1752 template <> 1753 struct B<int> {}; 1754 1755 template <> 1756 struct B<int>; 1757 )", 1758 Lang_CXX); 1759 // We should have only one definition. 1760 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>( 1761 [](const ClassTemplateSpecializationDecl *T) { 1762 return T->isThisDeclarationADefinition(); 1763 }) 1764 .match(ToTU, classTemplateSpecializationDecl())); 1765 1766 Decl *FromTU = getTuDecl( 1767 R"( 1768 template <typename T> 1769 struct B; 1770 1771 template <> 1772 struct B<int> {}; 1773 )", 1774 Lang_CXX, "input1.cc"); 1775 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 1776 FromTU, classTemplateSpecializationDecl(hasName("B"))); 1777 1778 Import(FromD, Lang_CXX); 1779 1780 // We should have only one definition. 1781 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>( 1782 [](const ClassTemplateSpecializationDecl *T) { 1783 return T->isThisDeclarationADefinition(); 1784 }) 1785 .match(ToTU, classTemplateSpecializationDecl())); 1786 } 1787 1788 TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) { 1789 Decl *FromTU = getTuDecl( 1790 R"( 1791 struct { int a; int b; } object0 = { 2, 3 }; 1792 struct { int x; int y; int z; } object1; 1793 )", 1794 Lang_CXX, "input0.cc"); 1795 1796 auto *Obj0 = 1797 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0"))); 1798 auto *From0 = getRecordDecl(Obj0); 1799 auto *Obj1 = 1800 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1"))); 1801 auto *From1 = getRecordDecl(Obj1); 1802 1803 auto *To0 = Import(From0, Lang_CXX); 1804 auto *To1 = Import(From1, Lang_CXX); 1805 1806 EXPECT_TRUE(To0); 1807 EXPECT_TRUE(To1); 1808 EXPECT_NE(To0, To1); 1809 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl()); 1810 } 1811 1812 TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) { 1813 auto Pattern = varDecl(hasName("x")); 1814 VarDecl *Imported1; 1815 { 1816 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc"); 1817 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); 1818 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX)); 1819 } 1820 VarDecl *Imported2; 1821 { 1822 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc"); 1823 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); 1824 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX)); 1825 } 1826 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl()); 1827 EXPECT_FALSE(Imported2->isUsed(false)); 1828 { 1829 Decl *FromTU = 1830 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc"); 1831 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 1832 FromTU, functionDecl(hasName("f"))); 1833 Import(FromD, Lang_CXX); 1834 } 1835 EXPECT_TRUE(Imported2->isUsed(false)); 1836 } 1837 1838 TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag2) { 1839 auto Pattern = varDecl(hasName("x")); 1840 VarDecl *ExistingD; 1841 { 1842 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX); 1843 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern); 1844 } 1845 EXPECT_FALSE(ExistingD->isUsed(false)); 1846 { 1847 Decl *FromTU = getTuDecl( 1848 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc"); 1849 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 1850 FromTU, functionDecl(hasName("f"))); 1851 Import(FromD, Lang_CXX); 1852 } 1853 EXPECT_TRUE(ExistingD->isUsed(false)); 1854 } 1855 1856 TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag3) { 1857 auto Pattern = varDecl(hasName("a")); 1858 VarDecl *ExistingD; 1859 { 1860 Decl *ToTU = getToTuDecl( 1861 R"( 1862 struct A { 1863 static const int a = 1; 1864 }; 1865 )", Lang_CXX); 1866 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern); 1867 } 1868 EXPECT_FALSE(ExistingD->isUsed(false)); 1869 { 1870 Decl *FromTU = getTuDecl( 1871 R"( 1872 struct A { 1873 static const int a = 1; 1874 }; 1875 const int *f() { return &A::a; } // requires storage, 1876 // thus used flag will be set 1877 )", Lang_CXX, "input1.cc"); 1878 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match( 1879 FromTU, functionDecl(hasName("f"))); 1880 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); 1881 ASSERT_TRUE(FromD->isUsed(false)); 1882 Import(FromFunD, Lang_CXX); 1883 } 1884 EXPECT_TRUE(ExistingD->isUsed(false)); 1885 } 1886 1887 TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) { 1888 auto Pattern = varDecl(hasName("x")); 1889 1890 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc"); 1891 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); 1892 1893 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX)); 1894 1895 ASSERT_FALSE(Imported1->isUsed(false)); 1896 1897 FromD->setIsUsed(); 1898 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX)); 1899 1900 EXPECT_EQ(Imported1, Imported2); 1901 EXPECT_TRUE(Imported2->isUsed(false)); 1902 } 1903 1904 struct ImportFunctions : ASTImporterTestBase {}; 1905 1906 TEST_P(ImportFunctions, 1907 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) { 1908 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX); 1909 auto Pattern = functionDecl(hasName("f")); 1910 FunctionDecl *FromD = // Definition 1911 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 1912 1913 Decl *ImportedD = Import(FromD, Lang_CXX); 1914 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 1915 1916 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 1917 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); 1918 } 1919 1920 TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) { 1921 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX); 1922 auto Pattern = functionDecl(hasName("f")); 1923 FunctionDecl *FromD = 1924 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 1925 1926 Decl *ImportedD = Import(FromD, Lang_CXX); 1927 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 1928 1929 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); 1930 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); 1931 } 1932 1933 TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) { 1934 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); 1935 auto Pattern = functionDecl(hasName("f")); 1936 auto *From = 1937 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto 1938 1939 Decl *ImportedD = Import(From, Lang_CXX); 1940 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 1941 1942 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 1943 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 1944 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 1945 EXPECT_TRUE(ImportedD == To0); 1946 EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); 1947 EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); 1948 EXPECT_EQ(To1->getPreviousDecl(), To0); 1949 } 1950 1951 TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) { 1952 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); 1953 auto Pattern = functionDecl(hasName("f")); 1954 auto *From = 1955 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def 1956 1957 Decl *ImportedD = Import(From, Lang_CXX); 1958 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 1959 1960 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 1961 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 1962 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 1963 EXPECT_TRUE(ImportedD == To1); 1964 EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); 1965 EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); 1966 EXPECT_EQ(To1->getPreviousDecl(), To0); 1967 } 1968 1969 TEST_P(ImportFunctions, ImportPrototypes) { 1970 auto Pattern = functionDecl(hasName("f")); 1971 1972 Decl *ImportedD; 1973 { 1974 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); 1975 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 1976 1977 ImportedD = Import(FromD, Lang_CXX); 1978 } 1979 { 1980 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); 1981 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 1982 Import(FromD, Lang_CXX); 1983 } 1984 1985 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 1986 1987 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 1988 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 1989 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 1990 EXPECT_TRUE(ImportedD == To0); 1991 EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); 1992 EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); 1993 EXPECT_EQ(To1->getPreviousDecl(), To0); 1994 } 1995 1996 TEST_P(ImportFunctions, ImportDefinitions) { 1997 auto Pattern = functionDecl(hasName("f")); 1998 1999 Decl *ImportedD; 2000 { 2001 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); 2002 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2003 ImportedD = Import(FromD, Lang_CXX); 2004 } 2005 { 2006 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc"); 2007 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2008 Import(FromD, Lang_CXX); 2009 } 2010 2011 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 2012 2013 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); 2014 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2015 EXPECT_TRUE(ImportedD == To0); 2016 EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); 2017 } 2018 2019 TEST_P(ImportFunctions, ImportDefinitionThenPrototype) { 2020 auto Pattern = functionDecl(hasName("f")); 2021 2022 Decl *ImportedD; 2023 { 2024 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); 2025 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2026 ImportedD = Import(FromD, Lang_CXX); 2027 } 2028 { 2029 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); 2030 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2031 Import(FromD, Lang_CXX); 2032 } 2033 2034 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2035 2036 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2037 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2038 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2039 EXPECT_TRUE(ImportedD == To0); 2040 EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); 2041 EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); 2042 EXPECT_EQ(To1->getPreviousDecl(), To0); 2043 } 2044 2045 TEST_P(ImportFunctions, ImportPrototypeThenDefinition) { 2046 auto Pattern = functionDecl(hasName("f")); 2047 2048 { 2049 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); 2050 FunctionDecl *FromD = 2051 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2052 2053 Import(FromD, Lang_CXX); 2054 } 2055 { 2056 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc"); 2057 FunctionDecl *FromD = 2058 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2059 Import(FromD, Lang_CXX); 2060 } 2061 2062 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2063 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2064 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2065 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); 2066 FunctionDecl *DefinitionD = 2067 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2068 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); 2069 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD); 2070 } 2071 2072 TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) { 2073 auto Pattern = functionDecl(hasName("f")); 2074 2075 { 2076 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); 2077 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2078 Import(FromD, Lang_CXX); 2079 } 2080 { 2081 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc"); 2082 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2083 Import(FromD, Lang_CXX); 2084 } 2085 2086 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2087 2088 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u); 2089 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2090 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); 2091 2092 FunctionDecl *DefinitionD = 2093 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2094 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); 2095 2096 EXPECT_TRUE(DefinitionD->getPreviousDecl()); 2097 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody()); 2098 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD); 2099 } 2100 2101 TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) { 2102 auto Code = 2103 R"( 2104 struct B { virtual void f(); }; 2105 void B::f() {} 2106 struct D : B { void f(); }; 2107 )"; 2108 auto Pattern = 2109 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D")))); 2110 Decl *FromTU = getTuDecl(Code, Lang_CXX); 2111 CXXMethodDecl *Proto = 2112 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern); 2113 2114 ASSERT_EQ(Proto->size_overridden_methods(), 1u); 2115 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX)); 2116 EXPECT_EQ(To->size_overridden_methods(), 1u); 2117 } 2118 2119 TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) { 2120 auto Code = 2121 R"( 2122 struct B { virtual void f(); }; 2123 void B::f() {} 2124 )"; 2125 auto Pattern = 2126 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B")))); 2127 Decl *FromTU = getTuDecl(Code, Lang_CXX); 2128 CXXMethodDecl *Proto = 2129 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern); 2130 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern); 2131 2132 ASSERT_TRUE(Proto->isVirtual()); 2133 ASSERT_TRUE(Def->isVirtual()); 2134 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX)); 2135 EXPECT_TRUE(To->isVirtual()); 2136 } 2137 2138 TEST_P(ImportFunctions, 2139 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) { 2140 Decl *ToTU = getToTuDecl( 2141 R"( 2142 void f() {} 2143 void f(); 2144 )", 2145 Lang_CXX); 2146 ASSERT_EQ(1u, 2147 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) { 2148 return FD->doesThisDeclarationHaveABody(); 2149 }).match(ToTU, functionDecl())); 2150 2151 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc"); 2152 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl()); 2153 2154 Import(FromD, Lang_CXX); 2155 2156 EXPECT_EQ(1u, 2157 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) { 2158 return FD->doesThisDeclarationHaveABody(); 2159 }).match(ToTU, functionDecl())); 2160 } 2161 2162 struct ImportFriendFunctions : ImportFunctions {}; 2163 2164 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) { 2165 auto Pattern = functionDecl(hasName("f")); 2166 2167 Decl *FromTU = getTuDecl("struct X { friend void f(); };" 2168 "void f();", 2169 Lang_CXX, 2170 "input0.cc"); 2171 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2172 2173 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2174 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2175 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2176 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); 2177 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2178 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); 2179 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); 2180 } 2181 2182 TEST_P(ImportFriendFunctions, 2183 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) { 2184 auto Pattern = functionDecl(hasName("f")); 2185 2186 Decl *FromTU = getTuDecl("void f();" 2187 "struct X { friend void f(); };", 2188 Lang_CXX, "input0.cc"); 2189 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2190 2191 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2192 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2193 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2194 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); 2195 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2196 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); 2197 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); 2198 } 2199 2200 TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) { 2201 auto Pattern = functionDecl(hasName("f")); 2202 2203 Decl *FromTU = getTuDecl("struct X { friend void f(){} };" 2204 "void f();", 2205 Lang_CXX, 2206 "input0.cc"); 2207 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2208 2209 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2210 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2211 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2212 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); 2213 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2214 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); 2215 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); 2216 } 2217 2218 TEST_P(ImportFriendFunctions, 2219 ImportFriendFunctionRedeclChainDef_OutOfClassDef) { 2220 auto Pattern = functionDecl(hasName("f")); 2221 2222 Decl *FromTU = getTuDecl("struct X { friend void f(); };" 2223 "void f(){}", 2224 Lang_CXX, "input0.cc"); 2225 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2226 2227 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2228 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2229 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2230 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); 2231 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 2232 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody()); 2233 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); 2234 } 2235 2236 // Disabled temporarily, because the new structural equivalence check 2237 // (https://reviews.llvm.org/D48628) breaks it. 2238 // PreviousDecl is not set because there is no structural match. 2239 // FIXME Enable! 2240 TEST_P(ImportFriendFunctions, 2241 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) { 2242 auto Pattern = functionDecl(hasName("f")); 2243 2244 Decl *FromTU = getTuDecl( 2245 R"( 2246 class X; 2247 void f(X *x){} 2248 class X{ 2249 friend void f(X *x); 2250 }; 2251 )", 2252 Lang_CXX, "input0.cc"); 2253 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2254 2255 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2256 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2257 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2258 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); 2259 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>() 2260 .match(ToTU, friendDecl()) 2261 ->getFriendDecl()); 2262 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody()); 2263 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD); 2264 // The parameters must refer the same type 2265 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(), 2266 (*ImportedD->param_begin())->getOriginalType()); 2267 } 2268 2269 // Disabled temporarily, because the new structural equivalence check 2270 // (https://reviews.llvm.org/D48628) breaks it. 2271 // PreviousDecl is not set because there is no structural match. 2272 // FIXME Enable! 2273 TEST_P(ImportFriendFunctions, 2274 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) { 2275 auto Pattern = functionDecl(hasName("f")); 2276 2277 Decl *FromTU = getTuDecl( 2278 R"( 2279 class X; 2280 void f(X *x){} 2281 class X{ 2282 friend void f(X *x); 2283 }; 2284 )", 2285 Lang_CXX, "input0.cc"); 2286 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2287 2288 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2289 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2290 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2291 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); 2292 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match( 2293 ToTU, functionDecl(unless(hasParent(friendDecl())))); 2294 2295 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody()); 2296 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD); 2297 // The parameters must refer the same type 2298 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(), 2299 (*ImportedD->param_begin())->getOriginalType()); 2300 } 2301 2302 TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) { 2303 auto Pattern = functionDecl(hasName("f")); 2304 2305 FunctionDecl *ImportedD; 2306 { 2307 Decl *FromTU = 2308 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc"); 2309 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2310 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2311 } 2312 FunctionDecl *ImportedD1; 2313 { 2314 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); 2315 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 2316 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2317 } 2318 2319 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2320 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2321 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); 2322 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody()); 2323 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD); 2324 } 2325 2326 TEST_P(ImportFriendFunctions, Lookup) { 2327 auto FunctionPattern = functionDecl(hasName("f")); 2328 auto ClassPattern = cxxRecordDecl(hasName("X")); 2329 2330 TranslationUnitDecl *FromTU = 2331 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc"); 2332 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern); 2333 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2334 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2335 { 2336 auto FromName = FromD->getDeclName(); 2337 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern); 2338 auto LookupRes = Class->noload_lookup(FromName); 2339 ASSERT_EQ(LookupRes.size(), 0u); 2340 LookupRes = FromTU->noload_lookup(FromName); 2341 ASSERT_EQ(LookupRes.size(), 1u); 2342 } 2343 2344 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); 2345 auto ToName = ToD->getDeclName(); 2346 2347 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2348 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern); 2349 auto LookupRes = Class->noload_lookup(ToName); 2350 EXPECT_EQ(LookupRes.size(), 0u); 2351 LookupRes = ToTU->noload_lookup(ToName); 2352 EXPECT_EQ(LookupRes.size(), 1u); 2353 2354 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u); 2355 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern); 2356 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2357 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2358 } 2359 2360 TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) { 2361 auto FunctionPattern = functionDecl(hasName("f")); 2362 auto ClassPattern = cxxRecordDecl(hasName("X")); 2363 2364 TranslationUnitDecl *FromTU = getTuDecl( 2365 "struct X { friend void f(); };" 2366 // This proto decl makes f available to normal 2367 // lookup, otherwise it is hidden. 2368 // Normal C++ lookup (implemented in 2369 // `clang::Sema::CppLookupName()` and in `LookupDirect()`) 2370 // returns the found `NamedDecl` only if the set IDNS is matched 2371 "void f();", 2372 Lang_CXX, "input0.cc"); 2373 auto *FromFriend = 2374 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern); 2375 auto *FromNormal = 2376 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern); 2377 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2378 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2379 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2380 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2381 2382 auto FromName = FromFriend->getDeclName(); 2383 auto *FromClass = 2384 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern); 2385 auto LookupRes = FromClass->noload_lookup(FromName); 2386 ASSERT_EQ(LookupRes.size(), 0u); 2387 LookupRes = FromTU->noload_lookup(FromName); 2388 ASSERT_EQ(LookupRes.size(), 1u); 2389 2390 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX)); 2391 auto ToName = ToFriend->getDeclName(); 2392 2393 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2394 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern); 2395 LookupRes = ToClass->noload_lookup(ToName); 2396 EXPECT_EQ(LookupRes.size(), 0u); 2397 LookupRes = ToTU->noload_lookup(ToName); 2398 // Test is disabled because this result is 2. 2399 EXPECT_EQ(LookupRes.size(), 1u); 2400 2401 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u); 2402 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern); 2403 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern); 2404 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2405 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2406 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2407 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2408 } 2409 2410 TEST_P(ImportFriendFunctions, LookupWithProtoBefore) { 2411 auto FunctionPattern = functionDecl(hasName("f")); 2412 auto ClassPattern = cxxRecordDecl(hasName("X")); 2413 2414 TranslationUnitDecl *FromTU = getTuDecl( 2415 "void f();" 2416 "struct X { friend void f(); };", 2417 Lang_CXX, "input0.cc"); 2418 auto *FromNormal = 2419 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern); 2420 auto *FromFriend = 2421 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern); 2422 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2423 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2424 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2425 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2426 2427 auto FromName = FromNormal->getDeclName(); 2428 auto *FromClass = 2429 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern); 2430 auto LookupRes = FromClass->noload_lookup(FromName); 2431 ASSERT_EQ(LookupRes.size(), 0u); 2432 LookupRes = FromTU->noload_lookup(FromName); 2433 ASSERT_EQ(LookupRes.size(), 1u); 2434 2435 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX)); 2436 auto ToName = ToNormal->getDeclName(); 2437 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2438 2439 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern); 2440 LookupRes = ToClass->noload_lookup(ToName); 2441 EXPECT_EQ(LookupRes.size(), 0u); 2442 LookupRes = ToTU->noload_lookup(ToName); 2443 EXPECT_EQ(LookupRes.size(), 1u); 2444 2445 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u); 2446 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern); 2447 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern); 2448 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2449 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2450 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2451 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2452 } 2453 2454 TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) { 2455 auto Pattern = functionDecl(hasName("f")); 2456 2457 TranslationUnitDecl *FromNormalTU = 2458 getTuDecl("void f();", Lang_CXX, "input0.cc"); 2459 auto *FromNormalF = 2460 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern); 2461 TranslationUnitDecl *FromFriendTU = 2462 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc"); 2463 auto *FromFriendF = 2464 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern); 2465 auto FromNormalName = FromNormalF->getDeclName(); 2466 auto FromFriendName = FromFriendF->getDeclName(); 2467 2468 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2469 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2470 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2471 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2472 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName); 2473 ASSERT_EQ(LookupRes.size(), 1u); 2474 LookupRes = FromFriendTU->noload_lookup(FromFriendName); 2475 ASSERT_EQ(LookupRes.size(), 1u); 2476 2477 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX)); 2478 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2479 auto ToName = ToNormalF->getDeclName(); 2480 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2481 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2482 LookupRes = ToTU->noload_lookup(ToName); 2483 EXPECT_EQ(LookupRes.size(), 1u); 2484 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); 2485 2486 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX)); 2487 LookupRes = ToTU->noload_lookup(ToName); 2488 EXPECT_EQ(LookupRes.size(), 1u); 2489 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 2490 2491 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2492 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2493 2494 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary)); 2495 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)); 2496 } 2497 2498 TEST_P(ImportFriendFunctions, ImportFriendList) { 2499 TranslationUnitDecl *FromTU = getTuDecl( 2500 "struct X { friend void f(); };" 2501 "void f();", 2502 Lang_CXX, "input0.cc"); 2503 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match( 2504 FromTU, functionDecl(hasName("f"))); 2505 2506 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match( 2507 FromTU, cxxRecordDecl(hasName("X"))); 2508 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl()); 2509 auto FromFriends = FromClass->friends(); 2510 unsigned int FrN = 0; 2511 for (auto Fr : FromFriends) { 2512 ASSERT_EQ(Fr, FromFriend); 2513 ++FrN; 2514 } 2515 ASSERT_EQ(FrN, 1u); 2516 2517 Import(FromFriendF, Lang_CXX); 2518 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2519 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match( 2520 ToTU, cxxRecordDecl(hasName("X"))); 2521 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl()); 2522 auto ToFriends = ToClass->friends(); 2523 FrN = 0; 2524 for (auto Fr : ToFriends) { 2525 EXPECT_EQ(Fr, ToFriend); 2526 ++FrN; 2527 } 2528 EXPECT_EQ(FrN, 1u); 2529 } 2530 2531 AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>, 2532 InnerMatcher) { 2533 if (auto *Typedef = Node.getTypedefNameForAnonDecl()) 2534 return InnerMatcher.matches(*Typedef, Finder, Builder); 2535 return false; 2536 } 2537 2538 TEST_P(ImportDecl, ImportEnumSequential) { 2539 CodeFiles Samples{{"main.c", 2540 {"void foo();" 2541 "void moo();" 2542 "int main() { foo(); moo(); }", 2543 Lang_C}}, 2544 2545 {"foo.c", 2546 {"typedef enum { THING_VALUE } thing_t;" 2547 "void conflict(thing_t type);" 2548 "void foo() { (void)THING_VALUE; }" 2549 "void conflict(thing_t type) {}", 2550 Lang_C}}, 2551 2552 {"moo.c", 2553 {"typedef enum { THING_VALUE } thing_t;" 2554 "void conflict(thing_t type);" 2555 "void moo() { conflict(THING_VALUE); }", 2556 Lang_C}}}; 2557 2558 auto VerificationMatcher = 2559 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))), 2560 hasTypedefForAnonDecl(hasName("thing_t"))); 2561 2562 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))}, 2563 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))}; 2564 2565 testImportSequence( 2566 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo". 2567 // Just check that there is only one enum decl in the result AST. 2568 "main.c", enumDecl(), VerificationMatcher); 2569 2570 // For different import order, result should be the same. 2571 testImportSequence( 2572 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo". 2573 // Check that there is only one enum decl in the result AST. 2574 "main.c", enumDecl(), VerificationMatcher); 2575 } 2576 2577 const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr> 2578 dependentScopeDeclRefExpr; 2579 2580 TEST_P(ImportExpr, DependentScopeDeclRefExpr) { 2581 MatchVerifier<Decl> Verifier; 2582 testImport("template <typename T> struct S { static T foo; };" 2583 "template <typename T> void declToImport() {" 2584 " (void) S<T>::foo;" 2585 "}" 2586 "void instantiate() { declToImport<int>(); }" 2587 "template <typename T> T S<T>::foo;", 2588 Lang_CXX11, "", Lang_CXX11, Verifier, 2589 functionTemplateDecl(has(functionDecl(has(compoundStmt( 2590 has(cStyleCastExpr(has(dependentScopeDeclRefExpr()))))))))); 2591 2592 testImport("template <typename T> struct S {" 2593 "template<typename S> static void foo(){};" 2594 "};" 2595 "template <typename T> void declToImport() {" 2596 " S<T>::template foo<T>();" 2597 "}" 2598 "void instantiate() { declToImport<int>(); }", 2599 Lang_CXX11, "", Lang_CXX11, Verifier, 2600 functionTemplateDecl(has(functionDecl(has(compoundStmt( 2601 has(callExpr(has(dependentScopeDeclRefExpr()))))))))); 2602 } 2603 2604 const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType> 2605 dependentNameType; 2606 2607 TEST_P(ImportExpr, DependentNameType) { 2608 MatchVerifier<Decl> Verifier; 2609 testImport("template <typename T> struct declToImport {" 2610 " typedef typename T::type dependent_name;" 2611 "};", 2612 Lang_CXX11, "", Lang_CXX11, Verifier, 2613 classTemplateDecl(has( 2614 cxxRecordDecl(has(typedefDecl(has(dependentNameType()))))))); 2615 } 2616 2617 TEST_P(ImportExpr, UnresolvedMemberExpr) { 2618 MatchVerifier<Decl> Verifier; 2619 testImport("struct S { template <typename T> void mem(); };" 2620 "template <typename U> void declToImport() {" 2621 " S s;" 2622 " s.mem<U>();" 2623 "}" 2624 "void instantiate() { declToImport<int>(); }", 2625 Lang_CXX11, "", Lang_CXX11, Verifier, 2626 functionTemplateDecl(has(functionDecl(has( 2627 compoundStmt(has(callExpr(has(unresolvedMemberExpr()))))))))); 2628 } 2629 2630 class ImportImplicitMethods : public ASTImporterTestBase { 2631 public: 2632 static constexpr auto DefaultCode = R"( 2633 struct A { int x; }; 2634 void f() { 2635 A a; 2636 A a1(a); 2637 A a2(A{}); 2638 a = a1; 2639 a = A{}; 2640 a.~A(); 2641 })"; 2642 2643 template <typename MatcherType> 2644 void testImportOf( 2645 const MatcherType &MethodMatcher, const char *Code = DefaultCode) { 2646 test(MethodMatcher, Code, /*ExpectedCount=*/1u); 2647 } 2648 2649 template <typename MatcherType> 2650 void testNoImportOf( 2651 const MatcherType &MethodMatcher, const char *Code = DefaultCode) { 2652 test(MethodMatcher, Code, /*ExpectedCount=*/0u); 2653 } 2654 2655 private: 2656 template <typename MatcherType> 2657 void test(const MatcherType &MethodMatcher, 2658 const char *Code, unsigned int ExpectedCount) { 2659 auto ClassMatcher = cxxRecordDecl(unless(isImplicit())); 2660 2661 Decl *ToTU = getToTuDecl(Code, Lang_CXX11); 2662 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match( 2663 ToTU, ClassMatcher); 2664 2665 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u); 2666 2667 { 2668 CXXMethodDecl *Method = 2669 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher); 2670 ToClass->removeDecl(Method); 2671 } 2672 2673 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u); 2674 2675 Decl *ImportedClass = nullptr; 2676 { 2677 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc"); 2678 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match( 2679 FromTU, ClassMatcher); 2680 ImportedClass = Import(FromClass, Lang_CXX11); 2681 } 2682 2683 EXPECT_EQ(ToClass, ImportedClass); 2684 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 2685 ExpectedCount); 2686 } 2687 }; 2688 2689 TEST_P(ImportImplicitMethods, DefaultConstructor) { 2690 testImportOf(cxxConstructorDecl(isDefaultConstructor())); 2691 } 2692 2693 TEST_P(ImportImplicitMethods, CopyConstructor) { 2694 testImportOf(cxxConstructorDecl(isCopyConstructor())); 2695 } 2696 2697 TEST_P(ImportImplicitMethods, MoveConstructor) { 2698 testImportOf(cxxConstructorDecl(isMoveConstructor())); 2699 } 2700 2701 TEST_P(ImportImplicitMethods, Destructor) { 2702 testImportOf(cxxDestructorDecl()); 2703 } 2704 2705 TEST_P(ImportImplicitMethods, CopyAssignment) { 2706 testImportOf(cxxMethodDecl(isCopyAssignmentOperator())); 2707 } 2708 2709 TEST_P(ImportImplicitMethods, MoveAssignment) { 2710 testImportOf(cxxMethodDecl(isMoveAssignmentOperator())); 2711 } 2712 2713 TEST_P(ImportImplicitMethods, DoNotImportUserProvided) { 2714 auto Code = R"( 2715 struct A { A() { int x; } }; 2716 )"; 2717 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code); 2718 } 2719 2720 TEST_P(ImportImplicitMethods, DoNotImportDefault) { 2721 auto Code = R"( 2722 struct A { A() = default; }; 2723 )"; 2724 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code); 2725 } 2726 2727 TEST_P(ImportImplicitMethods, DoNotImportDeleted) { 2728 auto Code = R"( 2729 struct A { A() = delete; }; 2730 )"; 2731 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code); 2732 } 2733 2734 TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) { 2735 auto Code = R"( 2736 struct A { void f() { } }; 2737 )"; 2738 testNoImportOf(cxxMethodDecl(hasName("f")), Code); 2739 } 2740 2741 TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) { 2742 Decl *ToR1; 2743 { 2744 Decl *FromTU = getTuDecl( 2745 "struct A { };", Lang_CXX, "input0.cc"); 2746 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( 2747 FromTU, cxxRecordDecl(hasName("A"))); 2748 2749 ToR1 = Import(FromR, Lang_CXX); 2750 } 2751 2752 Decl *ToR2; 2753 { 2754 Decl *FromTU = getTuDecl( 2755 "struct A { };", Lang_CXX, "input1.cc"); 2756 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( 2757 FromTU, cxxRecordDecl(hasName("A"))); 2758 2759 ToR2 = Import(FromR, Lang_CXX); 2760 } 2761 2762 EXPECT_EQ(ToR1, ToR2); 2763 } 2764 2765 TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) { 2766 Decl *ToR1; 2767 { 2768 Decl *FromTU = getTuDecl( 2769 "struct A { int x; };", Lang_CXX, "input0.cc"); 2770 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( 2771 FromTU, cxxRecordDecl(hasName("A"))); 2772 ToR1 = Import(FromR, Lang_CXX); 2773 } 2774 Decl *ToR2; 2775 { 2776 Decl *FromTU = getTuDecl( 2777 "struct A { unsigned x; };", Lang_CXX, "input1.cc"); 2778 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( 2779 FromTU, cxxRecordDecl(hasName("A"))); 2780 ToR2 = Import(FromR, Lang_CXX); 2781 } 2782 EXPECT_NE(ToR1, ToR2); 2783 } 2784 2785 TEST_P(ASTImporterTestBase, ImportOfEquivalentField) { 2786 Decl *ToF1; 2787 { 2788 Decl *FromTU = getTuDecl( 2789 "struct A { int x; };", Lang_CXX, "input0.cc"); 2790 auto *FromF = FirstDeclMatcher<FieldDecl>().match( 2791 FromTU, fieldDecl(hasName("x"))); 2792 ToF1 = Import(FromF, Lang_CXX); 2793 } 2794 Decl *ToF2; 2795 { 2796 Decl *FromTU = getTuDecl( 2797 "struct A { int x; };", Lang_CXX, "input1.cc"); 2798 auto *FromF = FirstDeclMatcher<FieldDecl>().match( 2799 FromTU, fieldDecl(hasName("x"))); 2800 ToF2 = Import(FromF, Lang_CXX); 2801 } 2802 EXPECT_EQ(ToF1, ToF2); 2803 } 2804 2805 TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) { 2806 Decl *ToF1; 2807 { 2808 Decl *FromTU = getTuDecl( 2809 "struct A { int x; };", Lang_CXX, "input0.cc"); 2810 auto *FromF = FirstDeclMatcher<FieldDecl>().match( 2811 FromTU, fieldDecl(hasName("x"))); 2812 ToF1 = Import(FromF, Lang_CXX); 2813 } 2814 Decl *ToF2; 2815 { 2816 Decl *FromTU = getTuDecl( 2817 "struct A { unsigned x; };", Lang_CXX, "input1.cc"); 2818 auto *FromF = FirstDeclMatcher<FieldDecl>().match( 2819 FromTU, fieldDecl(hasName("x"))); 2820 ToF2 = Import(FromF, Lang_CXX); 2821 } 2822 EXPECT_NE(ToF1, ToF2); 2823 } 2824 2825 TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) { 2826 Decl *ToM1; 2827 { 2828 Decl *FromTU = getTuDecl( 2829 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc"); 2830 auto *FromM = FirstDeclMatcher<FunctionDecl>().match( 2831 FromTU, functionDecl(hasName("x"), isDefinition())); 2832 ToM1 = Import(FromM, Lang_CXX); 2833 } 2834 Decl *ToM2; 2835 { 2836 Decl *FromTU = getTuDecl( 2837 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc"); 2838 auto *FromM = FirstDeclMatcher<FunctionDecl>().match( 2839 FromTU, functionDecl(hasName("x"), isDefinition())); 2840 ToM2 = Import(FromM, Lang_CXX); 2841 } 2842 EXPECT_EQ(ToM1, ToM2); 2843 } 2844 2845 TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) { 2846 Decl *ToM1; 2847 { 2848 Decl *FromTU = getTuDecl( 2849 "struct A { void x(); }; void A::x() { }", 2850 Lang_CXX, "input0.cc"); 2851 auto *FromM = FirstDeclMatcher<FunctionDecl>().match( 2852 FromTU, functionDecl(hasName("x"), isDefinition())); 2853 ToM1 = Import(FromM, Lang_CXX); 2854 } 2855 Decl *ToM2; 2856 { 2857 Decl *FromTU = getTuDecl( 2858 "struct A { void x() const; }; void A::x() const { }", 2859 Lang_CXX, "input1.cc"); 2860 auto *FromM = FirstDeclMatcher<FunctionDecl>().match( 2861 FromTU, functionDecl(hasName("x"), isDefinition())); 2862 ToM2 = Import(FromM, Lang_CXX); 2863 } 2864 EXPECT_NE(ToM1, ToM2); 2865 } 2866 2867 TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) { 2868 Decl *FromTU = getTuDecl( 2869 R"( 2870 struct A { 2871 struct { 2872 struct A *next; 2873 } entry0; 2874 struct { 2875 struct A *next; 2876 } entry1; 2877 }; 2878 )", 2879 Lang_C, "input0.cc"); 2880 auto *From = 2881 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A"))); 2882 2883 Import(From, Lang_C); 2884 2885 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 2886 auto *Entry0 = 2887 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0"))); 2888 auto *Entry1 = 2889 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1"))); 2890 auto *R0 = getRecordDecl(Entry0); 2891 auto *R1 = getRecordDecl(Entry1); 2892 EXPECT_NE(R0, R1); 2893 EXPECT_TRUE(MatchVerifier<RecordDecl>().match( 2894 R0, recordDecl(has(fieldDecl(hasName("next")))))); 2895 EXPECT_TRUE(MatchVerifier<RecordDecl>().match( 2896 R1, recordDecl(has(fieldDecl(hasName("next")))))); 2897 } 2898 2899 TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) { 2900 Decl *FromTU = getTuDecl( 2901 R"( 2902 void f(int X, int Y, bool Z) { 2903 (void)[X, Y, Z] { (void)Z; }; 2904 } 2905 )", 2906 Lang_CXX11, "input0.cc"); 2907 auto *FromF = FirstDeclMatcher<FunctionDecl>().match( 2908 FromTU, functionDecl(hasName("f"))); 2909 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11)); 2910 EXPECT_TRUE(ToF); 2911 2912 CXXRecordDecl *FromLambda = 2913 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>( 2914 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass(); 2915 2916 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11)); 2917 EXPECT_TRUE(ToLambda); 2918 2919 // Check if the fields of the lambda class are imported in correct order. 2920 unsigned FromIndex = 0u; 2921 for (auto *FromField : FromLambda->fields()) { 2922 ASSERT_FALSE(FromField->getDeclName()); 2923 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11)); 2924 EXPECT_TRUE(ToField); 2925 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField); 2926 EXPECT_TRUE(ToIndex); 2927 EXPECT_EQ(*ToIndex, FromIndex); 2928 ++FromIndex; 2929 } 2930 2931 EXPECT_EQ(FromIndex, 3u); 2932 } 2933 2934 TEST_P( 2935 ASTImporterTestBase, 2936 ImportOfFriendRecordDoesNotMergeDefinition) { 2937 Decl *FromTU = getTuDecl( 2938 R"( 2939 class A { 2940 template <int I> class F {}; 2941 class X { 2942 template <int I> friend class F; 2943 }; 2944 }; 2945 )", 2946 Lang_CXX, "input0.cc"); 2947 2948 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match( 2949 FromTU, cxxRecordDecl(hasName("F"), isDefinition())); 2950 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match( 2951 FromTU, cxxRecordDecl(hasName("F"))); 2952 2953 ASSERT_TRUE(FromClass); 2954 ASSERT_TRUE(FromFriendClass); 2955 ASSERT_NE(FromClass, FromFriendClass); 2956 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass); 2957 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass); 2958 ASSERT_EQ( 2959 FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(), 2960 FromClass->getDescribedClassTemplate()); 2961 2962 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX)); 2963 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX)); 2964 2965 EXPECT_TRUE(ToClass); 2966 EXPECT_TRUE(ToFriendClass); 2967 EXPECT_NE(ToClass, ToFriendClass); 2968 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass); 2969 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass); 2970 EXPECT_EQ( 2971 ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(), 2972 ToClass->getDescribedClassTemplate()); 2973 } 2974 2975 TEST_P( 2976 ASTImporterTestBase, 2977 ImportOfRecursiveFriendClass) { 2978 Decl *FromTu = getTuDecl( 2979 R"( 2980 class declToImport { 2981 friend class declToImport; 2982 }; 2983 )", 2984 Lang_CXX, "input.cc"); 2985 2986 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match( 2987 FromTu, cxxRecordDecl(hasName("declToImport"))); 2988 auto *ToD = Import(FromD, Lang_CXX); 2989 auto Pattern = cxxRecordDecl(hasName("declToImport"), has(friendDecl())); 2990 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern)); 2991 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern)); 2992 } 2993 2994 TEST_P( 2995 ASTImporterTestBase, 2996 ImportOfRecursiveFriendClassTemplate) { 2997 Decl *FromTu = getTuDecl( 2998 R"( 2999 template <class A> class declToImport { 3000 template <class A1> friend class declToImport; 3001 }; 3002 )", 3003 Lang_CXX, "input.cc"); 3004 3005 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match( 3006 FromTu, classTemplateDecl(hasName("declToImport"))); 3007 auto *ToD = Import(FromD, Lang_CXX); 3008 3009 auto Pattern = classTemplateDecl( 3010 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl())))))); 3011 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern)); 3012 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern)); 3013 3014 auto *Class = 3015 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl()); 3016 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl()); 3017 EXPECT_NE(Friend->getFriendDecl(), Class); 3018 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class); 3019 } 3020 3021 TEST_P(ASTImporterTestBase, MergeFieldDeclsOfClassTemplateSpecialization) { 3022 std::string ClassTemplate = 3023 R"( 3024 template <typename T> 3025 struct X { 3026 int a{0}; // FieldDecl with InitListExpr 3027 X(char) : a(3) {} // (1) 3028 X(int) {} // (2) 3029 }; 3030 )"; 3031 Decl *ToTU = getToTuDecl(ClassTemplate + 3032 R"( 3033 void foo() { 3034 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr 3035 X<char> xc('c'); 3036 } 3037 )", Lang_CXX11); 3038 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3039 ToTU, classTemplateSpecializationDecl(hasName("X"))); 3040 // FieldDecl without InitlistExpr: 3041 auto *ToField = *ToSpec->field_begin(); 3042 ASSERT_TRUE(ToField); 3043 ASSERT_FALSE(ToField->getInClassInitializer()); 3044 Decl *FromTU = getTuDecl(ClassTemplate + 3045 R"( 3046 void bar() { 3047 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr 3048 X<char> xc(1); 3049 } 3050 )", Lang_CXX11); 3051 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3052 FromTU, classTemplateSpecializationDecl(hasName("X"))); 3053 // FieldDecl with InitlistExpr: 3054 auto *FromField = *FromSpec->field_begin(); 3055 ASSERT_TRUE(FromField); 3056 ASSERT_TRUE(FromField->getInClassInitializer()); 3057 3058 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3059 ASSERT_TRUE(ImportedSpec); 3060 EXPECT_EQ(ImportedSpec, ToSpec); 3061 // After the import, the FieldDecl has to be merged, thus it should have the 3062 // InitListExpr. 3063 EXPECT_TRUE(ToField->getInClassInitializer()); 3064 } 3065 3066 TEST_P(ASTImporterTestBase, MergeFunctionOfClassTemplateSpecialization) { 3067 std::string ClassTemplate = 3068 R"( 3069 template <typename T> 3070 struct X { 3071 void f() {} 3072 void g() {} 3073 }; 3074 )"; 3075 Decl *ToTU = getToTuDecl(ClassTemplate + 3076 R"( 3077 void foo() { 3078 X<char> x; 3079 x.f(); 3080 } 3081 )", Lang_CXX11); 3082 Decl *FromTU = getTuDecl(ClassTemplate + 3083 R"( 3084 void bar() { 3085 X<char> x; 3086 x.g(); 3087 } 3088 )", Lang_CXX11); 3089 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3090 FromTU, classTemplateSpecializationDecl(hasName("X"))); 3091 auto FunPattern = functionDecl(hasName("g"), 3092 hasParent(classTemplateSpecializationDecl())); 3093 auto *FromFun = 3094 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern); 3095 auto *ToFun = 3096 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern); 3097 ASSERT_TRUE(FromFun->hasBody()); 3098 ASSERT_FALSE(ToFun->hasBody()); 3099 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3100 ASSERT_TRUE(ImportedSpec); 3101 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3102 ToTU, classTemplateSpecializationDecl(hasName("X"))); 3103 EXPECT_EQ(ImportedSpec, ToSpec); 3104 EXPECT_TRUE(ToFun->hasBody()); 3105 } 3106 3107 TEST_P(ASTImporterTestBase, 3108 ODRViolationOfClassTemplateSpecializationsShouldBeReported) { 3109 std::string ClassTemplate = 3110 R"( 3111 template <typename T> 3112 struct X {}; 3113 )"; 3114 Decl *ToTU = getToTuDecl(ClassTemplate + 3115 R"( 3116 template <> 3117 struct X<char> { 3118 int a; 3119 }; 3120 void foo() { 3121 X<char> x; 3122 } 3123 )", 3124 Lang_CXX11); 3125 Decl *FromTU = getTuDecl(ClassTemplate + 3126 R"( 3127 template <> 3128 struct X<char> { 3129 int b; 3130 }; 3131 void foo() { 3132 X<char> x; 3133 } 3134 )", 3135 Lang_CXX11); 3136 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3137 FromTU, classTemplateSpecializationDecl(hasName("X"))); 3138 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3139 3140 // We expect one (ODR) warning during the import. 3141 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings()); 3142 3143 // The second specialization is different from the first, thus it violates 3144 // ODR, consequently we expect to keep the first specialization only, which is 3145 // already in the "To" context. 3146 EXPECT_TRUE(ImportedSpec); 3147 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3148 ToTU, classTemplateSpecializationDecl(hasName("X"))); 3149 EXPECT_EQ(ImportedSpec, ToSpec); 3150 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match( 3151 ToTU, classTemplateSpecializationDecl())); 3152 } 3153 3154 TEST_P(ASTImporterTestBase, MergeCtorOfClassTemplateSpecialization) { 3155 std::string ClassTemplate = 3156 R"( 3157 template <typename T> 3158 struct X { 3159 X(char) {} 3160 X(int) {} 3161 }; 3162 )"; 3163 Decl *ToTU = getToTuDecl(ClassTemplate + 3164 R"( 3165 void foo() { 3166 X<char> x('c'); 3167 } 3168 )", Lang_CXX11); 3169 Decl *FromTU = getTuDecl(ClassTemplate + 3170 R"( 3171 void bar() { 3172 X<char> x(1); 3173 } 3174 )", Lang_CXX11); 3175 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3176 FromTU, classTemplateSpecializationDecl(hasName("X"))); 3177 // Match the void(int) ctor. 3178 auto CtorPattern = 3179 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))), 3180 hasParent(classTemplateSpecializationDecl())); 3181 auto *FromCtor = 3182 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern); 3183 auto *ToCtor = 3184 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern); 3185 ASSERT_TRUE(FromCtor->hasBody()); 3186 ASSERT_FALSE(ToCtor->hasBody()); 3187 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3188 ASSERT_TRUE(ImportedSpec); 3189 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3190 ToTU, classTemplateSpecializationDecl(hasName("X"))); 3191 EXPECT_EQ(ImportedSpec, ToSpec); 3192 EXPECT_TRUE(ToCtor->hasBody()); 3193 } 3194 3195 TEST_P(ASTImporterTestBase, 3196 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) { 3197 auto Code = 3198 R"( 3199 // primary template 3200 template<class T1, class T2, int I> 3201 class A {}; 3202 3203 // partial specialization 3204 template<class T, int I> 3205 class A<T, T*, I> {}; 3206 )"; 3207 Decl *ToTU = getToTuDecl(Code, Lang_CXX11); 3208 Decl *FromTU = getTuDecl(Code, Lang_CXX11); 3209 auto *FromSpec = 3210 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match( 3211 FromTU, classTemplatePartialSpecializationDecl()); 3212 auto *ToSpec = 3213 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match( 3214 ToTU, classTemplatePartialSpecializationDecl()); 3215 3216 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3217 EXPECT_EQ(ImportedSpec, ToSpec); 3218 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match( 3219 ToTU, classTemplatePartialSpecializationDecl())); 3220 } 3221 3222 TEST_P(ASTImporterTestBase, ClassTemplateSpecializationsShouldNotBeDuplicated) { 3223 auto Code = 3224 R"( 3225 // primary template 3226 template<class T1, class T2, int I> 3227 class A {}; 3228 3229 // full specialization 3230 template<> 3231 class A<int, int, 1> {}; 3232 )"; 3233 Decl *ToTU = getToTuDecl(Code, Lang_CXX11); 3234 Decl *FromTU = getTuDecl(Code, Lang_CXX11); 3235 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3236 FromTU, classTemplateSpecializationDecl()); 3237 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3238 ToTU, classTemplateSpecializationDecl()); 3239 3240 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3241 EXPECT_EQ(ImportedSpec, ToSpec); 3242 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match( 3243 ToTU, classTemplateSpecializationDecl())); 3244 } 3245 3246 TEST_P(ASTImporterTestBase, ClassTemplateFullAndPartialSpecsShouldNotBeMixed) { 3247 std::string PrimaryTemplate = 3248 R"( 3249 template<class T1, class T2, int I> 3250 class A {}; 3251 )"; 3252 auto PartialSpec = 3253 R"( 3254 template<class T, int I> 3255 class A<T, T*, I> {}; 3256 )"; 3257 auto FullSpec = 3258 R"( 3259 template<> 3260 class A<int, int, 1> {}; 3261 )"; 3262 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11); 3263 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11); 3264 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3265 FromTU, classTemplateSpecializationDecl()); 3266 3267 auto *ImportedSpec = Import(FromSpec, Lang_CXX11); 3268 EXPECT_TRUE(ImportedSpec); 3269 // Check the number of partial specializations. 3270 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match( 3271 ToTU, classTemplatePartialSpecializationDecl())); 3272 // Check the number of full specializations. 3273 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match( 3274 ToTU, classTemplateSpecializationDecl( 3275 unless(classTemplatePartialSpecializationDecl())))); 3276 } 3277 3278 TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) { 3279 Decl *TU = getTuDecl( 3280 R"( 3281 const int &init(); 3282 void foo() { const int &a{init()}; } 3283 )", Lang_CXX11, "input0.cc"); 3284 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a"))); 3285 ASSERT_TRUE(FromD->getAnyInitializer()); 3286 auto *InitExpr = FromD->getAnyInitializer(); 3287 ASSERT_TRUE(InitExpr); 3288 ASSERT_TRUE(InitExpr->isGLValue()); 3289 3290 auto *ToD = Import(FromD, Lang_CXX11); 3291 EXPECT_TRUE(ToD); 3292 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer(); 3293 EXPECT_TRUE(ToInitExpr); 3294 EXPECT_TRUE(ToInitExpr->isGLValue()); 3295 } 3296 3297 struct ImportVariables : ASTImporterTestBase {}; 3298 3299 TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) { 3300 Decl *FromTU = getTuDecl( 3301 R"( 3302 struct A { 3303 static const int a = 1 + 2; 3304 }; 3305 const int A::a; 3306 )", Lang_CXX, "input1.cc"); 3307 3308 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match( 3309 FromTU, varDecl(hasName("a"))); // Decl with init 3310 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match( 3311 FromTU, varDecl(hasName("a"))); // Decl with definition 3312 ASSERT_NE(FromDWithInit, FromDWithDef); 3313 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit); 3314 3315 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11)); 3316 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11)); 3317 ASSERT_TRUE(ToD0); 3318 ASSERT_TRUE(ToD1); 3319 EXPECT_NE(ToD0, ToD1); 3320 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0); 3321 } 3322 3323 TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) { 3324 auto StructA = 3325 R"( 3326 struct A { 3327 static const int a = 1 + 2; 3328 }; 3329 )"; 3330 Decl *ToTU = getToTuDecl(StructA, Lang_CXX); 3331 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX, 3332 "input1.cc"); 3333 3334 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match( 3335 FromTU, varDecl(hasName("a"))); // Decl with init 3336 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match( 3337 FromTU, varDecl(hasName("a"))); // Decl with definition 3338 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl()); 3339 ASSERT_TRUE(FromDWithInit->getInit()); 3340 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition()); 3341 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition()); 3342 ASSERT_FALSE(FromDWithDef->getInit()); 3343 3344 auto *ToD = FirstDeclMatcher<VarDecl>().match( 3345 ToTU, varDecl(hasName("a"))); // Decl with init 3346 ASSERT_TRUE(ToD->getInit()); 3347 ASSERT_FALSE(ToD->getDefinition()); 3348 3349 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11)); 3350 EXPECT_TRUE(ImportedD->getAnyInitializer()); 3351 EXPECT_TRUE(ImportedD->getDefinition()); 3352 } 3353 3354 TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) { 3355 auto StructA = 3356 R"( 3357 struct A { 3358 static const int a; 3359 }; 3360 )"; 3361 Decl *ToTU = getToTuDecl(StructA, Lang_CXX); 3362 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;", 3363 Lang_CXX, "input1.cc"); 3364 3365 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match( 3366 FromTU, varDecl(hasName("a"))); 3367 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match( 3368 FromTU, varDecl(hasName("a"))); // Decl with definition and with init. 3369 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl()); 3370 ASSERT_FALSE(FromDDeclarationOnly->getInit()); 3371 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition()); 3372 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition()); 3373 ASSERT_TRUE(FromDWithDef->getInit()); 3374 3375 auto *ToD = FirstDeclMatcher<VarDecl>().match( 3376 ToTU, varDecl(hasName("a"))); 3377 ASSERT_FALSE(ToD->getInit()); 3378 ASSERT_FALSE(ToD->getDefinition()); 3379 3380 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11)); 3381 EXPECT_TRUE(ImportedD->getAnyInitializer()); 3382 EXPECT_TRUE(ImportedD->getDefinition()); 3383 } 3384 3385 struct DeclContextTest : ASTImporterTestBase {}; 3386 3387 TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { 3388 Decl *TU = getTuDecl( 3389 R"( 3390 namespace NS { 3391 3392 template <typename T> 3393 struct S {}; 3394 template struct S<int>; 3395 3396 inline namespace INS { 3397 template <typename T> 3398 struct S {}; 3399 template struct S<int>; 3400 } 3401 3402 } 3403 )", Lang_CXX11, "input0.cc"); 3404 auto *NS = FirstDeclMatcher<NamespaceDecl>().match( 3405 TU, namespaceDecl()); 3406 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( 3407 TU, classTemplateSpecializationDecl()); 3408 ASSERT_TRUE(NS->containsDecl(Spec)); 3409 3410 NS->removeDecl(Spec); 3411 EXPECT_FALSE(NS->containsDecl(Spec)); 3412 } 3413 3414 struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {}; 3415 3416 TEST_P(ImportFunctionTemplateSpecializations, 3417 TUshouldNotContainFunctionTemplateImplicitInstantiation) { 3418 3419 Decl *FromTU = getTuDecl( 3420 R"( 3421 template<class T> 3422 int f() { return 0; } 3423 void foo() { f<int>(); } 3424 )", 3425 Lang_CXX, "input0.cc"); 3426 3427 // Check that the function template instantiation is NOT the child of the TU. 3428 auto Pattern = translationUnitDecl( 3429 unless(has(functionDecl(hasName("f"), isTemplateInstantiation())))); 3430 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern)); 3431 3432 auto *Foo = FirstDeclMatcher<FunctionDecl>().match( 3433 FromTU, functionDecl(hasName("foo"))); 3434 ASSERT_TRUE(Import(Foo, Lang_CXX)); 3435 3436 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 3437 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern)); 3438 } 3439 3440 TEST_P(ImportFunctionTemplateSpecializations, 3441 TUshouldNotContainFunctionTemplateExplicitInstantiation) { 3442 3443 Decl *FromTU = getTuDecl( 3444 R"( 3445 template<class T> 3446 int f() { return 0; } 3447 template int f<int>(); 3448 )", 3449 Lang_CXX, "input0.cc"); 3450 3451 // Check that the function template instantiation is NOT the child of the TU. 3452 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation()); 3453 auto Pattern = translationUnitDecl(unless(has(Instantiation))); 3454 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern)); 3455 3456 ASSERT_TRUE( 3457 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX)); 3458 3459 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 3460 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern)); 3461 } 3462 3463 TEST_P(ImportFunctionTemplateSpecializations, 3464 TUshouldContainFunctionTemplateSpecialization) { 3465 3466 Decl *FromTU = getTuDecl( 3467 R"( 3468 template<class T> 3469 int f() { return 0; } 3470 template <> int f<int>() { return 4; } 3471 )", 3472 Lang_CXX, "input0.cc"); 3473 3474 // Check that the function template specialization is the child of the TU. 3475 auto Specialization = 3476 functionDecl(hasName("f"), isExplicitTemplateSpecialization()); 3477 auto Pattern = translationUnitDecl(has(Specialization)); 3478 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern)); 3479 3480 ASSERT_TRUE( 3481 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX)); 3482 3483 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 3484 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern)); 3485 } 3486 3487 TEST_P(ImportFunctionTemplateSpecializations, 3488 FunctionTemplateSpecializationRedeclChain) { 3489 3490 Decl *FromTU = getTuDecl( 3491 R"( 3492 template<class T> 3493 int f() { return 0; } 3494 template <> int f<int>() { return 4; } 3495 )", 3496 Lang_CXX, "input0.cc"); 3497 3498 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(), 3499 hasParent(translationUnitDecl())); 3500 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec); 3501 { 3502 auto *TU = FromTU; 3503 auto *SpecD = FromSpecD; 3504 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match( 3505 TU, functionTemplateDecl()); 3506 auto *FirstSpecD = *(TemplateD->spec_begin()); 3507 ASSERT_EQ(SpecD, FirstSpecD); 3508 ASSERT_TRUE(SpecD->getPreviousDecl()); 3509 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl()) 3510 ->doesThisDeclarationHaveABody()); 3511 } 3512 3513 ASSERT_TRUE(Import(FromSpecD, Lang_CXX)); 3514 3515 { 3516 auto *TU = ToAST->getASTContext().getTranslationUnitDecl(); 3517 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec); 3518 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match( 3519 TU, functionTemplateDecl()); 3520 auto *FirstSpecD = *(TemplateD->spec_begin()); 3521 EXPECT_EQ(SpecD, FirstSpecD); 3522 ASSERT_TRUE(SpecD->getPreviousDecl()); 3523 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl()) 3524 ->doesThisDeclarationHaveABody()); 3525 } 3526 } 3527 3528 TEST_P(ImportFunctionTemplateSpecializations, 3529 MatchNumberOfFunctionTemplateSpecializations) { 3530 3531 Decl *FromTU = getTuDecl( 3532 R"( 3533 template <typename T> constexpr int f() { return 0; } 3534 template <> constexpr int f<int>() { return 4; } 3535 void foo() { 3536 static_assert(f<char>() == 0, ""); 3537 static_assert(f<int>() == 4, ""); 3538 } 3539 )", 3540 Lang_CXX11, "input0.cc"); 3541 auto *FromD = FirstDeclMatcher<FunctionDecl>().match( 3542 FromTU, functionDecl(hasName("foo"))); 3543 3544 Import(FromD, Lang_CXX11); 3545 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); 3546 EXPECT_EQ( 3547 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))), 3548 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f")))); 3549 } 3550 3551 TEST_P(ImportFunctionTemplateSpecializations, 3552 ImportPrototypes) { 3553 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); 3554 auto Code = 3555 R"( 3556 // Proto of the primary template. 3557 template <class T> 3558 void f(); 3559 // Proto of the specialization. 3560 template <> 3561 void f<int>(); 3562 )"; 3563 3564 Decl *ImportedD; 3565 { 3566 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); 3567 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 3568 3569 ImportedD = Import(FromD, Lang_CXX); 3570 } 3571 { 3572 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); 3573 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 3574 Import(FromD, Lang_CXX); 3575 } 3576 3577 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 3578 3579 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 3580 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 3581 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 3582 EXPECT_TRUE(ImportedD == To0); 3583 EXPECT_TRUE(ImportedD != To1); 3584 EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); 3585 EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); 3586 // Check that they are part of the same redecl chain. 3587 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl()); 3588 } 3589 3590 TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) { 3591 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); 3592 auto Code = 3593 R"( 3594 // Proto of the primary template. 3595 template <class T> 3596 void f(); 3597 // Specialization and definition. 3598 template <> 3599 void f<int>() {} 3600 )"; 3601 3602 Decl *ImportedD; 3603 { 3604 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); 3605 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 3606 ImportedD = Import(FromD, Lang_CXX); 3607 } 3608 { 3609 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); 3610 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 3611 Import(FromD, Lang_CXX); 3612 } 3613 3614 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 3615 3616 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); 3617 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 3618 EXPECT_TRUE(ImportedD == To0); 3619 EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); 3620 3621 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match( 3622 ToTU, functionTemplateDecl()); 3623 auto *FirstSpecD = *(TemplateD->spec_begin()); 3624 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl()); 3625 } 3626 3627 TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) { 3628 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); 3629 auto Code = 3630 R"( 3631 // Proto of the primary template. 3632 template <class T> 3633 void f(); 3634 // Specialization proto. 3635 template <> 3636 void f<int>(); 3637 // Specialization proto. 3638 template <> 3639 void f<int>(); 3640 )"; 3641 3642 Decl *ImportedD; 3643 { 3644 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); 3645 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 3646 ImportedD = Import(FromD, Lang_CXX); 3647 } 3648 3649 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 3650 3651 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 3652 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 3653 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 3654 EXPECT_TRUE(ImportedD == To0); 3655 EXPECT_TRUE(ImportedD != To1); 3656 EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); 3657 EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); 3658 EXPECT_EQ(To1->getPreviousDecl(), To0); 3659 } 3660 3661 TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) { 3662 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); 3663 auto Code = 3664 R"( 3665 // Proto of the primary template. 3666 template <class T> 3667 void f(); 3668 // Specialization proto. 3669 template <> 3670 void f<int>(); 3671 // Specialization definition. 3672 template <> 3673 void f<int>() {} 3674 )"; 3675 3676 Decl *ImportedD; 3677 { 3678 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); 3679 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 3680 ImportedD = Import(FromD, Lang_CXX); 3681 } 3682 3683 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 3684 3685 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 3686 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 3687 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 3688 EXPECT_TRUE(ImportedD == To0); 3689 EXPECT_TRUE(ImportedD != To1); 3690 EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); 3691 EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); 3692 EXPECT_EQ(To1->getPreviousDecl(), To0); 3693 } 3694 3695 TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) { 3696 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); 3697 auto Code = 3698 R"( 3699 // Proto of the primary template. 3700 template <class T> 3701 void f(); 3702 // Specialization definition. 3703 template <> 3704 void f<int>() {} 3705 // Specialization proto. 3706 template <> 3707 void f<int>(); 3708 )"; 3709 3710 Decl *ImportedD; 3711 { 3712 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); 3713 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); 3714 ImportedD = Import(FromD, Lang_CXX); 3715 } 3716 3717 Decl *ToTU = ImportedD->getTranslationUnitDecl(); 3718 3719 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); 3720 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 3721 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); 3722 EXPECT_TRUE(ImportedD == To0); 3723 EXPECT_TRUE(ImportedD != To1); 3724 EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); 3725 EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); 3726 EXPECT_EQ(To1->getPreviousDecl(), To0); 3727 } 3728 3729 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest, 3730 ::testing::Values(ArgVector()), ); 3731 3732 INSTANTIATE_TEST_CASE_P( 3733 ParameterizedTests, CanonicalRedeclChain, 3734 ::testing::Values(ArgVector()),); 3735 3736 auto DefaultTestValuesForRunOptions = ::testing::Values( 3737 ArgVector(), 3738 ArgVector{"-fdelayed-template-parsing"}, 3739 ArgVector{"-fms-compatibility"}, 3740 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"}); 3741 3742 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr, 3743 DefaultTestValuesForRunOptions, ); 3744 3745 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType, 3746 DefaultTestValuesForRunOptions, ); 3747 3748 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl, 3749 DefaultTestValuesForRunOptions, ); 3750 3751 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase, 3752 DefaultTestValuesForRunOptions, ); 3753 3754 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions, 3755 DefaultTestValuesForRunOptions, ); 3756 3757 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions, 3758 DefaultTestValuesForRunOptions, ); 3759 3760 INSTANTIATE_TEST_CASE_P(ParameterizedTests, 3761 ImportFunctionTemplateSpecializations, 3762 DefaultTestValuesForRunOptions, ); 3763 3764 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods, 3765 DefaultTestValuesForRunOptions, ); 3766 3767 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables, 3768 DefaultTestValuesForRunOptions, ); 3769 3770 TEST_P(ImportDecl, ImportFieldOrder) { 3771 MatchVerifier<Decl> Verifier; 3772 testImport("struct declToImport {" 3773 " int b = a + 2;" 3774 " int a = 5;" 3775 "};", 3776 Lang_CXX11, "", Lang_CXX11, Verifier, 3777 recordDecl(hasFieldOrder({"b", "a"}))); 3778 } 3779 3780 3781 } // end namespace ast_matchers 3782 } // end namespace clang 3783