summaryrefslogtreecommitdiffstats
path: root/clang/test/SemaCXX
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-05-10 20:05:32 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-05-10 20:05:32 +0000
commitc0fe5eb39c85756e02d1bf3e05127bc7e55a8973 (patch)
tree1c1b76932416544aa3a94743dd85f5607561eb09 /clang/test/SemaCXX
parent5b5e27afa441f13fab524cb81c05dfaf54e22895 (diff)
downloadbcm5719-llvm-c0fe5eb39c85756e02d1bf3e05127bc7e55a8973.tar.gz
bcm5719-llvm-c0fe5eb39c85756e02d1bf3e05127bc7e55a8973.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. llvm-svn: 360464
Diffstat (limited to 'clang/test/SemaCXX')
-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