[cfe-commits] r103948 - in /cfe/trunk: lib/AST/Decl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.decls/temp.friend/p4.cpp
Douglas Gregor
dgregor at apple.com
Mon May 17 10:34:56 PDT 2010
Author: dgregor
Date: Mon May 17 12:34:56 2010
New Revision: 103948
URL: http://llvm.org/viewvc/llvm-project?rev=103948&view=rev
Log:
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.
Modified:
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p4.cpp
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=103948&r1=103947&r2=103948&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Mon May 17 12:34:56 2010
@@ -1219,9 +1219,8 @@
}
bool FunctionDecl::isImplicitlyInstantiable() const {
- // If this function already has a definition or is invalid, it can't be
- // implicitly instantiated.
- if (isInvalidDecl() || getBody())
+ // If the function is invalid, it can't be implicitly instantiated.
+ if (isInvalidDecl())
return false;
switch (getTemplateSpecializationKind()) {
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=103948&r1=103947&r2=103948&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon May 17 12:34:56 2010
@@ -7527,7 +7527,7 @@
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// Implicit instantiation of function templates and member functions of
// class templates.
- if (!Function->getBody() && Function->isImplicitlyInstantiable()) {
+ if (Function->isImplicitlyInstantiable()) {
bool AlreadyInstantiated = false;
if (FunctionTemplateSpecializationInfo *SpecInfo
= Function->getTemplateSpecializationInfo()) {
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=103948&r1=103947&r2=103948&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon May 17 12:34:56 2010
@@ -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;
}
Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p4.cpp?rev=103948&r1=103947&r2=103948&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p4.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p4.cpp Mon May 17 12:34:56 2010
@@ -7,3 +7,34 @@
X<int> xi; // expected-note{{in instantiation of member function 'f' requested here}}
+void f0(double) { }
+void f0(int) { } // expected-note{{previous definition}}
+void f1(int) { } // expected-note{{previous definition}}
+void f2(int);
+void f3(int);
+
+template<typename T>
+struct X1 {
+ friend void f0(T) { } // expected-error{{redefinition of}}
+ friend void f1(T) { } // expected-error{{redefinition of}}
+ friend void f2(T) { } // expected-error{{redefinition of}}
+ friend void f3(T) { } // expected-error{{redefinition of}}
+ friend void f4(T) { } // expected-error{{redefinition of}}
+ friend void f5(T) { } // expected-error{{redefinition of}}
+
+ // FIXME: should have a redefinition error for f6(int)
+ friend void f6(int) { }
+};
+
+void f2(int) { } // expected-note{{previous definition}}
+void f4(int) { } // expected-note{{previous definition}}
+
+X1<int> x1a; // expected-note 6{{in instantiation of}}
+
+void f3(int) { } // expected-note{{previous definition}}
+void f5(int) { } // expected-note{{previous definition}}
+
+X1<float> x1b;
+
+
+X1<double> *X0d() { return 0;}
More information about the cfe-commits
mailing list