<div dir="ltr">This breaks Wfor-loop-analysis. Code (e.g. WebKit) has a pattern where a class has an accessor that takes an index and returns an element if the index is in bounds or nullptr else, and calling code passes indices starting at 0 until a nullptr element is returned. That used to be fine, but now clang warns:<div><br></div><div><div>../../third_party/WebKit/Source/core/html/HTMLInputElement.cpp(1843,49): error: variable 'option' used in loop condition not modified in loop body [-Werror,-Wfor-loop-analysis]</div><div> for (unsigned i = 0; HTMLOptionElement* option = options->item(i); ++i) {</div><div> ^~~~~~</div></div><div><br></div><div>(in many other places too.)</div><div><br></div><div>Can you take a look?</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jun 23, 2016 at 4:41 AM, Richard Smith via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Thu Jun 23 03:41:20 2016<br>
New Revision: 273548<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=273548&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=273548&view=rev</a><br>
Log:<br>
Rearrange condition handling so that semantic checks on a condition variable<br>
are performed before the other substatements of the construct are parsed,<br>
rather than deferring them until the end. This allows better error recovery<br>
from semantic errors in the condition, improves diagnostic order, and is a<br>
prerequisite for C++17 constexpr if.<br>
<br>
Modified:<br>
cfe/trunk/include/clang/Parse/Parser.h<br>
cfe/trunk/include/clang/Sema/Sema.h<br>
cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
cfe/trunk/lib/Parse/ParseExprCXX.cpp<br>
cfe/trunk/lib/Parse/ParseStmt.cpp<br>
cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
cfe/trunk/lib/Sema/SemaExpr.cpp<br>
cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
cfe/trunk/lib/Sema/SemaOpenMP.cpp<br>
cfe/trunk/lib/Sema/SemaStmt.cpp<br>
cfe/trunk/lib/Sema/TreeTransform.h<br>
cfe/trunk/test/FixIt/fixit-vexing-parse.cpp<br>
cfe/trunk/test/Parser/cxx0x-condition.cpp<br>
cfe/trunk/test/SemaCXX/crashes.cpp<br>
cfe/trunk/test/SemaCXX/for-range-examples.cpp<br>
cfe/trunk/test/SemaObjCXX/<a href="http://foreach.mm" rel="noreferrer" target="_blank">foreach.mm</a><br>
<br>
Modified: cfe/trunk/include/clang/Parse/Parser.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Parse/Parser.h (original)<br>
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Jun 23 03:41:20 2016<br>
@@ -1588,8 +1588,8 @@ private:<br>
<br>
//===--------------------------------------------------------------------===//<br>
// C++ if/switch/while condition expression.<br>
- bool ParseCXXCondition(ExprResult &ExprResult, Decl *&DeclResult,<br>
- SourceLocation Loc, bool ConvertToBoolean);<br>
+ Sema::ConditionResult ParseCXXCondition(SourceLocation Loc,<br>
+ Sema::ConditionKind CK);<br>
<br>
//===--------------------------------------------------------------------===//<br>
// C++ Coroutines<br>
@@ -1680,10 +1680,9 @@ private:<br>
unsigned ScopeFlags);<br>
void ParseCompoundStatementLeadingPragmas();<br>
StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);<br>
- bool ParseParenExprOrCondition(ExprResult &ExprResult,<br>
- Decl *&DeclResult,<br>
+ bool ParseParenExprOrCondition(Sema::ConditionResult &CondResult,<br>
SourceLocation Loc,<br>
- bool ConvertToBoolean);<br>
+ Sema::ConditionKind CK);<br>
StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc);<br>
StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc);<br>
StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc);<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jun 23 03:41:20 2016<br>
@@ -3298,6 +3298,7 @@ public:<br>
public:<br>
class FullExprArg {<br>
public:<br>
+ FullExprArg() : E(nullptr) { }<br>
FullExprArg(Sema &actions) : E(nullptr) { }<br>
<br>
ExprResult release() {<br>
@@ -3391,27 +3392,23 @@ public:<br>
ArrayRef<const Attr*> Attrs,<br>
Stmt *SubStmt);<br>
<br>
- StmtResult ActOnIfStmt(SourceLocation IfLoc,<br>
- FullExprArg CondVal, Decl *CondVar,<br>
- Stmt *ThenVal,<br>
- SourceLocation ElseLoc, Stmt *ElseVal);<br>
+ class ConditionResult;<br>
+ StmtResult ActOnIfStmt(SourceLocation IfLoc, ConditionResult Cond,<br>
+ Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal);<br>
StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,<br>
- Expr *Cond,<br>
- Decl *CondVar);<br>
+ ConditionResult Cond);<br>
StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,<br>
Stmt *Switch, Stmt *Body);<br>
- StmtResult ActOnWhileStmt(SourceLocation WhileLoc,<br>
- FullExprArg Cond,<br>
- Decl *CondVar, Stmt *Body);<br>
+ StmtResult ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,<br>
+ Stmt *Body);<br>
StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,<br>
- SourceLocation WhileLoc,<br>
- SourceLocation CondLParen, Expr *Cond,<br>
- SourceLocation CondRParen);<br>
+ SourceLocation WhileLoc, SourceLocation CondLParen,<br>
+ Expr *Cond, SourceLocation CondRParen);<br>
<br>
StmtResult ActOnForStmt(SourceLocation ForLoc,<br>
SourceLocation LParenLoc,<br>
- Stmt *First, FullExprArg Second,<br>
- Decl *SecondVar,<br>
+ Stmt *First,<br>
+ ConditionResult Second,<br>
FullExprArg Third,<br>
SourceLocation RParenLoc,<br>
Stmt *Body);<br>
@@ -4801,11 +4798,6 @@ public:<br>
bool WarnOnNonAbstractTypes,<br>
SourceLocation DtorLoc);<br>
<br>
- DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);<br>
- ExprResult CheckConditionVariable(VarDecl *ConditionVar,<br>
- SourceLocation StmtLoc,<br>
- bool ConvertToBoolean);<br>
-<br>
ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen,<br>
Expr *Operand, SourceLocation RParen);<br>
ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,<br>
@@ -8923,6 +8915,46 @@ public:<br>
/// type, and if so, emit a note describing what happened.<br>
void EmitRelatedResultTypeNoteForReturn(QualType destType);<br>
<br>
+ class ConditionResult {<br>
+ Decl *ConditionVar;<br>
+ FullExprArg Condition;<br>
+ bool Invalid;<br>
+<br>
+ friend class Sema;<br>
+ ConditionResult(Decl *ConditionVar, FullExprArg Condition)<br>
+ : ConditionVar(ConditionVar), Condition(Condition), Invalid(false) {}<br>
+ explicit ConditionResult(bool Invalid)<br>
+ : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid) {}<br>
+<br>
+ public:<br>
+ ConditionResult() : ConditionResult(false) {}<br>
+ bool isInvalid() const { return Invalid; }<br>
+ std::pair<VarDecl *, Expr *> get() const {<br>
+ return std::make_pair(cast_or_null<VarDecl>(ConditionVar),<br>
+ Condition.get());<br>
+ }<br>
+ };<br>
+ static ConditionResult ConditionError() { return ConditionResult(true); }<br>
+<br>
+ enum class ConditionKind {<br>
+ Boolean, ///< A boolean condition, from 'if', 'while', 'for', or 'do'.<br>
+ Switch ///< An integral condition for a 'switch' statement.<br>
+ };<br>
+<br>
+ ConditionResult ActOnCondition(Scope *S, SourceLocation Loc,<br>
+ Expr *SubExpr, ConditionKind CK);<br>
+<br>
+ ConditionResult ActOnConditionVariable(Decl *ConditionVar,<br>
+ SourceLocation StmtLoc,<br>
+ ConditionKind CK);<br>
+<br>
+ DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);<br>
+<br>
+ ExprResult CheckConditionVariable(VarDecl *ConditionVar,<br>
+ SourceLocation StmtLoc,<br>
+ ConditionKind CK);<br>
+ ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond);<br>
+<br>
/// CheckBooleanCondition - Diagnose problems involving the use of<br>
/// the given expression as a boolean condition (e.g. in an if<br>
/// statement). Also performs the standard function and array<br>
@@ -8931,10 +8963,7 @@ public:<br>
/// \param Loc - A location associated with the condition, e.g. the<br>
/// 'if' keyword.<br>
/// \return true iff there were any errors<br>
- ExprResult CheckBooleanCondition(Expr *E, SourceLocation Loc);<br>
-<br>
- ExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc,<br>
- Expr *SubExpr);<br>
+ ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E);<br>
<br>
/// DiagnoseAssignmentAsCondition - Given that an expression is<br>
/// being used as a boolean condition, warn if it's an assignment.<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Jun 23 03:41:20 2016<br>
@@ -3420,10 +3420,11 @@ Parser::tryParseExceptionSpecification(b<br>
NoexceptExpr = ParseConstantExpression();<br>
T.consumeClose();<br>
// The argument must be contextually convertible to bool. We use<br>
- // ActOnBooleanCondition for this purpose.<br>
+ // CheckBooleanCondition for this purpose.<br>
+ // FIXME: Add a proper Sema entry point for this.<br>
if (!NoexceptExpr.isInvalid()) {<br>
- NoexceptExpr = Actions.ActOnBooleanCondition(getCurScope(), KeywordLoc,<br>
- NoexceptExpr.get());<br>
+ NoexceptExpr =<br>
+ Actions.CheckBooleanCondition(KeywordLoc, NoexceptExpr.get());<br>
NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());<br>
} else {<br>
NoexceptType = EST_None;<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Jun 23 03:41:20 2016<br>
@@ -1726,27 +1726,19 @@ Parser::ParseCXXTypeConstructExpression(<br>
/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]<br>
/// '=' assignment-expression<br>
///<br>
-/// \param ExprOut if the condition was parsed as an expression, the parsed<br>
-/// expression.<br>
-///<br>
-/// \param DeclOut if the condition was parsed as a declaration, the parsed<br>
-/// declaration.<br>
-///<br>
/// \param Loc The location of the start of the statement that requires this<br>
/// condition, e.g., the "for" in a for loop.<br>
///<br>
/// \param ConvertToBoolean Whether the condition expression should be<br>
/// converted to a boolean value.<br>
///<br>
-/// \returns true if there was a parsing, false otherwise.<br>
-bool Parser::ParseCXXCondition(ExprResult &ExprOut,<br>
- Decl *&DeclOut,<br>
- SourceLocation Loc,<br>
- bool ConvertToBoolean) {<br>
+/// \returns The parsed condition.<br>
+Sema::ConditionResult Parser::ParseCXXCondition(SourceLocation Loc,<br>
+ Sema::ConditionKind CK) {<br>
if (Tok.is(tok::code_completion)) {<br>
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition);<br>
cutOffParsing();<br>
- return true;<br>
+ return Sema::ConditionError();<br>
}<br>
<br>
ParsedAttributesWithRange attrs(AttrFactory);<br>
@@ -1756,16 +1748,11 @@ bool Parser::ParseCXXCondition(ExprResul<br>
ProhibitAttributes(attrs);<br>
<br>
// Parse the expression.<br>
- ExprOut = ParseExpression(); // expression<br>
- DeclOut = nullptr;<br>
- if (ExprOut.isInvalid())<br>
- return true;<br>
-<br>
- // If required, convert to a boolean value.<br>
- if (ConvertToBoolean)<br>
- ExprOut<br>
- = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprOut.get());<br>
- return ExprOut.isInvalid();<br>
+ ExprResult Expr = ParseExpression(); // expression<br>
+ if (Expr.isInvalid())<br>
+ return Sema::ConditionError();<br>
+<br>
+ return Actions.ActOnCondition(getCurScope(), Loc, Expr.get(), CK);<br>
}<br>
<br>
// type-specifier-seq<br>
@@ -1783,7 +1770,7 @@ bool Parser::ParseCXXCondition(ExprResul<br>
ExprResult AsmLabel(ParseSimpleAsm(&Loc));<br>
if (AsmLabel.isInvalid()) {<br>
SkipUntil(tok::semi, StopAtSemi);<br>
- return true;<br>
+ return Sema::ConditionError();<br>
}<br>
DeclaratorInfo.setAsmLabel(AsmLabel.get());<br>
DeclaratorInfo.SetRangeEnd(Loc);<br>
@@ -1795,8 +1782,9 @@ bool Parser::ParseCXXCondition(ExprResul<br>
// Type-check the declaration itself.<br>
DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(),<br>
DeclaratorInfo);<br>
- DeclOut = Dcl.get();<br>
- ExprOut = ExprError();<br>
+ if (Dcl.isInvalid())<br>
+ return Sema::ConditionError();<br>
+ Decl *DeclOut = Dcl.get();<br>
<br>
// '=' assignment-expression<br>
// If a '==' or '+=' is found, suggest a fixit to '='.<br>
@@ -1816,12 +1804,11 @@ bool Parser::ParseCXXCondition(ExprResul<br>
SourceLocation LParen = ConsumeParen(), RParen = LParen;<br>
if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch))<br>
RParen = ConsumeParen();<br>
- Diag(DeclOut ? DeclOut->getLocation() : LParen,<br>
+ Diag(DeclOut->getLocation(),<br>
diag::err_expected_init_in_condition_lparen)<br>
<< SourceRange(LParen, RParen);<br>
} else {<br>
- Diag(DeclOut ? DeclOut->getLocation() : Tok.getLocation(),<br>
- diag::err_expected_init_in_condition);<br>
+ Diag(DeclOut->getLocation(), diag::err_expected_init_in_condition);<br>
}<br>
<br>
if (!InitExpr.isInvalid())<br>
@@ -1834,8 +1821,7 @@ bool Parser::ParseCXXCondition(ExprResul<br>
// (This is currently handled by Sema).<br>
<br>
Actions.FinalizeDeclaration(DeclOut);<br>
-<br>
- return false;<br>
+ return Actions.ActOnConditionVariable(DeclOut, Loc, CK);<br>
}<br>
<br>
/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Thu Jun 23 03:41:20 2016<br>
@@ -1052,29 +1052,28 @@ StmtResult Parser::ParseCompoundStatemen<br>
/// should try to recover harder. It returns false if the condition is<br>
/// successfully parsed. Note that a successful parse can still have semantic<br>
/// errors in the condition.<br>
-bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,<br>
- Decl *&DeclResult,<br>
+bool Parser::ParseParenExprOrCondition(Sema::ConditionResult &Cond,<br>
SourceLocation Loc,<br>
- bool ConvertToBoolean) {<br>
+ Sema::ConditionKind CK) {<br>
BalancedDelimiterTracker T(*this, tok::l_paren);<br>
T.consumeOpen();<br>
<br>
if (getLangOpts().CPlusPlus)<br>
- ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean);<br>
+ Cond = ParseCXXCondition(Loc, CK);<br>
else {<br>
- ExprResult = ParseExpression();<br>
- DeclResult = nullptr;<br>
+ ExprResult CondExpr = ParseExpression();<br>
<br>
// If required, convert to a boolean value.<br>
- if (!ExprResult.isInvalid() && ConvertToBoolean)<br>
- ExprResult<br>
- = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprResult.get());<br>
+ if (CondExpr.isInvalid())<br>
+ Cond = Sema::ConditionError();<br>
+ else<br>
+ Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK);<br>
}<br>
<br>
// If the parser was confused by the condition and we don't have a ')', try to<br>
// recover by skipping ahead to a semi and bailing out. If condexp is<br>
// semantically invalid but we have well formed code, keep going.<br>
- if (ExprResult.isInvalid() && !DeclResult && Tok.isNot(tok::r_paren)) {<br>
+ if (Cond.isInvalid() && Tok.isNot(tok::r_paren)) {<br>
SkipUntil(tok::semi);<br>
// Skipping may have stopped if it found the containing ')'. If so, we can<br>
// continue parsing the if statement.<br>
@@ -1132,13 +1131,10 @@ StmtResult Parser::ParseIfStatement(Sour<br>
ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);<br>
<br>
// Parse the condition.<br>
- ExprResult CondExp;<br>
- Decl *CondVar = nullptr;<br>
- if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true))<br>
+ Sema::ConditionResult Cond;<br>
+ if (ParseParenExprOrCondition(Cond, IfLoc, Sema::ConditionKind::Boolean))<br>
return StmtError();<br>
<br>
- FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), IfLoc));<br>
-<br>
// C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if<br>
// there is no compound stmt. C90 does not have this clause. We only do this<br>
// if the body isn't a compound statement to avoid push/pop in common cases.<br>
@@ -1221,8 +1217,8 @@ StmtResult Parser::ParseIfStatement(Sour<br>
if (ElseStmt.isInvalid())<br>
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);<br>
<br>
- return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, ThenStmt.get(),<br>
- ElseLoc, ElseStmt.get());<br>
+ return Actions.ActOnIfStmt(IfLoc, Cond, ThenStmt.get(), ElseLoc,<br>
+ ElseStmt.get());<br>
}<br>
<br>
/// ParseSwitchStatement<br>
@@ -1259,13 +1255,11 @@ StmtResult Parser::ParseSwitchStatement(<br>
ParseScope SwitchScope(this, ScopeFlags);<br>
<br>
// Parse the condition.<br>
- ExprResult Cond;<br>
- Decl *CondVar = nullptr;<br>
- if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false))<br>
+ Sema::ConditionResult Cond;<br>
+ if (ParseParenExprOrCondition(Cond, SwitchLoc, Sema::ConditionKind::Switch))<br>
return StmtError();<br>
<br>
- StmtResult Switch<br>
- = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar);<br>
+ StmtResult Switch = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond);<br>
<br>
if (Switch.isInvalid()) {<br>
// Skip the switch body.<br>
@@ -1347,13 +1341,10 @@ StmtResult Parser::ParseWhileStatement(S<br>
ParseScope WhileScope(this, ScopeFlags);<br>
<br>
// Parse the condition.<br>
- ExprResult Cond;<br>
- Decl *CondVar = nullptr;<br>
- if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true))<br>
+ Sema::ConditionResult Cond;<br>
+ if (ParseParenExprOrCondition(Cond, WhileLoc, Sema::ConditionKind::Boolean))<br>
return StmtError();<br>
<br>
- FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc));<br>
-<br>
// C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if<br>
// there is no compound stmt. C90 does not have this clause. We only do this<br>
// if the body isn't a compound statement to avoid push/pop in common cases.<br>
@@ -1374,10 +1365,10 @@ StmtResult Parser::ParseWhileStatement(S<br>
InnerScope.Exit();<br>
WhileScope.Exit();<br>
<br>
- if ((Cond.isInvalid() && !CondVar) || Body.isInvalid())<br>
+ if (Cond.isInvalid() || Body.isInvalid())<br>
return StmtError();<br>
<br>
- return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, Body.get());<br>
+ return Actions.ActOnWhileStmt(WhileLoc, Cond, Body.get());<br>
}<br>
<br>
/// ParseDoStatement<br>
@@ -1535,12 +1526,10 @@ StmtResult Parser::ParseForStatement(Sou<br>
<br>
bool ForEach = false, ForRange = false;<br>
StmtResult FirstPart;<br>
- bool SecondPartIsInvalid = false;<br>
- FullExprArg SecondPart(Actions);<br>
+ Sema::ConditionResult SecondPart;<br>
ExprResult Collection;<br>
ForRangeInit ForRangeInit;<br>
FullExprArg ThirdPart(Actions);<br>
- Decl *SecondVar = nullptr;<br>
<br>
if (Tok.is(tok::code_completion)) {<br>
Actions.CodeCompleteOrdinaryName(getCurScope(),<br>
@@ -1645,7 +1634,7 @@ StmtResult Parser::ParseForStatement(Sou<br>
Diag(Tok, diag::err_for_range_expected_decl)<br>
<< FirstPart.get()->getSourceRange();<br>
SkipUntil(tok::r_paren, StopBeforeMatch);<br>
- SecondPartIsInvalid = true;<br>
+ SecondPart = Sema::ConditionError();<br>
} else {<br>
if (!Value.isInvalid()) {<br>
Diag(Tok, diag::err_expected_semi_for);<br>
@@ -1660,29 +1649,28 @@ StmtResult Parser::ParseForStatement(Sou<br>
<br>
// Parse the second part of the for specifier.<br>
getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);<br>
- if (!ForEach && !ForRange) {<br>
- assert(!SecondPart.get() && "Shouldn't have a second expression yet.");<br>
+ if (!ForEach && !ForRange && !SecondPart.isInvalid()) {<br>
// Parse the second part of the for specifier.<br>
if (Tok.is(tok::semi)) { // for (...;;<br>
// no second part.<br>
} else if (Tok.is(tok::r_paren)) {<br>
// missing both semicolons.<br>
} else {<br>
- ExprResult Second;<br>
if (getLangOpts().CPlusPlus)<br>
- ParseCXXCondition(Second, SecondVar, ForLoc, true);<br>
+ SecondPart = ParseCXXCondition(ForLoc, Sema::ConditionKind::Boolean);<br>
else {<br>
- Second = ParseExpression();<br>
- if (!Second.isInvalid())<br>
- Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc,<br>
- Second.get());<br>
+ ExprResult SecondExpr = ParseExpression();<br>
+ if (SecondExpr.isInvalid())<br>
+ SecondPart = Sema::ConditionError();<br>
+ else<br>
+ SecondPart =<br>
+ Actions.ActOnCondition(getCurScope(), ForLoc, SecondExpr.get(),<br>
+ Sema::ConditionKind::Boolean);<br>
}<br>
- SecondPartIsInvalid = Second.isInvalid();<br>
- SecondPart = Actions.MakeFullExpr(Second.get(), ForLoc);<br>
}<br>
<br>
if (Tok.isNot(tok::semi)) {<br>
- if (!SecondPartIsInvalid || SecondVar)<br>
+ if (!SecondPart.isInvalid())<br>
Diag(Tok, diag::err_expected_semi_for);<br>
else<br>
// Skip until semicolon or rparen, don't consume it.<br>
@@ -1781,8 +1769,8 @@ StmtResult Parser::ParseForStatement(Sou<br>
return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());<br>
<br>
return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(),<br>
- SecondPart, SecondVar, ThirdPart,<br>
- T.getCloseLocation(), Body.get());<br>
+ SecondPart, ThirdPart, T.getCloseLocation(),<br>
+ Body.get());<br>
}<br>
<br>
/// ParseGotoStatement<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jun 23 03:41:20 2016<br>
@@ -10092,10 +10092,10 @@ buildSingleCopyAssignRecursively(Sema &S<br>
SizeType, VK_LValue, OK_Ordinary, Loc);<br>
<br>
// Construct the loop that copies all elements of this array.<br>
- return S.ActOnForStmt(Loc, Loc, InitStmt,<br>
- S.MakeFullExpr(Comparison),<br>
- nullptr, S.MakeFullDiscardedValueExpr(Increment),<br>
- Loc, Copy.get());<br>
+ return S.ActOnForStmt(<br>
+ Loc, Loc, InitStmt,<br>
+ S.ActOnCondition(nullptr, Loc, Comparison, Sema::ConditionKind::Boolean),<br>
+ S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.get());<br>
}<br>
<br>
static StmtResult<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jun 23 03:41:20 2016<br>
@@ -14341,7 +14341,7 @@ void Sema::DiagnoseEqualityWithExtraPare<br>
}<br>
}<br>
<br>
-ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) {<br>
+ExprResult Sema::CheckBooleanCondition(SourceLocation Loc, Expr *E) {<br>
DiagnoseAssignmentAsCondition(E);<br>
if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))<br>
DiagnoseEqualityWithExtraParens(parenE);<br>
@@ -14371,12 +14371,26 @@ ExprResult Sema::CheckBooleanCondition(E<br>
return E;<br>
}<br>
<br>
-ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc,<br>
- Expr *SubExpr) {<br>
+Sema::ConditionResult Sema::ActOnCondition(Scope *S, SourceLocation Loc,<br>
+ Expr *SubExpr, ConditionKind CK) {<br>
+ // Empty conditions are valid in for-statements.<br>
if (!SubExpr)<br>
- return ExprError();<br>
+ return ConditionResult();<br>
<br>
- return CheckBooleanCondition(SubExpr, Loc);<br>
+ ExprResult Cond;<br>
+ switch (CK) {<br>
+ case ConditionKind::Boolean:<br>
+ Cond = CheckBooleanCondition(Loc, SubExpr);<br>
+ break;<br>
+<br>
+ case ConditionKind::Switch:<br>
+ Cond = CheckSwitchCondition(Loc, SubExpr);<br>
+ break;<br>
+ }<br>
+ if (Cond.isInvalid())<br>
+ return ConditionError();<br>
+<br>
+ return ConditionResult(nullptr, MakeFullExpr(Cond.get(), Loc));<br>
}<br>
<br>
namespace {<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Jun 23 03:41:20 2016<br>
@@ -3054,11 +3054,21 @@ void Sema::CheckVirtualDtorCall(CXXDestr<br>
}<br>
}<br>
<br>
+Sema::ConditionResult Sema::ActOnConditionVariable(Decl *ConditionVar,<br>
+ SourceLocation StmtLoc,<br>
+ ConditionKind CK) {<br>
+ ExprResult E =<br>
+ CheckConditionVariable(cast<VarDecl>(ConditionVar), StmtLoc, CK);<br>
+ if (E.isInvalid())<br>
+ return ConditionError();<br>
+ return ConditionResult(ConditionVar, MakeFullExpr(E.get(), StmtLoc));<br>
+}<br>
+<br>
/// \brief Check the use of the given variable as a C++ condition in an if,<br>
/// while, do-while, or switch statement.<br>
ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,<br>
SourceLocation StmtLoc,<br>
- bool ConvertToBoolean) {<br>
+ ConditionKind CK) {<br>
if (ConditionVar->isInvalidDecl())<br>
return ExprError();<br>
<br>
@@ -3082,13 +3092,15 @@ ExprResult Sema::CheckConditionVariable(<br>
<br>
MarkDeclRefReferenced(cast<DeclRefExpr>(Condition.get()));<br>
<br>
- if (ConvertToBoolean) {<br>
- Condition = CheckBooleanCondition(Condition.get(), StmtLoc);<br>
- if (Condition.isInvalid())<br>
- return ExprError();<br>
+ switch (CK) {<br>
+ case ConditionKind::Boolean:<br>
+ return CheckBooleanCondition(StmtLoc, Condition.get());<br>
+<br>
+ case ConditionKind::Switch:<br>
+ return CheckSwitchCondition(StmtLoc, Condition.get());<br>
}<br>
<br>
- return Condition;<br>
+ llvm_unreachable("unexpected condition kind");<br>
}<br>
<br>
/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid.<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Thu Jun 23 03:41:20 2016<br>
@@ -6826,12 +6826,11 @@ OMPClause *Sema::ActOnOpenMPIfClause(Ope<br>
if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&<br>
!Condition->isInstantiationDependent() &&<br>
!Condition->containsUnexpandedParameterPack()) {<br>
- ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(),<br>
- Condition->getExprLoc(), Condition);<br>
+ ExprResult Val = CheckBooleanCondition(StartLoc, Condition);<br>
if (Val.isInvalid())<br>
return nullptr;<br>
<br>
- ValExpr = Val.get();<br>
+ ValExpr = MakeFullExpr(Val.get()).get();<br>
}<br>
<br>
return new (Context) OMPIfClause(NameModifier, ValExpr, StartLoc, LParenLoc,<br>
@@ -6846,12 +6845,11 @@ OMPClause *Sema::ActOnOpenMPFinalClause(<br>
if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&<br>
!Condition->isInstantiationDependent() &&<br>
!Condition->containsUnexpandedParameterPack()) {<br>
- ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(),<br>
- Condition->getExprLoc(), Condition);<br>
+ ExprResult Val = CheckBooleanCondition(StartLoc, Condition);<br>
if (Val.isInvalid())<br>
return nullptr;<br>
<br>
- ValExpr = Val.get();<br>
+ ValExpr = MakeFullExpr(Val.get()).get();<br>
}<br>
<br>
return new (Context) OMPFinalClause(ValExpr, StartLoc, LParenLoc, EndLoc);<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Thu Jun 23 03:41:20 2016<br>
@@ -504,39 +504,30 @@ public:<br>
}<br>
<br>
StmtResult<br>
-Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,<br>
+Sema::ActOnIfStmt(SourceLocation IfLoc, ConditionResult Cond,<br>
Stmt *thenStmt, SourceLocation ElseLoc,<br>
Stmt *elseStmt) {<br>
- ExprResult CondResult(CondVal.release());<br>
-<br>
- VarDecl *ConditionVar = nullptr;<br>
- if (CondVar) {<br>
- ConditionVar = cast<VarDecl>(CondVar);<br>
- CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);<br>
- CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc);<br>
+ auto CondVal = Cond.get();<br>
+ if (Cond.isInvalid()) {<br>
+ CondVal.first = nullptr;<br>
+ CondVal.second = new (Context)<br>
+ OpaqueValueExpr(SourceLocation(), Context.BoolTy, VK_RValue);<br>
}<br>
- Expr *ConditionExpr = CondResult.getAs<Expr>();<br>
- if (ConditionExpr) {<br>
-<br>
- if (!Diags.isIgnored(diag::warn_comma_operator,<br>
- ConditionExpr->getExprLoc()))<br>
- CommaVisitor(*this).Visit(ConditionExpr);<br>
<br>
- DiagnoseUnusedExprResult(thenStmt);<br>
+ if (!Diags.isIgnored(diag::warn_comma_operator,<br>
+ CondVal.second->getExprLoc()))<br>
+ CommaVisitor(*this).Visit(CondVal.second);<br>
<br>
- if (!elseStmt) {<br>
- DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt,<br>
- diag::warn_empty_if_body);<br>
- }<br>
+ DiagnoseUnusedExprResult(thenStmt);<br>
<br>
- DiagnoseUnusedExprResult(elseStmt);<br>
- } else {<br>
- // Create a dummy Expr for the condition for error recovery<br>
- ConditionExpr = new (Context) OpaqueValueExpr(SourceLocation(),<br>
- Context.BoolTy, VK_RValue);<br>
+ if (!elseStmt) {<br>
+ DiagnoseEmptyStmtBody(CondVal.second->getLocEnd(), thenStmt,<br>
+ diag::warn_empty_if_body);<br>
}<br>
<br>
- return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,<br>
+ DiagnoseUnusedExprResult(elseStmt);<br>
+<br>
+ return new (Context) IfStmt(Context, IfLoc, CondVal.first, CondVal.second,<br>
thenStmt, ElseLoc, elseStmt);<br>
}<br>
<br>
@@ -599,24 +590,7 @@ static QualType GetTypeBeforeIntegralPro<br>
return expr->getType();<br>
}<br>
<br>
-StmtResult<br>
-Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,<br>
- Decl *CondVar) {<br>
- ExprResult CondResult;<br>
-<br>
- VarDecl *ConditionVar = nullptr;<br>
- if (CondVar) {<br>
- ConditionVar = cast<VarDecl>(CondVar);<br>
- CondResult = CheckConditionVariable(ConditionVar, SourceLocation(), false);<br>
- if (CondResult.isInvalid())<br>
- return StmtError();<br>
-<br>
- Cond = CondResult.get();<br>
- }<br>
-<br>
- if (!Cond)<br>
- return StmtError();<br>
-<br>
+ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) {<br>
class SwitchConvertDiagnoser : public ICEConvertDiagnoser {<br>
Expr *Cond;<br>
<br>
@@ -664,24 +638,24 @@ Sema::ActOnStartOfSwitchStmt(SourceLocat<br>
}<br>
} SwitchDiagnoser(Cond);<br>
<br>
- CondResult =<br>
+ ExprResult CondResult =<br>
PerformContextualImplicitConversion(SwitchLoc, Cond, SwitchDiagnoser);<br>
- if (CondResult.isInvalid()) return StmtError();<br>
- Cond = CondResult.get();<br>
+ if (CondResult.isInvalid())<br>
+ return ExprError();<br>
<br>
// C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr.<br>
- CondResult = UsualUnaryConversions(Cond);<br>
- if (CondResult.isInvalid()) return StmtError();<br>
- Cond = CondResult.get();<br>
+ return UsualUnaryConversions(CondResult.get());<br>
+}<br>
<br>
- CondResult = ActOnFinishFullExpr(Cond, SwitchLoc);<br>
- if (CondResult.isInvalid())<br>
+StmtResult<br>
+Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ConditionResult Cond) {<br>
+ if (Cond.isInvalid())<br>
return StmtError();<br>
- Cond = CondResult.get();<br>
<br>
getCurFunction()->setHasBranchIntoScope();<br>
<br>
- SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, Cond);<br>
+ SwitchStmt *SS =<br>
+ new (Context) SwitchStmt(Context, Cond.get().first, Cond.get().second);<br>
getCurFunction()->SwitchStack.push_back(SS);<br>
return SS;<br>
}<br>
@@ -1242,27 +1216,17 @@ Sema::DiagnoseAssignmentEnum(QualType Ds<br>
}<br>
}<br>
<br>
-StmtResult<br>
-Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond,<br>
- Decl *CondVar, Stmt *Body) {<br>
- ExprResult CondResult(Cond.release());<br>
-<br>
- VarDecl *ConditionVar = nullptr;<br>
- if (CondVar) {<br>
- ConditionVar = cast<VarDecl>(CondVar);<br>
- CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true);<br>
- CondResult = ActOnFinishFullExpr(CondResult.get(), WhileLoc);<br>
- if (CondResult.isInvalid())<br>
- return StmtError();<br>
- }<br>
- Expr *ConditionExpr = CondResult.get();<br>
- if (!ConditionExpr)<br>
+StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,<br>
+ Stmt *Body) {<br>
+ if (Cond.isInvalid())<br>
return StmtError();<br>
- CheckBreakContinueBinding(ConditionExpr);<br>
<br>
- if (ConditionExpr &&<br>
- !Diags.isIgnored(diag::warn_comma_operator, ConditionExpr->getExprLoc()))<br>
- CommaVisitor(*this).Visit(ConditionExpr);<br>
+ auto CondVal = Cond.get();<br>
+ CheckBreakContinueBinding(CondVal.second);<br>
+<br>
+ if (CondVal.second &&<br>
+ !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc()))<br>
+ CommaVisitor(*this).Visit(CondVal.second);<br>
<br>
DiagnoseUnusedExprResult(Body);<br>
<br>
@@ -1270,7 +1234,7 @@ Sema::ActOnWhileStmt(SourceLocation Whil<br>
getCurCompoundScope().setHasEmptyLoopBodies();<br>
<br>
return new (Context)<br>
- WhileStmt(Context, ConditionVar, ConditionExpr, Body, WhileLoc);<br>
+ WhileStmt(Context, CondVal.first, CondVal.second, Body, WhileLoc);<br>
}<br>
<br>
StmtResult<br>
@@ -1280,7 +1244,7 @@ Sema::ActOnDoStmt(SourceLocation DoLoc,<br>
assert(Cond && "ActOnDoStmt(): missing expression");<br>
<br>
CheckBreakContinueBinding(Cond);<br>
- ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc);<br>
+ ExprResult CondResult = CheckBooleanCondition(DoLoc, Cond);<br>
if (CondResult.isInvalid())<br>
return StmtError();<br>
Cond = CondResult.get();<br>
@@ -1644,11 +1608,13 @@ void Sema::CheckBreakContinueBinding(Exp<br>
}<br>
}<br>
<br>
-StmtResult<br>
-Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,<br>
- Stmt *First, FullExprArg second, Decl *secondVar,<br>
- FullExprArg third,<br>
- SourceLocation RParenLoc, Stmt *Body) {<br>
+StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,<br>
+ Stmt *First, ConditionResult Second,<br>
+ FullExprArg third, SourceLocation RParenLoc,<br>
+ Stmt *Body) {<br>
+ if (Second.isInvalid())<br>
+ return StmtError();<br>
+<br>
if (!getLangOpts().CPlusPlus) {<br>
if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {<br>
// C99 6.8.5p3: The declaration part of a 'for' statement shall only<br>
@@ -1666,26 +1632,17 @@ Sema::ActOnForStmt(SourceLocation ForLoc<br>
}<br>
}<br>
<br>
- CheckBreakContinueBinding(second.get());<br>
+ CheckBreakContinueBinding(Second.get().second);<br>
CheckBreakContinueBinding(third.get());<br>
<br>
- CheckForLoopConditionalStatement(*this, second.get(), third.get(), Body);<br>
+ CheckForLoopConditionalStatement(*this, Second.get().second, third.get(),<br>
+ Body);<br>
CheckForRedundantIteration(*this, third.get(), Body);<br>
<br>
- ExprResult SecondResult(second.release());<br>
- VarDecl *ConditionVar = nullptr;<br>
- if (secondVar) {<br>
- ConditionVar = cast<VarDecl>(secondVar);<br>
- SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true);<br>
- SecondResult = ActOnFinishFullExpr(SecondResult.get(), ForLoc);<br>
- if (SecondResult.isInvalid())<br>
- return StmtError();<br>
- }<br>
-<br>
- if (SecondResult.get() &&<br>
+ if (Second.get().second &&<br>
!Diags.isIgnored(diag::warn_comma_operator,<br>
- SecondResult.get()->getExprLoc()))<br>
- CommaVisitor(*this).Visit(SecondResult.get());<br>
+ Second.get().second->getExprLoc()))<br>
+ CommaVisitor(*this).Visit(Second.get().second);<br>
<br>
Expr *Third = third.release().getAs<Expr>();<br>
<br>
@@ -1696,8 +1653,9 @@ Sema::ActOnForStmt(SourceLocation ForLoc<br>
if (isa<NullStmt>(Body))<br>
getCurCompoundScope().setHasEmptyLoopBodies();<br>
<br>
- return new (Context) ForStmt(Context, First, SecondResult.get(), ConditionVar,<br>
- Third, Body, ForLoc, LParenLoc, RParenLoc);<br>
+ return new (Context)<br>
+ ForStmt(Context, First, Second.get().second, Second.get().first, Third,<br>
+ Body, ForLoc, LParenLoc, RParenLoc);<br>
}<br>
<br>
/// In an Objective C collection iteration statement:<br>
@@ -2384,8 +2342,10 @@ Sema::BuildCXXForRangeStmt(SourceLocatio<br>
// Build and check __begin != __end expression.<br>
NotEqExpr = ActOnBinOp(S, ColonLoc, tok::exclaimequal,<br>
BeginRef.get(), EndRef.get());<br>
- NotEqExpr = ActOnBooleanCondition(S, ColonLoc, NotEqExpr.get());<br>
- NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get());<br>
+ if (!NotEqExpr.isInvalid())<br>
+ NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get());<br>
+ if (!NotEqExpr.isInvalid())<br>
+ NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get());<br>
if (NotEqExpr.isInvalid()) {<br>
Diag(RangeLoc, diag::note_for_range_invalid_iterator)<br>
<< RangeLoc << 0 << BeginRangeRef.get()->getType();<br>
<br>
Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jun 23 03:41:20 2016<br>
@@ -410,6 +410,14 @@ public:<br>
return D;<br>
}<br>
<br>
+ /// \brief Transform the specified condition.<br>
+ ///<br>
+ /// By default, this transforms the variable and expression and rebuilds<br>
+ /// the condition.<br>
+ Sema::ConditionResult TransformCondition(SourceLocation Loc, VarDecl *Var,<br>
+ Expr *Expr,<br>
+ Sema::ConditionKind Kind);<br>
+<br>
/// \brief Transform the attributes associated with the given declaration and<br>
/// place them on the new declaration.<br>
///<br>
@@ -1166,10 +1174,9 @@ public:<br>
///<br>
/// By default, performs semantic analysis to build the new statement.<br>
/// Subclasses may override this routine to provide different behavior.<br>
- StmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond,<br>
- VarDecl *CondVar, Stmt *Then,<br>
- SourceLocation ElseLoc, Stmt *Else) {<br>
- return getSema().ActOnIfStmt(IfLoc, Cond, CondVar, Then, ElseLoc, Else);<br>
+ StmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::ConditionResult Cond,<br>
+ Stmt *Then, SourceLocation ElseLoc, Stmt *Else) {<br>
+ return getSema().ActOnIfStmt(IfLoc, Cond, Then, ElseLoc, Else);<br>
}<br>
<br>
/// \brief Start building a new switch statement.<br>
@@ -1177,9 +1184,8 @@ public:<br>
/// By default, performs semantic analysis to build the new statement.<br>
/// Subclasses may override this routine to provide different behavior.<br>
StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc,<br>
- Expr *Cond, VarDecl *CondVar) {<br>
- return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Cond,<br>
- CondVar);<br>
+ Sema::ConditionResult Cond) {<br>
+ return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Cond);<br>
}<br>
<br>
/// \brief Attach the body to the switch statement.<br>
@@ -1195,9 +1201,9 @@ public:<br>
///<br>
/// By default, performs semantic analysis to build the new statement.<br>
/// Subclasses may override this routine to provide different behavior.<br>
- StmtResult RebuildWhileStmt(SourceLocation WhileLoc, Sema::FullExprArg Cond,<br>
- VarDecl *CondVar, Stmt *Body) {<br>
- return getSema().ActOnWhileStmt(WhileLoc, Cond, CondVar, Body);<br>
+ StmtResult RebuildWhileStmt(SourceLocation WhileLoc,<br>
+ Sema::ConditionResult Cond, Stmt *Body) {<br>
+ return getSema().ActOnWhileStmt(WhileLoc, Cond, Body);<br>
}<br>
<br>
/// \brief Build a new do-while statement.<br>
@@ -1216,11 +1222,11 @@ public:<br>
/// By default, performs semantic analysis to build the new statement.<br>
/// Subclasses may override this routine to provide different behavior.<br>
StmtResult RebuildForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,<br>
- Stmt *Init, Sema::FullExprArg Cond,<br>
- VarDecl *CondVar, Sema::FullExprArg Inc,<br>
- SourceLocation RParenLoc, Stmt *Body) {<br>
+ Stmt *Init, Sema::ConditionResult Cond,<br>
+ Sema::FullExprArg Inc, SourceLocation RParenLoc,<br>
+ Stmt *Body) {<br>
return getSema().ActOnForStmt(ForLoc, LParenLoc, Init, Cond,<br>
- CondVar, Inc, RParenLoc, Body);<br>
+ Inc, RParenLoc, Body);<br>
}<br>
<br>
/// \brief Build a new goto statement.<br>
@@ -3357,6 +3363,31 @@ bool TreeTransform<Derived>::TransformEx<br>
return false;<br>
}<br>
<br>
+template <typename Derived><br>
+Sema::ConditionResult TreeTransform<Derived>::TransformCondition(<br>
+ SourceLocation Loc, VarDecl *Var, Expr *Expr, Sema::ConditionKind Kind) {<br>
+ if (Var) {<br>
+ VarDecl *ConditionVar = cast_or_null<VarDecl>(<br>
+ getDerived().TransformDefinition(Var->getLocation(), Var));<br>
+<br>
+ if (!ConditionVar)<br>
+ return Sema::ConditionError();<br>
+<br>
+ return getSema().ActOnConditionVariable(ConditionVar, Loc, Kind);<br>
+ }<br>
+<br>
+ if (Expr) {<br>
+ ExprResult CondExpr = getDerived().TransformExpr(Expr);<br>
+<br>
+ if (CondExpr.isInvalid())<br>
+ return Sema::ConditionError();<br>
+<br>
+ return getSema().ActOnCondition(nullptr, Loc, CondExpr.get(), Kind);<br>
+ }<br>
+<br>
+ return Sema::ConditionResult();<br>
+}<br>
+<br>
template<typename Derived><br>
NestedNameSpecifierLoc<br>
TreeTransform<Derived>::TransformNestedNameSpecifierLoc(<br>
@@ -4962,8 +4993,8 @@ bool TreeTransform<Derived>::TransformEx<br>
if (NoexceptExpr.isInvalid())<br>
return true;<br>
<br>
- NoexceptExpr = getSema().CheckBooleanCondition(<br>
- NoexceptExpr.get(), NoexceptExpr.get()->getLocStart());<br>
+ // FIXME: This is bogus, a noexcept expression is not a condition.<br>
+ NoexceptExpr = getSema().CheckBooleanCondition(Loc, NoexceptExpr.get());<br>
if (NoexceptExpr.isInvalid())<br>
return true;<br>
<br>
@@ -6195,35 +6226,10 @@ template<typename Derived><br>
StmtResult<br>
TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {<br>
// Transform the condition<br>
- ExprResult Cond;<br>
- VarDecl *ConditionVar = nullptr;<br>
- if (S->getConditionVariable()) {<br>
- ConditionVar<br>
- = cast_or_null<VarDecl>(<br>
- getDerived().TransformDefinition(<br>
- S->getConditionVariable()->getLocation(),<br>
- S->getConditionVariable()));<br>
- if (!ConditionVar)<br>
- return StmtError();<br>
- } else {<br>
- Cond = getDerived().TransformExpr(S->getCond());<br>
-<br>
- if (Cond.isInvalid())<br>
- return StmtError();<br>
-<br>
- // Convert the condition to a boolean value.<br>
- if (S->getCond()) {<br>
- ExprResult CondE = getSema().ActOnBooleanCondition(nullptr, S->getIfLoc(),<br>
- Cond.get());<br>
- if (CondE.isInvalid())<br>
- return StmtError();<br>
-<br>
- Cond = CondE.get();<br>
- }<br>
- }<br>
-<br>
- Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get(), S->getIfLoc()));<br>
- if (!S->getConditionVariable() && S->getCond() && !FullCond.get())<br>
+ Sema::ConditionResult Cond = getDerived().TransformCondition(<br>
+ S->getIfLoc(), S->getConditionVariable(), S->getCond(),<br>
+ Sema::ConditionKind::Boolean);<br>
+ if (Cond.isInvalid())<br>
return StmtError();<br>
<br>
// Transform the "then" branch.<br>
@@ -6237,14 +6243,12 @@ TreeTransform<Derived>::TransformIfStmt(<br>
return StmtError();<br>
<br>
if (!getDerived().AlwaysRebuild() &&<br>
- FullCond.get() == S->getCond() &&<br>
- ConditionVar == S->getConditionVariable() &&<br>
+ Cond.get() == std::make_pair(S->getConditionVariable(), S->getCond()) &&<br>
Then.get() == S->getThen() &&<br>
Else.get() == S->getElse())<br>
return S;<br>
<br>
- return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar,<br>
- Then.get(),<br>
+ return getDerived().RebuildIfStmt(S->getIfLoc(), Cond, Then.get(),<br>
S->getElseLoc(), Else.get());<br>
}<br>
<br>
@@ -6252,27 +6256,15 @@ template<typename Derived><br>
StmtResult<br>
TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {<br>
// Transform the condition.<br>
- ExprResult Cond;<br>
- VarDecl *ConditionVar = nullptr;<br>
- if (S->getConditionVariable()) {<br>
- ConditionVar<br>
- = cast_or_null<VarDecl>(<br>
- getDerived().TransformDefinition(<br>
- S->getConditionVariable()->getLocation(),<br>
- S->getConditionVariable()));<br>
- if (!ConditionVar)<br>
- return StmtError();<br>
- } else {<br>
- Cond = getDerived().TransformExpr(S->getCond());<br>
-<br>
- if (Cond.isInvalid())<br>
- return StmtError();<br>
- }<br>
+ Sema::ConditionResult Cond = getDerived().TransformCondition(<br>
+ S->getSwitchLoc(), S->getConditionVariable(), S->getCond(),<br>
+ Sema::ConditionKind::Switch);<br>
+ if (Cond.isInvalid())<br>
+ return StmtError();<br>
<br>
// Rebuild the switch statement.<br>
StmtResult Switch<br>
- = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Cond.get(),<br>
- ConditionVar);<br>
+ = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Cond);<br>
if (Switch.isInvalid())<br>
return StmtError();<br>
<br>
@@ -6290,36 +6282,10 @@ template<typename Derived><br>
StmtResult<br>
TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {<br>
// Transform the condition<br>
- ExprResult Cond;<br>
- VarDecl *ConditionVar = nullptr;<br>
- if (S->getConditionVariable()) {<br>
- ConditionVar<br>
- = cast_or_null<VarDecl>(<br>
- getDerived().TransformDefinition(<br>
- S->getConditionVariable()->getLocation(),<br>
- S->getConditionVariable()));<br>
- if (!ConditionVar)<br>
- return StmtError();<br>
- } else {<br>
- Cond = getDerived().TransformExpr(S->getCond());<br>
-<br>
- if (Cond.isInvalid())<br>
- return StmtError();<br>
-<br>
- if (S->getCond()) {<br>
- // Convert the condition to a boolean value.<br>
- ExprResult CondE = getSema().ActOnBooleanCondition(nullptr,<br>
- S->getWhileLoc(),<br>
- Cond.get());<br>
- if (CondE.isInvalid())<br>
- return StmtError();<br>
- Cond = CondE;<br>
- }<br>
- }<br>
-<br>
- Sema::FullExprArg FullCond(<br>
- getSema().MakeFullExpr(Cond.get(), S->getWhileLoc()));<br>
- if (!S->getConditionVariable() && S->getCond() && !FullCond.get())<br>
+ Sema::ConditionResult Cond = getDerived().TransformCondition(<br>
+ S->getWhileLoc(), S->getConditionVariable(), S->getCond(),<br>
+ Sema::ConditionKind::Boolean);<br>
+ if (Cond.isInvalid())<br>
return StmtError();<br>
<br>
// Transform the body<br>
@@ -6328,13 +6294,11 @@ TreeTransform<Derived>::TransformWhileSt<br>
return StmtError();<br>
<br>
if (!getDerived().AlwaysRebuild() &&<br>
- FullCond.get() == S->getCond() &&<br>
- ConditionVar == S->getConditionVariable() &&<br>
+ Cond.get() == std::make_pair(S->getConditionVariable(), S->getCond()) &&<br>
Body.get() == S->getBody())<br>
return Owned(S);<br>
<br>
- return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond,<br>
- ConditionVar, Body.get());<br>
+ return getDerived().RebuildWhileStmt(S->getWhileLoc(), Cond, Body.get());<br>
}<br>
<br>
template<typename Derived><br>
@@ -6374,37 +6338,10 @@ TreeTransform<Derived>::TransformForStmt<br>
getSema().ActOnOpenMPLoopInitialization(S->getForLoc(), Init.get());<br>
<br>
// Transform the condition<br>
- ExprResult Cond;<br>
- VarDecl *ConditionVar = nullptr;<br>
- if (S->getConditionVariable()) {<br>
- ConditionVar<br>
- = cast_or_null<VarDecl>(<br>
- getDerived().TransformDefinition(<br>
- S->getConditionVariable()->getLocation(),<br>
- S->getConditionVariable()));<br>
- if (!ConditionVar)<br>
- return StmtError();<br>
- } else {<br>
- Cond = getDerived().TransformExpr(S->getCond());<br>
-<br>
- if (Cond.isInvalid())<br>
- return StmtError();<br>
-<br>
- if (S->getCond()) {<br>
- // Convert the condition to a boolean value.<br>
- ExprResult CondE = getSema().ActOnBooleanCondition(nullptr,<br>
- S->getForLoc(),<br>
- Cond.get());<br>
- if (CondE.isInvalid())<br>
- return StmtError();<br>
-<br>
- Cond = CondE.get();<br>
- }<br>
- }<br>
-<br>
- Sema::FullExprArg FullCond(<br>
- getSema().MakeFullExpr(Cond.get(), S->getForLoc()));<br>
- if (!S->getConditionVariable() && S->getCond() && !FullCond.get())<br>
+ Sema::ConditionResult Cond = getDerived().TransformCondition(<br>
+ S->getForLoc(), S->getConditionVariable(), S->getCond(),<br>
+ Sema::ConditionKind::Boolean);<br>
+ if (Cond.isInvalid())<br>
return StmtError();<br>
<br>
// Transform the increment<br>
@@ -6423,14 +6360,14 @@ TreeTransform<Derived>::TransformForStmt<br>
<br>
if (!getDerived().AlwaysRebuild() &&<br>
Init.get() == S->getInit() &&<br>
- FullCond.get() == S->getCond() &&<br>
+ Cond.get() == std::make_pair(S->getConditionVariable(), S->getCond()) &&<br>
Inc.get() == S->getInc() &&<br>
Body.get() == S->getBody())<br>
return S;<br>
<br>
return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(),<br>
- Init.get(), FullCond, ConditionVar,<br>
- FullInc, S->getRParenLoc(), Body.get());<br>
+ Init.get(), Cond, FullInc,<br>
+ S->getRParenLoc(), Body.get());<br>
}<br>
<br>
template<typename Derived><br>
@@ -6924,7 +6861,7 @@ TreeTransform<Derived>::TransformCXXForR<br>
if (Cond.isInvalid())<br>
return StmtError();<br>
if (Cond.get())<br>
- Cond = SemaRef.CheckBooleanCondition(Cond.get(), S->getColonLoc());<br>
+ Cond = SemaRef.CheckBooleanCondition(S->getColonLoc(), Cond.get());<br>
if (Cond.isInvalid())<br>
return StmtError();<br>
if (Cond.get())<br>
<br>
Modified: cfe/trunk/test/FixIt/fixit-vexing-parse.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-vexing-parse.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-vexing-parse.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/FixIt/fixit-vexing-parse.cpp (original)<br>
+++ cfe/trunk/test/FixIt/fixit-vexing-parse.cpp Thu Jun 23 03:41:20 2016<br>
@@ -60,7 +60,7 @@ namespace N {<br>
VO m(int (*p)[4]);<br>
<br>
// Don't emit warning and fixit because direct initializer is not permitted here.<br>
- if (int n(int())){} // expected-error {{function type is not allowed here}} expected-error {{condition must have an initializer}}<br>
+ if (int n(int())){} // expected-error {{function type is not allowed here}}<br>
<br>
// CHECK: fix-it:"{{.*}}":{66:8-66:10}:" = {}"<br>
U u(); // expected-warning {{function declaration}} expected-note {{replace parentheses with an initializer}}<br>
<br>
Modified: cfe/trunk/test/Parser/cxx0x-condition.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-condition.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-condition.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Parser/cxx0x-condition.cpp (original)<br>
+++ cfe/trunk/test/Parser/cxx0x-condition.cpp Thu Jun 23 03:41:20 2016<br>
@@ -23,9 +23,9 @@ void f() {<br>
<br>
if (S b(a)) {} // expected-error {{variable declaration in condition cannot have a parenthesized initializer}}<br>
<br>
- if (S b(n)) {} // expected-error {{a function type is not allowed here}} expected-error {{must have an initializer}}<br>
+ if (S b(n)) {} // expected-error {{a function type is not allowed here}}<br>
if (S b(n) = 0) {} // expected-error {{a function type is not allowed here}}<br>
- if (S b(n) == 0) {} // expected-error {{a function type is not allowed here}} expected-error {{did you mean '='?}}<br>
+ if (S b(n) == 0) {} // expected-error {{a function type is not allowed here}}<br>
<br>
S s(a);<br>
if (S{s}) {} // ok<br>
<br>
Modified: cfe/trunk/test/SemaCXX/crashes.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/crashes.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/crashes.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/crashes.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/crashes.cpp Thu Jun 23 03:41:20 2016<br>
@@ -105,8 +105,7 @@ namespace PR9026 {<br>
namespace PR10270 {<br>
template<typename T> class C;<br>
template<typename T> void f() {<br>
- if (C<T> == 1) // expected-error{{expected unqualified-id}} \<br>
- // expected-error{{invalid '==' at end of declaration}}<br>
+ if (C<T> == 1) // expected-error{{expected unqualified-id}}<br>
return;<br>
}<br>
}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/for-range-examples.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-examples.cpp?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-examples.cpp?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/for-range-examples.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/for-range-examples.cpp Thu Jun 23 03:41:20 2016<br>
@@ -176,9 +176,9 @@ namespace test4 {<br>
<br>
// Make sure these don't crash. Better diagnostics would be nice.<br>
for (: {1, 2, 3}) {} // expected-error {{expected expression}} expected-error {{expected ';'}}<br>
- for (1 : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}}<br>
+ for (1 : {1, 2, 3}) {} // expected-error {{must declare a variable}}<br>
for (+x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}}<br>
- for (+y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}}<br>
+ for (+y : {1, 2, 3}) {} // expected-error {{must declare a variable}}<br>
}<br>
}<br>
<br>
<br>
Modified: cfe/trunk/test/SemaObjCXX/<a href="http://foreach.mm" rel="noreferrer" target="_blank">foreach.mm</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/foreach.mm?rev=273548&r1=273547&r2=273548&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/foreach.mm?rev=273548&r1=273547&r2=273548&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaObjCXX/<a href="http://foreach.mm" rel="noreferrer" target="_blank">foreach.mm</a> (original)<br>
+++ cfe/trunk/test/SemaObjCXX/<a href="http://foreach.mm" rel="noreferrer" target="_blank">foreach.mm</a> Thu Jun 23 03:41:20 2016<br>
@@ -6,10 +6,8 @@<br>
void f(NSArray *a) {<br>
id keys;<br>
for (int i : a); // expected-error{{selector element type 'int' is not a valid object}}<br>
- for ((id)2 : a); // expected-error {{for range declaration must declare a variable}} \<br>
- // expected-warning {{expression result unused}}<br>
- for (2 : a); // expected-error {{for range declaration must declare a variable}} \<br>
- // expected-warning {{expression result unused}}<br>
+ for ((id)2 : a); // expected-error {{for range declaration must declare a variable}}<br>
+ for (2 : a); // expected-error {{for range declaration must declare a variable}}<br>
<br>
for (id thisKey : keys);<br>
<br>
@@ -65,8 +63,7 @@ int main ()<br>
@end<br>
void test2(NSObject<NSFastEnumeration> *collection) {<br>
Test2 *obj;<br>
- for (obj.prop : collection) { // expected-error {{for range declaration must declare a variable}} \<br>
- // expected-warning {{property access result unused - getters should not be used for side effects}}<br>
+ for (obj.prop : collection) { // expected-error {{for range declaration must declare a variable}}<br>
}<br>
}<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>