aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-12-12 06:31:07 +0000
committerChris Lattner <sabre@nondot.org>2008-12-12 06:31:07 +0000
commit15ff1110c96a26c9315142d407c1f29d86a5ad1f (patch)
treed4214e70592b11d1c597f7b12c3241f27acddd75
parenta9053e02ce56d89369c607573f9b71e8122e2921 (diff)
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
-rw-r--r--include/clang/Parse/Parser.h2
-rw-r--r--lib/Parse/ParseStmt.cpp91
2 files changed, 51 insertions, 42 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 73872913df..bb0a76e4ea 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -522,6 +522,7 @@ private:
TypeTy *CastTy;
return ParseParenExpression(Op, CastTy, RParenLoc);
}
+
OwningExprResult ParseStringLiteralExpression();
//===--------------------------------------------------------------------===//
@@ -639,6 +640,7 @@ private:
OwningStmtResult ParseDefaultStatement();
OwningStmtResult ParseCompoundStatement(bool isStmtExpr = false);
OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
+ bool ParseParenExprOrCondition(OwningExprResult &CondExp);
OwningStmtResult ParseIfStatement();
OwningStmtResult ParseSwitchStatement();
OwningStmtResult ParseWhileStatement();
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 263079f138..45092aa612 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -414,6 +414,42 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
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 @@ Parser::OwningStmtResult Parser::ParseIfStatement() {
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 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement() {
// 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 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement() {
SwitchScope.Exit();
+ if (Cond.isInvalid())
+ return StmtError();
+
return Owned(Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.release(),
Body.release()));
}
@@ -674,13 +687,8 @@ Parser::OwningStmtResult Parser::ParseWhileStatement() {
// 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 @@ Parser::OwningStmtResult Parser::ParseForStatement() {
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)) {