summaryrefslogtreecommitdiffstats
path: root/clang/test/SemaCXX/constant-expression-cxx1y.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/SemaCXX/constant-expression-cxx1y.cpp')
-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