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();