Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 06b9847

Browse files
committed
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224287 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 2931d65 commit 06b9847

File tree

6 files changed

+30
-6
lines changed

6 files changed

+30
-6
lines changed

include/clang/Parse/Parser.h

-1
Original file line numberDiff line numberDiff line change
@@ -1728,7 +1728,6 @@ class Parser : public CodeCompletionHandler {
17281728
ForRangeInit *FRI = nullptr);
17291729
bool MightBeDeclarator(unsigned Context);
17301730
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
1731-
bool AllowFunctionDefinitions,
17321731
SourceLocation *DeclEnd = nullptr,
17331732
ForRangeInit *FRI = nullptr);
17341733
Decl *ParseDeclarationAfterDeclarator(Declarator &D,

lib/Parse/ParseDecl.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,7 @@ Parser::ParseSimpleDeclaration(unsigned Context,
14661466
}
14671467

14681468
DS.takeAttributesFrom(Attrs);
1469-
return ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false, &DeclEnd, FRI);
1469+
return ParseDeclGroup(DS, Context, &DeclEnd, FRI);
14701470
}
14711471

14721472
/// Returns true if this might be the start of a declarator, or a common typo
@@ -1621,7 +1621,6 @@ void Parser::SkipMalformedDecl() {
16211621
/// result.
16221622
Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
16231623
unsigned Context,
1624-
bool AllowFunctionDefinitions,
16251624
SourceLocation *DeclEnd,
16261625
ForRangeInit *FRI) {
16271626
// Parse the first declarator.
@@ -1669,7 +1668,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
16691668
// start of a function definition in GCC-extended K&R C.
16701669
!isDeclarationAfterDeclarator()) {
16711670

1672-
if (AllowFunctionDefinitions) {
1671+
// Function definitions are only allowed at file scope and in C++ classes.
1672+
// The C++ inline method definition case is handled elsewhere, so we only
1673+
// need to handle the file scope definition case.
1674+
if (Context == Declarator::FileContext) {
16731675
if (isStartOfFunctionDefinition(D)) {
16741676
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
16751677
Diag(Tok, diag::err_function_declared_typedef);

lib/Parse/ParseTemplate.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,16 @@ Parser::ParseSingleDeclarationAfterTemplate(
231231

232232
if (DeclaratorInfo.isFunctionDeclarator() &&
233233
isStartOfFunctionDefinition(DeclaratorInfo)) {
234+
235+
// Function definitions are only allowed at file scope and in C++ classes.
236+
// The C++ inline method definition case is handled elsewhere, so we only
237+
// need to handle the file scope definition case.
238+
if (Context != Declarator::FileContext) {
239+
Diag(Tok, diag::err_function_definition_not_allowed);
240+
SkipMalformedDecl();
241+
return nullptr;
242+
}
243+
234244
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
235245
// Recover by ignoring the 'typedef'. This was probably supposed to be
236246
// the 'typename' keyword, which we should have already suggested adding

lib/Parse/Parser.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
890890
return Actions.ConvertDeclToDeclGroup(TheDecl);
891891
}
892892

893-
return ParseDeclGroup(DS, Declarator::FileContext, true);
893+
return ParseDeclGroup(DS, Declarator::FileContext);
894894
}
895895

896896
Parser::DeclGroupPtrTy

test/CXX/drs/dr5xx.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ namespace dr575 { // dr575: yes
798798
}
799799

800800
namespace dr576 { // dr576: yes
801-
typedef void f() {} // expected-error {{function definition is not allowed}}
801+
typedef void f() {} // expected-error {{function definition declared 'typedef'}}
802802
void f(typedef int n); // expected-error {{invalid storage class}}
803803
void f(char c) { typedef int n; }
804804
}

test/Parser/cxx-template-decl.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,19 @@ void Instantiate() {
211211

212212
}
213213

214+
namespace func_tmpl_spec_def_in_func {
215+
// We failed to diagnose function template specialization definitions inside
216+
// functions during recovery previously.
217+
template <class> void FuncTemplate() {}
218+
void TopLevelFunc() {
219+
// expected-error@+2 {{expected a qualified name after 'typename'}}
220+
// expected-error@+1 {{function definition is not allowed here}}
221+
typename template <> void FuncTemplate<void>() { }
222+
// expected-error@+1 {{function definition is not allowed here}}
223+
void NonTemplateInner() { }
224+
}
225+
}
226+
214227
namespace broken_baseclause {
215228
template<typename T>
216229
struct base { };

0 commit comments

Comments
 (0)