Implement template instantiation for static data members of class
templates, including in-class initializers. For example:
template<typename T, T Divisor>
class X {
public:
static const T value = 10 / Divisor;
};
instantiated with, e.g.,
X<int, 5>::value
to get the value '2'.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67715 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ff474fa..46076f2 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -42,6 +42,7 @@
Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
Decl *VisitNamespaceDecl(NamespaceDecl *D);
Decl *VisitTypedefDecl(TypedefDecl *D);
+ Decl *VisitVarDecl(VarDecl *D);
Decl *VisitFieldDecl(FieldDecl *D);
Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitEnumDecl(EnumDecl *D);
@@ -56,6 +57,7 @@
// Base case. FIXME: Remove once we can instantiate everything.
Decl *VisitDecl(Decl *) {
+ assert(false && "Template instantiation of unknown declaration kind!");
return 0;
}
@@ -102,6 +104,45 @@
return Typedef;
}
+Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
+ // Instantiate the type of the declaration
+ QualType T = SemaRef.InstantiateType(D->getType(), TemplateArgs,
+ NumTemplateArgs,
+ D->getTypeSpecStartLoc(),
+ D->getDeclName());
+ if (T.isNull())
+ return 0;
+
+ // Build the instantiataed declaration
+ VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,
+ D->getLocation(), D->getIdentifier(),
+ T, D->getStorageClass(),
+ D->getTypeSpecStartLoc());
+ Var->setThreadSpecified(D->isThreadSpecified());
+ Var->setCXXDirectInitializer(D->hasCXXDirectInitializer());
+ Var->setDeclaredInCondition(D->isDeclaredInCondition());
+
+ // FIXME: In theory, we could have a previous declaration for
+ // variables that are not static data members.
+ bool Redeclaration = false;
+ if (SemaRef.CheckVariableDeclaration(Var, 0, Redeclaration))
+ Var->setInvalidDecl();
+
+ Owner->addDecl(Var);
+
+ if (D->getInit()) {
+ OwningExprResult Init
+ = SemaRef.InstantiateExpr(D->getInit(), TemplateArgs, NumTemplateArgs);
+ if (Init.isInvalid())
+ Var->setInvalidDecl();
+ else
+ SemaRef.AddInitializerToDecl(Var, move(Init),
+ D->hasCXXDirectInitializer());
+ }
+
+ return Var;
+}
+
Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
bool Invalid = false;
QualType T = D->getType();