summaryrefslogtreecommitdiffstats
path: root/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-10-03 00:39:35 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-10-03 00:39:35 +0000
commitb542602c5f351d66b0a4213f537fd6fb8dde8dcd (patch)
tree0c4be96a0f3b7a5e94398fee08c980c9f187a371 /clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
parent19ad5239713ce0f2742ca2f9e30ff4663ee5ad90 (diff)
downloadbcm5719-llvm-b542602c5f351d66b0a4213f537fd6fb8dde8dcd.tar.gz
bcm5719-llvm-b542602c5f351d66b0a4213f537fd6fb8dde8dcd.zip
For P0784R7: support placement new-expressions in constant evaluation.
For now, we restrict this support to use from within the standard library implementation, since we're required to make parts of the standard library that use placement new work, but not permitted to make uses of placement new from user code work. llvm-svn: 373547
Diffstat (limited to 'clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp')
-rw-r--r--clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
index 5a39b33a87c..23582f2e302 100644
--- a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
+++ b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp
@@ -83,3 +83,86 @@ static_assert(mismatched(2, 2));
constexpr int *escape = std::allocator<int>().allocate(3); // expected-error {{constant expression}} expected-note {{pointer to subobject of heap-allocated}}
constexpr int leak = (std::allocator<int>().allocate(3), 0); // expected-error {{constant expression}}
constexpr int no_lifetime_start = (*std::allocator<int>().allocate(1) = 1); // expected-error {{constant expression}} expected-note {{assignment to object outside its lifetime}}
+
+void *operator new(std::size_t, void *p) { return p; }
+constexpr bool no_placement_new_in_user_code() { // expected-error {{never produces a constant expression}}
+ int a;
+ new (&a) int(42); // expected-note {{call to placement 'operator new'}}
+ return a == 42;
+}
+
+namespace std {
+ constexpr bool placement_new_in_stdlib() {
+ int a;
+ new (&a) int(42);
+ return a == 42;
+ }
+}
+static_assert(std::placement_new_in_stdlib());
+
+namespace std {
+ template<typename T, typename ...Args>
+ constexpr void construct_at(void *p, Args &&...args) {
+ new (p) T((Args&&)args...); // #new
+ }
+}
+
+constexpr bool call_std_construct_at() {
+ int *p = std::allocator<int>().allocate(3);
+ std::construct_at<int>(p, 1);
+ std::construct_at<int>(p + 1, 2);
+ std::construct_at<int>(p + 2, 3);
+ bool good = p[0] + p[1] + p[2] == 6;
+ std::allocator<int>().deallocate(p);
+ return good;
+}
+static_assert(call_std_construct_at());
+
+constexpr bool bad_construct_at_type() {
+ int a;
+ // expected-note@#new {{placement new would change type of storage from 'int' to 'float'}}
+ std::construct_at<float>(&a, 1.0f); // expected-note {{in call}}
+ return true;
+}
+static_assert(bad_construct_at_type()); // expected-error{{}} expected-note {{in call}}
+
+constexpr bool bad_construct_at_subobject() {
+ struct X { int a, b; };
+ union A {
+ int a;
+ X x;
+ };
+ A a = {1};
+ // expected-note@#new {{construction of subobject of member 'x' of union with active member 'a' is not allowed in a constant expression}}
+ std::construct_at<int>(&a.x.a, 1); // expected-note {{in call}}
+ return true;
+}
+static_assert(bad_construct_at_subobject()); // expected-error{{}} expected-note {{in call}}
+
+constexpr bool change_union_member() {
+ union U {
+ int a;
+ int b;
+ };
+ U u = {.a = 1};
+ std::construct_at<int>(&u.b, 2);
+ return u.b == 2;
+}
+static_assert(change_union_member());
+
+int external;
+// expected-note@#new {{visible outside}}
+static_assert((std::construct_at<int>(&external, 1), true)); // expected-error{{}} expected-note {{in call}}
+
+constexpr int &&temporary = 0; // expected-note {{created here}}
+// expected-note@#new {{construction of temporary is not allowed in a constant expression outside the expression that created the temporary}}
+static_assert((std::construct_at<int>(&temporary, 1), true)); // expected-error{{}} expected-note {{in call}}
+
+constexpr bool construct_after_lifetime() {
+ int *p = new int;
+ delete p;
+ // expected-note@#new {{construction of heap allocated object that has been deleted}}
+ std::construct_at<int>(p); // expected-note {{in call}}
+ return true;
+}
+static_assert(construct_after_lifetime()); // expected-error {{}} expected-note {{in call}}
OpenPOWER on IntegriCloud