From: Chris Lattner Date: Thu, 13 Nov 2008 18:52:53 +0000 (+0000) Subject: Fix a couple of suboptimalities in error recovery. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=195044028b76133e2a1f245b094468fe07db7330;p=clang Fix a couple of suboptimalities in error recovery. 1. In the top level of ParseStatementOrDeclaration, don't eat a } if we just parsed a statement if it list there. Also, don't even bother emitting an error about a missing semicolon if the statement had a bug (an rbrace is fine). 2. In do/while parsing, don't require a 'while' to be present if the do body didn't parse. This allows us to generate a clean diagnostic for this code: t.c:1:22: error: expected expression void foo (void) { do . while (0); } ^ Thanks to Neil for pointing this out. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59256 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index f5cdfffba5..30c62e3a3c 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -170,9 +170,10 @@ Parser::StmtResult Parser::ParseStatementOrDeclaration(bool OnlyStatement) { // If we reached this code, the statement must end in a semicolon. if (Tok.is(tok::semi)) { ConsumeToken(); - } else { + } else if (!Res.isInvalid) { Diag(Tok, diag::err_expected_semi_after, SemiError); - SkipUntil(tok::semi); + // Skip until we see a } or ;, but don't eat it. + SkipUntil(tok::r_brace, true, true); } return Res; } @@ -717,8 +718,8 @@ Parser::StmtResult Parser::ParseDoStatement() { // The substatement in an iteration-statement implicitly defines a local scope // which is entered and exited each time through the loop. // - bool NeedsInnerScope = (getLang().C99 || getLang().CPlusPlus) && - Tok.isNot(tok::l_brace); + bool NeedsInnerScope = + (getLang().C99 || getLang().CPlusPlus) && Tok.isNot(tok::l_brace); if (NeedsInnerScope) EnterScope(Scope::DeclScope); // Read the body statement. @@ -729,9 +730,11 @@ Parser::StmtResult Parser::ParseDoStatement() { if (Tok.isNot(tok::kw_while)) { ExitScope(); - Diag(Tok, diag::err_expected_while); - Diag(DoLoc, diag::err_matching, "do"); - SkipUntil(tok::semi); + if (!Body.isInvalid) { + Diag(Tok, diag::err_expected_while); + Diag(DoLoc, diag::err_matching, "do"); + SkipUntil(tok::semi, false, true); + } return true; } SourceLocation WhileLoc = ConsumeToken(); @@ -739,7 +742,7 @@ Parser::StmtResult Parser::ParseDoStatement() { if (Tok.isNot(tok::l_paren)) { ExitScope(); Diag(Tok, diag::err_expected_lparen_after, "do/while"); - SkipUntil(tok::semi); + SkipUntil(tok::semi, false, true); return true; } diff --git a/test/Parser/statements.c b/test/Parser/statements.c index db2ec628ee..26b26624da 100644 --- a/test/Parser/statements.c +++ b/test/Parser/statements.c @@ -47,3 +47,10 @@ void test5() { if (0); // expected-warning {{if statement has empty body}} } + +void test6(void) { + do + . // expected-error {{expected expression}} + while (0); +} +