diff options
Diffstat (limited to 'lib/Parse/ParseStmt.cpp')
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 313793c3e8..2974e6a245 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -439,7 +439,7 @@ StmtResult Parser::ParseExprStatement() { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Expr); + return Actions.ActOnExprStmt(Expr, isExprValueDiscarded()); } /// ParseSEHTryBlockCommon @@ -958,6 +958,16 @@ bool Parser::ConsumeNullStmt(StmtVector &Stmts) { return true; } +bool Parser::isExprValueDiscarded() { + if (Actions.isCurCompoundStmtAStmtExpr()) { + // Look to see if the next two tokens close the statement expression; + // if so, this expression statement is the last statement in a + // statment expression. + return Tok.isNot(tok::r_brace) || NextToken().isNot(tok::r_paren); + } + return true; +} + /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the /// ActOnCompoundStmt action. This expects the '{' to be the current token, and /// consume the '}' at the end of the block. It does not manipulate the scope @@ -1062,7 +1072,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // Eat the semicolon at the end of stmt and convert the expr into a // statement. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - R = Actions.ActOnExprStmt(Res); + R = Actions.ActOnExprStmt(Res, isExprValueDiscarded()); } } @@ -1698,8 +1708,16 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { if (!Value.isInvalid()) { if (ForEach) FirstPart = Actions.ActOnForEachLValueExpr(Value.get()); - else - FirstPart = Actions.ActOnExprStmt(Value); + else { + // We already know this is not an init-statement within a for loop, so + // if we are parsing a C++11 range-based for loop, we should treat this + // expression statement as being a discarded value expression because + // we will err below. This way we do not warn on an unused expression + // that was an error in the first place, like with: for (expr : expr); + bool IsRangeBasedFor = + getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon); + FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor); + } } if (Tok.is(tok::semi)) { |