From b004a8e5aa700108de2acc8f81b0dd2ec7518899 Mon Sep 17 00:00:00 2001 From: Douglas Gregor <dgregor@apple.com> Date: Tue, 16 Apr 2013 16:01:32 +0000 Subject: [PATCH] Fix PR4296: Add parser detection/error recovery for nested functions, from Serve Pavlov! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179603 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticParseKinds.td | 2 + lib/Parse/ParseDecl.cpp | 47 ++++++++++++--------- test/Sema/function.c | 11 +++++ 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 788b1cf3174..277d2d7df42 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -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< diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 0094e13d4cc..47826aa3b91 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -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); + } } } diff --git a/test/Sema/function.c b/test/Sema/function.c index 1b0dc2adeb7..bbf81a56cbb 100644 --- a/test/Sema/function.c +++ b/test/Sema/function.c @@ -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; +} -- GitLab