summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-05-17 17:34:56 +0000
committerDouglas Gregor <dgregor@apple.com>2010-05-17 17:34:56 +0000
commit69f6a365d3b42c2d7e39de0d601acfad62173ad1 (patch)
treeb87b05832dc18cd729962c7273bb2992fc781083 /clang/lib
parent176a9c4272ea29598cb96622f19fb3f38b895031 (diff)
downloadbcm5719-llvm-69f6a365d3b42c2d7e39de0d601acfad62173ad1.tar.gz
bcm5719-llvm-69f6a365d3b42c2d7e39de0d601acfad62173ad1.zip
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. llvm-svn: 103948
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp5
-rw-r--r--clang/lib/Sema/SemaExpr.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp25
3 files changed, 24 insertions, 8 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 28332bdb9ab..535bd341794 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1219,9 +1219,8 @@ FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD,
}
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()) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b573e2dcc94..5af5585f7f8 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7527,7 +7527,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
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()) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 41c62186640..31284071ff6 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1983,11 +1983,29 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
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 @@ void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) {
Context.getSourceManager(),
"instantiating function definition");
- if (!Function->getBody())
- InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true);
+ InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true);
continue;
}
OpenPOWER on IntegriCloud