]> granicus.if.org Git - clang/commitdiff
Fix a couple of suboptimalities in error recovery.
authorChris Lattner <sabre@nondot.org>
Thu, 13 Nov 2008 18:52:53 +0000 (18:52 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 13 Nov 2008 18:52:53 +0000 (18:52 +0000)
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

lib/Parse/ParseStmt.cpp
test/Parser/statements.c

index f5cdfffba50673e13d3cf6a5ed66606de4b0c3f9..30c62e3a3cd3fceaa710394aa163df1309d3a448 100644 (file)
@@ -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;
   }
   
index db2ec628ee9a9ddf68fcc429ed26b2ccaa664153..26b26624da12ec0db394c99021816e3a3722af8e 100644 (file)
@@ -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);
+}
+