diff --git a/clang/Parse/Parser.cpp b/clang/Parse/Parser.cpp index 860a44f9e94d76a02fafbfb8a2215bda6bd2cee0..703144b3c443b796c354ea57a93c838b0535e5fb 100644 --- a/clang/Parse/Parser.cpp +++ b/clang/Parse/Parser.cpp @@ -367,9 +367,6 @@ Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() { // Parse the common declaration-specifiers piece. DeclSpec DS; ParseDeclarationSpecifiers(DS); - // If the decl specs are invalid, there is no need to continue. - if (DS.isInvalid()) - return 0; // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' @@ -422,6 +419,20 @@ Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() { } else if (DeclaratorInfo.isFunctionDeclarator() && (Tok.is(tok::l_brace) || // int X() {} isDeclarationSpecifier())) { // int X(f) int f; {} + if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { + Diag(Tok, diag::err_function_declared_typedef); + + if (Tok.is(tok::l_brace)) { + // This recovery skips the entire function body. It would be nice + // to simply call ParseFunctionDefintion() below, however Sema + // assumes the declarator represents a function, not a typedef. + ConsumeBrace(); + SkipUntil(tok::r_brace, true); + } else { + SkipUntil(tok::semi); + } + return 0; + } return ParseFunctionDefinition(DeclaratorInfo); } else { if (DeclaratorInfo.isFunctionDeclarator()) diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 7d0e684ce7d9e67663c3e5ff3ebddca240a76dfb..1c97120a72ecb9aa51f0a8b74eafa48bfd6a2feb 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -352,6 +352,8 @@ DIAG(err_expected_semi_decl_list, ERROR, "expected ';' at end of declaration list") DIAG(ext_expected_semi_decl_list, EXTENSION, "expected ';' at end of declaration list") +DIAG(err_function_declared_typedef, ERROR, + "function definition declared 'typedef'") DIAG(err_expected_fn_body, ERROR, "expected function body after function declarator") DIAG(err_expected_after_declarator, ERROR, diff --git a/clang/test/Sema/declspec.c b/clang/test/Sema/declspec.c index fd57540681281b1188e687e515e274c9126deff5..e262b343cbb9856f45349005b3e256c8320bdbfc 100644 --- a/clang/test/Sema/declspec.c +++ b/clang/test/Sema/declspec.c @@ -5,8 +5,12 @@ T foo(int n, int m) { } // expected-error {{cannot return array or function}} void foof(const char *, ...) __attribute__((__format__(__printf__, 1, 2))), barf (void); +int typedef validTypeDecl() { } // expected-error {{function definition declared 'typedef'}} + struct _zend_module_entry { } typedef struct _zend_function_entry { } // expected-error {{cannot combine with previous 'struct' declaration specifier}} -static void buggy(int *x) { // expected-error {{cannot combine with previous 'typedef' declaration specifier}} \ - // expected-error {{cannot combine with previous 'struct' declaration specifier}} - // expected-error {{expected '}'}} +static void buggy(int *x) { } // expected-error {{function definition declared 'typedef'}} \ + // expected-error {{cannot combine with previous 'typedef' declaration specifier}} \ + // expected-error {{cannot combine with previous 'struct' declaration specifier}} + +