summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-05-12 08:57:59 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-05-12 08:57:59 +0000
commitd3d6f4f65c77344ccf57f0ae9bea45d8c664ae0f (patch)
tree32d1efa4eb05a3ebcb8c3e987cf4d31910f4b300 /clang/test
parent91ab86fd29be1a2e0201cf214f8aaf3f24fafd8b (diff)
downloadbcm5719-llvm-d3d6f4f65c77344ccf57f0ae9bea45d8c664ae0f.tar.gz
bcm5719-llvm-d3d6f4f65c77344ccf57f0ae9bea45d8c664ae0f.zip
Fix handling of objects under construction during constant expression
evaluation. It's not enough to just track the LValueBase that we're evaluating, we need to also track the path to the objects whose constructors are running. This reinstates r360464 (reverted in r360531) with a workaround for an MSVC bug that previously caused the Windows bots to fail. llvm-svn: 360537
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/SemaCXX/constant-expression-cxx1y.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/constant-expression-cxx1y.cpp b/clang/test/SemaCXX/constant-expression-cxx1y.cpp
index 07ef7974d11..fe69d105023 100644
--- a/clang/test/SemaCXX/constant-expression-cxx1y.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx1y.cpp
@@ -1159,3 +1159,49 @@ enum InEnum2 : int {
enum class InEnum3 {
THREE = indirect_builtin_constant_p("abc")
};
+
+// [class.ctor]p4:
+// A constructor can be invoked for a const, volatile or const volatile
+// object. const and volatile semantics are not applied on an object under
+// construction. They come into effect when the constructor for the most
+// derived object ends.
+namespace ObjectsUnderConstruction {
+ struct A {
+ int n;
+ constexpr A() : n(1) { n = 2; }
+ };
+ struct B {
+ const A a;
+ constexpr B(bool mutate) {
+ if (mutate)
+ const_cast<A &>(a).n = 3; // expected-note {{modification of object of const-qualified type 'const int'}}
+ }
+ };
+ constexpr B b(false);
+ static_assert(b.a.n == 2, "");
+ constexpr B bad(true); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'B(true)'}}
+
+ struct C {
+ int n;
+ constexpr C() : n(1) { n = 2; }
+ };
+ constexpr int f(bool get) {
+ volatile C c; // expected-note {{here}}
+ return get ? const_cast<int&>(c.n) : 0; // expected-note {{read of volatile object 'c'}}
+ }
+ static_assert(f(false) == 0, ""); // ok, can modify volatile c.n during c's initialization: it's not volatile then
+ static_assert(f(true) == 2, ""); // expected-error {{constant}} expected-note {{in call}}
+
+ struct Aggregate {
+ int x = 0;
+ int y = ++x;
+ };
+ constexpr Aggregate aggr1;
+ static_assert(aggr1.x == 1 && aggr1.y == 1, "");
+ // FIXME: This is not specified by the standard, but sanity requires it.
+ constexpr Aggregate aggr2 = {};
+ static_assert(aggr2.x == 1 && aggr2.y == 1, "");
+
+ // The lifetime of 'n' begins at the initialization, not before.
+ constexpr int n = ++const_cast<int&>(n); // expected-error {{constant expression}} expected-note {{modification}}
+}
OpenPOWER on IntegriCloud