Fix PR4296: Add parser detection/error recovery for nested functions, from Serve Pavlov!

llvm-svn: 179603
This commit is contained in:
Douglas Gregor 2013-04-16 16:01:32 +00:00
parent abd62140c0
commit 012efe22bc
3 changed files with 40 additions and 20 deletions

View File

@ -352,6 +352,8 @@ def warn_cxx98_compat_static_assert : Warning<
InGroup<CXX98Compat>, DefaultIgnore;
def err_paren_after_colon_colon : Error<
"unexpected parenthesis after '::'">;
def err_function_definition_not_allowed : Error<
"function definition is not allowed here">;
/// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error<

View File

@ -1591,35 +1591,42 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
MaybeParseGNUAttributes(D, &LateParsedAttrs);
// Check to see if we have a function *definition* which must have a body.
if (AllowFunctionDefinitions && D.isFunctionDeclarator() &&
if (D.isFunctionDeclarator() &&
// Look at the next token to make sure that this isn't a function
// declaration. We have to check this because __attribute__ might be the
// start of a function definition in GCC-extended K&R C.
!isDeclarationAfterDeclarator()) {
if (isStartOfFunctionDefinition(D)) {
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
Diag(Tok, diag::err_function_declared_typedef);
if (AllowFunctionDefinitions) {
if (isStartOfFunctionDefinition(D)) {
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
Diag(Tok, diag::err_function_declared_typedef);
// Recover by treating the 'typedef' as spurious.
DS.ClearStorageClassSpecs();
// Recover by treating the 'typedef' as spurious.
DS.ClearStorageClassSpecs();
}
Decl *TheDecl =
ParseFunctionDefinition(D, ParsedTemplateInfo(), &LateParsedAttrs);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
Decl *TheDecl =
ParseFunctionDefinition(D, ParsedTemplateInfo(), &LateParsedAttrs);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
if (isDeclarationSpecifier()) {
// If there is an invalid declaration specifier right after the function
// prototype, then we must be in a missing semicolon case where this isn't
// actually a body. Just fall through into the code that handles it as a
// prototype, and let the top-level code handle the erroneous declspec
// where it would otherwise expect a comma or semicolon.
if (isDeclarationSpecifier()) {
// If there is an invalid declaration specifier right after the function
// prototype, then we must be in a missing semicolon case where this isn't
// actually a body. Just fall through into the code that handles it as a
// prototype, and let the top-level code handle the erroneous declspec
// where it would otherwise expect a comma or semicolon.
} else {
Diag(Tok, diag::err_expected_fn_body);
SkipUntil(tok::semi);
return DeclGroupPtrTy();
}
} else {
Diag(Tok, diag::err_expected_fn_body);
SkipUntil(tok::semi);
return DeclGroupPtrTy();
if (Tok.is(tok::l_brace)) {
Diag(Tok, diag::err_function_definition_not_allowed);
SkipUntil(tok::r_brace, true, true);
}
}
}

View File

@ -92,3 +92,14 @@ void t20(int i...) { } // expected-error {{requires a comma}}
int n;
void t21(int n, int (*array)[n]);
int func_e(int x) {
int func_n(int y) { // expected-error {{function definition is not allowed here}}
if (y > 22) {
return y+2;
} else {
return y-2;
}
}
return x + 3;
}