summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseStmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseStmt.cpp')
-rw-r--r--clang/lib/Parse/ParseStmt.cpp80
1 files changed, 46 insertions, 34 deletions
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index c849554238e..8173d09cbbe 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1052,28 +1052,29 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
/// 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(Sema::ConditionResult &Cond,
+bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,
+ Decl *&DeclResult,
SourceLocation Loc,
- Sema::ConditionKind CK) {
+ bool ConvertToBoolean) {
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
if (getLangOpts().CPlusPlus)
- Cond = ParseCXXCondition(Loc, CK);
+ ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean);
else {
- ExprResult CondExpr = ParseExpression();
+ ExprResult = ParseExpression();
+ DeclResult = nullptr;
// If required, convert to a boolean value.
- if (CondExpr.isInvalid())
- Cond = Sema::ConditionError();
- else
- Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK);
+ if (!ExprResult.isInvalid() && ConvertToBoolean)
+ ExprResult
+ = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprResult.get());
}
// 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 (Cond.isInvalid() && Tok.isNot(tok::r_paren)) {
+ if (ExprResult.isInvalid() && !DeclResult && 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.
@@ -1131,10 +1132,13 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
// Parse the condition.
- Sema::ConditionResult Cond;
- if (ParseParenExprOrCondition(Cond, IfLoc, Sema::ConditionKind::Boolean))
+ ExprResult CondExp;
+ Decl *CondVar = nullptr;
+ if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true))
return StmtError();
+ FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), IfLoc));
+
// 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.
@@ -1217,8 +1221,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
if (ElseStmt.isInvalid())
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
- return Actions.ActOnIfStmt(IfLoc, Cond, ThenStmt.get(), ElseLoc,
- ElseStmt.get());
+ return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, ThenStmt.get(),
+ ElseLoc, ElseStmt.get());
}
/// ParseSwitchStatement
@@ -1255,11 +1259,13 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
ParseScope SwitchScope(this, ScopeFlags);
// Parse the condition.
- Sema::ConditionResult Cond;
- if (ParseParenExprOrCondition(Cond, SwitchLoc, Sema::ConditionKind::Switch))
+ ExprResult Cond;
+ Decl *CondVar = nullptr;
+ if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false))
return StmtError();
- StmtResult Switch = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond);
+ StmtResult Switch
+ = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar);
if (Switch.isInvalid()) {
// Skip the switch body.
@@ -1341,10 +1347,13 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
ParseScope WhileScope(this, ScopeFlags);
// Parse the condition.
- Sema::ConditionResult Cond;
- if (ParseParenExprOrCondition(Cond, WhileLoc, Sema::ConditionKind::Boolean))
+ ExprResult Cond;
+ Decl *CondVar = nullptr;
+ if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true))
return StmtError();
+ FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc));
+
// C99 6.8.5p5 - In C99, the body of the while 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.
@@ -1365,10 +1374,10 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
InnerScope.Exit();
WhileScope.Exit();
- if (Cond.isInvalid() || Body.isInvalid())
+ if ((Cond.isInvalid() && !CondVar) || Body.isInvalid())
return StmtError();
- return Actions.ActOnWhileStmt(WhileLoc, Cond, Body.get());
+ return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, Body.get());
}
/// ParseDoStatement
@@ -1526,10 +1535,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
bool ForEach = false, ForRange = false;
StmtResult FirstPart;
- Sema::ConditionResult SecondPart;
+ bool SecondPartIsInvalid = false;
+ FullExprArg SecondPart(Actions);
ExprResult Collection;
ForRangeInit ForRangeInit;
FullExprArg ThirdPart(Actions);
+ Decl *SecondVar = nullptr;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(),
@@ -1634,7 +1645,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
Diag(Tok, diag::err_for_range_expected_decl)
<< FirstPart.get()->getSourceRange();
SkipUntil(tok::r_paren, StopBeforeMatch);
- SecondPart = Sema::ConditionError();
+ SecondPartIsInvalid = true;
} else {
if (!Value.isInvalid()) {
Diag(Tok, diag::err_expected_semi_for);
@@ -1649,28 +1660,29 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// Parse the second part of the for specifier.
getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
- if (!ForEach && !ForRange && !SecondPart.isInvalid()) {
+ if (!ForEach && !ForRange) {
+ assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
// Parse the second part of the for specifier.
if (Tok.is(tok::semi)) { // for (...;;
// no second part.
} else if (Tok.is(tok::r_paren)) {
// missing both semicolons.
} else {
+ ExprResult Second;
if (getLangOpts().CPlusPlus)
- SecondPart = ParseCXXCondition(ForLoc, Sema::ConditionKind::Boolean);
+ ParseCXXCondition(Second, SecondVar, ForLoc, true);
else {
- ExprResult SecondExpr = ParseExpression();
- if (SecondExpr.isInvalid())
- SecondPart = Sema::ConditionError();
- else
- SecondPart =
- Actions.ActOnCondition(getCurScope(), ForLoc, SecondExpr.get(),
- Sema::ConditionKind::Boolean);
+ Second = ParseExpression();
+ if (!Second.isInvalid())
+ Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc,
+ Second.get());
}
+ SecondPartIsInvalid = Second.isInvalid();
+ SecondPart = Actions.MakeFullExpr(Second.get(), ForLoc);
}
if (Tok.isNot(tok::semi)) {
- if (!SecondPart.isInvalid())
+ if (!SecondPartIsInvalid || SecondVar)
Diag(Tok, diag::err_expected_semi_for);
else
// Skip until semicolon or rparen, don't consume it.
@@ -1769,8 +1781,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(),
- SecondPart, ThirdPart, T.getCloseLocation(),
- Body.get());
+ SecondPart, SecondVar, ThirdPart,
+ T.getCloseLocation(), Body.get());
}
/// ParseGotoStatement
OpenPOWER on IntegriCloud