Improve support for static data member templates. This revision still has at least one bug, as it does not respect the variable template specialization hierarchy well.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188969 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 9dad47f..9f2e757 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -5333,18 +5333,13 @@
// If we are providing an explicit specialization of a static variable
// template, make a note of that.
if (PrevVarTemplate && PrevVarTemplate->getInstantiatedFromMemberTemplate())
- NewTemplate->setMemberSpecialization();
+ PrevVarTemplate->setMemberSpecialization();
// Set the lexical context of this template
NewTemplate->setLexicalDeclContext(CurContext);
if (NewVD->isStaticDataMember() && NewVD->isOutOfLine())
NewTemplate->setAccess(NewVD->getAccess());
- if (PrevVarTemplate)
- mergeDeclAttributes(NewVD, PrevVarTemplate->getTemplatedDecl());
-
- AddPushedVisibilityAttribute(NewVD);
-
PushOnScopeChains(NewTemplate, S);
AddToScope = false;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 5d01691..f4f43ab 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2391,7 +2391,7 @@
// If we are providing an explicit specialization of a member variable
// template specialization, make a note of that.
if (PrevPartial && PrevPartial->getInstantiatedFromMember())
- Partial->setMemberSpecialization();
+ PrevPartial->setMemberSpecialization();
// Check that all of the template parameters of the variable template
// partial specialization are deducible from the template
@@ -2477,6 +2477,9 @@
ForRedeclaration);
PrevSpec.addDecl(PrevDecl);
D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec));
+ } else if (Specialization->isStaticDataMember() &&
+ Specialization->isOutOfLine()) {
+ Specialization->setAccess(VarTemplate->getAccess());
}
// Link instantiations of static data members back to the template from
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index b53c197..8d066a0 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -952,7 +952,6 @@
Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
assert(D->getTemplatedDecl()->isStaticDataMember() &&
"Only static data member templates are allowed.");
- // FIXME: Also only when instantiating a class?
// Create a local instantiation scope for this variable template, which
// will contain the instantiations of the template parameters.
@@ -971,28 +970,11 @@
PrevVarTemplate = dyn_cast<VarTemplateDecl>(Found.front());
}
- // FIXME: This, and ForVarTemplate, is a hack that is probably unnecessary.
- // We should use a simplified version of VisitVarDecl.
VarDecl *VarInst =
cast_or_null<VarDecl>(VisitVarDecl(Pattern, /*ForVarTemplate=*/ true));
DeclContext *DC = Owner;
- /* FIXME: This should be handled in VisitVarDecl, as used to produce
- VarInst above.
- // Instantiate the qualifier.
- NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc();
- if (QualifierLoc) {
- QualifierLoc =
- SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs);
- if (!QualifierLoc)
- return 0;
- }
-
- if (QualifierLoc)
- VarInst->setQualifierInfo(QualifierLoc);
- */
-
VarTemplateDecl *Inst = VarTemplateDecl::Create(
SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams,
VarInst, PrevVarTemplate);
@@ -1028,7 +1010,6 @@
VarTemplatePartialSpecializationDecl *D) {
assert(D->isStaticDataMember() &&
"Only static data member templates are allowed.");
- // FIXME: Also only when instantiating a class?
VarTemplateDecl *VarTemplate = D->getSpecializedTemplate();
@@ -2669,11 +2650,18 @@
InstPartialSpec->setTypeAsWritten(WrittenTy);
InstPartialSpec->setAccess(PartialSpec->getAccess());
- // FIXME: How much of BuildVariableInstantiation() should go in here?
// Add this partial specialization to the set of variable template partial
// specializations. The instantiation of the initializer is not necessary.
VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
+
+ // Set the initializer, to use as pattern for initialization.
+ if (VarDecl *Def = PartialSpec->getDefinition(SemaRef.getASTContext()))
+ PartialSpec = cast<VarTemplatePartialSpecializationDecl>(Def);
+ SemaRef.BuildVariableInstantiation(InstPartialSpec, PartialSpec, TemplateArgs,
+ LateAttrs, StartingScope);
+ InstPartialSpec->setInit(PartialSpec->getInit());
+
return InstPartialSpec;
}
@@ -3303,8 +3291,10 @@
const MultiLevelTemplateArgumentList &TemplateArgs) {
// Do substitution on the type of the declaration
+ MultiLevelTemplateArgumentList Innermost;
+ Innermost.addOuterTemplateArguments(TemplateArgs.getInnermost());
TypeSourceInfo *DI =
- SubstType(PatternDecl->getTypeSourceInfo(), TemplateArgs,
+ SubstType(PatternDecl->getTypeSourceInfo(), Innermost,
PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName());
if (!DI)
return 0;
@@ -3386,6 +3376,11 @@
if (isa<VarTemplateSpecializationDecl>(NewVar)) {
// Do not instantiate the variable just yet.
+ } else if (ForVarTemplate) {
+ assert(!NewVar->getInit() &&
+ "A variable should not have an initializer if it is templated"
+ " and we are instantiating its template");
+ NewVar->setInit(OldVar->getInit());
} else
InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);