For instantiations of static data members of class templates, keep
track of the kind of specialization or instantiation. Also, check the
scope of the specialization and ensure that a specialization
declaration without an initializer is not a definition.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83533 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index fcacb4a..bafcea0 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -155,6 +155,12 @@
     Owner->addDecl(Var);
   }
 
+  // Link instantiations of static data members back to the template from
+  // which they were instantiated.
+  if (Var->isStaticDataMember())
+    SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D, 
+                                                        TSK_ImplicitInstantiation);
+  
   if (D->getInit()) {
     OwningExprResult Init
       = SemaRef.SubstExpr(D->getInit(), TemplateArgs);
@@ -191,11 +197,6 @@
   } else if (!Var->isStaticDataMember() || Var->isOutOfLine())
     SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);
 
-  // Link instantiations of static data members back to the template from
-  // which they were instantiated.
-  if (Var->isStaticDataMember())
-    SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D);
-
   return Var;
 }
 
@@ -977,6 +978,10 @@
 
   assert(!Function->getBody() && "Already instantiated!");
 
+  // Never instantiate an explicit specialization.
+  if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+    return;
+  
   // Find the function body that we'll be substituting.
   const FunctionDecl *PatternDecl = 0;
   if (FunctionTemplateDecl *Primary = Function->getPrimaryTemplate()) {
@@ -1084,7 +1089,6 @@
     return;
 
   // Find the out-of-line definition of this static data member.
-  // FIXME: Do we have to look for specializations separately?
   VarDecl *Def = Var->getInstantiatedFromStaticDataMember();
   bool FoundOutOfLineDef = false;
   assert(Def && "This data member was not instantiated from a template?");
@@ -1106,7 +1110,17 @@
     return;
   }
 
-  // FIXME: extern templates
+  // Never instantiate an explicit specialization.
+  if (Def->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+    return;
+  
+  // C++0x [temp.explicit]p9:
+  //   Except for inline functions, other explicit instantiation declarations
+  //   have the effect of suppressing the implicit instantiation of the entity
+  //   to which they refer.
+  if (Def->getTemplateSpecializationKind() 
+        == TSK_ExplicitInstantiationDeclaration)
+    return;
 
   InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
   if (Inst)