From bc2d77cdf232ac0cda7ba5cf100582f4613d628e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 12 Dec 2008 06:19:11 +0000 Subject: 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 --- clang/lib/Parse/ParseStmt.cpp | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'clang/lib/Parse/ParseStmt.cpp') 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 -- cgit v1.2.3