diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/clang/AST/Stmt.h | 14 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 5 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 8 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 59 |
4 files changed, 68 insertions, 18 deletions
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 202ad330e9..30c237ef36 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -93,6 +93,13 @@ protected: unsigned NumStmts : 32 - NumStmtBits; }; + class IfStmtBitfields { + friend class IfStmt; + unsigned : NumStmtBits; + + unsigned IsConstexpr : 1; + }; + class ExprBitfields { friend class Expr; friend class DeclRefExpr; // computeDependence @@ -248,6 +255,7 @@ protected: union { StmtBitfields StmtBits; CompoundStmtBitfields CompoundStmtBits; + IfStmtBitfields IfStmtBits; ExprBitfields ExprBits; CharacterLiteralBitfields CharacterLiteralBits; FloatingLiteralBitfields FloatingLiteralBits; @@ -878,7 +886,8 @@ class IfStmt : public Stmt { SourceLocation ElseLoc; public: - IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, + IfStmt(const ASTContext &C, SourceLocation IL, + bool IsConstexpr, VarDecl *var, Expr *cond, Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = nullptr); @@ -918,6 +927,9 @@ public: SourceLocation getElseLoc() const { return ElseLoc; } void setElseLoc(SourceLocation L) { ElseLoc = L; } + bool isConstexpr() const { return IfStmtBits.IsConstexpr; } + void setConstexpr(bool C) { IfStmtBits.IsConstexpr = C; } + SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; } SourceLocation getLocEnd() const LLVM_READONLY { if (SubExprs[ELSE]) diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 48e1a2765d..d7ecef77a2 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -512,6 +512,11 @@ def err_function_is_not_record : Error< "unexpected %0 in function call; perhaps remove the %0?">; def err_super_in_using_declaration : Error< "'__super' cannot be used with a using declaration">; +def ext_constexpr_if : ExtWarn< + "constexpr if is a C++1z extension">, InGroup<CXX1z>; +def warn_cxx14_compat_constexpr_if : Warning< + "constexpr if is incompatible with C++ standards before C++1z">, + DefaultIgnore, InGroup<CXXPre1zCompat>; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a27b356ab6..44d59dc537 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -75,10 +75,12 @@ def err_typecheck_converted_constant_expression_indirect : Error< "conversion from %0 to %1 in converted constant expression would " "bind reference to a temporary">; def err_expr_not_cce : Error< - "%select{case value|enumerator value|non-type template argument|array size}0 " + "%select{case value|enumerator value|non-type template argument|" + "array size|constexpr if condition}0 " "is not a constant expression">; def ext_cce_narrowing : ExtWarn< - "%select{case value|enumerator value|non-type template argument|array size}0 " + "%select{case value|enumerator value|non-type template argument|" + "array size|constexpr if condition}0 " "%select{cannot be narrowed from type %2 to %3|" "evaluates to %2, which cannot be narrowed to type %3}1">, InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure; @@ -4641,6 +4643,8 @@ def note_protected_by_vla_typedef : Note< "jump bypasses initialization of VLA typedef">; def note_protected_by_vla_type_alias : Note< "jump bypasses initialization of VLA type alias">; +def note_protected_by_constexpr_if : Note< + "jump enters controlled statement of constexpr if">; def note_protected_by_vla : Note< "jump bypasses initialization of variable length array">; def note_protected_by_objc_try : Note< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 7f2a942962..7063c6f706 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -797,6 +797,11 @@ public: /// run time. Unevaluated, + /// \brief The current expression occurs within a discarded statement. + /// This behaves largely similarly to an unevaluated operand in preventing + /// definitions from being required, but not in other ways. + DiscardedStatement, + /// \brief The current expression occurs within an unevaluated /// operand that unconditionally permits abstract references to /// fields, such as a SIZE operator in MS-style inline assembly. @@ -2329,7 +2334,8 @@ public: CCEK_CaseValue, ///< Expression in a case label. CCEK_Enumerator, ///< Enumerator value with fixed underlying type. CCEK_TemplateArg, ///< Value of a non-type template parameter. - CCEK_NewExpr ///< Constant expression in a noptr-new-declarator. + CCEK_NewExpr, ///< Constant expression in a noptr-new-declarator. + CCEK_ConstexprIf ///< Condition in a constexpr if statement. }; ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE); @@ -3393,8 +3399,12 @@ public: Stmt *SubStmt); class ConditionResult; - StmtResult ActOnIfStmt(SourceLocation IfLoc, ConditionResult Cond, - Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal); + StmtResult ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr, + ConditionResult Cond, Stmt *ThenVal, + SourceLocation ElseLoc, Stmt *ElseVal); + StmtResult BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, + ConditionResult Cond, Stmt *ThenVal, + SourceLocation ElseLoc, Stmt *ElseVal); StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ConditionResult Cond); StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, @@ -8919,12 +8929,20 @@ public: Decl *ConditionVar; FullExprArg Condition; bool Invalid; + bool HasKnownValue; + bool KnownValue; friend class Sema; - ConditionResult(Decl *ConditionVar, FullExprArg Condition) - : ConditionVar(ConditionVar), Condition(Condition), Invalid(false) {} + ConditionResult(Sema &S, Decl *ConditionVar, FullExprArg Condition, + bool IsConstexpr) + : ConditionVar(ConditionVar), Condition(Condition), Invalid(false), + HasKnownValue(IsConstexpr && Condition.get() && + !Condition.get()->isValueDependent()), + KnownValue(HasKnownValue && + !!Condition.get()->EvaluateKnownConstInt(S.Context)) {} explicit ConditionResult(bool Invalid) - : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid) {} + : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid), + HasKnownValue(false), KnownValue(false) {} public: ConditionResult() : ConditionResult(false) {} @@ -8933,12 +8951,18 @@ public: return std::make_pair(cast_or_null<VarDecl>(ConditionVar), Condition.get()); } + llvm::Optional<bool> getKnownValue() const { + if (!HasKnownValue) + return None; + return KnownValue; + } }; 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. + Boolean, ///< A boolean condition, from 'if', 'while', 'for', or 'do'. + ConstexprIf, ///< A constant boolean condition from 'if constexpr'. + Switch ///< An integral condition for a 'switch' statement. }; ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, @@ -8963,7 +8987,8 @@ public: /// \param Loc - A location associated with the condition, e.g. the /// 'if' keyword. /// \return true iff there were any errors - ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E); + ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, + bool IsConstexpr = false); /// DiagnoseAssignmentAsCondition - Given that an expression is /// being used as a boolean condition, warn if it's an assignment. @@ -8974,7 +8999,7 @@ public: void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE); /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid. - ExprResult CheckCXXBooleanCondition(Expr *CondExpr); + ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false); /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have /// the specified width and sign. If an overflow occurs, detect it and emit @@ -9533,15 +9558,18 @@ public: /// \brief RAII object that enters a new expression evaluation context. class EnterExpressionEvaluationContext { Sema &Actions; + bool Entered = true; public: EnterExpressionEvaluationContext(Sema &Actions, Sema::ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, - bool IsDecltype = false) - : Actions(Actions) { - Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, - IsDecltype); + bool IsDecltype = false, + bool ShouldEnter = true) + : Actions(Actions), Entered(ShouldEnter) { + if (Entered) + Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, + IsDecltype); } EnterExpressionEvaluationContext(Sema &Actions, Sema::ExpressionEvaluationContext NewContext, @@ -9554,7 +9582,8 @@ public: } ~EnterExpressionEvaluationContext() { - Actions.PopExpressionEvaluationContext(); + if (Entered) + Actions.PopExpressionEvaluationContext(); } }; |