Determine when the instantiation of a friend function defined inside a
class template conflicts with an existing (non-template)
definition. This is another part of PR6952.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103948 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 41c6218..3128407 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1983,11 +1983,29 @@
   if (Function->isInvalidDecl())
     return;
 
-  assert(!Function->getBody() && "Already instantiated!");
-
   // Never instantiate an explicit specialization.
   if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
     return;
+
+  const FunctionDecl *Definition = 0;
+  if (Function->getBody(Definition)) {
+    // We are trying to instantiate a friend function specialization inside
+    // a class template, but there is already another (non-template) definition
+    // of the same function.
+    if (Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
+      InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
+      if (Inst)
+        return;  
+      
+      Diag(Function->getLocation(), diag::err_redefinition) 
+        << Function->getDeclName();
+      Diag(Definition->getLocation(), diag::note_previous_definition);
+    }
+    
+    // We have an explicit instantiation (which already occurred) and an
+    // implicit instantiation. Return without complaint.
+    return;
+  }
   
   // Find the function body that we'll be substituting.
   const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern();
@@ -2680,8 +2698,7 @@
                                             Context.getSourceManager(),
                                            "instantiating function definition");
 
-      if (!Function->getBody())
-        InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true);
+      InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true);
       continue;
     }