Variable templates: handle instantiation of static data member templates
appropriately, especially when they appear within class templates.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191548 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index fd9c7cf..043ed99 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -7864,14 +7864,7 @@
if (!VD->isExternallyVisible())
return GVA_Internal;
- // If this is a static data member, compute the kind of template
- // specialization. Otherwise, this variable is not part of a
- // template.
- TemplateSpecializationKind TSK = TSK_Undeclared;
- if (VD->isStaticDataMember())
- TSK = VD->getTemplateSpecializationKind();
-
- switch (TSK) {
+ switch (VD->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
return GVA_StrongExternal;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index dbbf475..587b18e 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1689,13 +1689,24 @@
// A declaration is a definition unless [...] it contains the 'extern'
// specifier or a linkage-specification and neither an initializer [...],
// it declares a static data member in a class declaration [...].
- // C++ [temp.expl.spec]p15:
- // An explicit specialization of a static data member of a template is a
- // definition if the declaration includes an initializer; otherwise, it is
- // a declaration.
+ // C++1y [temp.expl.spec]p15:
+ // An explicit specialization of a static data member or an explicit
+ // specialization of a static data member template is a definition if the
+ // declaration includes an initializer; otherwise, it is a declaration.
+ //
+ // FIXME: How do you declare (but not define) a partial specialization of
+ // a static data member template outside the containing class?
if (isStaticDataMember()) {
- if (isOutOfLine() && (hasInit() ||
- getTemplateSpecializationKind() != TSK_ExplicitSpecialization))
+ if (isOutOfLine() &&
+ (hasInit() ||
+ // If the first declaration is out-of-line, this may be an
+ // instantiation of an out-of-line partial specialization of a variable
+ // template for which we have not yet instantiated the initializer.
+ (getFirstDeclaration()->isOutOfLine()
+ ? getTemplateSpecializationKind() == TSK_Undeclared
+ : getTemplateSpecializationKind() !=
+ TSK_ExplicitSpecialization) ||
+ isa<VarTemplatePartialSpecializationDecl>(this)))
return Definition;
else
return DeclarationOnly;
@@ -1710,6 +1721,13 @@
if (hasInit())
return Definition;
+ // A variable template specialization (other than a static data member
+ // template or an explicit specialization) is a declaration until we
+ // instantiate its initializer.
+ if (isa<VarTemplateSpecializationDecl>(this) &&
+ getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+ return DeclarationOnly;
+
if (hasExternalStorage())
return DeclarationOnly;
@@ -1978,10 +1996,21 @@
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return MSI->getTemplateSpecializationKind();
-
+
return TSK_Undeclared;
}
+SourceLocation VarDecl::getPointOfInstantiation() const {
+ if (const VarTemplateSpecializationDecl *Spec =
+ dyn_cast<VarTemplateSpecializationDecl>(this))
+ return Spec->getPointOfInstantiation();
+
+ if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
+ return MSI->getPointOfInstantiation();
+
+ return SourceLocation();
+}
+
VarTemplateDecl *VarDecl::getDescribedVarTemplate() const {
return getASTContext().getTemplateOrSpecializationInfo(this)
.dyn_cast<VarTemplateDecl *>();
@@ -2002,13 +2031,16 @@
void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
SourceLocation PointOfInstantiation) {
+ assert((isa<VarTemplateSpecializationDecl>(this) ||
+ getMemberSpecializationInfo()) &&
+ "not a variable or static data member template specialization");
+
if (VarTemplateSpecializationDecl *Spec =
dyn_cast<VarTemplateSpecializationDecl>(this)) {
Spec->setSpecializationKind(TSK);
if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
Spec->getPointOfInstantiation().isInvalid())
Spec->setPointOfInstantiation(PointOfInstantiation);
- return;
}
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) {
@@ -2016,11 +2048,7 @@
if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
MSI->getPointOfInstantiation().isInvalid())
MSI->setPointOfInstantiation(PointOfInstantiation);
- return;
}
-
- llvm_unreachable(
- "Not a variable or static data member template specialization");
}
void