diff options
author | Chris Lattner <sabre@nondot.org> | 2008-12-12 06:19:11 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-12-12 06:19:11 +0000 |
commit | bc2d77cdf232ac0cda7ba5cf100582f4613d628e (patch) | |
tree | e27136bf3755e91b8a70529a1421b62f4a4175dc /clang/lib/Parse/ParseStmt.cpp | |
parent | d8980509b34da2399b197fc0bd01cd20ee16918b (diff) | |
download | bcm5719-llvm-bc2d77cdf232ac0cda7ba5cf100582f4613d628e.tar.gz bcm5719-llvm-bc2d77cdf232ac0cda7ba5cf100582f4613d628e.zip |
merge recovery-2.c into recovery-3.c.
Substantially improve error recovery after broken if conditions by
parsing the full if when we have a semantic error instead of using
parser recovery techniques to recover from a semantic error.
This fixes rdar://6094870 - spurious error after invalid 'if' condition
llvm-svn: 60929
Diffstat (limited to 'clang/lib/Parse/ParseStmt.cpp')
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index bde4a502178..263079f1380 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -448,20 +448,28 @@ Parser::OwningStmtResult Parser::ParseIfStatement() { ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX); // Parse the condition. + SourceLocation LParenLoc = ConsumeParen(); + OwningExprResult CondExp(Actions); - if (getLang().CPlusPlus) { - SourceLocation LParenLoc = ConsumeParen(); + if (getLang().CPlusPlus) CondExp = ParseCXXCondition(); - MatchRHSPunctuation(tok::r_paren, LParenLoc); - } else { - CondExp = ParseSimpleParenExpression(); - } - - if (CondExp.isInvalid()) { + else + CondExp = ParseExpression(); + + // If the parser was confused by the condition and we don't have a ')', try to + // recover by skipping ahead to a semi and bailing out. If condexp is + // semantically invalid but we have well formed code, keep going. + if (CondExp.isInvalid() && Tok.isNot(tok::r_paren)) { SkipUntil(tok::semi); - return StmtError(); + // Skipping may have stopped if it found the containing ')'. If so, we can + // continue parsing the if statement. + if (Tok.isNot(tok::r_paren)) + return StmtError(); } + // Otherwise the condition is valid or the rparen is present. + MatchRHSPunctuation(tok::r_paren, LParenLoc); + // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -521,6 +529,11 @@ Parser::OwningStmtResult Parser::ParseIfStatement() { } IfScope.Exit(); + + // If the condition was invalid, discard the if statement. We could recover + // better by replacing it with a valid expr, but don't do that yet. + if (CondExp.isInvalid()) + return StmtError(); // 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 |