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