Author: martong Date: Mon Jun 25 09:25:30 2018 New Revision: 335491 URL: http://llvm.org/viewvc/llvm-project?rev=335491&view=rev Log: Revert "[ASTImporter] Import the whole redecl chain of functions"
This reverts commit r335480. Modified: cfe/trunk/include/clang/AST/ASTImporter.h cfe/trunk/lib/AST/ASTImporter.cpp cfe/trunk/lib/AST/DeclBase.cpp cfe/trunk/test/ASTMerge/class/test.cpp cfe/trunk/unittests/AST/ASTImporterTest.cpp Modified: cfe/trunk/include/clang/AST/ASTImporter.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=335491&r1=335490&r2=335491&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTImporter.h (original) +++ cfe/trunk/include/clang/AST/ASTImporter.h Mon Jun 25 09:25:30 2018 @@ -43,15 +43,6 @@ class TagDecl; class TypeSourceInfo; class Attr; - // \brief Returns with a list of declarations started from the canonical decl - // then followed by subsequent decls in the translation unit. - // This gives a canonical list for each entry in the redecl chain. - // `Decl::redecls()` gives a list of decls which always start from the - // previous decl and the next item is actually the previous item in the order - // of source locations. Thus, `Decl::redecls()` gives different lists for - // the different entries in a given redecl chain. - llvm::SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D); - /// Imports selected nodes from one AST context into another context, /// merging AST nodes where appropriate. class ASTImporter { Modified: cfe/trunk/lib/AST/ASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=335491&r1=335490&r2=335491&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp (original) +++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Jun 25 09:25:30 2018 @@ -71,25 +71,6 @@ namespace clang { - template <class T> - SmallVector<Decl*, 2> - getCanonicalForwardRedeclChain(Redeclarable<T>* D) { - SmallVector<Decl*, 2> Redecls; - for (auto *R : D->getFirstDecl()->redecls()) { - if (R != D->getFirstDecl()) - Redecls.push_back(R); - } - Redecls.push_back(D->getFirstDecl()); - std::reverse(Redecls.begin(), Redecls.end()); - return Redecls; - } - - SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D) { - // Currently only FunctionDecl is supported - auto FD = cast<FunctionDecl>(D); - return getCanonicalForwardRedeclChain<FunctionDecl>(FD); - } - class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>, public DeclVisitor<ASTNodeImporter, Decl *>, public StmtVisitor<ASTNodeImporter, Stmt *> { @@ -214,12 +195,6 @@ namespace clang { const InContainerTy &Container, TemplateArgumentListInfo &Result); - using TemplateArgsTy = SmallVector<TemplateArgument, 8>; - using OptionalTemplateArgsTy = Optional<TemplateArgsTy>; - std::tuple<FunctionTemplateDecl *, OptionalTemplateArgsTy> - ImportFunctionTemplateWithTemplateArgsFromSpecialization( - FunctionDecl *FromFD); - bool ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, @@ -433,8 +408,6 @@ namespace clang { // Importing overrides. void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod); - - FunctionDecl *FindFunctionTemplateSpecialization(FunctionDecl *FromFD); }; template <typename InContainerTy> @@ -464,25 +437,6 @@ bool ASTNodeImporter::ImportTemplateArgu From.arguments(), Result); } -std::tuple<FunctionTemplateDecl *, ASTNodeImporter::OptionalTemplateArgsTy> -ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization( - FunctionDecl *FromFD) { - assert(FromFD->getTemplatedKind() == - FunctionDecl::TK_FunctionTemplateSpecialization); - auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); - auto *Template = cast_or_null<FunctionTemplateDecl>( - Importer.Import(FTSInfo->getTemplate())); - - // Import template arguments. - auto TemplArgs = FTSInfo->TemplateArguments->asArray(); - TemplateArgsTy ToTemplArgs; - if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), - ToTemplArgs)) // Error during import. - return std::make_tuple(Template, OptionalTemplateArgsTy()); - - return std::make_tuple(Template, ToTemplArgs); -} - } // namespace clang //---------------------------------------------------------------------------- @@ -2298,17 +2252,23 @@ bool ASTNodeImporter::ImportTemplateInfo } case FunctionDecl::TK_FunctionTemplateSpecialization: { - FunctionTemplateDecl* Template; - OptionalTemplateArgsTy ToTemplArgs; - std::tie(Template, ToTemplArgs) = - ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); - if (!Template || !ToTemplArgs) + auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); + auto *Template = cast_or_null<FunctionTemplateDecl>( + Importer.Import(FTSInfo->getTemplate())); + if (!Template) + return true; + TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); + + // Import template arguments. + auto TemplArgs = FTSInfo->TemplateArguments->asArray(); + SmallVector<TemplateArgument, 8> ToTemplArgs; + if (ImportTemplateArguments(TemplArgs.data(), TemplArgs.size(), + ToTemplArgs)) return true; TemplateArgumentList *ToTAList = TemplateArgumentList::CreateCopy( - Importer.getToContext(), *ToTemplArgs); + Importer.getToContext(), ToTemplArgs); - auto *FTSInfo = FromFD->getTemplateSpecializationInfo(); TemplateArgumentListInfo ToTAInfo; const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten; if (FromTAArgsAsWritten) @@ -2317,7 +2277,6 @@ bool ASTNodeImporter::ImportTemplateInfo SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation()); - TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind(); ToFD->setFunctionTemplateSpecialization( Template, ToTAList, /* InsertPos= */ nullptr, TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, POI); @@ -2353,31 +2312,7 @@ bool ASTNodeImporter::ImportTemplateInfo llvm_unreachable("All cases should be covered!"); } -FunctionDecl * -ASTNodeImporter::FindFunctionTemplateSpecialization(FunctionDecl *FromFD) { - FunctionTemplateDecl* Template; - OptionalTemplateArgsTy ToTemplArgs; - std::tie(Template, ToTemplArgs) = - ImportFunctionTemplateWithTemplateArgsFromSpecialization(FromFD); - if (!Template || !ToTemplArgs) - return nullptr; - - void *InsertPos = nullptr; - auto *FoundSpec = Template->findSpecialization(*ToTemplArgs, InsertPos); - return FoundSpec; -} - Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { - - SmallVector<Decl*, 2> Redecls = getCanonicalForwardRedeclChain(D); - auto RedeclIt = Redecls.begin(); - // Import the first part of the decl chain. I.e. import all previous - // declarations starting from the canonical decl. - for (; RedeclIt != Redecls.end() && *RedeclIt != D; ++RedeclIt) - if (!Importer.Import(*RedeclIt)) - return nullptr; - assert(*RedeclIt == D); - // Import the major distinguishing characteristics of this function. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -2388,27 +2323,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl if (ToD) return ToD; - const FunctionDecl *FoundByLookup = nullptr; + const FunctionDecl *FoundWithoutBody = nullptr; - // If this is a function template specialization, then try to find the same - // existing specialization in the "to" context. The localUncachedLookup - // below will not find any specialization, but would find the primary - // template; thus, we have to skip normal lookup in case of specializations. - // FIXME handle member function templates (TK_MemberSpecialization) similarly? - if (D->getTemplatedKind() == - FunctionDecl::TK_FunctionTemplateSpecialization) { - if (FunctionDecl *FoundFunction = FindFunctionTemplateSpecialization(D)) { - if (D->doesThisDeclarationHaveABody() && - FoundFunction->hasBody()) - return Importer.Imported(D, FoundFunction); - FoundByLookup = FoundFunction; - } - } // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. - else if (!LexicalDC->isFunctionOrMethod()) { + if (!LexicalDC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; - unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; + unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls); for (auto *FoundDecl : FoundDecls) { @@ -2420,11 +2341,15 @@ Decl *ASTNodeImporter::VisitFunctionDecl D->hasExternalFormalLinkage()) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundFunction->getType())) { - if (D->doesThisDeclarationHaveABody() && - FoundFunction->hasBody()) - return Importer.Imported(D, FoundFunction); - FoundByLookup = FoundFunction; + // FIXME: Actually try to merge the body and other attributes. + const FunctionDecl *FromBodyDecl = nullptr; + D->hasBody(FromBodyDecl); + if (D == FromBodyDecl && !FoundFunction->hasBody()) { + // This function is needed to merge completely. + FoundWithoutBody = FoundFunction; break; + } + return Importer.Imported(D, FoundFunction); } // FIXME: Check for overloading more carefully, e.g., by boosting @@ -2574,9 +2499,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl } ToFunction->setParams(Parameters); - if (FoundByLookup) { + if (FoundWithoutBody) { auto *Recent = const_cast<FunctionDecl *>( - FoundByLookup->getMostRecentDecl()); + FoundWithoutBody->getMostRecentDecl()); ToFunction->setPreviousDecl(Recent); } @@ -2598,11 +2523,10 @@ Decl *ASTNodeImporter::VisitFunctionDecl ToFunction->setType(T); } - if (D->doesThisDeclarationHaveABody()) { - if (Stmt *FromBody = D->getBody()) { - if (Stmt *ToBody = Importer.Import(FromBody)) { - ToFunction->setBody(ToBody); - } + // Import the body, if any. + if (Stmt *FromBody = D->getBody()) { + if (Stmt *ToBody = Importer.Import(FromBody)) { + ToFunction->setBody(ToBody); } } @@ -2612,29 +2536,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl if (ImportTemplateInformation(D, ToFunction)) return nullptr; - bool IsFriend = D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend); - - // TODO Can we generalize this approach to other AST nodes as well? - if (D->getDeclContext()->containsDecl(D)) - DC->addDeclInternal(ToFunction); - if (DC != LexicalDC && D->getLexicalDeclContext()->containsDecl(D)) + // Add this function to the lexical context. + // NOTE: If the function is templated declaration, it should be not added into + // LexicalDC. But described template is imported during import of + // FunctionTemplateDecl (it happens later). So, we use source declaration + // to determine if we should add the result function. + if (!D->getDescribedFunctionTemplate()) LexicalDC->addDeclInternal(ToFunction); - // Friend declaration's lexical context is the befriending class, but the - // semantic context is the enclosing scope of the befriending class. - // We want the friend functions to be found in the semantic context by lookup. - // FIXME should we handle this generically in VisitFriendDecl? - // In Other cases when LexicalDC != DC we don't want it to be added, - // e.g out-of-class definitions like void B::f() {} . - if (LexicalDC != DC && IsFriend) { - DC->makeDeclVisibleInContext(ToFunction); - } - - // Import the rest of the chain. I.e. import all subsequent declarations. - for (++RedeclIt; RedeclIt != Redecls.end(); ++RedeclIt) - if (!Importer.Import(*RedeclIt)) - return nullptr; - if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D)) ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod); Modified: cfe/trunk/lib/AST/DeclBase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=335491&r1=335490&r2=335491&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclBase.cpp (original) +++ cfe/trunk/lib/AST/DeclBase.cpp Mon Jun 25 09:25:30 2018 @@ -1343,8 +1343,6 @@ bool DeclContext::decls_empty() const { } bool DeclContext::containsDecl(Decl *D) const { - if (hasExternalLexicalStorage()) - LoadLexicalDeclsFromExternalStorage(); return (D->getLexicalDeclContext() == this && (D->NextInContextAndBits.getPointer() || D == LastDecl)); } Modified: cfe/trunk/test/ASTMerge/class/test.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/class/test.cpp?rev=335491&r1=335490&r2=335491&view=diff ============================================================================== --- cfe/trunk/test/ASTMerge/class/test.cpp (original) +++ cfe/trunk/test/ASTMerge/class/test.cpp Mon Jun 25 09:25:30 2018 @@ -13,12 +13,12 @@ // CHECK: class1.cpp:19:3: note: enumerator 'b' with value 1 here // CHECK: class2.cpp:12:3: note: enumerator 'a' with value 0 here -// CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units -// CHECK: class1.cpp:46:3: note: friend declared here -// CHECK: class2.cpp:36:8: note: no corresponding friend here - // CHECK: class1.cpp:36:8: warning: type 'F2' has incompatible definitions in different translation units // CHECK: class1.cpp:39:3: note: friend declared here // CHECK: class2.cpp:30:8: note: no corresponding friend here +// CHECK: class1.cpp:43:8: warning: type 'F3' has incompatible definitions in different translation units +// CHECK: class1.cpp:46:3: note: friend declared here +// CHECK: class2.cpp:36:8: note: no corresponding friend here + // CHECK: 4 warnings generated. Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=335491&r1=335490&r2=335491&view=diff ============================================================================== --- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original) +++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Mon Jun 25 09:25:30 2018 @@ -20,7 +20,7 @@ #include "DeclMatcher.h" #include "Language.h" -#include "gmock/gmock.h" +#include "gtest/gtest.h" #include "llvm/ADT/StringMap.h" namespace clang { @@ -428,48 +428,6 @@ struct ImportExpr : TestImportBase {}; struct ImportType : TestImportBase {}; struct ImportDecl : TestImportBase {}; -struct CanonicalRedeclChain : ASTImporterTestBase {}; - -TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) { - Decl *FromTU = getTuDecl("void f();", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - - auto Redecls = getCanonicalForwardRedeclChain(D0); - ASSERT_EQ(Redecls.size(), 1u); - EXPECT_EQ(D0, Redecls[0]); -} - -TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) { - Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - FunctionDecl *D1 = D2->getPreviousDecl(); - - auto Redecls = getCanonicalForwardRedeclChain(D0); - ASSERT_EQ(Redecls.size(), 3u); - EXPECT_EQ(D0, Redecls[0]); - EXPECT_EQ(D1, Redecls[1]); - EXPECT_EQ(D2, Redecls[2]); -} - -TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) { - Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX); - auto Pattern = functionDecl(hasName("f")); - auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - FunctionDecl *D1 = D2->getPreviousDecl(); - - auto RedeclsD0 = getCanonicalForwardRedeclChain(D0); - auto RedeclsD1 = getCanonicalForwardRedeclChain(D1); - auto RedeclsD2 = getCanonicalForwardRedeclChain(D2); - - EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1)); - EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2)); -} - - TEST_P(ImportExpr, ImportStringLiteral) { MatchVerifier<Decl> Verifier; testImport("void declToImport() { \"foo\"; }", @@ -1715,6 +1673,34 @@ TEST_P( struct ImportFunctions : ASTImporterTestBase {}; TEST_P(ImportFunctions, + PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) { + Decl *FromTU = getTuDecl("void f();", Lang_CXX); + auto Pattern = functionDecl(hasName("f")); + FunctionDecl *FromD = + FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); + + Decl *ImportedD = Import(FromD, Lang_CXX); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); + EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); +} + +TEST_P(ImportFunctions, + PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) { + Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX); + auto Pattern = functionDecl(hasName("f")); + FunctionDecl *FromD = // Prototype + FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); + + Decl *ImportedD = Import(FromD, Lang_CXX); + Decl *ToTU = ImportedD->getTranslationUnitDecl(); + + EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); + EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); +} + +TEST_P(ImportFunctions, DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) { Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX); auto Pattern = functionDecl(hasName("f")); @@ -1724,7 +1710,7 @@ TEST_P(ImportFunctions, Decl *ImportedD = Import(FromD, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); + EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); } @@ -1741,40 +1727,30 @@ TEST_P(ImportFunctions, DefinitionShould EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); } -TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) { +TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) { Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); auto Pattern = functionDecl(hasName("f")); - auto *From = - FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto + FunctionDecl *PrototypeFD = + FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Decl *ImportedD = Import(From, Lang_CXX); + Decl *ImportedD = Import(PrototypeFD, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); + EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); + EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); } TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) { Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX); auto Pattern = functionDecl(hasName("f")); - auto *From = - LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def + FunctionDecl *DefinitionFD = + LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Decl *ImportedD = Import(From, Lang_CXX); + Decl *ImportedD = Import(DefinitionFD, Lang_CXX); Decl *ToTU = ImportedD->getTranslationUnitDecl(); - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); + EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); + EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); } TEST_P(ImportFunctions, ImportPrototypes) { @@ -1783,48 +1759,23 @@ TEST_P(ImportFunctions, ImportPrototypes Decl *ImportedD; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); + FunctionDecl *FromD = + FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); ImportedD = Import(FromD, Lang_CXX); } + Decl *ImportedD1; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportFunctions, ImportDefinitions) { - auto Pattern = functionDecl(hasName("f")); - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); + FunctionDecl *FromD = + FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); + ImportedD1 = Import(FromD, Lang_CXX); } - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - + Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); + EXPECT_EQ(ImportedD, ImportedD1); + EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); } TEST_P(ImportFunctions, ImportDefinitionThenPrototype) { @@ -1833,24 +1784,23 @@ TEST_P(ImportFunctions, ImportDefinition Decl *ImportedD; { Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); + FunctionDecl *FromD = + FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); + ImportedD = Import(FromD, Lang_CXX); } + Decl *ImportedD1; { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); + FunctionDecl *FromD = + FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); + ImportedD1 = Import(FromD, Lang_CXX); } Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); + EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); + EXPECT_EQ(ImportedD, ImportedD1); + EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody()); } TEST_P(ImportFunctions, ImportPrototypeThenDefinition) { @@ -1873,40 +1823,38 @@ TEST_P(ImportFunctions, ImportPrototypeT Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); + EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody()); FunctionDecl *DefinitionD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD); } -TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) { +TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) { auto Pattern = functionDecl(hasName("f")); { Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); + FunctionDecl *FromD = + FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); + Import(FromD, Lang_CXX); } { Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); + FunctionDecl *FromD = + FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); Import(FromD, Lang_CXX); } Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - - ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u); + ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody()); - + EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody()); FunctionDecl *DefinitionD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody()); - - EXPECT_TRUE(DefinitionD->getPreviousDecl()); - EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody()); - EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD); + EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD); } TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) { @@ -1946,202 +1894,6 @@ TEST_P(ImportFunctions, VirtualFlagShoul EXPECT_TRUE(To->isVirtual()); } -TEST_P(ImportFunctions, - ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) { - Decl *ToTU = getToTuDecl( - R"( - void f() {} - void f(); - )", - Lang_CXX); - ASSERT_EQ(1u, - DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) { - return FD->doesThisDeclarationHaveABody(); - }).match(ToTU, functionDecl())); - - Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl()); - - Import(FromD, Lang_CXX); - - EXPECT_EQ(1u, - DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) { - return FD->doesThisDeclarationHaveABody(); - }).match(ToTU, functionDecl())); -} - -struct ImportFriendFunctions : ImportFunctions {}; - -TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl("struct X { friend void f(); };" - "void f();", - Lang_CXX, - "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - - auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); - auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); -} - -TEST_P(ImportFriendFunctions, - ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl("void f();" - "struct X { friend void f(); };", - Lang_CXX, "input0.cc"); - auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - - auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); - auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); -} - -TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl("struct X { friend void f(){} };" - "void f();", - Lang_CXX, - "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - - auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); - auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); -} - -TEST_P(ImportFriendFunctions, - ImportFriendFunctionRedeclChainDef_OutOfClassDef) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl("struct X { friend void f(); };" - "void f(){}", - Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - - auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); - auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); -} - -// This test is disabled, because ATM we create a redundant FunctionDecl. We -// start the import with the definition of `f` then we continue with the import -// of the type of `f` which involves `X`. During the import of `X` we start -// again the import of the definition of `f` and then finally we create the -// node. But then in the first frame of `VisitFunctionDecl` we create a node -// again since we do not check if such a node exists yet or not. This is being -// fixed in a separate patch: https://reviews.llvm.org/D47632 -// FIXME enable this test once the above patch is approved. -TEST_P(ImportFriendFunctions, - DISABLED_ImportFriendFunctionRedeclChainDefWithClass) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl( - R"( - class X; - void f(X *x){} - class X{ - friend void f(X *x); - }; - )", - Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - - auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); - auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>() - .match(ToTU, friendDecl()) - ->getFriendDecl()); - EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD); - // The parameters must refer the same type - EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(), - (*ImportedD->param_begin())->getOriginalType()); -} - -// This test is disabled, because ATM we create a redundant FunctionDecl. We -// start the import with the definition of `f` then we continue with the import -// of the type of `f` which involves `X`. During the import of `X` we start -// again the import of the definition of `f` and then finally we create the -// node. But then in the first frame of `VisitFunctionDecl` we create a node -// again since we do not check if such a node exists yet or not. This is being -// fixed in a separate patch: https://reviews.llvm.org/D47632 -// FIXME enable this test once the above patch is approved. -TEST_P(ImportFriendFunctions, - DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) { - auto Pattern = functionDecl(hasName("f")); - - Decl *FromTU = getTuDecl( - R"( - class X; - void f(X *x){} - class X{ - friend void f(X *x); - }; - )", - Lang_CXX, "input0.cc"); - auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - - auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody()); - auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match( - ToTU, functionDecl(unless(hasParent(friendDecl())))); - - EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody()); - EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD); - // The parameters must refer the same type - EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(), - (*ImportedD->param_begin())->getOriginalType()); -} - -TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) { - auto Pattern = functionDecl(hasName("f")); - - FunctionDecl *ImportedD; - { - Decl *FromTU = - getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX)); - } - FunctionDecl *ImportedD1; - { - Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX)); - } - - Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody()); - EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody()); - EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD); -} - AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>, InnerMatcher) { if (auto *Typedef = Node.getTypedefNameForAnonDecl()) @@ -2272,328 +2024,9 @@ TEST_P(DeclContextTest, removeDeclOfClas EXPECT_FALSE(NS->containsDecl(Spec)); } -struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {}; - -TEST_P(ImportFunctionTemplateSpecializations, - TUshouldNotContainFunctionTemplateImplicitInstantiation) { - - Decl *FromTU = getTuDecl( - R"( - template<class T> - int f() { return 0; } - void foo() { f<int>(); } - )", - Lang_CXX, "input0.cc"); - - // Check that the function template instantiation is NOT the child of the TU. - auto Pattern = translationUnitDecl( - unless(has(functionDecl(hasName("f"), isTemplateInstantiation())))); - ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern)); - - auto *Foo = FirstDeclMatcher<FunctionDecl>().match( - FromTU, functionDecl(hasName("foo"))); - ASSERT_TRUE(Import(Foo, Lang_CXX)); - - auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern)); -} - -TEST_P(ImportFunctionTemplateSpecializations, - TUshouldNotContainFunctionTemplateExplicitInstantiation) { - - Decl *FromTU = getTuDecl( - R"( - template<class T> - int f() { return 0; } - template int f<int>(); - )", - Lang_CXX, "input0.cc"); - - // Check that the function template instantiation is NOT the child of the TU. - auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation()); - auto Pattern = translationUnitDecl(unless(has(Instantiation))); - ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern)); - - ASSERT_TRUE( - Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX)); - - auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern)); -} - -TEST_P(ImportFunctionTemplateSpecializations, - TUshouldContainFunctionTemplateSpecialization) { - - Decl *FromTU = getTuDecl( - R"( - template<class T> - int f() { return 0; } - template <> int f<int>() { return 4; } - )", - Lang_CXX, "input0.cc"); - - // Check that the function template specialization is the child of the TU. - auto Specialization = - functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Pattern = translationUnitDecl(has(Specialization)); - ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern)); - - ASSERT_TRUE( - Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX)); - - auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern)); -} - -TEST_P(ImportFunctionTemplateSpecializations, - FunctionTemplateSpecializationRedeclChain) { - - Decl *FromTU = getTuDecl( - R"( - template<class T> - int f() { return 0; } - template <> int f<int>() { return 4; } - )", - Lang_CXX, "input0.cc"); - - auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(), - hasParent(translationUnitDecl())); - auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec); - { - auto *TU = FromTU; - auto *SpecD = FromSpecD; - auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match( - TU, functionTemplateDecl()); - auto *FirstSpecD = *(TemplateD->spec_begin()); - ASSERT_EQ(SpecD, FirstSpecD); - ASSERT_TRUE(SpecD->getPreviousDecl()); - ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl()) - ->doesThisDeclarationHaveABody()); - } - - ASSERT_TRUE(Import(FromSpecD, Lang_CXX)); - - { - auto *TU = ToAST->getASTContext().getTranslationUnitDecl(); - auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec); - auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match( - TU, functionTemplateDecl()); - auto *FirstSpecD = *(TemplateD->spec_begin()); - EXPECT_EQ(SpecD, FirstSpecD); - ASSERT_TRUE(SpecD->getPreviousDecl()); - EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl()) - ->doesThisDeclarationHaveABody()); - } -} - -TEST_P(ImportFunctionTemplateSpecializations, - MatchNumberOfFunctionTemplateSpecializations) { - - Decl *FromTU = getTuDecl( - R"( - template <typename T> constexpr int f() { return 0; } - template <> constexpr int f<int>() { return 4; } - void foo() { - static_assert(f<char>() == 0, ""); - static_assert(f<int>() == 4, ""); - } - )", - Lang_CXX11, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match( - FromTU, functionDecl(hasName("foo"))); - - Import(FromD, Lang_CXX11); - auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl(); - EXPECT_EQ( - DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))), - DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f")))); -} - -TEST_P(ImportFunctionTemplateSpecializations, - ImportPrototypes) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template <class T> - void f(); - // Proto of the specialization. - template <> - void f<int>(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); - auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - // Check that they are part of the same redecl chain. - EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl()); -} - -TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template <class T> - void f(); - // Specialization and definition. - template <> - void f<int>() {} - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); - - auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match( - ToTU, functionTemplateDecl()); - auto *FirstSpecD = *(TemplateD->spec_begin()); - EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl()); -} - -TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template <class T> - void f(); - // Specialization proto. - template <> - void f<int>(); - // Specialization proto. - template <> - void f<int>(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template <class T> - void f(); - // Specialization proto. - template <> - void f<int>(); - // Specialization definition. - template <> - void f<int>() {} - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_FALSE(To0->doesThisDeclarationHaveABody()); - EXPECT_TRUE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - -TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) { - auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization()); - auto Code = - R"( - // Proto of the primary template. - template <class T> - void f(); - // Specialization definition. - template <> - void f<int>() {} - // Specialization proto. - template <> - void f<int>(); - )"; - - Decl *ImportedD; - { - Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc"); - auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); - ImportedD = Import(FromD, Lang_CXX); - } - - Decl *ToTU = ImportedD->getTranslationUnitDecl(); - - EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u); - auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern); - EXPECT_TRUE(ImportedD == To0); - EXPECT_TRUE(ImportedD != To1); - EXPECT_TRUE(To0->doesThisDeclarationHaveABody()); - EXPECT_FALSE(To1->doesThisDeclarationHaveABody()); - EXPECT_EQ(To1->getPreviousDecl(), To0); -} - INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest, ::testing::Values(ArgVector()), ); -INSTANTIATE_TEST_CASE_P( - ParameterizedTests, CanonicalRedeclChain, - ::testing::Values(ArgVector()),); - auto DefaultTestValuesForRunOptions = ::testing::Values( ArgVector(), ArgVector{"-fdelayed-template-parsing"}, @@ -2615,12 +2048,5 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTes INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions, DefaultTestValuesForRunOptions, ); -INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions, - DefaultTestValuesForRunOptions, ); - -INSTANTIATE_TEST_CASE_P(ParameterizedTests, - ImportFunctionTemplateSpecializations, - DefaultTestValuesForRunOptions, ); - } // end namespace ast_matchers } // end namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits