apply the new error recovery smarts we have for if's to while's and switch's.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60932 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 263079f..45092aa 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -414,6 +414,42 @@
Stmts.size(), isStmtExpr));
}
+/// ParseParenExprOrCondition:
+/// [C ] '(' expression ')'
+/// [C++] '(' condition ')'
+///
+/// This function parses and performs error recovery on the specified condition
+/// or expression (depending on whether we're in C++ or C mode). This function
+/// goes out of its way to recover well. It returns true if there was a parser
+/// error (the right paren couldn't be found), which indicates that the caller
+/// should try to recover harder. It returns false if the condition is
+/// successfully parsed. Note that a successful parse can still have semantic
+/// errors in the condition.
+bool Parser::ParseParenExprOrCondition(OwningExprResult &CondExp) {
+ SourceLocation LParenLoc = ConsumeParen();
+
+ if (getLang().CPlusPlus)
+ CondExp = ParseCXXCondition();
+ 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);
+ // 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 true;
+ }
+
+ // Otherwise the condition is valid or the rparen is present.
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ return false;
+}
+
+
/// ParseIfStatement
/// if-statement: [C99 6.8.4.1]
/// 'if' '(' expression ')' statement
@@ -448,27 +484,9 @@
ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
// Parse the condition.
- SourceLocation LParenLoc = ConsumeParen();
-
OwningExprResult CondExp(Actions);
- if (getLang().CPlusPlus)
- CondExp = ParseCXXCondition();
- 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);
- // 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);
+ if (ParseParenExprOrCondition(CondExp))
+ return StmtError();
// 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
@@ -583,24 +601,16 @@
// while, for, and switch statements are local to the if, while, for, or
// switch statement (including the controlled statement).
//
- unsigned ScopeFlags
- = C99orCXX? Scope::BreakScope | Scope::DeclScope | Scope::ControlScope
- : Scope::BreakScope;
+ unsigned ScopeFlags = Scope::BreakScope;
+ if (C99orCXX)
+ ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
ParseScope SwitchScope(this, ScopeFlags);
// Parse the condition.
OwningExprResult Cond(Actions);
- if (getLang().CPlusPlus) {
- SourceLocation LParenLoc = ConsumeParen();
- Cond = ParseCXXCondition();
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
- } else {
- Cond = ParseSimpleParenExpression();
- }
-
- if (Cond.isInvalid())
+ if (ParseParenExprOrCondition(Cond))
return StmtError();
-
+
OwningStmtResult Switch(Actions,
Actions.ActOnStartOfSwitchStmt(Cond.release()));
@@ -631,6 +641,9 @@
SwitchScope.Exit();
+ if (Cond.isInvalid())
+ return StmtError();
+
return Owned(Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.release(),
Body.release()));
}
@@ -674,13 +687,8 @@
// Parse the condition.
OwningExprResult Cond(Actions);
- if (getLang().CPlusPlus) {
- SourceLocation LParenLoc = ConsumeParen();
- Cond = ParseCXXCondition();
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
- } else {
- Cond = ParseSimpleParenExpression();
- }
+ if (ParseParenExprOrCondition(Cond))
+ return StmtError();
// C99 6.8.5p5 - 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
@@ -871,8 +879,7 @@
if (Tok.is(tok::semi)) { // for (...;;
// no second part.
} else {
- SecondPart = getLang().CPlusPlus ? ParseCXXCondition()
- : ParseExpression();
+ SecondPart =getLang().CPlusPlus ? ParseCXXCondition() : ParseExpression();
}
if (Tok.is(tok::semi)) {