Permalink
Browse files

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
  • Loading branch information...
1 parent 2096fd6 commit d0629eb137d06bf6d46a430abdb7fa044909298b @zygoloid zygoloid committed Sep 27, 2013
View
@@ -1146,10 +1146,16 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
/// from which it was instantiated.
VarDecl *getInstantiatedFromStaticDataMember() const;
- /// \brief If this variable is a static data member, determine what kind of
+ /// \brief If this variable is an instantiation of a variable template or a
+ /// static data member of a class template, determine what kind of
/// template specialization or instantiation this is.
TemplateSpecializationKind getTemplateSpecializationKind() const;
+ /// \brief If this variable is an instantiation of a variable template or a
+ /// static data member of a class template, determine its point of
+ /// instantiation.
+ SourceLocation getPointOfInstantiation() const;
+
/// \brief If this variable is an instantiation of a static data member of a
/// class template specialization, retrieves the member specialization
/// information.
@@ -1387,7 +1387,7 @@ class ClassTemplateSpecializationDecl
/// \brief The template argument list deduced for the class template
/// partial specialization itself.
- TemplateArgumentList *TemplateArgs;
+ const TemplateArgumentList *TemplateArgs;
};
/// \brief The template that this specialization specializes
@@ -1412,7 +1412,7 @@ class ClassTemplateSpecializationDecl
ExplicitSpecializationInfo *ExplicitInfo;
/// \brief The template arguments used to describe this specialization.
- TemplateArgumentList *TemplateArgs;
+ const TemplateArgumentList *TemplateArgs;
/// \brief The point where this template was instantiated (if any)
SourceLocation PointOfInstantiation;
@@ -1563,7 +1563,7 @@ class ClassTemplateSpecializationDecl
/// instantiation of the given class template partial specialization whose
/// template arguments have been deduced.
void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
- TemplateArgumentList *TemplateArgs) {
+ const TemplateArgumentList *TemplateArgs) {
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
"Already set to a class template partial specialization!");
SpecializedPartialSpecialization *PS
@@ -2250,7 +2250,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// \brief The template argument list deduced for the variable template
/// partial specialization itself.
- TemplateArgumentList *TemplateArgs;
+ const TemplateArgumentList *TemplateArgs;
};
/// \brief The template that this specialization specializes.
@@ -2275,7 +2275,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
ExplicitSpecializationInfo *ExplicitInfo;
/// \brief The template arguments used to describe this specialization.
- TemplateArgumentList *TemplateArgs;
+ const TemplateArgumentList *TemplateArgs;
TemplateArgumentListInfo TemplateArgsInfo;
/// \brief The point where this template was instantiated (if any).
@@ -2421,7 +2421,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// instantiation of the given variable template partial specialization whose
/// template arguments have been deduced.
void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec,
- TemplateArgumentList *TemplateArgs) {
+ const TemplateArgumentList *TemplateArgs) {
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
"Already set to a variable template partial specialization!");
SpecializedPartialSpecialization *PS =
@@ -3302,11 +3302,11 @@ def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning<
InGroup<CXX11Compat>, DefaultIgnore;
def err_explicit_instantiation_undefined_member : Error<
"explicit instantiation of undefined %select{member class|member function|"
- "static data member|static data member template}0 %1 of class template %2">;
+ "static data member}0 %1 of class template %2">;
def err_explicit_instantiation_undefined_func_template : Error<
"explicit instantiation of undefined function template %0">;
def err_explicit_instantiation_undefined_var_template : Error<
- "explicit instantiation of undefined variable template %0">;
+ "explicit instantiation of undefined variable template %q0">;
def err_explicit_instantiation_declaration_after_definition : Error<
"explicit instantiation declaration (with 'extern') follows explicit "
"instantiation definition (without 'extern')">;
@@ -493,7 +493,7 @@ namespace clang {
Decl *VisitVarTemplateSpecializationDecl(
VarTemplateDecl *VarTemplate, VarDecl *FromVar, void *InsertPos,
const TemplateArgumentListInfo &TemplateArgsInfo,
- SmallVectorImpl<TemplateArgument> &Converted);
+ llvm::ArrayRef<TemplateArgument> Converted);
Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
ClassTemplatePartialSpecializationDecl *
View
@@ -7864,14 +7864,7 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
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;
View
@@ -1689,13 +1689,24 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(
// 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 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(
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 @@ TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
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,25 +2031,24 @@ MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
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()) {
MSI->setTemplateSpecializationKind(TSK);
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
View
@@ -8338,7 +8338,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
if (VDecl->getStorageClass() == SC_Extern &&
(!getLangOpts().CPlusPlus ||
!(Context.getBaseElementType(VDecl->getType()).isConstQualified() ||
- VDecl->isExternC())))
+ VDecl->isExternC())) &&
+ !isTemplateInstantiation(VDecl->getTemplateSpecializationKind()))
Diag(VDecl->getLocation(), diag::warn_extern_init);
// C99 6.7.8p4. All file scoped initializers need to be constant.
View
@@ -11767,45 +11767,33 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
VarTemplateSpecializationDecl *VarSpec =
dyn_cast<VarTemplateSpecializationDecl>(Var);
+ assert(!isa<VarTemplatePartialSpecializationDecl>(Var) &&
+ "Can't instantiate a partial template specialization.");
// Implicit instantiation of static data members, static data member
// templates of class templates, and variable template specializations.
// Delay instantiations of variable templates, except for those
// that could be used in a constant expression.
- if (VarSpec || (Var->isStaticDataMember() &&
- Var->getInstantiatedFromStaticDataMember())) {
- MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
- if (VarSpec)
- assert(!isa<VarTemplatePartialSpecializationDecl>(Var) &&
- "Can't instantiate a partial template specialization.");
- if (Var->isStaticDataMember())
- assert(MSInfo && "Missing member specialization information?");
-
- SourceLocation PointOfInstantiation;
- bool InstantiationIsOkay = true;
- if (MSInfo) {
- bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid();
- TemplateSpecializationKind TSK = MSInfo->getTemplateSpecializationKind();
-
- if (TSK == TSK_ImplicitInstantiation &&
- (!AlreadyInstantiated ||
- Var->isUsableInConstantExpressions(SemaRef.Context))) {
- if (!AlreadyInstantiated) {
- // This is a modification of an existing AST node. Notify listeners.
- if (ASTMutationListener *L = SemaRef.getASTMutationListener())
- L->StaticDataMemberInstantiated(Var);
- MSInfo->setPointOfInstantiation(Loc);
- }
- PointOfInstantiation = MSInfo->getPointOfInstantiation();
- } else
- InstantiationIsOkay = false;
- } else {
- if (VarSpec->getPointOfInstantiation().isInvalid())
- VarSpec->setPointOfInstantiation(Loc);
- PointOfInstantiation = VarSpec->getPointOfInstantiation();
- }
-
- if (InstantiationIsOkay) {
+ TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
+ if (isTemplateInstantiation(TSK)) {
+ bool TryInstantiating = TSK == TSK_ImplicitInstantiation;
+
+ if (TryInstantiating && !isa<VarTemplateSpecializationDecl>(Var)) {
+ if (Var->getPointOfInstantiation().isInvalid()) {
+ // This is a modification of an existing AST node. Notify listeners.
+ if (ASTMutationListener *L = SemaRef.getASTMutationListener())
+ L->StaticDataMemberInstantiated(Var);
+ } else if (!Var->isUsableInConstantExpressions(SemaRef.Context))
+ // Don't bother trying to instantiate it again, unless we might need
+ // its initializer before we get to the end of the TU.
+ TryInstantiating = false;
+ }
+
+ if (Var->getPointOfInstantiation().isInvalid())
+ Var->setTemplateSpecializationKind(TSK, Loc);
+
+ if (TryInstantiating) {
+ SourceLocation PointOfInstantiation = Var->getPointOfInstantiation();
bool InstantiationDependent = false;
bool IsNonDependent =
VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments(
@@ -7372,13 +7372,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true);
// Verify that it is okay to explicitly instantiate here.
- MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
- TemplateSpecializationKind PrevTSK =
- MSInfo ? MSInfo->getTemplateSpecializationKind()
- : Prev->getTemplateSpecializationKind();
- SourceLocation POI = MSInfo ? MSInfo->getPointOfInstantiation()
- : cast<VarTemplateSpecializationDecl>(Prev)
- ->getPointOfInstantiation();
+ TemplateSpecializationKind PrevTSK = Prev->getTemplateSpecializationKind();
+ SourceLocation POI = Prev->getPointOfInstantiation();
bool HasNoEffect = false;
if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
PrevTSK, POI, HasNoEffect))
@@ -2471,6 +2471,9 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
}
}
} else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
+ if (isa<VarTemplateSpecializationDecl>(Var))
+ continue;
+
if (Var->isStaticDataMember()) {
MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
assert(MSInfo && "No member specialization information?");
Oops, something went wrong.

0 comments on commit d0629eb

Please sign in to comment.