forked from OSchip/llvm-project
[ASTImporter] Improved variable template redecl chain handling.
Reviewers: martong, a.sidorin, shafik Reviewed By: martong Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, teemperor, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D74720
This commit is contained in:
parent
e0568ef2c5
commit
7b6168e7be
|
@ -3881,6 +3881,13 @@ ExpectedDecl ASTNodeImporter::VisitVarDecl(VarDecl *D) {
|
|||
ToVar->setPreviousDecl(Recent);
|
||||
}
|
||||
|
||||
// Import the described template, if any.
|
||||
if (D->getDescribedVarTemplate()) {
|
||||
auto ToVTOrErr = import(D->getDescribedVarTemplate());
|
||||
if (!ToVTOrErr)
|
||||
return ToVTOrErr.takeError();
|
||||
}
|
||||
|
||||
if (Error Err = ImportInitializer(D, ToVar))
|
||||
return std::move(Err);
|
||||
|
||||
|
@ -5460,20 +5467,6 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
|
|||
}
|
||||
|
||||
ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
|
||||
// If this variable has a definition in the translation unit we're coming
|
||||
// from,
|
||||
// but this particular declaration is not that definition, import the
|
||||
// definition and map to that.
|
||||
auto *Definition =
|
||||
cast_or_null<VarDecl>(D->getTemplatedDecl()->getDefinition());
|
||||
if (Definition && Definition != D->getTemplatedDecl()) {
|
||||
if (ExpectedDecl ImportedDefOrErr = import(
|
||||
Definition->getDescribedVarTemplate()))
|
||||
return Importer.MapImported(D, *ImportedDefOrErr);
|
||||
else
|
||||
return ImportedDefOrErr.takeError();
|
||||
}
|
||||
|
||||
// Import the major distinguishing characteristics of this variable template.
|
||||
DeclContext *DC, *LexicalDC;
|
||||
DeclarationName Name;
|
||||
|
@ -5487,19 +5480,26 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
|
|||
// We may already have a template of the same name; try to find and match it.
|
||||
assert(!DC->isFunctionOrMethod() &&
|
||||
"Variable templates cannot be declared at function scope");
|
||||
|
||||
SmallVector<NamedDecl *, 4> ConflictingDecls;
|
||||
auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
|
||||
VarTemplateDecl *FoundByLookup = nullptr;
|
||||
for (auto *FoundDecl : FoundDecls) {
|
||||
if (!FoundDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
|
||||
continue;
|
||||
|
||||
Decl *Found = FoundDecl;
|
||||
if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(Found)) {
|
||||
if (VarTemplateDecl *FoundTemplate = dyn_cast<VarTemplateDecl>(FoundDecl)) {
|
||||
if (IsStructuralMatch(D, FoundTemplate)) {
|
||||
// The variable templates structurally match; call it the same template.
|
||||
Importer.MapImported(D->getTemplatedDecl(),
|
||||
FoundTemplate->getTemplatedDecl());
|
||||
return Importer.MapImported(D, FoundTemplate);
|
||||
// The Decl in the "From" context has a definition, but in the
|
||||
// "To" context we already have a definition.
|
||||
VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate);
|
||||
if (D->isThisDeclarationADefinition() && FoundDef)
|
||||
// FIXME Check for ODR error if the two definitions have
|
||||
// different initializers?
|
||||
return Importer.MapImported(D, FoundDef);
|
||||
|
||||
FoundByLookup = FoundTemplate;
|
||||
break;
|
||||
}
|
||||
ConflictingDecls.push_back(FoundDecl);
|
||||
}
|
||||
|
@ -5544,6 +5544,18 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
|
|||
ToVarTD->setLexicalDeclContext(LexicalDC);
|
||||
LexicalDC->addDeclInternal(ToVarTD);
|
||||
|
||||
if (FoundByLookup) {
|
||||
auto *Recent =
|
||||
const_cast<VarTemplateDecl *>(FoundByLookup->getMostRecentDecl());
|
||||
if (!ToTemplated->getPreviousDecl()) {
|
||||
auto *PrevTemplated =
|
||||
FoundByLookup->getTemplatedDecl()->getMostRecentDecl();
|
||||
if (ToTemplated != PrevTemplated)
|
||||
ToTemplated->setPreviousDecl(PrevTemplated);
|
||||
}
|
||||
ToVarTD->setPreviousDecl(Recent);
|
||||
}
|
||||
|
||||
if (DTemplated->isThisDeclarationADefinition() &&
|
||||
!ToTemplated->isThisDeclarationADefinition()) {
|
||||
// FIXME: Import definition!
|
||||
|
|
|
@ -74,6 +74,21 @@ struct ClassTemplate {
|
|||
}
|
||||
};
|
||||
|
||||
struct VariableTemplate {
|
||||
using DeclTy = VarTemplateDecl;
|
||||
static constexpr auto *Prototype = "template <class T> extern T X;";
|
||||
static constexpr auto *Definition =
|
||||
R"(
|
||||
template <class T> T X;
|
||||
template <> int X<int>;
|
||||
)";
|
||||
// There is no matcher for varTemplateDecl so use a work-around.
|
||||
BindableMatcher<Decl> getPattern() {
|
||||
return namedDecl(hasName("X"), unless(isImplicit()),
|
||||
has(templateTypeParmDecl()));
|
||||
}
|
||||
};
|
||||
|
||||
struct FunctionTemplateSpec {
|
||||
using DeclTy = FunctionDecl;
|
||||
static constexpr auto *Prototype =
|
||||
|
@ -427,6 +442,9 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
|
|||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
|
||||
RedeclChain, ClassTemplate, ,
|
||||
PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
|
||||
RedeclChain, VariableTemplate, ,
|
||||
PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
|
||||
RedeclChain, FunctionTemplateSpec, ,
|
||||
PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
|
||||
|
@ -446,6 +464,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
|
|||
DefinitionShouldBeImportedAsADefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
|
||||
DefinitionShouldBeImportedAsADefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, ,
|
||||
DefinitionShouldBeImportedAsADefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
|
||||
DefinitionShouldBeImportedAsADefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
|
||||
|
@ -463,6 +483,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
|
|||
ImportPrototypeAfterImportedPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
|
||||
ImportPrototypeAfterImportedPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, ,
|
||||
ImportPrototypeAfterImportedPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
|
||||
ImportPrototypeAfterImportedPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
|
||||
|
@ -480,6 +502,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
|
|||
ImportDefinitionAfterImportedPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
|
||||
ImportDefinitionAfterImportedPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, ,
|
||||
ImportDefinitionAfterImportedPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
|
||||
ImportDefinitionAfterImportedPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
|
||||
|
@ -497,6 +521,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
|
|||
ImportPrototypeAfterImportedDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
|
||||
ImportPrototypeAfterImportedDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, ,
|
||||
ImportPrototypeAfterImportedDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
|
||||
ImportPrototypeAfterImportedDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
|
||||
|
@ -513,6 +539,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
|
|||
ImportPrototypes)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
|
||||
ImportPrototypes)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, ,
|
||||
ImportPrototypes)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
|
||||
ImportPrototypes)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
|
||||
|
@ -529,6 +557,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
|
|||
ImportDefinitions)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
|
||||
ImportDefinitions)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, ,
|
||||
ImportDefinitions)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
|
||||
ImportDefinitions)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
|
||||
|
@ -546,6 +576,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
|
|||
ImportDefinitionThenPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
|
||||
ImportDefinitionThenPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, ,
|
||||
ImportDefinitionThenPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
|
||||
ImportDefinitionThenPrototype)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
|
||||
|
@ -563,6 +595,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
|
|||
ImportPrototypeThenDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
|
||||
ImportPrototypeThenDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, ,
|
||||
ImportPrototypeThenDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
|
||||
ImportPrototypeThenDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplateSpec, ,
|
||||
|
@ -574,6 +608,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
|
|||
WholeRedeclChainIsImportedAtOnce)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
|
||||
WholeRedeclChainIsImportedAtOnce)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, ,
|
||||
WholeRedeclChainIsImportedAtOnce)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
|
||||
WholeRedeclChainIsImportedAtOnce)
|
||||
|
||||
|
@ -583,6 +619,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
|
|||
ImportPrototypeThenProtoAndDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, ,
|
||||
ImportPrototypeThenProtoAndDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, VariableTemplate, ,
|
||||
ImportPrototypeThenProtoAndDefinition)
|
||||
ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
|
||||
ImportPrototypeThenProtoAndDefinition)
|
||||
|
||||
|
@ -598,6 +636,8 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate,
|
|||
DefaultTestValuesForRunOptions, );
|
||||
INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate,
|
||||
DefaultTestValuesForRunOptions, );
|
||||
INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariableTemplate,
|
||||
DefaultTestValuesForRunOptions, );
|
||||
INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec,
|
||||
DefaultTestValuesForRunOptions, );
|
||||
INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplateSpec,
|
||||
|
|
Loading…
Reference in New Issue