Make sure that we're diagnosing duplicate explicit instantiation definitions.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84189 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 8d7e199..730fea3 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3818,8 +3818,11 @@
   CheckExplicitInstantiationScope(*this, Record, NameLoc, true);
   
   // Verify that it is okay to explicitly instantiate here.
-  if (CXXRecordDecl *PrevDecl 
-        = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration())) {
+  CXXRecordDecl *PrevDecl 
+    = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration());
+  if (!PrevDecl && Record->getDefinition(Context))
+    PrevDecl = Record;
+  if (PrevDecl) {
     MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
     bool SuppressNew = false;
     assert(MSInfo && "No member specialization information?");
@@ -4065,6 +4068,9 @@
   } 
   
   FunctionDecl *PrevDecl = Specialization->getPreviousDeclaration();
+  if (!PrevDecl && Specialization->isThisDeclarationADefinition())
+    PrevDecl = Specialization;
+
   if (PrevDecl) {
     bool SuppressNew = false;
     if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK,
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ca05d59..4bbef29 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1258,7 +1258,10 @@
 
   if (Var) {
     Var->setPreviousDeclaration(OldVar);
-    Var->setTemplateSpecializationKind(OldVar->getTemplateSpecializationKind());
+    MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
+    assert(MSInfo && "Missing member specialization information?");
+    Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),
+                                       MSInfo->getPointOfInstantiation());
     DeclGroupRef DG(Var);
     Consumer.HandleTopLevelDecl(DG);
   }
diff --git a/test/CXX/temp/temp.spec/p5.cpp b/test/CXX/temp/temp.spec/p5.cpp
new file mode 100644
index 0000000..d5632e7
--- /dev/null
+++ b/test/CXX/temp/temp.spec/p5.cpp
@@ -0,0 +1,29 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> inline void f(T) { }
+template void f(int); // expected-note{{previous explicit instantiation}}
+template void f(int); // expected-error{{duplicate explicit instantiation}}
+
+template<typename T>
+struct X0 {
+  union Inner { };
+  
+  void f(T) { }
+  
+  static T value;
+};
+
+template<typename T>
+T X0<T>::value = 3.14;
+
+template struct X0<int>; // expected-note{{previous explicit instantiation}}
+template struct X0<int>; // expected-error{{duplicate explicit instantiation}}
+
+template void X0<float>::f(float); // expected-note{{previous explicit instantiation}}
+template void X0<float>::f(float); // expected-error{{duplicate explicit instantiation}}
+
+template union X0<float>::Inner; // expected-note{{previous explicit instantiation}}
+template union X0<float>::Inner; // expected-error{{duplicate explicit instantiation}}
+
+template float X0<float>::value; // expected-note{{previous explicit instantiation}}
+template float X0<float>::value; // expected-error{{duplicate explicit instantiation}}