diff --git a/clang/Parse/ParseStmt.cpp b/clang/Parse/ParseStmt.cpp index dfedc9da7576..4f176386ce86 100644 --- a/clang/Parse/ParseStmt.cpp +++ b/clang/Parse/ParseStmt.cpp @@ -76,10 +76,23 @@ ParseNextStatement: // the token to end in a semicolon (in which case SemiError should be set), // or they directly 'return;' if not. switch (Tok.getKind()) { + case tok::identifier: // C99 6.8.1: labeled-statement + // identifier ':' statement + // declaration (if !OnlyStatement) + // expression[opt] ';' + return ParseIdentifierStatement(OnlyStatement); + default: - Diag(Tok, OnlyStatement ? diag::err_expected_statement : - diag::err_expected_statement_declaration); - SkipUntil(tok::semi); + if (!OnlyStatement && isDeclarationSpecifier()) { + // TODO: warn/disable if declaration is in the middle of a block and !C99. + ParseDeclaration(Declarator::BlockContext); + return; + } else if (Tok.getKind() == tok::r_brace) { + Diag(Tok, diag::err_expected_statement); + } else { + // expression[opt] ';' + ParseExpression(); + } return; case tok::kw_case: // C99 6.8.1: labeled-statement @@ -140,8 +153,6 @@ ParseNextStatement: ParseReturnStatement(); SemiError = "return statement"; break; - - // TODO: Handle OnlyStatement.. } // If we reached this code, the statement must end in a semicolon. @@ -153,6 +164,17 @@ ParseNextStatement: } } +/// ParseIdentifierStatement - Because we don't have two-token lookahead, we +/// have a bit of a quandry here. Reading the identifier is necessary to see if +/// there is a ':' after it. If there is, this is a label, regardless of what +/// else the identifier can mean. If not, this is either part of a declaration +/// (if the identifier is a type-name) or part of an expression. +void Parser::ParseIdentifierStatement(bool OnlyStatement) { + + assert(0); + +} + /// ParseCaseStatement /// labeled-statement: /// 'case' constant-expression ':' statement diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 9d9d73c1d0da..97cf5e79863d 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -278,8 +278,6 @@ DIAG(err_expected_after_declarator, ERROR, "expected '=', ',', ';', 'asm', or '__attribute__' after declarator") DIAG(err_expected_statement, ERROR, "expected statement") -DIAG(err_expected_statement_declaration, ERROR, - "expected statement or declaration") DIAG(err_expected_lparen_after, ERROR, "expected '(' after '%s'") DIAG(err_expected_while, ERROR, diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 6424e825ec76..b476867707b2 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -160,6 +160,7 @@ private: // C99 6.8: Statements and Blocks. void ParseStatement() { ParseStatementOrDeclaration(true); } void ParseStatementOrDeclaration(bool OnlyStatement = false); + void ParseIdentifierStatement(bool OnlyStatement); void ParseCaseStatement(); void ParseDefaultStatement(); void ParseCompoundStatement(); diff --git a/clang/test/Parser/statements.c b/clang/test/Parser/statements.c index 8c48d58b5704..729fe31b6bff 100644 --- a/clang/test/Parser/statements.c +++ b/clang/test/Parser/statements.c @@ -29,3 +29,11 @@ int test3() { ; } } + +int test4() { + if (0); + + int X; // declaration in a block. + + if (0); +}