mirror of https://github.com/microsoft/clang.git
Don't warn about runtime behavior problems in variable initializers that we
know are going to be constant-evaluated. Any relevant diagnostics should be produced by constant expression evaluation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@314067 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1de6f9cae3
commit
eaedd47dbd
|
@ -15179,10 +15179,24 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement,
|
|||
if (Statement && getCurFunctionOrMethodDecl()) {
|
||||
FunctionScopes.back()->PossiblyUnreachableDiags.
|
||||
push_back(sema::PossiblyUnreachableDiag(PD, Loc, Statement));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
Diag(Loc, PD);
|
||||
|
||||
|
||||
// The initializer of a constexpr variable or of the first declaration of a
|
||||
// static data member is not syntactically a constant evaluated constant,
|
||||
// but nonetheless is always required to be a constant expression, so we
|
||||
// can skip diagnosing.
|
||||
// FIXME: Using the mangling context here is a hack.
|
||||
if (auto *VD = dyn_cast_or_null<VarDecl>(
|
||||
ExprEvalContexts.back().ManglingContextDecl)) {
|
||||
if (VD->isConstexpr() ||
|
||||
(VD->isStaticDataMember() && VD->isFirstDecl() && !VD->isInline()))
|
||||
break;
|
||||
// FIXME: For any other kind of variable, we should build a CFG for its
|
||||
// initializer and check whether the context in question is reachable.
|
||||
}
|
||||
|
||||
Diag(Loc, PD);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,4 +50,4 @@ U<NonLit> u2; // expected-note {{here}}
|
|||
|
||||
static_assert(U<int>::a == 0, "");
|
||||
|
||||
constexpr int outofline = (U<NonLit>::d, 0); // expected-note {{here}} expected-warning {{unused}}
|
||||
constexpr int outofline = (U<NonLit>::d, 0); // expected-note {{here}}
|
||||
|
|
|
@ -145,19 +145,19 @@ namespace UndefinedBehavior {
|
|||
|
||||
constexpr int int_min = ~0x7fffffff;
|
||||
constexpr int minus_int_min = -int_min; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}}
|
||||
constexpr int div0 = 3 / 0; // expected-error {{constant expression}} expected-note {{division by zero}} expected-warning {{undefined}}
|
||||
constexpr int mod0 = 3 % 0; // expected-error {{constant expression}} expected-note {{division by zero}} expected-warning {{undefined}}
|
||||
constexpr int div0 = 3 / 0; // expected-error {{constant expression}} expected-note {{division by zero}}
|
||||
constexpr int mod0 = 3 % 0; // expected-error {{constant expression}} expected-note {{division by zero}}
|
||||
constexpr int int_min_div_minus_1 = int_min / -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}}
|
||||
constexpr int int_min_mod_minus_1 = int_min % -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}}
|
||||
|
||||
constexpr int shl_m1 = 0 << -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}}
|
||||
constexpr int shl_m1 = 0 << -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}}
|
||||
constexpr int shl_0 = 0 << 0; // ok
|
||||
constexpr int shl_31 = 0 << 31; // ok
|
||||
constexpr int shl_32 = 0 << 32; // expected-error {{constant expression}} expected-note {{shift count 32 >= width of type 'int' (32}} expected-warning {{>= width of type}}
|
||||
constexpr int shl_32 = 0 << 32; // expected-error {{constant expression}} expected-note {{shift count 32 >= width of type 'int' (32}}
|
||||
constexpr int shl_unsigned_negative = unsigned(-3) << 1; // ok
|
||||
constexpr int shl_unsigned_into_sign = 1u << 31; // ok
|
||||
constexpr int shl_unsigned_overflow = 1024u << 31; // ok
|
||||
constexpr int shl_signed_negative = (-3) << 1; // expected-warning {{shifting a negative signed value is undefined}} // expected-error {{constant expression}} expected-note {{left shift of negative value -3}}
|
||||
constexpr int shl_signed_negative = (-3) << 1; // expected-error {{constant expression}} expected-note {{left shift of negative value -3}}
|
||||
constexpr int shl_signed_ok = 1 << 30; // ok
|
||||
constexpr int shl_signed_into_sign = 1 << 31; // ok (DR1457)
|
||||
constexpr int shl_signed_into_sign_2 = 0x7fffffff << 1; // ok (DR1457)
|
||||
|
@ -166,10 +166,10 @@ namespace UndefinedBehavior {
|
|||
constexpr int shl_signed_overflow = 1024 << 31; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{requires 43 bits to represent}}
|
||||
constexpr int shl_signed_ok2 = 1024 << 20; // ok
|
||||
|
||||
constexpr int shr_m1 = 0 >> -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}}
|
||||
constexpr int shr_m1 = 0 >> -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}}
|
||||
constexpr int shr_0 = 0 >> 0; // ok
|
||||
constexpr int shr_31 = 0 >> 31; // ok
|
||||
constexpr int shr_32 = 0 >> 32; // expected-error {{constant expression}} expected-note {{shift count 32 >= width of type}} expected-warning {{>= width of type}}
|
||||
constexpr int shr_32 = 0 >> 32; // expected-error {{constant expression}} expected-note {{shift count 32 >= width of type}}
|
||||
|
||||
struct S {
|
||||
int m;
|
||||
|
|
|
@ -328,7 +328,7 @@ struct Str {
|
|||
|
||||
extern char externalvar[];
|
||||
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}}
|
||||
constexpr bool litaddress = "foo" == "foo"; // expected-error {{must be initialized by a constant expression}}
|
||||
static_assert(0 != "foo", "");
|
||||
|
||||
}
|
||||
|
@ -364,7 +364,7 @@ void foo() {
|
|||
constexpr B b3 { { 1 }, { 2 } }; // expected-error {{constant expression}} expected-note {{reference to temporary}} expected-note {{here}}
|
||||
}
|
||||
|
||||
constexpr B &&b4 = ((1, 2), 3, 4, B { {10}, {{20}} }); // expected-warning 4{{unused}}
|
||||
constexpr B &&b4 = ((1, 2), 3, 4, B { {10}, {{20}} });
|
||||
static_assert(&b4 != &b2, "");
|
||||
|
||||
// Proposed DR: copy-elision doesn't trigger lifetime extension.
|
||||
|
@ -1965,7 +1965,7 @@ namespace NeverConstantTwoWays {
|
|||
|
||||
constexpr int n = // expected-error {{must be initialized by a constant expression}}
|
||||
(int *)(long)&n == &n ? // expected-note {{reinterpret_cast}}
|
||||
1 / 0 : // expected-warning {{division by zero}}
|
||||
1 / 0 :
|
||||
0;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
template<typename T, T Divisor>
|
||||
class X {
|
||||
public:
|
||||
static const T value = 10 / Divisor; // expected-error{{in-class initializer for static data member is not a constant expression}} expected-warning {{division by zero}}
|
||||
static const T value = 10 / Divisor; // expected-error{{in-class initializer for static data member is not a constant expression}}
|
||||
};
|
||||
|
||||
int array1[X<int, 2>::value == 5? 1 : -1];
|
||||
|
|
Loading…
Reference in New Issue