forked from OSchip/llvm-project
Fix PR4296: Add parser detection/error recovery for nested functions, from Serve Pavlov!
llvm-svn: 179603
This commit is contained in:
parent
abd62140c0
commit
012efe22bc
|
@ -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<
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue