Tyker updated this revision to Diff 200231. Tyker edited the summary of this revision.
CHANGES SINCE LAST ACTION https://reviews.llvm.org/D62009/new/ https://reviews.llvm.org/D62009 Files: clang/include/clang/AST/Expr.h clang/include/clang/Sema/Sema.h clang/lib/AST/ExprConstant.cpp clang/lib/Sema/SemaChecking.cpp clang/test/CXX/expr/expr.const/p3-0x.cpp clang/test/Sema/integer-overflow.c clang/test/Sema/switch.c clang/test/SemaCXX/builtin-is-constant-evaluated.cpp clang/test/SemaCXX/constant-expression-cxx11.cpp clang/test/SemaCXX/integer-overflow.cpp
Index: clang/test/SemaCXX/integer-overflow.cpp =================================================================== --- clang/test/SemaCXX/integer-overflow.cpp +++ clang/test/SemaCXX/integer-overflow.cpp @@ -92,6 +92,7 @@ // expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} case ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)): return 9; +// expected-warning@+3 {{implicit conversion}} // expected-warning@+2 2{{overflow in expression; result is 536870912 with type 'int'}} // expected-warning@+1 {{overflow converting case value to switch condition type (288230376151711744 to 0)}} case ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))): Index: clang/test/SemaCXX/constant-expression-cxx11.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx11.cpp +++ clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -438,8 +438,8 @@ constexpr char c0 = "nought index"[0]; constexpr char c1 = "nice index"[10]; -constexpr char c2 = "nasty index"[12]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is past the end}} expected-note {{read of dereferenced one-past-the-end pointer}} -constexpr char c3 = "negative index"[-1]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is before the beginning}} expected-note {{cannot refer to element -1 of array of 15 elements}} +constexpr char c2 = "nasty index"[12]; // expected-error {{must be initialized by a constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} +constexpr char c3 = "negative index"[-1]; // expected-error {{must be initialized by a constant expression}} expected-note {{cannot refer to element -1 of array of 15 elements}} constexpr char c4 = ((char*)(int*)"no reinterpret_casts allowed")[14]; // expected-error {{must be initialized by a constant expression}} expected-note {{cast that performs the conversions of a reinterpret_cast}} constexpr const char *p = "test" + 2; @@ -547,7 +547,7 @@ constexpr int xs0 = p[-3]; // ok constexpr int xs_1 = p[-4]; // expected-error {{constant expression}} expected-note {{cannot refer to element -1}} -constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; // expected-note {{array 'zs' declared here}} +constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; static_assert(zs[0][0][0][0] == 1, ""); static_assert(zs[1][1][1][1] == 16, ""); static_assert(zs[0][0][0][2] == 3, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} @@ -557,8 +557,7 @@ static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2) == 11, ""); constexpr int err_zs_1_2_0_0 = zs[1][2][0][0]; // \ expected-error {{constant expression}} \ -expected-note {{cannot access array element of pointer past the end}} \ -expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} +expected-note {{cannot access array element of pointer past the end}} constexpr int fail(const int &p) { return (&p)[64]; // expected-note {{cannot refer to element 64 of array of 2 elements}} Index: clang/test/SemaCXX/builtin-is-constant-evaluated.cpp =================================================================== --- clang/test/SemaCXX/builtin-is-constant-evaluated.cpp +++ clang/test/SemaCXX/builtin-is-constant-evaluated.cpp @@ -119,3 +119,15 @@ }; TestConditionalExplicit e = 42; #endif + +constexpr int i1 = (long long)__builtin_is_constant_evaluated() * (1ll << 33); +// expected-warning@-1 {{implicit conversion}} + +constexpr int i2 = (long long)!__builtin_is_constant_evaluated() * (1ll << 33); + + void f(int i) { + switch (i) { + case (long long)__builtin_is_constant_evaluated() * (1ll << 33):; +// expected-warning@-1 {{implicit conversion}} + } + } Index: clang/test/Sema/switch.c =================================================================== --- clang/test/Sema/switch.c +++ clang/test/Sema/switch.c @@ -8,7 +8,7 @@ void foo(int X) { switch (X) { case 42: ; // expected-note {{previous case}} - case 5000000000LL: // expected-warning {{overflow}} + case 5000000000LL: // expected-warning {{overflow}} expected-warning {{implicit conversion}} case 42: // expected-error {{duplicate case value '42'}} ; @@ -381,8 +381,8 @@ // check for duplicates in the promoted type. switch (c) case 1: case 257: ; // expected-warning {{overflow}} - switch (n) case 0x100000001LL: case 1: ; // expected-warning {{overflow}} expected-error {{duplicate}} expected-note {{previous}} - switch ((int)ll) case 0x100000001LL: case 1: ; // expected-warning {{overflow}} expected-error {{duplicate}} expected-note {{previous}} + switch (n) case 0x100000001LL: case 1: ; // expected-warning {{overflow}} expected-error {{duplicate}} expected-note {{previous}} expected-warning {{implicit conversion}} + switch ((int)ll) case 0x100000001LL: case 1: ; // expected-warning {{overflow}} expected-error {{duplicate}} expected-note {{previous}} expected-warning {{implicit conversion}} switch ((long long)n) case 0x100000001LL: case 1: ; switch (ll) case 0x100000001LL: case 1: ; } Index: clang/test/Sema/integer-overflow.c =================================================================== --- clang/test/Sema/integer-overflow.c +++ clang/test/Sema/integer-overflow.c @@ -76,6 +76,7 @@ // expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}} case ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)): return 9; +// expected-warning@+3 {{implicit conversion from}} // expected-warning@+2 2{{overflow in expression; result is 536870912 with type 'int'}} // expected-warning@+1 {{overflow converting case value to switch condition type (288230376151711744 to 0)}} case ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))): Index: clang/test/CXX/expr/expr.const/p3-0x.cpp =================================================================== --- clang/test/CXX/expr/expr.const/p3-0x.cpp +++ clang/test/CXX/expr/expr.const/p3-0x.cpp @@ -52,6 +52,7 @@ case (int)EE::EE32: case 1000: case (long long)1e10: // expected-error {{case value evaluates to 10000000000, which cannot be narrowed to type 'unsigned int'}} + //expected-warning@-1 {{implicit conversion}} case -3: // expected-error {{case value evaluates to -3, which cannot be narrowed to type 'unsigned int'}} return n; } Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -307,7 +307,8 @@ // - Analyze the format string of sprintf to see how much of buffer is used. // - Evaluate strlen of strcpy arguments, use as object size. - if (TheCall->isValueDependent() || TheCall->isTypeDependent()) + if (TheCall->isValueDependent() || TheCall->isTypeDependent() || + isConstantEvaluated()) return; unsigned BuiltinID = FD->getBuiltinID(/*ConsiderWrappers=*/true); @@ -4049,16 +4050,26 @@ bool Result; return (!Expr->isValueDependent() && - Expr->EvaluateAsBooleanCondition(Result, S.Context) && + Expr->EvaluateAsBooleanCondition(Result, S.Context, + S.isConstantEvaluated()) && !Result); } +static void DiagRuntimeOrConstant(Sema &S, SourceLocation Loc, const Expr *Expr, + PartialDiagnostic PDiag) { + if (!S.isConstantEvaluated()) + S.DiagRuntimeBehavior(Loc, Expr, PDiag); + else + S.Diag(Loc, PDiag); +} + static void CheckNonNullArgument(Sema &S, const Expr *ArgExpr, SourceLocation CallSiteLoc) { if (CheckNonNullExpr(S, ArgExpr)) - S.DiagRuntimeBehavior(CallSiteLoc, ArgExpr, - S.PDiag(diag::warn_null_arg) << ArgExpr->getSourceRange()); + DiagRuntimeOrConstant(S, CallSiteLoc, ArgExpr, + S.PDiag(diag::warn_null_arg) + << ArgExpr->getSourceRange()); } bool Sema::GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx) { @@ -6075,7 +6086,7 @@ return true; if (Result.getSExtValue() < Low || Result.getSExtValue() > High) { - if (RangeIsError) + if (RangeIsError || isConstantEvaluated()) return Diag(TheCall->getBeginLoc(), diag::err_argument_invalid_range) << Result.toString(10) << Low << High << Arg->getSourceRange(); else @@ -6598,7 +6609,8 @@ bool CheckLeft = true, CheckRight = true; bool Cond; - if (C->getCond()->EvaluateAsBooleanCondition(Cond, S.getASTContext())) { + if (C->getCond()->EvaluateAsBooleanCondition(Cond, S.getASTContext(), + S.isConstantEvaluated())) { if (Cond) CheckRight = false; else @@ -6799,8 +6811,10 @@ if (BinOp->isAdditiveOp()) { Expr::EvalResult LResult, RResult; - bool LIsInt = BinOp->getLHS()->EvaluateAsInt(LResult, S.Context); - bool RIsInt = BinOp->getRHS()->EvaluateAsInt(RResult, S.Context); + bool LIsInt = BinOp->getLHS()->EvaluateAsInt( + LResult, S.Context, Expr::SE_NoSideEffects, S.isConstantEvaluated()); + bool RIsInt = BinOp->getRHS()->EvaluateAsInt( + RResult, S.Context, Expr::SE_NoSideEffects, S.isConstantEvaluated()); if (LIsInt != RIsInt) { BinaryOperatorKind BinOpKind = BinOp->getOpcode(); @@ -6826,7 +6840,9 @@ auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr()); if (UnaOp->getOpcode() == UO_AddrOf && ASE) { Expr::EvalResult IndexResult; - if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context)) { + if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context, + Expr::SE_NoSideEffects, + S.isConstantEvaluated())) { sumOffsets(Offset, IndexResult.Val.getInt(), BO_Add, /*RHS is int*/ true); E = ASE->getBase(); @@ -9906,12 +9922,13 @@ /// range of values it might take. /// /// \param MaxWidth - the width to which the value will be truncated -static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth) { +static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, + bool InConstantContext) { E = E->IgnoreParens(); // Try a full evaluation first. Expr::EvalResult result; - if (E->EvaluateAsRValue(result, C)) + if (E->EvaluateAsRValue(result, C, InConstantContext)) return GetValueRange(C, result.Val, GetExprType(E), MaxWidth); // I think we only want to look through implicit casts here; if the @@ -9919,7 +9936,7 @@ // being of the new, wider type. if (const auto *CE = dyn_cast<ImplicitCastExpr>(E)) { if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue) - return GetExprRange(C, CE->getSubExpr(), MaxWidth); + return GetExprRange(C, CE->getSubExpr(), MaxWidth, InConstantContext); IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE)); @@ -9930,9 +9947,9 @@ if (!isIntegerCast) return OutputTypeRange; - IntRange SubRange - = GetExprRange(C, CE->getSubExpr(), - std::min(MaxWidth, OutputTypeRange.Width)); + IntRange SubRange = GetExprRange(C, CE->getSubExpr(), + std::min(MaxWidth, OutputTypeRange.Width), + InConstantContext); // Bail out if the subexpr's range is as wide as the cast type. if (SubRange.Width >= OutputTypeRange.Width) @@ -9948,13 +9965,15 @@ // If we can fold the condition, just take that operand. bool CondResult; if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C)) - return GetExprRange(C, CondResult ? CO->getTrueExpr() - : CO->getFalseExpr(), - MaxWidth); + return GetExprRange(C, + CondResult ? CO->getTrueExpr() : CO->getFalseExpr(), + MaxWidth, InConstantContext); // Otherwise, conservatively merge. - IntRange L = GetExprRange(C, CO->getTrueExpr(), MaxWidth); - IntRange R = GetExprRange(C, CO->getFalseExpr(), MaxWidth); + IntRange L = + GetExprRange(C, CO->getTrueExpr(), MaxWidth, InConstantContext); + IntRange R = + GetExprRange(C, CO->getFalseExpr(), MaxWidth, InConstantContext); return IntRange::join(L, R); } @@ -9990,7 +10009,7 @@ // been coerced to the LHS type. case BO_Assign: // TODO: bitfields? - return GetExprRange(C, BO->getRHS(), MaxWidth); + return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext); // Operations with opaque sources are black-listed. case BO_PtrMemD: @@ -10000,8 +10019,9 @@ // Bitwise-and uses the *infinum* of the two source ranges. case BO_And: case BO_AndAssign: - return IntRange::meet(GetExprRange(C, BO->getLHS(), MaxWidth), - GetExprRange(C, BO->getRHS(), MaxWidth)); + return IntRange::meet( + GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext), + GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext)); // Left shift gets black-listed based on a judgement call. case BO_Shl: @@ -10022,7 +10042,7 @@ // Right shift by a constant can narrow its left argument. case BO_Shr: case BO_ShrAssign: { - IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth); + IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext); // If the shift amount is a positive constant, drop the width by // that much. @@ -10041,7 +10061,7 @@ // Comma acts as its right operand. case BO_Comma: - return GetExprRange(C, BO->getRHS(), MaxWidth); + return GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext); // Black-list pointer subtractions. case BO_Sub: @@ -10054,7 +10074,7 @@ case BO_Div: { // Don't 'pre-truncate' the operands. unsigned opWidth = C.getIntWidth(GetExprType(E)); - IntRange L = GetExprRange(C, BO->getLHS(), opWidth); + IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext); // If the divisor is constant, use that. llvm::APSInt divisor; @@ -10068,7 +10088,7 @@ } // Otherwise, just use the LHS's width. - IntRange R = GetExprRange(C, BO->getRHS(), opWidth); + IntRange R = GetExprRange(C, BO->getRHS(), opWidth, InConstantContext); return IntRange(L.Width, L.NonNegative && R.NonNegative); } @@ -10077,8 +10097,8 @@ case BO_Rem: { // Don't 'pre-truncate' the operands. unsigned opWidth = C.getIntWidth(GetExprType(E)); - IntRange L = GetExprRange(C, BO->getLHS(), opWidth); - IntRange R = GetExprRange(C, BO->getRHS(), opWidth); + IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext); + IntRange R = GetExprRange(C, BO->getRHS(), opWidth, InConstantContext); IntRange meet = IntRange::meet(L, R); meet.Width = std::min(meet.Width, MaxWidth); @@ -10095,8 +10115,8 @@ // The default case is to treat the operation as if it were closed // on the narrowest type that encompasses both operands. - IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth); - IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth); + IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth, InConstantContext); + IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext); return IntRange::join(L, R); } @@ -10112,12 +10132,12 @@ return IntRange::forValueOfType(C, GetExprType(E)); default: - return GetExprRange(C, UO->getSubExpr(), MaxWidth); + return GetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext); } } if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) - return GetExprRange(C, OVE->getSourceExpr(), MaxWidth); + return GetExprRange(C, OVE->getSourceExpr(), MaxWidth, InConstantContext); if (const auto *BitField = E->getSourceBitField()) return IntRange(BitField->getBitWidthValue(C), @@ -10126,8 +10146,9 @@ return IntRange::forValueOfType(C, GetExprType(E)); } -static IntRange GetExprRange(ASTContext &C, const Expr *E) { - return GetExprRange(C, E, C.getIntWidth(GetExprType(E))); +static IntRange GetExprRange(ASTContext &C, const Expr *E, + bool InConstantContext) { + return GetExprRange(C, E, C.getIntWidth(GetExprType(E)), InConstantContext); } /// Checks whether the given value, which currently has the given @@ -10415,13 +10436,13 @@ // cases involving boolean values for historical reasons. We should pick a // consistent way of presenting these diagnostics. if (!InRange || Other->isKnownToHaveBooleanValue()) { - S.DiagRuntimeBehavior( - E->getOperatorLoc(), E, - S.PDiag(!InRange ? diag::warn_out_of_range_compare - : diag::warn_tautological_bool_compare) - << OS.str() << classifyConstantValue(Constant) - << OtherT << OtherIsBooleanDespiteType << *Result - << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange()); + DiagRuntimeOrConstant( + S, E->getOperatorLoc(), E, + S.PDiag(!InRange ? diag::warn_out_of_range_compare + : diag::warn_tautological_bool_compare) + << OS.str() << classifyConstantValue(Constant) << OtherT + << OtherIsBooleanDespiteType << *Result + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange()); } else { unsigned Diag = (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0) ? (HasEnumType(OriginalOther) @@ -10525,7 +10546,8 @@ } // Otherwise, calculate the effective range of the signed operand. - IntRange signedRange = GetExprRange(S.Context, signedOperand); + IntRange signedRange = + GetExprRange(S.Context, signedOperand, S.isConstantEvaluated()); // Go ahead and analyze implicit conversions in the operands. Note // that we skip the implicit conversions on both sides. @@ -10542,7 +10564,8 @@ // change the result of the comparison. if (E->isEqualityOp()) { unsigned comparisonWidth = S.Context.getIntWidth(T); - IntRange unsignedRange = GetExprRange(S.Context, unsignedOperand); + IntRange unsignedRange = + GetExprRange(S.Context, unsignedOperand, S.isConstantEvaluated()); // We should never be unable to prove that the unsigned operand is // non-negative. @@ -10552,10 +10575,10 @@ return; } - S.DiagRuntimeBehavior(E->getOperatorLoc(), E, - S.PDiag(diag::warn_mixed_sign_comparison) - << LHS->getType() << RHS->getType() - << LHS->getSourceRange() << RHS->getSourceRange()); + DiagRuntimeOrConstant(S, E->getOperatorLoc(), E, + S.PDiag(diag::warn_mixed_sign_comparison) + << LHS->getType() << RHS->getType() + << LHS->getSourceRange() << RHS->getSourceRange()); } /// Analyzes an attempt to assign the given value to a bitfield. @@ -10721,10 +10744,10 @@ SourceLocation CContext, unsigned diag, bool pruneControlFlow = false) { if (pruneControlFlow) { - S.DiagRuntimeBehavior(E->getExprLoc(), E, + DiagRuntimeOrConstant(S, E->getExprLoc(), E, S.PDiag(diag) - << SourceType << T << E->getSourceRange() - << SourceRange(CContext)); + << SourceType << T << E->getSourceRange() + << SourceRange(CContext)); return; } S.Diag(E->getExprLoc(), diag) @@ -10828,7 +10851,7 @@ IntegerValue.toString(PrettyTargetValue); if (PruneWarnings) { - S.DiagRuntimeBehavior(E->getExprLoc(), E, + DiagRuntimeOrConstant(S, E->getExprLoc(), E, S.PDiag(DiagID) << E->getType() << T.getUnqualifiedType() << PrettySourceValue << PrettyTargetValue @@ -11259,13 +11282,13 @@ if (Source->isFixedPointType()) { if (Target->isUnsaturatedFixedPointType()) { Expr::EvalResult Result; - if (E->EvaluateAsFixedPoint(Result, S.Context, - Expr::SE_AllowSideEffects)) { + if (E->EvaluateAsFixedPoint(Result, S.Context, Expr::SE_AllowSideEffects, + S.isConstantEvaluated())) { APFixedPoint Value = Result.Val.getFixedPoint(); APFixedPoint MaxVal = S.Context.getFixedPointMax(T); APFixedPoint MinVal = S.Context.getFixedPointMin(T); if (Value > MaxVal || Value < MinVal) { - S.DiagRuntimeBehavior(E->getExprLoc(), E, + DiagRuntimeOrConstant(S, E->getExprLoc(), E, S.PDiag(diag::warn_impcast_fixed_point_range) << Value.toString() << T << E->getSourceRange() @@ -11275,7 +11298,8 @@ } } else if (Target->isIntegerType()) { Expr::EvalResult Result; - if (E->EvaluateAsFixedPoint(Result, S.Context, + if (!S.isConstantEvaluated() && + E->EvaluateAsFixedPoint(Result, S.Context, Expr::SE_AllowSideEffects)) { APFixedPoint FXResult = Result.Val.getFixedPoint(); @@ -11297,7 +11321,8 @@ } else if (Target->isUnsaturatedFixedPointType()) { if (Source->isIntegerType()) { Expr::EvalResult Result; - if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) { + if (!S.isConstantEvaluated() && + E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) { llvm::APSInt Value = Result.Val.getInt(); bool Overflowed; @@ -11328,14 +11353,15 @@ if (Target->isSpecificBuiltinType(BuiltinType::Bool)) return; - IntRange SourceRange = GetExprRange(S.Context, E); + IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated()); IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); if (SourceRange.Width > TargetRange.Width) { // If the source is a constant, use a default-on diagnostic. // TODO: this should happen for bitfield stores, too. Expr::EvalResult Result; - if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) { + if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects, + S.isConstantEvaluated())) { llvm::APSInt Value(32); Value = Result.Val.getInt(); @@ -11345,11 +11371,11 @@ std::string PrettySourceValue = Value.toString(10); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); - S.DiagRuntimeBehavior(E->getExprLoc(), E, - S.PDiag(diag::warn_impcast_integer_precision_constant) - << PrettySourceValue << PrettyTargetValue - << E->getType() << T << E->getSourceRange() - << clang::SourceRange(CC)); + DiagRuntimeOrConstant( + S, E->getExprLoc(), E, + S.PDiag(diag::warn_impcast_integer_precision_constant) + << PrettySourceValue << PrettyTargetValue << E->getType() << T + << E->getSourceRange() << clang::SourceRange(CC)); return; } @@ -11390,8 +11416,8 @@ std::string PrettySourceValue = Value.toString(10); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); - S.DiagRuntimeBehavior( - E->getExprLoc(), E, + DiagRuntimeOrConstant( + S, E->getExprLoc(), E, S.PDiag(diag::warn_impcast_integer_precision_constant) << PrettySourceValue << PrettyTargetValue << E->getType() << T << E->getSourceRange() << clang::SourceRange(CC)); @@ -12097,7 +12123,8 @@ bool evaluate(const Expr *E, bool &Result) { if (!EvalOK || E->isValueDependent()) return false; - EvalOK = E->EvaluateAsBooleanCondition(Result, Self.SemaRef.Context); + EvalOK = E->EvaluateAsBooleanCondition( + Result, Self.SemaRef.Context, Self.SemaRef.isConstantEvaluated()); return EvalOK; } @@ -12450,12 +12477,17 @@ void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc, bool IsConstexpr) { + if (IsConstexpr) + PushExpressionEvaluationContext( + ExpressionEvaluationContext::ConstantEvaluated); CheckImplicitConversions(E, CheckLoc); if (!E->isInstantiationDependent()) CheckUnsequencedOperations(E); if (!IsConstexpr && !E->isValueDependent()) CheckForIntOverflow(E); DiagnoseMisalignedMembers(); + if (IsConstexpr) + PopExpressionEvaluationContext(); } void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, @@ -12692,6 +12724,10 @@ if (IndexExpr->isValueDependent()) return; + // already diagnosed by the constant evaluator. + if (isConstantEvaluated()) + return; + const Type *EffectiveType = BaseExpr->getType()->getPointeeOrArrayElementType(); BaseExpr = BaseExpr->IgnoreParenCasts(); @@ -13825,8 +13861,12 @@ /// \param VD Declaration of an identifier that appears in a type tag. /// /// \param MagicValue Type tag magic value. +/// +/// \param isConstantEvaluated wether the evalaution should be permormed in +/// constant context. static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx, - const ValueDecl **VD, uint64_t *MagicValue) { + const ValueDecl **VD, uint64_t *MagicValue, + bool isConstantEvaluated) { while(true) { if (!TypeExpr) return false; @@ -13864,7 +13904,8 @@ const AbstractConditionalOperator *ACO = cast<AbstractConditionalOperator>(TypeExpr); bool Result; - if (ACO->getCond()->EvaluateAsBooleanCondition(Result, Ctx)) { + if (ACO->getCond()->EvaluateAsBooleanCondition(Result, Ctx, + isConstantEvaluated)) { if (Result) TypeExpr = ACO->getTrueExpr(); else @@ -13900,14 +13941,17 @@ /// /// \param TypeInfo Information about the corresponding C type. /// +/// \param isConstantEvaluated wether the evalaution should be permormed in +/// constant context. +/// /// \returns true if the corresponding C type was found. static bool GetMatchingCType( - const IdentifierInfo *ArgumentKind, - const Expr *TypeExpr, const ASTContext &Ctx, - const llvm::DenseMap<Sema::TypeTagMagicValue, - Sema::TypeTagData> *MagicValues, - bool &FoundWrongKind, - Sema::TypeTagData &TypeInfo) { + const IdentifierInfo *ArgumentKind, const Expr *TypeExpr, + const ASTContext &Ctx, + const llvm::DenseMap<Sema::TypeTagMagicValue, Sema::TypeTagData> + *MagicValues, + bool &FoundWrongKind, Sema::TypeTagData &TypeInfo, + bool isConstantEvaluated) { FoundWrongKind = false; // Variable declaration that has type_tag_for_datatype attribute. @@ -13915,7 +13959,7 @@ uint64_t MagicValue; - if (!FindTypeTagExpr(TypeExpr, Ctx, &VD, &MagicValue)) + if (!FindTypeTagExpr(TypeExpr, Ctx, &VD, &MagicValue, isConstantEvaluated)) return false; if (VD) { @@ -13993,8 +14037,8 @@ bool FoundWrongKind; TypeTagData TypeInfo; if (!GetMatchingCType(ArgumentKind, TypeTagExpr, Context, - TypeTagForDatatypeMagicValues.get(), - FoundWrongKind, TypeInfo)) { + TypeTagForDatatypeMagicValues.get(), FoundWrongKind, + TypeInfo, isConstantEvaluated())) { if (FoundWrongKind) Diag(TypeTagExpr->getExprLoc(), diag::warn_type_tag_for_datatype_wrong_kind) Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -11665,8 +11665,8 @@ return ::EvaluateAsRValue(this, Result, Ctx, Info); } -bool Expr::EvaluateAsBooleanCondition(bool &Result, - const ASTContext &Ctx) const { +bool Expr::EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, + bool InConstantContext) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); EvalResult Scratch; @@ -11675,23 +11675,28 @@ } bool Expr::EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, - SideEffectsKind AllowSideEffects) const { + SideEffectsKind AllowSideEffects, + bool InConstantContext) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + Info.InConstantContext = InConstantContext; return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info); } bool Expr::EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx, - SideEffectsKind AllowSideEffects) const { + SideEffectsKind AllowSideEffects, + bool InConstantContext) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); + Info.InConstantContext = InConstantContext; return ::EvaluateAsFixedPoint(this, Result, Ctx, AllowSideEffects, Info); } bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx, - SideEffectsKind AllowSideEffects) const { + SideEffectsKind AllowSideEffects, + bool InConstantContext) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); @@ -11707,12 +11712,13 @@ return true; } -bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { +bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx, + bool InConstantContext) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold); - + Info.InConstantContext = InConstantContext; LValue LV; if (!EvaluateLValue(this, LV, Info) || Result.HasSideEffects || !CheckLValueConstantExpression(Info, getExprLoc(), Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -797,6 +797,10 @@ } }; + bool isConstantEvaluated() { + return ExprEvalContexts.back().isConstantEvaluated(); + } + /// RAII object to handle the state changes required to synthesize /// a function body. class SynthesizedFunctionScope { Index: clang/include/clang/AST/Expr.h =================================================================== --- clang/include/clang/AST/Expr.h +++ clang/include/clang/AST/Expr.h @@ -592,7 +592,8 @@ /// which we can fold and convert to a boolean condition using /// any crazy technique that we want to, even if the expression has /// side-effects. - bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const; + bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, + bool InConstantContext = false) const; enum SideEffectsKind { SE_NoSideEffects, ///< Strictly evaluate the expression. @@ -604,20 +605,21 @@ /// EvaluateAsInt - Return true if this is a constant which we can fold and /// convert to an integer, using any crazy technique that we want to. bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, - SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; + SideEffectsKind AllowSideEffects = SE_NoSideEffects, + bool InConstantContext = false) const; /// EvaluateAsFloat - Return true if this is a constant which we can fold and /// convert to a floating point value, using any crazy technique that we /// want to. - bool - EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx, - SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; + bool EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx, + SideEffectsKind AllowSideEffects = SE_NoSideEffects, + bool InConstantContext = false) const; /// EvaluateAsFloat - Return true if this is a constant which we can fold and /// convert to a fixed point value. - bool EvaluateAsFixedPoint( - EvalResult &Result, const ASTContext &Ctx, - SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; + bool EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx, + SideEffectsKind AllowSideEffects = SE_NoSideEffects, + bool InConstantContext = false) const; /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be /// constant folded without side-effects, but discard the result. @@ -653,7 +655,8 @@ /// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an /// lvalue with link time known address, with no side-effects. - bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const; + bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx, + bool InConstantContext = false) const; /// EvaluateAsInitializer - Evaluate an expression as if it were the /// initializer of the given declaration. Returns true if the initializer
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits