]> granicus.if.org Git - clang/commitdiff
Diagnose function template definitions inside functions
authorReid Kleckner <reid@kleckner.net>
Mon, 15 Dec 2014 23:16:32 +0000 (23:16 +0000)
committerReid Kleckner <reid@kleckner.net>
Mon, 15 Dec 2014 23:16:32 +0000 (23:16 +0000)
The parser can only be tricked into parsing a function template
definition by inserting a typename keyword before the function template
declaration. This used to make us crash, and now it's fixed.

While here, remove an unneeded boolean parameter from ParseDeclGroup.
This boolean always corresponded to non-typedef declarators at file
scope. ParseDeclGroup already has precise diagnostics for the function
definition typedef case, so we can let that through.

Fixes PR21839.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224287 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseTemplate.cpp
lib/Parse/Parser.cpp
test/CXX/drs/dr5xx.cpp
test/Parser/cxx-template-decl.cpp

index ba5c946d359c6d750354a129cb89bbd6b17cee18..f12bec6929e1aae04d9f542fdf9718403e76a194 100644 (file)
@@ -1728,7 +1728,6 @@ private:
                                         ForRangeInit *FRI = nullptr);
   bool MightBeDeclarator(unsigned Context);
   DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
-                                bool AllowFunctionDefinitions,
                                 SourceLocation *DeclEnd = nullptr,
                                 ForRangeInit *FRI = nullptr);
   Decl *ParseDeclarationAfterDeclarator(Declarator &D,
index 03e827e69c03e54dd3b9ad96940485db9cc9fc77..0b84f2fbbd50b97f9790d9be91acf363346c6db6 100644 (file)
@@ -1466,7 +1466,7 @@ Parser::ParseSimpleDeclaration(unsigned Context,
   }
 
   DS.takeAttributesFrom(Attrs);
-  return ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, &DeclEnd, FRI);
+  return ParseDeclGroup(DS, Context, &DeclEnd, FRI);
 }
 
 /// Returns true if this might be the start of a declarator, or a common typo
@@ -1621,7 +1621,6 @@ void Parser::SkipMalformedDecl() {
 /// result.
 Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
                                               unsigned Context,
-                                              bool AllowFunctionDefinitions,
                                               SourceLocation *DeclEnd,
                                               ForRangeInit *FRI) {
   // Parse the first declarator.
@@ -1669,7 +1668,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
       // start of a function definition in GCC-extended K&R C.
       !isDeclarationAfterDeclarator()) {
 
-    if (AllowFunctionDefinitions) {
+    // Function definitions are only allowed at file scope and in C++ classes.
+    // The C++ inline method definition case is handled elsewhere, so we only
+    // need to handle the file scope definition case.
+    if (Context == Declarator::FileContext) {
       if (isStartOfFunctionDefinition(D)) {
         if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
           Diag(Tok, diag::err_function_declared_typedef);
index ba1f98515edc4974e6cfc9caad3099ae7ee50658..53de72cd3cc5e6604851383c70e755ac6df02008 100644 (file)
@@ -231,6 +231,16 @@ Parser::ParseSingleDeclarationAfterTemplate(
 
   if (DeclaratorInfo.isFunctionDeclarator() &&
       isStartOfFunctionDefinition(DeclaratorInfo)) {
+
+    // Function definitions are only allowed at file scope and in C++ classes.
+    // The C++ inline method definition case is handled elsewhere, so we only
+    // need to handle the file scope definition case.
+    if (Context != Declarator::FileContext) {
+      Diag(Tok, diag::err_function_definition_not_allowed);
+      SkipMalformedDecl();
+      return nullptr;
+    }
+
     if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
       // Recover by ignoring the 'typedef'. This was probably supposed to be
       // the 'typename' keyword, which we should have already suggested adding
index 7119e9af7600b93b438afdc8ba66ea52275edda8..cf7c0fe32da52bd99cd87552fc6c8d5212827fff 100644 (file)
@@ -890,7 +890,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
     return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
 
-  return ParseDeclGroup(DS, Declarator::FileContext, true);
+  return ParseDeclGroup(DS, Declarator::FileContext);
 }
 
 Parser::DeclGroupPtrTy
index b0254f298ee6319bcb96d515d3516bc9ca65c6a9..5bf085f52204ad73d064555795ff5c2e0be8bf56 100644 (file)
@@ -798,7 +798,7 @@ namespace dr575 { // dr575: yes
 }
 
 namespace dr576 { // dr576: yes
-  typedef void f() {} // expected-error {{function definition is not allowed}}
+  typedef void f() {} // expected-error {{function definition declared 'typedef'}}
   void f(typedef int n); // expected-error {{invalid storage class}}
   void f(char c) { typedef int n; }
 }
index bce1b7cbdeb81818a8974f940c995ac6d3ef79fe..efa42ad30d049715d6c74a3ced860cfc3ff61a4f 100644 (file)
@@ -211,6 +211,19 @@ void Instantiate() {
 
 }
 
+namespace func_tmpl_spec_def_in_func {
+// We failed to diagnose function template specialization definitions inside
+// functions during recovery previously.
+template <class> void FuncTemplate() {}
+void TopLevelFunc() {
+  // expected-error@+2 {{expected a qualified name after 'typename'}}
+  // expected-error@+1 {{function definition is not allowed here}}
+  typename template <> void FuncTemplate<void>() { }
+  // expected-error@+1 {{function definition is not allowed here}}
+  void NonTemplateInner() { }
+}
+}
+
 namespace broken_baseclause {
 template<typename T>
 struct base { };