summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/clang/AST/Stmt.h14
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td5
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td8
-rw-r--r--include/clang/Sema/Sema.h59
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();
}
};