1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
// RUN: %clang_cc1 -std=c++2c -verify %s
namespace std {
using size_t = decltype(sizeof(0));
}
void *operator new(std::size_t, void *p) { return p; }
void* operator new[] (std::size_t, void* p) {return p;}
consteval int ok() {
int i;
new (&i) int(0);
new (&i) int[1]{1};
new (static_cast<void*>(&i)) int(0);
return 0;
}
consteval int conversion() {
int i;
new (static_cast<void*>(&i)) float(0);
// expected-note@-1 {{placement new would change type of storage from 'int' to 'float'}}
return 0;
}
consteval int indeterminate() {
int * indeterminate;
new (indeterminate) int(0);
// expected-note@-1 {{read of uninitialized object is not allowed in a constant expression}}
return 0;
}
consteval int array1() {
int i[2];
new (&i) int[]{1,2};
new (&i) int[]{1};
new (&i) int(0);
new (static_cast<void*>(&i)) int[]{1,2};
new (static_cast<void*>(&i)) int[]{1};
return 0;
}
consteval int array2() {
int i[1];
new (&i) int[2];
//expected-note@-1 {{placement new would change type of storage from 'int[1]' to 'int[2]'}}
return 0;
}
struct S{
int* i;
constexpr S() : i(new int(42)) {} // #no-deallocation
constexpr ~S() {delete i;}
};
consteval void alloc() {
S* s = new S();
s->~S();
new (s) S();
delete s;
}
consteval void alloc_err() {
S* s = new S();
new (s) S();
delete s;
}
int a = ok();
int b = conversion(); // expected-error {{call to consteval function 'conversion' is not a constant expression}} \
// expected-note {{in call to 'conversion()'}}
int c = indeterminate(); // expected-error {{call to consteval function 'indeterminate' is not a constant expression}} \
// expected-note {{in call to 'indeterminate()'}}
int d = array1();
int e = array2(); // expected-error {{call to consteval function 'array2' is not a constant expression}} \
// expected-note {{in call to 'array2()'}}
int alloc1 = (alloc(), 0);
int alloc2 = (alloc_err(), 0); // expected-error {{call to consteval function 'alloc_err' is not a constant expression}}
// expected-note@#no-deallocation {{allocation performed here was not deallocated}}
constexpr int *intptr() {
return new int;
}
constexpr bool yay() {
int *ptr = new (intptr()) int(42);
bool ret = *ptr == 42;
delete ptr;
return ret;
}
static_assert(yay());
constexpr bool blah() {
int *ptr = new (intptr()) int[3]{ 1, 2, 3 }; // expected-note {{placement new would change type of storage from 'int' to 'int[3]'}}
bool ret = ptr[0] == 1 && ptr[1] == 2 && ptr[2] == 3;
delete [] ptr;
return ret;
}
static_assert(blah()); // expected-error {{not an integral constant expression}} \
// expected-note {{in call to 'blah()'}}
constexpr int *get_indeterminate() {
int *evil;
return evil; // expected-note {{read of uninitialized object is not allowed in a constant expression}}
}
constexpr bool bleh() {
int *ptr = new (get_indeterminate()) int; // expected-note {{in call to 'get_indeterminate()'}}
return true;
}
static_assert(bleh()); // expected-error {{not an integral constant expression}} \
// expected-note {{in call to 'bleh()'}}
constexpr int modify_const_variable() {
const int a = 10;
new ((int *)&a) int(12); // expected-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}}
return a;
}
static_assert(modify_const_variable()); // expected-error {{not an integral constant expression}} \
// expected-note {{in call to}}
typedef const int T0;
typedef T0 T1;
constexpr T1 modify_const_variable_td() {
T1 a = 10;
new ((int *)&a) int(12); // expected-note {{modification of object of const-qualified type 'T1' (aka 'const int') is not allowed in a constant expression}}
return a;
}
static_assert(modify_const_variable_td()); // expected-error {{not an integral constant expression}} \
// expected-note {{in call to}}
template<typename T>
constexpr T modify_const_variable_tmpl() {
T a = 10;
new ((int *)&a) int(12); // expected-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}}
return a;
}
static_assert(modify_const_variable_tmpl<const int>()); // expected-error {{not an integral constant expression}} \
// expected-note {{in call to}}
namespace ModifyMutableMember {
struct S {
mutable int a {10};
};
constexpr int modify_mutable_member() {
const S s;
new ((int *)&s.a) int(12);
return s.a;
}
static_assert(modify_mutable_member() == 12);
}
|