r254574 - PR17381: Treat undefined behavior during expression evaluation as an unmodeled
Robinson, Paul via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 7 18:45:37 PST 2015
Two more questions:
(1) Commit message implied this is only for C, but I see it with C++11
(but not C++03).
$ cat t.cpp
enum { foo = 123456 * 234567 };
$ clang -c t.cpp -std=c++03
$ clang -c t.cpp -std=c++11
t.cpp:1:14: error: expression is not an integral constant expression
....
(2) Shouldn't it diagnose each bad expression in an initializer?
I see the error only for the first such expression.
$ cat t.c
int foo[2] = { 123456 * 234567, 654321 * 765432 };
$ clang -c t.c
t.c:1:23: error: initializer element is not a compile-time constant
int foo[2] = { 123456 * 234567, 654321 * 765432 };
~~~~~~~^~~~~~~~
1 error generated.
Thanks,
--paulr
> -----Original Message-----
> From: cfe-commits [mailto:cfe-commits-bounces at lists.llvm.org] On Behalf Of
> Richard Smith via cfe-commits
> Sent: Wednesday, December 02, 2015 5:36 PM
> To: cfe-commits at lists.llvm.org
> Subject: r254574 - PR17381: Treat undefined behavior during expression
> evaluation as an unmodeled
>
> Author: rsmith
> Date: Wed Dec 2 19:36:22 2015
> New Revision: 254574
>
> URL: http://llvm.org/viewvc/llvm-project?rev=254574&view=rev
> Log:
> PR17381: Treat undefined behavior during expression evaluation as an
> unmodeled
> side-effect, so that we don't allow speculative evaluation of such
> expressions
> during code generation.
>
> This caused a diagnostic quality regression, so fix constant expression
> diagnostics to prefer either the first "can't be constant folded"
> diagnostic or
> the first "not a constant expression" diagnostic depending on the kind of
> evaluation we're doing. This was always the intent, but didn't quite work
> correctly before.
>
> This results in certain initializers that used to be constant initializers
> to
> no longer be; in particular, things like:
>
> float f = 1e100;
>
> are no longer accepted in C. This seems appropriate, as such constructs
> would
> lead to code being executed if sanitizers are enabled.
>
> Added:
> cfe/trunk/test/CodeGen/ubsan-conditional.c
> Modified:
> cfe/trunk/lib/AST/ExprConstant.cpp
> cfe/trunk/lib/Sema/SemaChecking.cpp
> cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
> cfe/trunk/test/CodeGen/complex-init-list.c
> cfe/trunk/test/PCH/floating-literal.c
> cfe/trunk/test/Sema/const-eval.c
> cfe/trunk/test/Sema/integer-overflow.c
> cfe/trunk/test/Sema/switch-1.c
> cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
> cfe/trunk/test/SemaCXX/constexpr-printing.cpp
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=254574&r1=254573&r2=254574&
> view=diff
> ==========================================================================
> ====
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Dec 2 19:36:22 2015
> @@ -473,6 +473,10 @@ namespace {
> /// notes attached to it will also be stored, otherwise they will not
> be.
> bool HasActiveDiagnostic;
>
> + /// \brief Have we emitted a diagnostic explaining why we couldn't
> constant
> + /// fold (not just why it's not strictly a constant expression)?
> + bool HasFoldFailureDiagnostic;
> +
> enum EvaluationMode {
> /// Evaluate as a constant expression. Stop if we find that the
> expression
> /// is not a constant expression.
> @@ -537,7 +541,7 @@ namespace {
> BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
> EvaluatingDecl((const ValueDecl *)nullptr),
> EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
> - EvalMode(Mode) {}
> + HasFoldFailureDiagnostic(false), EvalMode(Mode) {}
>
> void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
> EvaluatingDecl = Base;
> @@ -597,7 +601,7 @@ namespace {
> /// Diagnose that the evaluation cannot be folded.
> OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId
> = diag::note_invalid_subexpr_in_const_expr,
> - unsigned ExtraNotes = 0) {
> + unsigned ExtraNotes = 0, bool IsCCEDiag =
> false) {
> if (EvalStatus.Diag) {
> // If we have a prior diagnostic, it will be noting that the
> expression
> // isn't a constant expression. This diagnostic is more
> important,
> @@ -610,10 +614,9 @@ namespace {
> case EM_ConstantFold:
> case EM_IgnoreSideEffects:
> case EM_EvaluateForOverflow:
> - if (!EvalStatus.HasSideEffects)
> + if (!HasFoldFailureDiagnostic)
> break;
> - // We've had side-effects; we want the diagnostic from them,
> not
> - // some later problem.
> + // We've already failed to fold something. Keep that
> diagnostic.
> case EM_ConstantExpression:
> case EM_PotentialConstantExpression:
> case EM_ConstantExpressionUnevaluated:
> @@ -632,6 +635,7 @@ namespace {
> CallStackNotes = 0;
>
> HasActiveDiagnostic = true;
> + HasFoldFailureDiagnostic = !IsCCEDiag;
> EvalStatus.Diag->clear();
> EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes);
> addDiag(Loc, DiagId);
> @@ -645,9 +649,9 @@ namespace {
>
> OptionalDiagnostic Diag(const Expr *E, diag::kind DiagId
> = diag::note_invalid_subexpr_in_const_expr,
> - unsigned ExtraNotes = 0) {
> + unsigned ExtraNotes = 0, bool IsCCEDiag =
> false) {
> if (EvalStatus.Diag)
> - return Diag(E->getExprLoc(), DiagId, ExtraNotes);
> + return Diag(E->getExprLoc(), DiagId, ExtraNotes, IsCCEDiag);
> HasActiveDiagnostic = false;
> return OptionalDiagnostic();
> }
> @@ -667,7 +671,7 @@ namespace {
> HasActiveDiagnostic = false;
> return OptionalDiagnostic();
> }
> - return Diag(Loc, DiagId, ExtraNotes);
> + return Diag(Loc, DiagId, ExtraNotes, true);
> }
>
> /// Add a note to a prior diagnostic.
> @@ -1541,10 +1545,11 @@ static bool EvaluateAsBooleanCondition(c
> }
>
> template<typename T>
> -static void HandleOverflow(EvalInfo &Info, const Expr *E,
> +static bool HandleOverflow(EvalInfo &Info, const Expr *E,
> const T &SrcValue, QualType DestType) {
> Info.CCEDiag(E, diag::note_constexpr_overflow)
> << SrcValue << DestType;
> + return Info.noteSideEffect();
> }
>
> static bool HandleFloatToIntCast(EvalInfo &Info, const Expr *E,
> @@ -1558,7 +1563,7 @@ static bool HandleFloatToIntCast(EvalInf
> bool ignored;
> if (Value.convertToInteger(Result, llvm::APFloat::rmTowardZero,
> &ignored)
> & APFloat::opInvalidOp)
> - HandleOverflow(Info, E, Value, DestType);
> + return HandleOverflow(Info, E, Value, DestType);
> return true;
> }
>
> @@ -1570,7 +1575,7 @@ static bool HandleFloatToFloatCast(EvalI
> if (Result.convert(Info.Ctx.getFloatTypeSemantics(DestType),
> APFloat::rmNearestTiesToEven, &ignored)
> & APFloat::opOverflow)
> - HandleOverflow(Info, E, Value, DestType);
> + return HandleOverflow(Info, E, Value, DestType);
> return true;
> }
>
> @@ -1593,7 +1598,7 @@ static bool HandleIntToFloatCast(EvalInf
> if (Result.convertFromAPInt(Value, Value.isSigned(),
> APFloat::rmNearestTiesToEven)
> & APFloat::opOverflow)
> - HandleOverflow(Info, E, Value, DestType);
> + return HandleOverflow(Info, E, Value, DestType);
> return true;
> }
>
> @@ -1669,23 +1674,26 @@ static bool EvalAndBitcastToAPInt(EvalIn
> /// bits, and check for overflow in the original type (if that type was
> not an
> /// unsigned type).
> template<typename Operation>
> -static APSInt CheckedIntArithmetic(EvalInfo &Info, const Expr *E,
> - const APSInt &LHS, const APSInt &RHS,
> - unsigned BitWidth, Operation Op) {
> - if (LHS.isUnsigned())
> - return Op(LHS, RHS);
> +static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E,
> + const APSInt &LHS, const APSInt &RHS,
> + unsigned BitWidth, Operation Op,
> + APSInt &Result) {
> + if (LHS.isUnsigned()) {
> + Result = Op(LHS, RHS);
> + return true;
> + }
>
> APSInt Value(Op(LHS.extend(BitWidth), RHS.extend(BitWidth)), false);
> - APSInt Result = Value.trunc(LHS.getBitWidth());
> + Result = Value.trunc(LHS.getBitWidth());
> if (Result.extend(BitWidth) != Value) {
> if (Info.checkingForOverflow())
> Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
> - diag::warn_integer_constant_overflow)
> +
> diag::warn_integer_constant_overflow)
> << Result.toString(10) << E->getType();
> else
> - HandleOverflow(Info, E, Value, E->getType());
> + return HandleOverflow(Info, E, Value, E->getType());
> }
> - return Result;
> + return true;
> }
>
> /// Perform the given binary integer operation.
> @@ -1697,17 +1705,14 @@ static bool handleIntIntBinOp(EvalInfo &
> Info.Diag(E);
> return false;
> case BO_Mul:
> - Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() *
> 2,
> - std::multiplies<APSInt>());
> - return true;
> + return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2,
> + std::multiplies<APSInt>(), Result);
> case BO_Add:
> - Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() +
> 1,
> - std::plus<APSInt>());
> - return true;
> + return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1,
> + std::plus<APSInt>(), Result);
> case BO_Sub:
> - Result = CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() +
> 1,
> - std::minus<APSInt>());
> - return true;
> + return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() + 1,
> + std::minus<APSInt>(), Result);
> case BO_And: Result = LHS & RHS; return true;
> case BO_Xor: Result = LHS ^ RHS; return true;
> case BO_Or: Result = LHS | RHS; return true;
> @@ -1717,11 +1722,13 @@ static bool handleIntIntBinOp(EvalInfo &
> Info.Diag(E, diag::note_expr_divide_by_zero);
> return false;
> }
> - // Check for overflow case: INT_MIN / -1 or INT_MIN % -1.
> + Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS);
> + // Check for overflow case: INT_MIN / -1 or INT_MIN % -1. APSInt
> supports
> + // this operation and gives the two's complement result.
> if (RHS.isNegative() && RHS.isAllOnesValue() &&
> LHS.isSigned() && LHS.isMinSignedValue())
> - HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1), E-
> >getType());
> - Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS);
> + return HandleOverflow(Info, E, -LHS.extend(LHS.getBitWidth() + 1),
> + E->getType());
> return true;
> case BO_Shl: {
> if (Info.getLangOpts().OpenCL)
> @@ -1809,8 +1816,11 @@ static bool handleFloatFloatBinOp(EvalIn
> break;
> }
>
> - if (LHS.isInfinity() || LHS.isNaN())
> + if (LHS.isInfinity() || LHS.isNaN()) {
> Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) <<
> LHS.isNaN();
> + // Undefined behavior is a side-effect.
> + return Info.noteSideEffect();
> + }
> return true;
> }
>
> @@ -3009,7 +3019,7 @@ struct IncDecSubobjectHandler {
> if (!WasNegative && Value.isNegative() &&
> isOverflowingIntegerType(Info.Ctx, SubobjType)) {
> APSInt ActualValue(Value, /*IsUnsigned*/true);
> - HandleOverflow(Info, E, ActualValue, SubobjType);
> + return HandleOverflow(Info, E, ActualValue, SubobjType);
> }
> } else {
> --Value;
> @@ -3019,7 +3029,7 @@ struct IncDecSubobjectHandler {
> unsigned BitWidth = Value.getBitWidth();
> APSInt ActualValue(Value.sext(BitWidth + 1),
> /*IsUnsigned*/false);
> ActualValue.setBit(BitWidth);
> - HandleOverflow(Info, E, ActualValue, SubobjType);
> + return HandleOverflow(Info, E, ActualValue, SubobjType);
> }
> }
> return true;
> @@ -6240,8 +6250,8 @@ static bool EvaluateBuiltinConstantP(AST
> APValue &V = Result.Val;
> if (V.getKind() == APValue::Int)
> return true;
> -
> - return EvaluateBuiltinConstantPForLValue(V);
> + if (V.getKind() == APValue::LValue)
> + return EvaluateBuiltinConstantPForLValue(V);
> } else if (ArgType->isFloatingType() || ArgType->isAnyComplexType()) {
> return Arg->isEvaluatable(Ctx);
> } else if (ArgType->isPointerType() || Arg->isGLValue()) {
> @@ -7258,7 +7268,7 @@ bool IntExprEvaluator::VisitBinaryOperat
> LValue LHSValue, RHSValue;
>
> bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info);
> - if (!LHSOK && Info.keepEvaluatingAfterFailure())
> + if (!LHSOK && !Info.keepEvaluatingAfterFailure())
> return false;
>
> if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
> @@ -7270,21 +7280,20 @@ bool IntExprEvaluator::VisitBinaryOperat
> if (E->getOpcode() == BO_Sub) {
> // Handle &&A - &&B.
> if (!LHSValue.Offset.isZero() || !RHSValue.Offset.isZero())
> - return false;
> + return Error(E);
> const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr*>();
> const Expr *RHSExpr = RHSValue.Base.dyn_cast<const Expr*>();
> if (!LHSExpr || !RHSExpr)
> - return false;
> + return Error(E);
> const AddrLabelExpr *LHSAddrExpr =
> dyn_cast<AddrLabelExpr>(LHSExpr);
> const AddrLabelExpr *RHSAddrExpr =
> dyn_cast<AddrLabelExpr>(RHSExpr);
> if (!LHSAddrExpr || !RHSAddrExpr)
> - return false;
> + return Error(E);
> // Make sure both labels come from the same function.
> if (LHSAddrExpr->getLabel()->getDeclContext() !=
> RHSAddrExpr->getLabel()->getDeclContext())
> - return false;
> - Result = APValue(LHSAddrExpr, RHSAddrExpr);
> - return true;
> + return Error(E);
> + return Success(APValue(LHSAddrExpr, RHSAddrExpr), E);
> }
> // Inequalities and subtractions between unrelated pointers have
> // unspecified or undefined behavior.
> @@ -7375,8 +7384,9 @@ bool IntExprEvaluator::VisitBinaryOperat
> APSInt TrueResult = (LHS - RHS) / ElemSize;
> APSInt Result = TrueResult.trunc(Info.Ctx.getIntWidth(E-
> >getType()));
>
> - if (Result.extend(65) != TrueResult)
> - HandleOverflow(Info, E, TrueResult, E->getType());
> + if (Result.extend(65) != TrueResult &&
> + !HandleOverflow(Info, E, TrueResult, E->getType()))
> + return false;
> return Success(Result, E);
> }
>
> @@ -7662,9 +7672,10 @@ bool IntExprEvaluator::VisitUnaryOperato
> return false;
> if (!Result.isInt()) return Error(E);
> const APSInt &Value = Result.getInt();
> - if (Value.isSigned() && Value.isMinSignedValue())
> - HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
> - E->getType());
> + if (Value.isSigned() && Value.isMinSignedValue() &&
> + !HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
> + E->getType()))
> + return false;
> return Success(-Value, E);
> }
> case UO_Not: {
> @@ -8863,7 +8874,9 @@ bool Expr::EvaluateAsInitializer(APValue
> Expr::EvalStatus EStatus;
> EStatus.Diag = &Notes;
>
> - EvalInfo InitInfo(Ctx, EStatus, EvalInfo::EM_ConstantFold);
> + EvalInfo InitInfo(Ctx, EStatus, VD->isConstexpr()
> + ? EvalInfo::EM_ConstantExpression
> + : EvalInfo::EM_ConstantFold);
> InitInfo.setEvaluatingDecl(VD, Value);
>
> LValue LVal;
>
> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=254574&r1=254573&r2=254574
> &view=diff
> ==========================================================================
> ====
> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Dec 2 19:36:22 2015
> @@ -8547,7 +8547,7 @@ void Sema::CheckArrayAccess(const Expr *
> return;
>
> llvm::APSInt index;
> - if (!IndexExpr->EvaluateAsInt(index, Context))
> + if (!IndexExpr->EvaluateAsInt(index, Context,
> Expr::SE_AllowSideEffects))
> return;
> if (IndexNegated)
> index = -index;
>
> Modified: cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
> URL: http://llvm.org/viewvc/llvm-
> project/cfe/trunk/test/CXX/expr/expr.const/p2-
> 0x.cpp?rev=254574&r1=254573&r2=254574&view=diff
> ==========================================================================
> ====
> --- cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp (original)
> +++ cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp Wed Dec 2 19:36:22 2015
> @@ -601,11 +601,11 @@ namespace rdar13090123 {
> typedef __INTPTR_TYPE__ intptr_t;
>
> constexpr intptr_t f(intptr_t x) {
> - return (((x) >> 21) * 8); // expected-note{{subexpression not valid
> in a constant expression}}
> + return (((x) >> 21) * 8);
> }
>
> extern "C" int foo;
>
> constexpr intptr_t i = f((intptr_t)&foo - 10); // expected-
> error{{constexpr variable 'i' must be initialized by a constant
> expression}} \
> - // expected-note{{in call to 'f((char*)&foo + -10)'}}
> + // expected-note{{reinterpret_cast}}
> }
>
> Modified: cfe/trunk/test/CodeGen/complex-init-list.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/complex-
> init-list.c?rev=254574&r1=254573&r2=254574&view=diff
> ==========================================================================
> ====
> --- cfe/trunk/test/CodeGen/complex-init-list.c (original)
> +++ cfe/trunk/test/CodeGen/complex-init-list.c Wed Dec 2 19:36:22 2015
> @@ -4,8 +4,8 @@
> // of a complex number individually using an initialization list. (There
> is a
> // extensive description and test in test/Sema/complex-init-list.c.)
>
> -_Complex float x = { 1.0f, 1.0f/0.0f };
> -// CHECK: @x = global { float, float } { float 1.000000e+00, float
> 0x7FF0000000000000 }, align 4
> +_Complex float x = { 1.0f, -1.0f };
> +// CHECK: @x = global { float, float } { float 1.000000e+00, float -
> 1.000000e+00 }, align 4
>
> _Complex float f(float x, float y) { _Complex float z = { x, y }; return
> z; }
> // CHECK-LABEL: define <2 x float> @f
>
> Added: cfe/trunk/test/CodeGen/ubsan-conditional.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ubsan-
> conditional.c?rev=254574&view=auto
> ==========================================================================
> ====
> --- cfe/trunk/test/CodeGen/ubsan-conditional.c (added)
> +++ cfe/trunk/test/CodeGen/ubsan-conditional.c Wed Dec 2 19:36:22 2015
> @@ -0,0 +1,10 @@
> +// RUN: %clang_cc1 %s -emit-llvm -fsanitize=float-divide-by-zero -o - |
> FileCheck %s
> +
> +_Bool b;
> +// CHECK: @f(
> +double f() {
> + // CHECK: %[[B:.*]] = load {{.*}} @b
> + // CHECK: %[[COND:.*]] = trunc {{.*}} %[[B]] to i1
> + // CHECK: br i1 %[[COND]]
> + return b ? 0.0 / 0.0 : 0.0;
> +}
>
> Modified: cfe/trunk/test/PCH/floating-literal.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/floating-
> literal.c?rev=254574&r1=254573&r2=254574&view=diff
> ==========================================================================
> ====
> --- cfe/trunk/test/PCH/floating-literal.c (original)
> +++ cfe/trunk/test/PCH/floating-literal.c Wed Dec 2 19:36:22 2015
> @@ -15,5 +15,5 @@ long double foo = 1.0E4000L;
> double bar = 1.0E300;
> // CHECK: double bar = 1.0000000000000001E+300;
>
> -float wibble = 1.0E40;
> -// CHECK: float wibble = 1.0E+40;
> +float wibble = 2.0E38;
> +// CHECK: float wibble = 2.0E+38;
>
> Modified: cfe/trunk/test/Sema/const-eval.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/const-
> eval.c?rev=254574&r1=254573&r2=254574&view=diff
> ==========================================================================
> ====
> --- cfe/trunk/test/Sema/const-eval.c (original)
> +++ cfe/trunk/test/Sema/const-eval.c Wed Dec 2 19:36:22 2015
> @@ -129,7 +129,7 @@ extern struct Test50S Test50;
> EVAL_EXPR(50, &Test50 < (struct Test50S*)((unsigned)&Test50 + 10)) //
> expected-error {{must have a constant size}}
>
> // <rdar://problem/11874571>
> -EVAL_EXPR(51, 0 != (float)1e99)
> +EVAL_EXPR(51, 0 != (float)1e38)
>
> // PR21945
> void PR21945() { int i = (({}), 0l); }
>
> Modified: cfe/trunk/test/Sema/integer-overflow.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/integer-
> overflow.c?rev=254574&r1=254573&r2=254574&view=diff
> ==========================================================================
> ====
> --- cfe/trunk/test/Sema/integer-overflow.c (original)
> +++ cfe/trunk/test/Sema/integer-overflow.c Wed Dec 2 19:36:22 2015
> @@ -7,6 +7,7 @@ uint64_t f1(uint64_t, uint32_t);
> uint64_t f2(uint64_t, ...);
>
> static const uint64_t overflow = 1 * 4608 * 1024 * 1024; // expected-
> warning {{overflow in expression; result is 536870912 with type 'int'}}
> +// expected-error at -1 {{not a compile-time constant}}
>
> uint64_t check_integer_overflows(int i) {
> // expected-warning at +1 {{overflow in expression; result is 536870912 with
> type 'int'}}
>
> Modified: cfe/trunk/test/Sema/switch-1.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/switch-
> 1.c?rev=254574&r1=254573&r2=254574&view=diff
> ==========================================================================
> ====
> --- cfe/trunk/test/Sema/switch-1.c (original)
> +++ cfe/trunk/test/Sema/switch-1.c Wed Dec 2 19:36:22 2015
> @@ -55,5 +55,8 @@ int f(int i) {
>
> // rdar://18405357
> unsigned long long l = 65536 * 65536; // expected-warning {{overflow in
> expression; result is 0 with type 'int'}}
> +#ifndef __cplusplus
> +// expected-error at -2 {{not a compile-time constant}}
> +#endif
> unsigned long long l2 = 65536 * (unsigned)65536;
> unsigned long long l3 = 65536 * 65536ULL;
>
> Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-
> expression-cxx11.cpp?rev=254574&r1=254573&r2=254574&view=diff
> ==========================================================================
> ====
> --- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Wed Dec 2
> 19:36:22 2015
> @@ -327,7 +327,7 @@ struct Str {
> };
>
> extern char externalvar[];
> -constexpr bool constaddress = (void *)externalvar == (void *)0x4000UL; //
> expected-error {{must be initialized by a constant expression}}
> +constexpr bool constaddress = (void *)externalvar == (void *)0x4000UL; //
> expected-error {{must be initialized by a constant expression}} expected-
> note {{reinterpret_cast}}
> constexpr bool litaddress = "foo" == "foo"; // expected-error {{must be
> initialized by a constant expression}} expected-warning {{unspecified}}
> static_assert(0 != "foo", "");
>
> @@ -1874,10 +1874,9 @@ namespace NeverConstantTwoWays {
> 0;
> }
>
> - // FIXME: We should diagnose the cast to long here, not the division by
> zero.
> constexpr int n = // expected-error {{must be initialized by a constant
> expression}}
> - (int *)(long)&n == &n ?
> - 1 / 0 : // expected-warning {{division by zero}} expected-note
> {{division by zero}}
> + (int *)(long)&n == &n ? // expected-note {{reinterpret_cast}}
> + 1 / 0 : // expected-warning {{division by zero}}
> 0;
> }
>
>
> Modified: cfe/trunk/test/SemaCXX/constexpr-printing.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constexpr-
> printing.cpp?rev=254574&r1=254573&r2=254574&view=diff
> ==========================================================================
> ====
> --- cfe/trunk/test/SemaCXX/constexpr-printing.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constexpr-printing.cpp Wed Dec 2 19:36:22 2015
> @@ -90,10 +90,12 @@ constexpr wchar_t wc = get(L"test\0\\\"\
>
> constexpr char32_t c32_err = get(U"\U00110000"); // expected-error
> {{invalid universal character}}
>
> +#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
> +
> typedef decltype(sizeof(int)) LabelDiffTy;
> constexpr LabelDiffTy mulBy3(LabelDiffTy x) { return x * 3; } //
> expected-note {{subexpression}}
> void LabelDiffTest() {
> - static_assert(mulBy3((LabelDiffTy)&&a-(LabelDiffTy)&&b) == 3, ""); //
> expected-error {{constant expression}} expected-note {{call to 'mulBy3(&&a
> - &&b)'}}
> + static_assert(mulBy3(fold((LabelDiffTy)&&a-(LabelDiffTy)&&b)) == 3,
> ""); // expected-error {{constant expression}} expected-note {{call to
> 'mulBy3(&&a - &&b)'}}
> a:b:return;
> }
>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list