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