diff options
-rw-r--r-- | include/clang/Parse/Parser.h | 9 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 75 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 7 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 44 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 80 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 24 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 24 | ||||
-rw-r--r-- | lib/Sema/SemaOpenMP.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 157 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 209 | ||||
-rw-r--r-- | test/FixIt/fixit-vexing-parse.cpp | 2 | ||||
-rw-r--r-- | test/Parser/cxx0x-condition.cpp | 4 | ||||
-rw-r--r-- | test/SemaCXX/crashes.cpp | 3 | ||||
-rw-r--r-- | test/SemaCXX/for-range-examples.cpp | 4 | ||||
-rw-r--r-- | test/SemaObjCXX/foreach.mm | 9 |
16 files changed, 295 insertions, 374 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 9cbad6b634..3ddbcf5245 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1588,8 +1588,8 @@ private: //===--------------------------------------------------------------------===// // C++ if/switch/while condition expression. - bool ParseCXXCondition(ExprResult &ExprResult, Decl *&DeclResult, - SourceLocation Loc, bool ConvertToBoolean); + Sema::ConditionResult ParseCXXCondition(SourceLocation Loc, + Sema::ConditionKind CK); //===--------------------------------------------------------------------===// // C++ Coroutines @@ -1680,10 +1680,9 @@ private: unsigned ScopeFlags); void ParseCompoundStatementLeadingPragmas(); StmtResult ParseCompoundStatementBody(bool isStmtExpr = false); - bool ParseParenExprOrCondition(ExprResult &ExprResult, - Decl *&DeclResult, + bool ParseParenExprOrCondition(Sema::ConditionResult &CondResult, SourceLocation Loc, - bool ConvertToBoolean); + Sema::ConditionKind CK); StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc); StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc); StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 977ffb4dd2..7f2a942962 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3298,6 +3298,7 @@ public: public: class FullExprArg { public: + FullExprArg() : E(nullptr) { } FullExprArg(Sema &actions) : E(nullptr) { } ExprResult release() { @@ -3391,27 +3392,23 @@ public: ArrayRef<const Attr*> Attrs, Stmt *SubStmt); - StmtResult ActOnIfStmt(SourceLocation IfLoc, - FullExprArg CondVal, Decl *CondVar, - Stmt *ThenVal, - SourceLocation ElseLoc, Stmt *ElseVal); + class ConditionResult; + StmtResult ActOnIfStmt(SourceLocation IfLoc, ConditionResult Cond, + Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal); StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, - Expr *Cond, - Decl *CondVar); + ConditionResult Cond); StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, Stmt *Body); - StmtResult ActOnWhileStmt(SourceLocation WhileLoc, - FullExprArg Cond, - Decl *CondVar, Stmt *Body); + StmtResult ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond, + Stmt *Body); StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, - SourceLocation WhileLoc, - SourceLocation CondLParen, Expr *Cond, - SourceLocation CondRParen); + SourceLocation WhileLoc, SourceLocation CondLParen, + Expr *Cond, SourceLocation CondRParen); StmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - Stmt *First, FullExprArg Second, - Decl *SecondVar, + Stmt *First, + ConditionResult Second, FullExprArg Third, SourceLocation RParenLoc, Stmt *Body); @@ -4801,11 +4798,6 @@ public: bool WarnOnNonAbstractTypes, SourceLocation DtorLoc); - DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D); - ExprResult CheckConditionVariable(VarDecl *ConditionVar, - SourceLocation StmtLoc, - bool ConvertToBoolean); - ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen, Expr *Operand, SourceLocation RParen); ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand, @@ -8923,6 +8915,46 @@ public: /// type, and if so, emit a note describing what happened. void EmitRelatedResultTypeNoteForReturn(QualType destType); + class ConditionResult { + Decl *ConditionVar; + FullExprArg Condition; + bool Invalid; + + friend class Sema; + ConditionResult(Decl *ConditionVar, FullExprArg Condition) + : ConditionVar(ConditionVar), Condition(Condition), Invalid(false) {} + explicit ConditionResult(bool Invalid) + : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid) {} + + public: + ConditionResult() : ConditionResult(false) {} + bool isInvalid() const { return Invalid; } + std::pair<VarDecl *, Expr *> get() const { + return std::make_pair(cast_or_null<VarDecl>(ConditionVar), + Condition.get()); + } + }; + static ConditionResult ConditionError() { return ConditionResult(true); } + + enum class ConditionKind { + Boolean, ///< A boolean condition, from 'if', 'while', 'for', or 'do'. + Switch ///< An integral condition for a 'switch' statement. + }; + + ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, + Expr *SubExpr, ConditionKind CK); + + ConditionResult ActOnConditionVariable(Decl *ConditionVar, + SourceLocation StmtLoc, + ConditionKind CK); + + DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D); + + ExprResult CheckConditionVariable(VarDecl *ConditionVar, + SourceLocation StmtLoc, + ConditionKind CK); + ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond); + /// CheckBooleanCondition - Diagnose problems involving the use of /// the given expression as a boolean condition (e.g. in an if /// statement). Also performs the standard function and array @@ -8931,10 +8963,7 @@ public: /// \param Loc - A location associated with the condition, e.g. the /// 'if' keyword. /// \return true iff there were any errors - ExprResult CheckBooleanCondition(Expr *E, SourceLocation Loc); - - ExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc, - Expr *SubExpr); + ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E); /// DiagnoseAssignmentAsCondition - Given that an expression is /// being used as a boolean condition, warn if it's an assignment. diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index d55b2d9442..5718e1e50e 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -3420,10 +3420,11 @@ Parser::tryParseExceptionSpecification(bool Delayed, NoexceptExpr = ParseConstantExpression(); T.consumeClose(); // The argument must be contextually convertible to bool. We use - // ActOnBooleanCondition for this purpose. + // CheckBooleanCondition for this purpose. + // FIXME: Add a proper Sema entry point for this. if (!NoexceptExpr.isInvalid()) { - NoexceptExpr = Actions.ActOnBooleanCondition(getCurScope(), KeywordLoc, - NoexceptExpr.get()); + NoexceptExpr = + Actions.CheckBooleanCondition(KeywordLoc, NoexceptExpr.get()); NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation()); } else { NoexceptType = EST_None; diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index b0740970d8..00f20e5e7b 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1726,27 +1726,19 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { /// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] /// '=' assignment-expression /// -/// \param ExprOut if the condition was parsed as an expression, the parsed -/// expression. -/// -/// \param DeclOut if the condition was parsed as a declaration, the parsed -/// declaration. -/// /// \param Loc The location of the start of the statement that requires this /// condition, e.g., the "for" in a for loop. /// /// \param ConvertToBoolean Whether the condition expression should be /// converted to a boolean value. /// -/// \returns true if there was a parsing, false otherwise. -bool Parser::ParseCXXCondition(ExprResult &ExprOut, - Decl *&DeclOut, - SourceLocation Loc, - bool ConvertToBoolean) { +/// \returns The parsed condition. +Sema::ConditionResult Parser::ParseCXXCondition(SourceLocation Loc, + Sema::ConditionKind CK) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition); cutOffParsing(); - return true; + return Sema::ConditionError(); } ParsedAttributesWithRange attrs(AttrFactory); @@ -1756,16 +1748,11 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, ProhibitAttributes(attrs); // Parse the expression. - ExprOut = ParseExpression(); // expression - DeclOut = nullptr; - if (ExprOut.isInvalid()) - return true; + ExprResult Expr = ParseExpression(); // expression + if (Expr.isInvalid()) + return Sema::ConditionError(); - // If required, convert to a boolean value. - if (ConvertToBoolean) - ExprOut - = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprOut.get()); - return ExprOut.isInvalid(); + return Actions.ActOnCondition(getCurScope(), Loc, Expr.get(), CK); } // type-specifier-seq @@ -1783,7 +1770,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, ExprResult AsmLabel(ParseSimpleAsm(&Loc)); if (AsmLabel.isInvalid()) { SkipUntil(tok::semi, StopAtSemi); - return true; + return Sema::ConditionError(); } DeclaratorInfo.setAsmLabel(AsmLabel.get()); DeclaratorInfo.SetRangeEnd(Loc); @@ -1795,8 +1782,9 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, // Type-check the declaration itself. DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(), DeclaratorInfo); - DeclOut = Dcl.get(); - ExprOut = ExprError(); + if (Dcl.isInvalid()) + return Sema::ConditionError(); + Decl *DeclOut = Dcl.get(); // '=' assignment-expression // If a '==' or '+=' is found, suggest a fixit to '='. @@ -1816,12 +1804,11 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, SourceLocation LParen = ConsumeParen(), RParen = LParen; if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) RParen = ConsumeParen(); - Diag(DeclOut ? DeclOut->getLocation() : LParen, + Diag(DeclOut->getLocation(), diag::err_expected_init_in_condition_lparen) << SourceRange(LParen, RParen); } else { - Diag(DeclOut ? DeclOut->getLocation() : Tok.getLocation(), - diag::err_expected_init_in_condition); + Diag(DeclOut->getLocation(), diag::err_expected_init_in_condition); } if (!InitExpr.isInvalid()) @@ -1834,8 +1821,7 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, // (This is currently handled by Sema). Actions.FinalizeDeclaration(DeclOut); - - return false; + return Actions.ActOnConditionVariable(DeclOut, Loc, CK); } /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 8173d09cbb..c849554238 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1052,29 +1052,28 @@ 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(ExprResult &ExprResult, - Decl *&DeclResult, +bool Parser::ParseParenExprOrCondition(Sema::ConditionResult &Cond, SourceLocation Loc, - bool ConvertToBoolean) { + Sema::ConditionKind CK) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); if (getLangOpts().CPlusPlus) - ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean); + Cond = ParseCXXCondition(Loc, CK); else { - ExprResult = ParseExpression(); - DeclResult = nullptr; + ExprResult CondExpr = ParseExpression(); // If required, convert to a boolean value. - if (!ExprResult.isInvalid() && ConvertToBoolean) - ExprResult - = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprResult.get()); + if (CondExpr.isInvalid()) + Cond = Sema::ConditionError(); + else + Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK); } // 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 (ExprResult.isInvalid() && !DeclResult && Tok.isNot(tok::r_paren)) { + if (Cond.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. @@ -1132,13 +1131,10 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX); // Parse the condition. - ExprResult CondExp; - Decl *CondVar = nullptr; - if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true)) + Sema::ConditionResult Cond; + if (ParseParenExprOrCondition(Cond, IfLoc, Sema::ConditionKind::Boolean)) 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. @@ -1221,8 +1217,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { if (ElseStmt.isInvalid()) ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc); - return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, ThenStmt.get(), - ElseLoc, ElseStmt.get()); + return Actions.ActOnIfStmt(IfLoc, Cond, ThenStmt.get(), ElseLoc, + ElseStmt.get()); } /// ParseSwitchStatement @@ -1259,13 +1255,11 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { ParseScope SwitchScope(this, ScopeFlags); // Parse the condition. - ExprResult Cond; - Decl *CondVar = nullptr; - if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false)) + Sema::ConditionResult Cond; + if (ParseParenExprOrCondition(Cond, SwitchLoc, Sema::ConditionKind::Switch)) return StmtError(); - StmtResult Switch - = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar); + StmtResult Switch = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond); if (Switch.isInvalid()) { // Skip the switch body. @@ -1347,13 +1341,10 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { ParseScope WhileScope(this, ScopeFlags); // Parse the condition. - ExprResult Cond; - Decl *CondVar = nullptr; - if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true)) + Sema::ConditionResult Cond; + if (ParseParenExprOrCondition(Cond, WhileLoc, Sema::ConditionKind::Boolean)) 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. @@ -1374,10 +1365,10 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { InnerScope.Exit(); WhileScope.Exit(); - if ((Cond.isInvalid() && !CondVar) || Body.isInvalid()) + if (Cond.isInvalid() || Body.isInvalid()) return StmtError(); - return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, Body.get()); + return Actions.ActOnWhileStmt(WhileLoc, Cond, Body.get()); } /// ParseDoStatement @@ -1535,12 +1526,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { bool ForEach = false, ForRange = false; StmtResult FirstPart; - bool SecondPartIsInvalid = false; - FullExprArg SecondPart(Actions); + Sema::ConditionResult SecondPart; ExprResult Collection; ForRangeInit ForRangeInit; FullExprArg ThirdPart(Actions); - Decl *SecondVar = nullptr; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), @@ -1645,7 +1634,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { Diag(Tok, diag::err_for_range_expected_decl) << FirstPart.get()->getSourceRange(); SkipUntil(tok::r_paren, StopBeforeMatch); - SecondPartIsInvalid = true; + SecondPart = Sema::ConditionError(); } else { if (!Value.isInvalid()) { Diag(Tok, diag::err_expected_semi_for); @@ -1660,29 +1649,28 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // Parse the second part of the for specifier. getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope); - if (!ForEach && !ForRange) { - assert(!SecondPart.get() && "Shouldn't have a second expression yet."); + if (!ForEach && !ForRange && !SecondPart.isInvalid()) { // 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) - ParseCXXCondition(Second, SecondVar, ForLoc, true); + SecondPart = ParseCXXCondition(ForLoc, Sema::ConditionKind::Boolean); else { - Second = ParseExpression(); - if (!Second.isInvalid()) - Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc, - Second.get()); + ExprResult SecondExpr = ParseExpression(); + if (SecondExpr.isInvalid()) + SecondPart = Sema::ConditionError(); + else + SecondPart = + Actions.ActOnCondition(getCurScope(), ForLoc, SecondExpr.get(), + Sema::ConditionKind::Boolean); } - SecondPartIsInvalid = Second.isInvalid(); - SecondPart = Actions.MakeFullExpr(Second.get(), ForLoc); } if (Tok.isNot(tok::semi)) { - if (!SecondPartIsInvalid || SecondVar) + if (!SecondPart.isInvalid()) Diag(Tok, diag::err_expected_semi_for); else // Skip until semicolon or rparen, don't consume it. @@ -1781,8 +1769,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), - SecondPart, SecondVar, ThirdPart, - T.getCloseLocation(), Body.get()); + SecondPart, ThirdPart, T.getCloseLocation(), + Body.get()); } /// ParseGotoStatement diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 00d5651b14..8eeaef7df5 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -10092,10 +10092,10 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, SizeType, VK_LValue, OK_Ordinary, Loc); // Construct the loop that copies all elements of this array. - return S.ActOnForStmt(Loc, Loc, InitStmt, - S.MakeFullExpr(Comparison), - nullptr, S.MakeFullDiscardedValueExpr(Increment), - Loc, Copy.get()); + return S.ActOnForStmt( + Loc, Loc, InitStmt, + S.ActOnCondition(nullptr, Loc, Comparison, Sema::ConditionKind::Boolean), + S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.get()); } static StmtResult diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 755d99d54b..f975b817e0 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -14341,7 +14341,7 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) { } } -ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) { +ExprResult Sema::CheckBooleanCondition(SourceLocation Loc, Expr *E) { DiagnoseAssignmentAsCondition(E); if (ParenExpr *parenE = dyn_cast<ParenExpr>(E)) DiagnoseEqualityWithExtraParens(parenE); @@ -14371,12 +14371,26 @@ ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) { return E; } -ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc, - Expr *SubExpr) { +Sema::ConditionResult Sema::ActOnCondition(Scope *S, SourceLocation Loc, + Expr *SubExpr, ConditionKind CK) { + // Empty conditions are valid in for-statements. if (!SubExpr) - return ExprError(); + return ConditionResult(); + + ExprResult Cond; + switch (CK) { + case ConditionKind::Boolean: + Cond = CheckBooleanCondition(Loc, SubExpr); + break; + + case ConditionKind::Switch: + Cond = CheckSwitchCondition(Loc, SubExpr); + break; + } + if (Cond.isInvalid()) + return ConditionError(); - return CheckBooleanCondition(SubExpr, Loc); + return ConditionResult(nullptr, MakeFullExpr(Cond.get(), Loc)); } namespace { diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index d5e944fa11..f97b9c9d81 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -3054,11 +3054,21 @@ void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc, } } +Sema::ConditionResult Sema::ActOnConditionVariable(Decl *ConditionVar, + SourceLocation StmtLoc, + ConditionKind CK) { + ExprResult E = + CheckConditionVariable(cast<VarDecl>(ConditionVar), StmtLoc, CK); + if (E.isInvalid()) + return ConditionError(); + return ConditionResult(ConditionVar, MakeFullExpr(E.get(), StmtLoc)); +} + /// \brief Check the use of the given variable as a C++ condition in an if, /// while, do-while, or switch statement. ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, SourceLocation StmtLoc, - bool ConvertToBoolean) { + ConditionKind CK) { if (ConditionVar->isInvalidDecl()) return ExprError(); @@ -3082,13 +3092,15 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, MarkDeclRefReferenced(cast<DeclRefExpr>(Condition.get())); - if (ConvertToBoolean) { - Condition = CheckBooleanCondition(Condition.get(), StmtLoc); - if (Condition.isInvalid()) - return ExprError(); + switch (CK) { + case ConditionKind::Boolean: + return CheckBooleanCondition(StmtLoc, Condition.get()); + + case ConditionKind::Switch: + return CheckSwitchCondition(StmtLoc, Condition.get()); } - return Condition; + llvm_unreachable("unexpected condition kind"); } /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 5f28aa37e6..ca84b8cfed 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -6826,12 +6826,11 @@ OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, if (!Condition->isValueDependent() && !Condition->isTypeDependent() && !Condition->isInstantiationDependent() && !Condition->containsUnexpandedParameterPack()) { - ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(), - Condition->getExprLoc(), Condition); + ExprResult Val = CheckBooleanCondition(StartLoc, Condition); if (Val.isInvalid()) return nullptr; - ValExpr = Val.get(); + ValExpr = MakeFullExpr(Val.get()).get(); } return new (Context) OMPIfClause(NameModifier, ValExpr, StartLoc, LParenLoc, @@ -6846,12 +6845,11 @@ OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition, if (!Condition->isValueDependent() && !Condition->isTypeDependent() && !Condition->isInstantiationDependent() && !Condition->containsUnexpandedParameterPack()) { - ExprResult Val = ActOnBooleanCondition(DSAStack->getCurScope(), - Condition->getExprLoc(), Condition); + ExprResult Val = CheckBooleanCondition(StartLoc, Condition); if (Val.isInvalid()) return nullptr; - ValExpr = Val.get(); + ValExpr = MakeFullExpr(Val.get()).get(); } return new (Context) OMPFinalClause(ValExpr, StartLoc, LParenLoc, EndLoc); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 7156cd2a9a..8d5bec80a1 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -504,39 +504,30 @@ public: } StmtResult -Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, +Sema::ActOnIfStmt(SourceLocation IfLoc, ConditionResult Cond, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { - ExprResult CondResult(CondVal.release()); - - VarDecl *ConditionVar = nullptr; - if (CondVar) { - ConditionVar = cast<VarDecl>(CondVar); - CondResult = CheckConditionVariable(ConditionVar, IfLoc, true); - CondResult = ActOnFinishFullExpr(CondResult.get(), IfLoc); + auto CondVal = Cond.get(); + if (Cond.isInvalid()) { + CondVal.first = nullptr; + CondVal.second = new (Context) + OpaqueValueExpr(SourceLocation(), Context.BoolTy, VK_RValue); } - Expr *ConditionExpr = CondResult.getAs<Expr>(); - if (ConditionExpr) { - - if (!Diags.isIgnored(diag::warn_comma_operator, - ConditionExpr->getExprLoc())) - CommaVisitor(*this).Visit(ConditionExpr); - DiagnoseUnusedExprResult(thenStmt); + if (!Diags.isIgnored(diag::warn_comma_operator, + CondVal.second->getExprLoc())) + CommaVisitor(*this).Visit(CondVal.second); - if (!elseStmt) { - DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, - diag::warn_empty_if_body); - } + DiagnoseUnusedExprResult(thenStmt); - DiagnoseUnusedExprResult(elseStmt); - } else { - // Create a dummy Expr for the condition for error recovery - ConditionExpr = new (Context) OpaqueValueExpr(SourceLocation(), - Context.BoolTy, VK_RValue); + if (!elseStmt) { + DiagnoseEmptyStmtBody(CondVal.second->getLocEnd(), thenStmt, + diag::warn_empty_if_body); } - return new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, + DiagnoseUnusedExprResult(elseStmt); + + return new (Context) IfStmt(Context, IfLoc, CondVal.first, CondVal.second, thenStmt, ElseLoc, elseStmt); } @@ -599,24 +590,7 @@ static QualType GetTypeBeforeIntegralPromotion(Expr *&expr) { return expr->getType(); } -StmtResult -Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, - Decl *CondVar) { - ExprResult CondResult; - - VarDecl *ConditionVar = nullptr; - if (CondVar) { - ConditionVar = cast<VarDecl>(CondVar); - CondResult = CheckConditionVariable(ConditionVar, SourceLocation(), false); - if (CondResult.isInvalid()) - return StmtError(); - - Cond = CondResult.get(); - } - - if (!Cond) - return StmtError(); - +ExprResult Sema::CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond) { class SwitchConvertDiagnoser : public ICEConvertDiagnoser { Expr *Cond; @@ -664,24 +638,24 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, } } SwitchDiagnoser(Cond); - CondResult = + ExprResult CondResult = PerformContextualImplicitConversion(SwitchLoc, Cond, SwitchDiagnoser); - if (CondResult.isInvalid()) return StmtError(); - Cond = CondResult.get(); + if (CondResult.isInvalid()) + return ExprError(); // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr. - CondResult = UsualUnaryConversions(Cond); - if (CondResult.isInvalid()) return StmtError(); - Cond = CondResult.get(); + return UsualUnaryConversions(CondResult.get()); +} - CondResult = ActOnFinishFullExpr(Cond, SwitchLoc); - if (CondResult.isInvalid()) +StmtResult +Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ConditionResult Cond) { + if (Cond.isInvalid()) return StmtError(); - Cond = CondResult.get(); getCurFunction()->setHasBranchIntoScope(); - SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, Cond); + SwitchStmt *SS = + new (Context) SwitchStmt(Context, Cond.get().first, Cond.get().second); getCurFunction()->SwitchStack.push_back(SS); return SS; } @@ -1242,27 +1216,17 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, } } -StmtResult -Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, - Decl *CondVar, Stmt *Body) { - ExprResult CondResult(Cond.release()); - - VarDecl *ConditionVar = nullptr; - if (CondVar) { - ConditionVar = cast<VarDecl>(CondVar); - CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true); - CondResult = ActOnFinishFullExpr(CondResult.get(), WhileLoc); - if (CondResult.isInvalid()) - return StmtError(); - } - Expr *ConditionExpr = CondResult.get(); - if (!ConditionExpr) +StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond, + Stmt *Body) { + if (Cond.isInvalid()) return StmtError(); - CheckBreakContinueBinding(ConditionExpr); - if (ConditionExpr && - !Diags.isIgnored(diag::warn_comma_operator, ConditionExpr->getExprLoc())) - CommaVisitor(*this).Visit(ConditionExpr); + auto CondVal = Cond.get(); + CheckBreakContinueBinding(CondVal.second); + + if (CondVal.second && + !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc())) + CommaVisitor(*this).Visit(CondVal.second); DiagnoseUnusedExprResult(Body); @@ -1270,7 +1234,7 @@ Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, getCurCompoundScope().setHasEmptyLoopBodies(); return new (Context) - WhileStmt(Context, ConditionVar, ConditionExpr, Body, WhileLoc); + WhileStmt(Context, CondVal.first, CondVal.second, Body, WhileLoc); } StmtResult @@ -1280,7 +1244,7 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, assert(Cond && "ActOnDoStmt(): missing expression"); CheckBreakContinueBinding(Cond); - ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc); + ExprResult CondResult = CheckBooleanCondition(DoLoc, Cond); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.get(); @@ -1644,11 +1608,13 @@ void Sema::CheckBreakContinueBinding(Expr *E) { } } -StmtResult -Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - Stmt *First, FullExprArg second, Decl *secondVar, - FullExprArg third, - SourceLocation RParenLoc, Stmt *Body) { +StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, + Stmt *First, ConditionResult Second, + FullExprArg third, SourceLocation RParenLoc, + Stmt *Body) { + if (Second.isInvalid()) + return StmtError(); + if (!getLangOpts().CPlusPlus) { if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) { // C99 6.8.5p3: The declaration part of a 'for' statement shall only @@ -1666,26 +1632,18 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, } } - CheckBreakContinueBinding(second.get()); + CheckBreakContinueBinding(Second.get().second); CheckBreakContinueBinding(third.get()); - CheckForLoopConditionalStatement(*this, second.get(), third.get(), Body); + if (!Second.get().first) + CheckForLoopConditionalStatement(*this, Second.get().second, third.get(), + Body); CheckForRedundantIteration(*this, third.get(), Body); - ExprResult SecondResult(second.release()); - VarDecl *ConditionVar = nullptr; - if (secondVar) { - ConditionVar = cast<VarDecl>(secondVar); - SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true); - SecondResult = ActOnFinishFullExpr(SecondResult.get(), ForLoc); - if (SecondResult.isInvalid()) - return StmtError(); - } - - if (SecondResult.get() && + if (Second.get().second && !Diags.isIgnored(diag::warn_comma_operator, - SecondResult.get()->getExprLoc())) - CommaVisitor(*this).Visit(SecondResult.get()); + Second.get().second->getExprLoc())) + CommaVisitor(*this).Visit(Second.get().second); Expr *Third = third.release().getAs<Expr>(); @@ -1696,8 +1654,9 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, if (isa<NullStmt>(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); - return new (Context) ForStmt(Context, First, SecondResult.get(), ConditionVar, - Third, Body, ForLoc, LParenLoc, RParenLoc); + return new (Context) + ForStmt(Context, First, Second.get().second, Second.get().first, Third, + Body, ForLoc, LParenLoc, RParenLoc); } /// In an Objective C collection iteration statement: @@ -2384,8 +2343,10 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc, // Build and check __begin != __end expression. NotEqExpr = ActOnBinOp(S, ColonLoc, tok::exclaimequal, BeginRef.get(), EndRef.get()); - NotEqExpr = ActOnBooleanCondition(S, ColonLoc, NotEqExpr.get()); - NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); + if (!NotEqExpr.isInvalid()) + NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get()); + if (!NotEqExpr.isInvalid()) + NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); if (NotEqExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 0 << BeginRangeRef.get()->getType(); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 4bdd9e548a..5814197a7a 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -410,6 +410,14 @@ public: return D; } + /// \brief Transform the specified condition. + /// + /// By default, this transforms the variable and expression and rebuilds + /// the condition. + Sema::ConditionResult TransformCondition(SourceLocation Loc, VarDecl *Var, + Expr *Expr, + Sema::ConditionKind Kind); + /// \brief Transform the attributes associated with the given declaration and /// place them on the new declaration. /// @@ -1166,10 +1174,9 @@ public: /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond, - VarDecl *CondVar, Stmt *Then, - SourceLocation ElseLoc, Stmt *Else) { - return getSema().ActOnIfStmt(IfLoc, Cond, CondVar, Then, ElseLoc, Else); + StmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::ConditionResult Cond, + Stmt *Then, SourceLocation ElseLoc, Stmt *Else) { + return getSema().ActOnIfStmt(IfLoc, Cond, Then, ElseLoc, Else); } /// \brief Start building a new switch statement. @@ -1177,9 +1184,8 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc, - Expr *Cond, VarDecl *CondVar) { - return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Cond, - CondVar); + Sema::ConditionResult Cond) { + return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Cond); } /// \brief Attach the body to the switch statement. @@ -1195,9 +1201,9 @@ public: /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildWhileStmt(SourceLocation WhileLoc, Sema::FullExprArg Cond, - VarDecl *CondVar, Stmt *Body) { - return getSema().ActOnWhileStmt(WhileLoc, Cond, CondVar, Body); + StmtResult RebuildWhileStmt(SourceLocation WhileLoc, + Sema::ConditionResult Cond, Stmt *Body) { + return getSema().ActOnWhileStmt(WhileLoc, Cond, Body); } /// \brief Build a new do-while statement. @@ -1216,11 +1222,11 @@ public: /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. StmtResult RebuildForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - Stmt *Init, Sema::FullExprArg Cond, - VarDecl *CondVar, Sema::FullExprArg Inc, - SourceLocation RParenLoc, Stmt *Body) { + Stmt *Init, Sema::ConditionResult Cond, + Sema::FullExprArg Inc, SourceLocation RParenLoc, + Stmt *Body) { return getSema().ActOnForStmt(ForLoc, LParenLoc, Init, Cond, - CondVar, Inc, RParenLoc, Body); + Inc, RParenLoc, Body); } /// \brief Build a new goto statement. @@ -3357,6 +3363,31 @@ bool TreeTransform<Derived>::TransformExprs(Expr *const *Inputs, return false; } +template <typename Derived> +Sema::ConditionResult TreeTransform<Derived>::TransformCondition( + SourceLocation Loc, VarDecl *Var, Expr *Expr, Sema::ConditionKind Kind) { + if (Var) { + VarDecl *ConditionVar = cast_or_null<VarDecl>( + getDerived().TransformDefinition(Var->getLocation(), Var)); + + if (!ConditionVar) + return Sema::ConditionError(); + + return getSema().ActOnConditionVariable(ConditionVar, Loc, Kind); + } + + if (Expr) { + ExprResult CondExpr = getDerived().TransformExpr(Expr); + + if (CondExpr.isInvalid()) + return Sema::ConditionError(); + + return getSema().ActOnCondition(nullptr, Loc, CondExpr.get(), Kind); + } + + return Sema::ConditionResult(); +} + template<typename Derived> NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc( @@ -4962,8 +4993,8 @@ bool TreeTransform<Derived>::TransformExceptionSpec( if (NoexceptExpr.isInvalid()) return true; - NoexceptExpr = getSema().CheckBooleanCondition( - NoexceptExpr.get(), NoexceptExpr.get()->getLocStart()); + // FIXME: This is bogus, a noexcept expression is not a condition. + NoexceptExpr = getSema().CheckBooleanCondition(Loc, NoexceptExpr.get()); if (NoexceptExpr.isInvalid()) return true; @@ -6195,35 +6226,10 @@ template<typename Derived> StmtResult TreeTransform<Derived>::TransformIfStmt(IfStmt *S) { // Transform the condition - ExprResult Cond; - VarDecl *ConditionVar = nullptr; - if (S->getConditionVariable()) { - ConditionVar - = cast_or_null<VarDecl>( - getDerived().TransformDefinition( - S->getConditionVariable()->getLocation(), - S->getConditionVariable())); - if (!ConditionVar) - return StmtError(); - } else { - Cond = getDerived().TransformExpr(S->getCond()); - - if (Cond.isInvalid()) - return StmtError(); - - // Convert the condition to a boolean value. - if (S->getCond()) { - ExprResult CondE = getSema().ActOnBooleanCondition(nullptr, S->getIfLoc(), - Cond.get()); - if (CondE.isInvalid()) - return StmtError(); - - Cond = CondE.get(); - } - } - - Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.get(), S->getIfLoc())); - if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) + Sema::ConditionResult Cond = getDerived().TransformCondition( + S->getIfLoc(), S->getConditionVariable(), S->getCond(), + Sema::ConditionKind::Boolean); + if (Cond.isInvalid()) return StmtError(); // Transform the "then" branch. @@ -6237,14 +6243,12 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) { return StmtError(); if (!getDerived().AlwaysRebuild() && - FullCond.get() == S->getCond() && - ConditionVar == S->getConditionVariable() && + Cond.get() == std::make_pair(S->getConditionVariable(), S->getCond()) && Then.get() == S->getThen() && Else.get() == S->getElse()) return S; - return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar, - Then.get(), + return getDerived().RebuildIfStmt(S->getIfLoc(), Cond, Then.get(), S->getElseLoc(), Else.get()); } @@ -6252,27 +6256,15 @@ template<typename Derived> StmtResult TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) { // Transform the condition. - ExprResult Cond; - VarDecl *ConditionVar = nullptr; - if (S->getConditionVariable()) { - ConditionVar - = cast_or_null<VarDecl>( - getDerived().TransformDefinition( - S->getConditionVariable()->getLocation(), - S->getConditionVariable())); - if (!ConditionVar) - return StmtError(); - } else { - Cond = getDerived().TransformExpr(S->getCond()); - - if (Cond.isInvalid()) - return StmtError(); - } + Sema::ConditionResult Cond = getDerived().TransformCondition( + S->getSwitchLoc(), S->getConditionVariable(), S->getCond(), + Sema::ConditionKind::Switch); + if (Cond.isInvalid()) + return StmtError(); // Rebuild the switch statement. StmtResult Switch - = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Cond.get(), - ConditionVar); + = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Cond); if (Switch.isInvalid()) return StmtError(); @@ -6290,36 +6282,10 @@ template<typename Derived> StmtResult TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) { // Transform the condition - ExprResult Cond; - VarDecl *ConditionVar = nullptr; - if (S->getConditionVariable()) { - ConditionVar - = cast_or_null<VarDecl>( - getDerived().TransformDefinition( - S->getConditionVariable()->getLocation(), - S->getConditionVariable())); - if (!ConditionVar) - return StmtError(); - } else { - Cond = getDerived().TransformExpr(S->getCond()); - - if (Cond.isInvalid()) - return StmtError(); - - if (S->getCond()) { - // Convert the condition to a boolean value. - ExprResult CondE = getSema().ActOnBooleanCondition(nullptr, - S->getWhileLoc(), - Cond.get()); - if (CondE.isInvalid()) - return StmtError(); - Cond = CondE; - } - } - - Sema::FullExprArg FullCond( - getSema().MakeFullExpr(Cond.get(), S->getWhileLoc())); - if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) + Sema::ConditionResult Cond = getDerived().TransformCondition( + S->getWhileLoc(), S->getConditionVariable(), S->getCond(), + Sema::ConditionKind::Boolean); + if (Cond.isInvalid()) return StmtError(); // Transform the body @@ -6328,13 +6294,11 @@ TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) { return StmtError(); if (!getDerived().AlwaysRebuild() && - FullCond.get() == S->getCond() && - ConditionVar == S->getConditionVariable() && + Cond.get() == std::make_pair(S->getConditionVariable(), S->getCond()) && Body.get() == S->getBody()) return Owned(S); - return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond, - ConditionVar, Body.get()); + return getDerived().RebuildWhileStmt(S->getWhileLoc(), Cond, Body.get()); } template<typename Derived> @@ -6374,37 +6338,10 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) { getSema().ActOnOpenMPLoopInitialization(S->getForLoc(), Init.get()); // Transform the condition - ExprResult Cond; - VarDecl *ConditionVar = nullptr; - if (S->getConditionVariable()) { - ConditionVar - = cast_or_null<VarDecl>( - getDerived().TransformDefinition( - S->getConditionVariable()->getLocation(), - S->getConditionVariable())); - if (!ConditionVar) - return StmtError(); - } else { - Cond = getDerived().TransformExpr(S->getCond()); - - if (Cond.isInvalid()) - return StmtError(); - - if (S->getCond()) { - // Convert the condition to a boolean value. - ExprResult CondE = getSema().ActOnBooleanCondition(nullptr, - S->getForLoc(), - Cond.get()); - if (CondE.isInvalid()) - return StmtError(); - - Cond = CondE.get(); - } - } - - Sema::FullExprArg FullCond( - getSema().MakeFullExpr(Cond.get(), S->getForLoc())); - if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) + Sema::ConditionResult Cond = getDerived().TransformCondition( + S->getForLoc(), S->getConditionVariable(), S->getCond(), + Sema::ConditionKind::Boolean); + if (Cond.isInvalid()) return StmtError(); // Transform the increment @@ -6423,14 +6360,14 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) { if (!getDerived().AlwaysRebuild() && Init.get() == S->getInit() && - FullCond.get() == S->getCond() && + Cond.get() == std::make_pair(S->getConditionVariable(), S->getCond()) && Inc.get() == S->getInc() && Body.get() == S->getBody()) return S; return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(), - Init.get(), FullCond, ConditionVar, - FullInc, S->getRParenLoc(), Body.get()); + Init.get(), Cond, FullInc, + S->getRParenLoc(), Body.get()); } template<typename Derived> @@ -6924,7 +6861,7 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { if (Cond.isInvalid()) return StmtError(); if (Cond.get()) - Cond = SemaRef.CheckBooleanCondition(Cond.get(), S->getColonLoc()); + Cond = SemaRef.CheckBooleanCondition(S->getColonLoc(), Cond.get()); if (Cond.isInvalid()) return StmtError(); if (Cond.get()) diff --git a/test/FixIt/fixit-vexing-parse.cpp b/test/FixIt/fixit-vexing-parse.cpp index 0232f5dbb0..71d3eff532 100644 --- a/test/FixIt/fixit-vexing-parse.cpp +++ b/test/FixIt/fixit-vexing-parse.cpp @@ -60,7 +60,7 @@ namespace N { VO m(int (*p)[4]); // Don't emit warning and fixit because direct initializer is not permitted here. - if (int n(int())){} // expected-error {{function type is not allowed here}} expected-error {{condition must have an initializer}} + if (int n(int())){} // expected-error {{function type is not allowed here}} // CHECK: fix-it:"{{.*}}":{66:8-66:10}:" = {}" U u(); // expected-warning {{function declaration}} expected-note {{replace parentheses with an initializer}} diff --git a/test/Parser/cxx0x-condition.cpp b/test/Parser/cxx0x-condition.cpp index 8b64bcf127..071e09e415 100644 --- a/test/Parser/cxx0x-condition.cpp +++ b/test/Parser/cxx0x-condition.cpp @@ -23,9 +23,9 @@ void f() { if (S b(a)) {} // expected-error {{variable declaration in condition cannot have a parenthesized initializer}} - if (S b(n)) {} // expected-error {{a function type is not allowed here}} expected-error {{must have an initializer}} + if (S b(n)) {} // expected-error {{a function type is not allowed here}} if (S b(n) = 0) {} // expected-error {{a function type is not allowed here}} - if (S b(n) == 0) {} // expected-error {{a function type is not allowed here}} expected-error {{did you mean '='?}} + if (S b(n) == 0) {} // expected-error {{a function type is not allowed here}} S s(a); if (S{s}) {} // ok diff --git a/test/SemaCXX/crashes.cpp b/test/SemaCXX/crashes.cpp index 926d13ab45..a80587d840 100644 --- a/test/SemaCXX/crashes.cpp +++ b/test/SemaCXX/crashes.cpp @@ -105,8 +105,7 @@ namespace PR9026 { namespace PR10270 { template<typename T> class C; template<typename T> void f() { - if (C<T> == 1) // expected-error{{expected unqualified-id}} \ - // expected-error{{invalid '==' at end of declaration}} + if (C<T> == 1) // expected-error{{expected unqualified-id}} return; } } diff --git a/test/SemaCXX/for-range-examples.cpp b/test/SemaCXX/for-range-examples.cpp index 83023e3110..08a9982c63 100644 --- a/test/SemaCXX/for-range-examples.cpp +++ b/test/SemaCXX/for-range-examples.cpp @@ -176,9 +176,9 @@ namespace test4 { // Make sure these don't crash. Better diagnostics would be nice. for (: {1, 2, 3}) {} // expected-error {{expected expression}} expected-error {{expected ';'}} - for (1 : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}} + for (1 : {1, 2, 3}) {} // expected-error {{must declare a variable}} for (+x : {1, 2, 3}) {} // expected-error {{undeclared identifier}} expected-error {{expected ';'}} - for (+y : {1, 2, 3}) {} // expected-error {{must declare a variable}} expected-warning {{result unused}} + for (+y : {1, 2, 3}) {} // expected-error {{must declare a variable}} } } diff --git a/test/SemaObjCXX/foreach.mm b/test/SemaObjCXX/foreach.mm index d1302c19a5..99f5d0ce55 100644 --- a/test/SemaObjCXX/foreach.mm +++ b/test/SemaObjCXX/foreach.mm @@ -6,10 +6,8 @@ void f(NSArray *a) { id keys; for (int i : a); // expected-error{{selector element type 'int' is not a valid object}} - for ((id)2 : a); // expected-error {{for range declaration must declare a variable}} \ - // expected-warning {{expression result unused}} - for (2 : a); // expected-error {{for range declaration must declare a variable}} \ - // expected-warning {{expression result unused}} + for ((id)2 : a); // expected-error {{for range declaration must declare a variable}} + for (2 : a); // expected-error {{for range declaration must declare a variable}} for (id thisKey : keys); @@ -65,8 +63,7 @@ int main () @end void test2(NSObject<NSFastEnumeration> *collection) { Test2 *obj; - for (obj.prop : collection) { // expected-error {{for range declaration must declare a variable}} \ - // expected-warning {{property access result unused - getters should not be used for side effects}} + for (obj.prop : collection) { // expected-error {{for range declaration must declare a variable}} } } |