diff options
author | Francois Pichet <pichet2000@gmail.com> | 2011-04-22 23:20:44 +0000 |
---|---|---|
committer | Francois Pichet <pichet2000@gmail.com> | 2011-04-22 23:20:44 +0000 |
commit | d4a0caf78e7c18e7aca65fbfd799a6c024ff51fb (patch) | |
tree | e0c749c65c3d296353cb862f69c8934d5576e9d8 | |
parent | b464a5b18916b467ed884d07f9e34295d39cec0a (diff) |
Correctly emit a diagnostic for multiple templated function definitions in -flate-template-parsing mode.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130030 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Sema/Sema.h | 1 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 36 | ||||
-rw-r--r-- | test/Parser/DelayedTemplateParsing.cpp | 17 |
5 files changed, 35 insertions, 21 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index b1746ac308..3694d7e354 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -889,6 +889,7 @@ public: bool TypeMayContainAuto = true); void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls); + void CheckForFunctionRedefinition(FunctionDecl *FD); Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D); Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D); void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 778aa11087..c02d75c37f 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -65,6 +65,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, FD = FunTmpl->getTemplatedDecl(); else FD = cast<FunctionDecl>(FnD); + Actions.CheckForFunctionRedefinition(FD);
LateParsedTemplateMap[FD] = LPT; Actions.MarkAsLateParsedTemplate(FD); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 6522306dce..e0f7852e3c 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -821,6 +821,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, FnD = FunTmpl->getTemplatedDecl(); else FnD = cast<FunctionDecl>(DP); + Actions.CheckForFunctionRedefinition(FnD); LateParsedTemplateMap[FnD] = LPT; Actions.MarkAsLateParsedTemplate(FnD); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2abc6dafa8..b1d9bc2c8e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5729,6 +5729,22 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { return MissingPrototype; } +void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) { + // Don't complain if we're in GNU89 mode and the previous definition + // was an extern inline function. + const FunctionDecl *Definition; + if (FD->hasBody(Definition) && + !canRedefineFunction(Definition, getLangOptions())) { + if (getLangOptions().GNUMode && Definition->isInlineSpecified() && + Definition->getStorageClass() == SC_Extern) + Diag(FD->getLocation(), diag::err_redefinition_extern_inline) + << FD->getDeclName() << getLangOptions().CPlusPlus; + else + Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); + Diag(Definition->getLocation(), diag::note_previous_definition); + } +} + Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // Clear the last template instantiation error context. LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation(); @@ -5746,24 +5762,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { PushFunctionScope(); // See if this is a redefinition. - // But don't complain if we're in GNU89 mode and the previous definition - // was an extern inline function. - - // FIXME: This code doesn't complain about multiple definition for late - // parsed template function. - bool IsLateParsingRedefinition = LateTemplateParser && - FD->isLateTemplateParsed(); - const FunctionDecl *Definition; - if (FD->hasBody(Definition) && !IsLateParsingRedefinition && - !canRedefineFunction(Definition, getLangOptions())) { - if (getLangOptions().GNUMode && Definition->isInlineSpecified() && - Definition->getStorageClass() == SC_Extern) - Diag(FD->getLocation(), diag::err_redefinition_extern_inline) - << FD->getDeclName() << getLangOptions().CPlusPlus; - else - Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); - Diag(Definition->getLocation(), diag::note_previous_definition); - } + if (!FD->isLateTemplateParsed()) + CheckForFunctionRedefinition(FD); // Builtin functions cannot be defined. if (unsigned BuiltinID = FD->getBuiltinID()) { diff --git a/test/Parser/DelayedTemplateParsing.cpp b/test/Parser/DelayedTemplateParsing.cpp index 355250e4b0..50cf7412cc 100644 --- a/test/Parser/DelayedTemplateParsing.cpp +++ b/test/Parser/DelayedTemplateParsing.cpp @@ -2,14 +2,23 @@ template <class T>
class A {
-
void foo() {
undeclared();
}
-
- void foo2();
+ void foo2();
+};
+
+template <class T>
+class B {
+ void foo4() { } // expected-note {{previous definition is here}} expected-note {{previous definition is here}}
+ void foo4() { } // expected-error {{class member cannot be redeclared}} expected-error {{redefinition of 'foo4'}} expected-note {{previous definition is here}}
};
+
+template <class T>
+void B<T>::foo4() {// expected-error {{redefinition of 'foo4'}}
+}
+
template <class T>
void A<T>::foo2() {
undeclared();
@@ -29,3 +38,5 @@ void undeclared() }
+template <class T> void foo5() {} //expected-note {{previous definition is here}}
+template <class T> void foo5() {} // expected-error {{redefinition of 'foo5'}}
|