diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-05-17 17:34:56 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-05-17 17:34:56 +0000 |
| commit | 69f6a365d3b42c2d7e39de0d601acfad62173ad1 (patch) | |
| tree | b87b05832dc18cd729962c7273bb2992fc781083 /clang/lib | |
| parent | 176a9c4272ea29598cb96622f19fb3f38b895031 (diff) | |
| download | bcm5719-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.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 25 |
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; } |

