diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 7b264d346134..ad996b7eeb5c 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -78,6 +78,8 @@ def err_expected_rparen : Error<"expected ')'">; def err_expected_rsquare : Error<"expected ']'">; def err_expected_rbrace : Error<"expected '}'">; def err_expected_greater : Error<"expected '>'">; +def err_expected_semi_declation : Error< + "expected ';' at end of declaration">; def err_expected_semi_decl_list : Error< "expected ';' at end of declaration list">; def ext_expected_semi_decl_list : Extension< diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 1f8522f094ce..5de4dd4a7c60 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -273,7 +273,30 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context) { Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context); ParseDeclarator(DeclaratorInfo); - return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); + DeclGroupPtrTy DG = + ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); + + if (Tok.is(tok::semi)) { + ConsumeToken(); + // for(is key; in keys) is error. + if (Context == Declarator::ForContext && isTokIdentifier_in()) + Diag(Tok, diag::err_parse_error); + + return DG; + } + + // If this is an ObjC2 for-each loop, this is a successful declarator + // parse. The syntax for these looks like: + // 'for' '(' declaration 'in' expr ')' statement + if (Context == Declarator::ForContext && isTokIdentifier_in()) + return DG; + + Diag(Tok, diag::err_expected_semi_declation); + // Skip to end of block or statement + SkipUntil(tok::r_brace, true, true); + if (Tok.is(tok::semi)) + ConsumeToken(); + return DG; } @@ -315,7 +338,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { SourceLocation Loc; OwningExprResult AsmLabel(ParseSimpleAsm(&Loc)); if (AsmLabel.isInvalid()) { - SkipUntil(tok::semi); + SkipUntil(tok::semi, true, true); return DeclGroupPtrTy(); } @@ -343,7 +366,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { } else { OwningExprResult Init(ParseInitializer()); if (Init.isInvalid()) { - SkipUntil(tok::semi); + SkipUntil(tok::semi, true, true); return DeclGroupPtrTy(); } Actions.AddInitializerToDecl(ThisDecl, move(Init)); @@ -400,31 +423,8 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { ParseDeclarator(D); } - if (Tok.is(tok::semi)) { - ConsumeToken(); - // for(is key; in keys) is error. - if (D.getContext() == Declarator::ForContext && isTokIdentifier_in()) { - Diag(Tok, diag::err_parse_error); - return DeclGroupPtrTy(); - } - - return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0], - DeclsInGroup.size()); - } - - // If this is an ObjC2 for-each loop, this is a successful declarator - // parse. The syntax for these looks like: - // 'for' '(' declaration 'in' expr ')' statement - if (D.getContext() == Declarator::ForContext && isTokIdentifier_in()) - return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0], - DeclsInGroup.size()); - - Diag(Tok, diag::err_parse_error); - // Skip to end of block or statement - SkipUntil(tok::r_brace, true, true); - if (Tok.is(tok::semi)) - ConsumeToken(); - return DeclGroupPtrTy(); + return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0], + DeclsInGroup.size()); } /// ParseSpecifierQualifierList diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 56f922d4005e..b34c241fd1b2 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -517,9 +517,13 @@ Parser::ParseDeclarationOrFunctionDefinition( Tok.is(tok::kw_asm) || // int X() __asm__ -> not a function def Tok.is(tok::kw___attribute) || // int X() __attr__ -> not a function def (getLang().CPlusPlus && - Tok.is(tok::l_paren)) ) { // int X(0) -> not a function def [C++] + Tok.is(tok::l_paren))) { // int X(0) -> not a function def [C++] // Parse the init-declarator-list for a normal declaration. - return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); + DeclGroupPtrTy DG = + ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); + // Eat the semi colon after the declaration. + ExpectAndConsume(tok::semi, diag::err_expected_semi_declation); + return DG; } @@ -564,7 +568,8 @@ Parser::ParseDeclarationOrFunctionDefinition( /// [C90] function-definition: [C99 6.7.1] - implicit int result /// [C90] decl-specs[opt] declarator declaration-list[opt] compound-statement /// [C++] function-definition: [C++ 8.4] -/// decl-specifier-seq[opt] declarator ctor-initializer[opt] function-body +/// decl-specifier-seq[opt] declarator ctor-initializer[opt] +/// function-body /// [C++] function-definition: [C++ 8.4] /// decl-specifier-seq[opt] declarator function-try-block [TODO] /// diff --git a/clang/test/Parser/typeof.c b/clang/test/Parser/typeof.c index 8cb16c36f2a9..76e8d479fcf6 100644 --- a/clang/test/Parser/typeof.c +++ b/clang/test/Parser/typeof.c @@ -9,8 +9,8 @@ static void test() { short typeof (int) aShortInt; // expected-error{{'short typeof' is invalid}} int int ttt; // expected-error{{cannot combine with previous 'int' declaration specifier}} typeof(TInt) anInt; - short TInt eee; // expected-error{{parse error}} - void ary[7] fff; // expected-error{{array has incomplete element type 'void'}} expected-error{{parse error}} + short TInt eee; // expected-error{{expected ';' at end of declaration}} + void ary[7] fff; // expected-error{{array has incomplete element type 'void'}} expected-error{{expected ';' at end of declaration}} typeof(void ary[7]) anIntError; // expected-error{{expected ')'}} expected-note {{to match this '('}} expected-warning {{type specifier missing, defaults to 'int'}} typeof(const int) aci; const typeof (*pi) aConstInt; diff --git a/clang/test/Sema/init.c b/clang/test/Sema/init.c index 9430f312ad68..cbf75e1bb1c6 100644 --- a/clang/test/Sema/init.c +++ b/clang/test/Sema/init.c @@ -20,7 +20,7 @@ int *h = &x; int test() { int a[10]; int b[10] = a; // expected-error {{initialization with '{...}' expected}} -int +; // expected-error {{expected identifier or '('}} expected-error {{parse error}} +int +; // expected-error {{expected identifier or '('}} expected-error {{expected ';' at end of declaration}} }