]> granicus.if.org Git - clang/commitdiff
improve error recovery handling broken 'then' or 'else' stmts in
authorChris Lattner <sabre@nondot.org>
Mon, 29 Oct 2007 05:08:52 +0000 (05:08 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 29 Oct 2007 05:08:52 +0000 (05:08 +0000)
if statements.  This implements Sema/if-empty-body.c:f3, silencing
a bogus secondary warning.  It also improve the location info for
the nullstmts created for recovery purposes.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43440 91177308-0d34-0410-b5e6-96231b3b80d8

Parse/ParseStmt.cpp
test/Sema/if-empty-body.c

index 068921a616b1e5f47d9b56702e2dd846d1e3a037..9e18bbaebd31e47d87e556630847e72b1b60c1b9 100644 (file)
@@ -512,19 +512,18 @@ Parser::StmtResult Parser::ParseIfStatement() {
   bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
   if (NeedsInnerScope) EnterScope(Scope::DeclScope);
   
-  // Read the if condition.
-  StmtResult CondStmt = ParseStatement();
+  // Read the 'then' stmt.
+  SourceLocation ThenStmtLoc = Tok.getLocation();
+  StmtResult ThenStmt = ParseStatement();
 
-  // Broken substmt shouldn't prevent the label from being added to the AST.
-  if (CondStmt.isInvalid)
-    CondStmt = Actions.ActOnNullStmt(Tok.getLocation());
-  
   // Pop the 'if' scope if needed.
   if (NeedsInnerScope) ExitScope();
   
   // If it has an else, parse it.
   SourceLocation ElseLoc;
+  SourceLocation ElseStmtLoc;
   StmtResult ElseStmt(false);
+  
   if (Tok.is(tok::kw_else)) {
     ElseLoc = ConsumeToken();
     
@@ -535,19 +534,37 @@ Parser::StmtResult Parser::ParseIfStatement() {
     NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
     if (NeedsInnerScope) EnterScope(Scope::DeclScope);
     
+    ElseStmtLoc = Tok.getLocation();
     ElseStmt = ParseStatement();
 
     // Pop the 'else' scope if needed.
     if (NeedsInnerScope) ExitScope();
-    
-    if (ElseStmt.isInvalid)
-      ElseStmt = Actions.ActOnNullStmt(ElseLoc);
   }
   
   if (getLang().C99)
     ExitScope();
 
-  return Actions.ActOnIfStmt(IfLoc, CondExp.Val, CondStmt.Val,
+  // If the then or else stmt is invalid and the other is valid (and present),
+  // make turn the invalid one into a null stmt to avoid dropping the other 
+  // part.  If both are invalid, return error.
+  if ((ThenStmt.isInvalid && ElseStmt.isInvalid) ||
+      (ThenStmt.isInvalid && ElseStmt.Val == 0) ||
+      (ThenStmt.Val == 0  && ElseStmt.isInvalid)) {
+    // Both invalid, or one is invalid and other is non-present: delete cond and
+    // return error.
+    Actions.DeleteExpr(CondExp.Val);
+    return true;
+  }
+  
+  // Now if either are invalid, replace with a ';'.
+  if (ThenStmt.isInvalid)
+    ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
+  if (ElseStmt.isInvalid)
+    ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
+  
+  
+  
+  return Actions.ActOnIfStmt(IfLoc, CondExp.Val, ThenStmt.Val,
                              ElseLoc, ElseStmt.Val);
 }
 
index 1de6ad573d4a0b032c86e3f31b4d146ef4b0c613..376eb9865a067cc49735570061c4420400827b89 100644 (file)
@@ -7,3 +7,10 @@ void f1(int a) {
 void f2(int a) {
     if (a) {}
 }
+
+void f3() {
+  if (1)
+    xx;      // expected-error {{use of undeclared identifier}}
+  return;    // no empty body warning.
+}
+