summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/AST/ASTImporter.cpp56
-rw-r--r--clang/unittests/AST/ASTImporterTest.cpp48
2 files changed, 54 insertions, 50 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 3b484f94003..da102988dec 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -4943,15 +4943,15 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
return ToD;
}
-// Returns the definition for a (forward) declaration of a ClassTemplateDecl, if
+// Returns the definition for a (forward) declaration of a TemplateDecl, if
// it has any definition in the redecl chain.
-static ClassTemplateDecl *getDefinition(ClassTemplateDecl *D) {
- CXXRecordDecl *ToTemplatedDef = D->getTemplatedDecl()->getDefinition();
+template <typename T> static auto getTemplateDefinition(T *D) -> T * {
+ assert(D->getTemplatedDecl() && "Should be called on templates only");
+ auto *ToTemplatedDef = D->getTemplatedDecl()->getDefinition();
if (!ToTemplatedDef)
return nullptr;
- ClassTemplateDecl *TemplateWithDef =
- ToTemplatedDef->getDescribedClassTemplate();
- return TemplateWithDef;
+ auto *TemplateWithDef = ToTemplatedDef->getDescribedTemplate();
+ return cast_or_null<T>(TemplateWithDef);
}
ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
@@ -4983,7 +4983,8 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
if (FoundTemplate) {
if (IsStructuralMatch(D, FoundTemplate)) {
- ClassTemplateDecl *TemplateWithDef = getDefinition(FoundTemplate);
+ ClassTemplateDecl *TemplateWithDef =
+ getTemplateDefinition(FoundTemplate);
if (D->isThisDeclarationADefinition() && TemplateWithDef) {
return Importer.MapImported(D, TemplateWithDef);
}
@@ -5046,6 +5047,8 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// and this time the lookup finds the previous fwd friend class template.
// In this case we must set up the previous decl for the templated decl.
if (!ToTemplated->getPreviousDecl()) {
+ assert(FoundByLookup->getTemplatedDecl() &&
+ "Found decl must have its templated decl set");
CXXRecordDecl *PrevTemplated =
FoundByLookup->getTemplatedDecl()->getMostRecentDecl();
if (ToTemplated != PrevTemplated)
@@ -5508,8 +5511,11 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (ToD)
return ToD;
+ const FunctionTemplateDecl *FoundByLookup = nullptr;
+
// 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.
+ // FIXME Split this into a separate function.
if (!LexicalDC->isFunctionOrMethod()) {
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend;
auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
@@ -5517,18 +5523,21 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (!FoundDecl->isInIdentifierNamespace(IDNS))
continue;
- if (auto *FoundFunction =
- dyn_cast<FunctionTemplateDecl>(FoundDecl)) {
- if (FoundFunction->hasExternalFormalLinkage() &&
+ if (auto *FoundTemplate = dyn_cast<FunctionTemplateDecl>(FoundDecl)) {
+ if (FoundTemplate->hasExternalFormalLinkage() &&
D->hasExternalFormalLinkage()) {
- if (IsStructuralMatch(D, FoundFunction)) {
- Importer.MapImported(D, FoundFunction);
- // FIXME: Actually try to merge the body and other attributes.
- return FoundFunction;
+ if (IsStructuralMatch(D, FoundTemplate)) {
+ FunctionTemplateDecl *TemplateWithDef =
+ getTemplateDefinition(FoundTemplate);
+ if (D->isThisDeclarationADefinition() && TemplateWithDef) {
+ return Importer.MapImported(D, TemplateWithDef);
+ }
+ FoundByLookup = FoundTemplate;
+ break;
}
+ // TODO: handle conflicting names
}
}
- // TODO: handle conflicting names
}
}
@@ -5547,10 +5556,25 @@ ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
return ToFunc;
TemplatedFD->setDescribedFunctionTemplate(ToFunc);
+
ToFunc->setAccess(D->getAccess());
ToFunc->setLexicalDeclContext(LexicalDC);
-
LexicalDC->addDeclInternal(ToFunc);
+
+ if (FoundByLookup) {
+ auto *Recent =
+ const_cast<FunctionTemplateDecl *>(FoundByLookup->getMostRecentDecl());
+ if (!TemplatedFD->getPreviousDecl()) {
+ assert(FoundByLookup->getTemplatedDecl() &&
+ "Found decl must have its templated decl set");
+ auto *PrevTemplated =
+ FoundByLookup->getTemplatedDecl()->getMostRecentDecl();
+ if (TemplatedFD != PrevTemplated)
+ TemplatedFD->setPreviousDecl(PrevTemplated);
+ }
+ ToFunc->setPreviousDecl(Recent);
+ }
+
return ToFunc;
}
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 08d57e2e433..00e12d75bc8 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -4197,9 +4197,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
RedeclChain, Variable, ,
PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
-// FIXME Enable this test, once we import function templates chains correctly.
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, FunctionTemplate, DISABLED_,
+ RedeclChain, FunctionTemplate, ,
PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
RedeclChain, ClassTemplate, ,
@@ -4214,9 +4213,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition)
-// FIXME Enable this test, once we import function templates chains correctly.
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
- RedeclChain, FunctionTemplate, DISABLED_,
+ RedeclChain, FunctionTemplate, ,
DefinitionShouldBeImportedAsADefinition)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition)
@@ -4230,9 +4228,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
ImportPrototypeAfterImportedPrototype)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
ImportPrototypeAfterImportedPrototype)
-// FIXME Enable this test, once we import function templates chains correctly.
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
- DISABLED_,
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
ImportPrototypeAfterImportedPrototype)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
ImportPrototypeAfterImportedPrototype)
@@ -4245,9 +4241,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
ImportDefinitionAfterImportedPrototype)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
ImportDefinitionAfterImportedPrototype)
-// FIXME Enable this test, once we import function templates chains correctly.
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
- DISABLED_,
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
ImportDefinitionAfterImportedPrototype)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
ImportDefinitionAfterImportedPrototype)
@@ -4260,9 +4254,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
ImportPrototypeAfterImportedDefinition)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
ImportPrototypeAfterImportedDefinition)
-// FIXME Enable this test, once we import function templates chains correctly.
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
- DISABLED_,
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
ImportPrototypeAfterImportedDefinition)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
ImportPrototypeAfterImportedDefinition)
@@ -4274,9 +4266,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
ImportPrototypes)
-// FIXME Enable this test, once we import function templates chains correctly.
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
- DISABLED_, ImportPrototypes)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ ImportPrototypes)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
ImportPrototypes)
// FIXME This does not pass, possible error with Spec import.
@@ -4289,9 +4280,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
ImportDefinitions)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
ImportDefinitions)
-// FIXME Enable this test, once we import function templates chains correctly.
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
- DISABLED_, ImportDefinitions)
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
+ ImportDefinitions)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
ImportDefinitions)
// FIXME This does not pass, possible error with Spec import.
@@ -4304,9 +4294,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
ImportDefinitionThenPrototype)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
ImportDefinitionThenPrototype)
-// FIXME Enable this test, once we import function templates chains correctly.
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
- DISABLED_,
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
ImportDefinitionThenPrototype)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
ImportDefinitionThenPrototype)
@@ -4321,9 +4309,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
ImportPrototypeThenDefinition)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
ImportPrototypeThenDefinition)
-// FIXME Enable this test, once we import function templates chains correctly.
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
- DISABLED_,
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
ImportPrototypeThenDefinition)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
ImportPrototypeThenDefinition)
@@ -4336,9 +4322,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
WholeRedeclChainIsImportedAtOnce)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
WholeRedeclChainIsImportedAtOnce)
-// FIXME Enable this test, once we import function templates chains correctly.
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
- DISABLED_,
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
WholeRedeclChainIsImportedAtOnce)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
WholeRedeclChainIsImportedAtOnce)
@@ -4347,9 +4331,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
ImportPrototypeThenProtoAndDefinition)
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
ImportPrototypeThenProtoAndDefinition)
-// FIXME Enable this test, once we import function templates chains correctly.
-ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
- DISABLED_,
+ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
ImportPrototypeThenProtoAndDefinition)
// FIXME This does not pass, possible error with Spec import.
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
@@ -5442,9 +5424,7 @@ TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
FromTU, functionTemplateDecl(hasName("foo")));
auto *Imported = Import(FromFoo, Lang_CXX);
- // FIXME Currently chains of FunctionTemplateDecls are not implemented.
- //EXPECT_EQ(Imported->getPreviousDecl(), Friend);
- EXPECT_EQ(Imported, Friend);
+ EXPECT_EQ(Imported->getPreviousDecl(), Friend);
}
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
OpenPOWER on IntegriCloud