r224287 - Diagnose function template definitions inside functions

Reid Kleckner reid at kleckner.net
Mon Dec 15 15:16:32 PST 2014


Author: rnk
Date: Mon Dec 15 17:16:32 2014
New Revision: 224287

URL: http://llvm.org/viewvc/llvm-project?rev=224287&view=rev
Log:
Diagnose function template definitions inside functions

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.

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

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=224287&r1=224286&r2=224287&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Dec 15 17:16:32 2014
@@ -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,

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=224287&r1=224286&r2=224287&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Dec 15 17:16:32 2014
@@ -1466,7 +1466,7 @@ Parser::ParseSimpleDeclaration(unsigned
   }
 
   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::ParseDecl
       // 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);

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=224287&r1=224286&r2=224287&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Mon Dec 15 17:16:32 2014
@@ -231,6 +231,16 @@ Parser::ParseSingleDeclarationAfterTempl
 
   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

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=224287&r1=224286&r2=224287&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Dec 15 17:16:32 2014
@@ -890,7 +890,7 @@ Parser::ParseDeclOrFunctionDefInternal(P
     return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
 
-  return ParseDeclGroup(DS, Declarator::FileContext, true);
+  return ParseDeclGroup(DS, Declarator::FileContext);
 }
 
 Parser::DeclGroupPtrTy

Modified: cfe/trunk/test/CXX/drs/dr5xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr5xx.cpp?rev=224287&r1=224286&r2=224287&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr5xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr5xx.cpp Mon Dec 15 17:16:32 2014
@@ -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; }
 }

Modified: cfe/trunk/test/Parser/cxx-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-decl.cpp?rev=224287&r1=224286&r2=224287&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Mon Dec 15 17:16:32 2014
@@ -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 at +2 {{expected a qualified name after 'typename'}}
+  // expected-error at +1 {{function definition is not allowed here}}
+  typename template <> void FuncTemplate<void>() { }
+  // expected-error at +1 {{function definition is not allowed here}}
+  void NonTemplateInner() { }
+}
+}
+
 namespace broken_baseclause {
 template<typename T>
 struct base { };





More information about the cfe-commits mailing list