File: cxx2c-constexpr-placement-new.cpp

package info (click to toggle)
llvm-toolchain-21 1%3A21.1.6-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,245,028 kB
  • sloc: cpp: 7,619,726; ansic: 1,434,018; asm: 1,058,748; python: 252,740; f90: 94,671; objc: 70,685; lisp: 42,813; pascal: 18,401; sh: 8,601; ml: 5,111; perl: 4,720; makefile: 3,675; awk: 3,523; javascript: 2,409; xml: 892; fortran: 770
file content (155 lines) | stat: -rw-r--r-- 4,805 bytes parent folder | download | duplicates (2)
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);
}