summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-09-23 18:27:11 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-09-23 18:27:11 +0000
commiteaedd47dbde3c4312be1b89b02368be78780ca34 (patch)
tree28293ce7089335a5d0d8a1540836e7d3df9cb833
parent1de6f9cae36189a1481570c05329c338291110a0 (diff)
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
-rw-r--r--lib/Sema/SemaExpr.cpp20
-rw-r--r--test/CXX/class/class.static/class.static.data/p3.cpp2
-rw-r--r--test/CXX/expr/expr.const/p2-0x.cpp14
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp6
-rw-r--r--test/SemaTemplate/instantiate-static-var.cpp2
5 files changed, 29 insertions, 15 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7784126377..75b09cf218 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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;
}
diff --git a/test/CXX/class/class.static/class.static.data/p3.cpp b/test/CXX/class/class.static/class.static.data/p3.cpp
index 413017d133..5640bc30ad 100644
--- a/test/CXX/class/class.static/class.static.data/p3.cpp
+++ b/test/CXX/class/class.static/class.static.data/p3.cpp
@@ -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}}
diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp
index 6d46bf5d77..4daed23bf9 100644
--- a/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/test/CXX/expr/expr.const/p2-0x.cpp
@@ -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;
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index b1575077cd..e64f2d5a33 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -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;
}
diff --git a/test/SemaTemplate/instantiate-static-var.cpp b/test/SemaTemplate/instantiate-static-var.cpp
index 547470db5c..648ee4153f 100644
--- a/test/SemaTemplate/instantiate-static-var.cpp
+++ b/test/SemaTemplate/instantiate-static-var.cpp
@@ -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];