aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-10-29 05:08:52 +0000
committerChris Lattner <sabre@nondot.org>2007-10-29 05:08:52 +0000
commitb96728d90abc35a520798066d2a75ca36400a617 (patch)
tree37118dc3718fa361c30677ba8a0b0323a5ca6a79
parent85f9bceab1542aafff012d4d28e998f4ba16e362 (diff)
improve error recovery handling broken 'then' or 'else' stmts in
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
-rw-r--r--Parse/ParseStmt.cpp37
-rw-r--r--test/Sema/if-empty-body.c7
2 files changed, 34 insertions, 10 deletions
diff --git a/Parse/ParseStmt.cpp b/Parse/ParseStmt.cpp
index 068921a616..9e18bbaebd 100644
--- a/Parse/ParseStmt.cpp
+++ b/Parse/ParseStmt.cpp
@@ -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);
}
diff --git a/test/Sema/if-empty-body.c b/test/Sema/if-empty-body.c
index 1de6ad573d..376eb9865a 100644
--- a/test/Sema/if-empty-body.c
+++ b/test/Sema/if-empty-body.c
@@ -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.
+}
+