]> granicus.if.org Git - clang/commitdiff
Correctly emit a diagnostic for multiple templated function definitions in -flate...
authorFrancois Pichet <pichet2000@gmail.com>
Fri, 22 Apr 2011 23:20:44 +0000 (23:20 +0000)
committerFrancois Pichet <pichet2000@gmail.com>
Fri, 22 Apr 2011 23:20:44 +0000 (23:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130030 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Parse/ParseCXXInlineMethods.cpp
lib/Parse/Parser.cpp
lib/Sema/SemaDecl.cpp
test/Parser/DelayedTemplateParsing.cpp

index b1746ac308805a275b5353f6c986177347f35d9c..3694d7e35418512cf989e29f35dba8ea3d6b0d51 100644 (file)
@@ -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);
index 778aa11087229e56ef82b68f46091348bf9eb5d5..c02d75c37f84d32738990d7f6bfb312eaaaecb3f 100644 (file)
@@ -65,6 +65,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
         FD = FunTmpl->getTemplatedDecl();
       else
         FD = cast<FunctionDecl>(FnD);
+      Actions.CheckForFunctionRedefinition(FD);\r
 
       LateParsedTemplateMap[FD] = LPT;
       Actions.MarkAsLateParsedTemplate(FD);
index 6522306dce23a27cad0d2d9b7a3e81cc13b0b0d6..e0f7852e3c70a2722b8b19c3811be9b48e2fa0b4 100644 (file)
@@ -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);
index 2abc6dafa854c1854ad1bb3f7200fab69a38e4a2..b1d9bc2c8efab48d573ee8dd32d9f7894b733291 100644 (file)
@@ -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()) {
index 355250e4b04a61af0f3f5ae6ca93c0218f2773fb..50cf7412cc423d43ac064d57318f503ec0a92fa2 100644 (file)
@@ -2,14 +2,23 @@
 \r
 template <class T>\r
 class A {\r
-\r
    void foo() {\r
        undeclared();\r
    }\r
-   \r
-   void foo2();\r
+      void foo2();\r
+};\r
+\r
+template <class T>\r
+class B {\r
+   void foo4() { } // expected-note {{previous definition is here}}  expected-note {{previous definition is here}}\r
+   void foo4() { } // expected-error {{class member cannot be redeclared}} expected-error {{redefinition of 'foo4'}}  expected-note {{previous definition is here}}\r
 };\r
 \r
+\r
+template <class T>\r
+void B<T>::foo4() {// expected-error {{redefinition of 'foo4'}}\r
+}\r
+\r
 template <class T>\r
 void A<T>::foo2() {\r
     undeclared();\r
@@ -29,3 +38,5 @@ void undeclared()
 \r
 }\r
 \r
+template <class T> void foo5() {} //expected-note {{previous definition is here}} \r
+template <class T> void foo5() {} // expected-error {{redefinition of 'foo5'}}\r