1 /* { dg-do compile } */
2 /* { dg-options "-Wplacement-new -fpermissive" } */
3
4 typedef __typeof__ (sizeof 0) size_t;
5
new(size_t,void * p)6 void* operator new (size_t, void *p) { return p; }
7 void* operator new[] (size_t, void *p) { return p; }
8
9 static __attribute__ ((used))char c;
10 static __attribute__ ((used))char ac1 [1];
11 static __attribute__ ((used))char ac2 [2];
12 static __attribute__ ((used))char ac3 [3];
13 static __attribute__ ((used))char ac4 [4];
14 static __attribute__ ((used))char ac5 [5];
15 static __attribute__ ((used))char ac6 [6];
16 static __attribute__ ((used))char ac7 [7];
17 static __attribute__ ((used))char ac8 [8];
18
19 static __attribute__ ((used))char ac1_1 [1][1];
20 static __attribute__ ((used))char ac1_2 [1][2];
21 static __attribute__ ((used))char ac2_1 [2][1];
22 static __attribute__ ((used))char ac2_2 [2][2];
23
24 static __attribute__ ((used))short s;
25 static __attribute__ ((used))short as1 [1];
26 static __attribute__ ((used))short as2 [2];
27
28 static __attribute__ ((used))struct SC { char c; char *pc; void *pv; } sc;
29 static __attribute__ ((used))struct SAC1 { char ac [1]; } sac1;
30 static __attribute__ ((used))struct SAC2 { char ac [2]; } sac2;
31 static __attribute__ ((used))struct SAC3 { char ac [3]; } sac3;
32 static __attribute__ ((used))struct SAC4 { char ac [4]; } sac4;
33
34 static __attribute__ ((used))struct SSC { SC sc; int x; } ssc;
35 static __attribute__ ((used))struct SSAC1 { SAC1 sac; } ssac1;
36 static __attribute__ ((used))struct SSAC2 { SAC2 sac; } ssac2;
37 static __attribute__ ((used))struct SSAC3 { SAC3 sac; } ssac3;
38 static __attribute__ ((used))struct SSAC4 { SAC4 sac; } ssac4;
39
40 static __attribute__ ((used))struct SSAC4_2 { SSAC4 ssac4_2 [2]; } sssac4_2;
41
42 static __attribute__ ((used))union UAC1 { char c; char ac [1]; } uac1;
43 static __attribute__ ((used))union UAC2 { char c; char ac [2]; } uac2;
44 static __attribute__ ((used))union UAC3 { char c; char ac [3]; } uac3;
45 static __attribute__ ((used))union UAC4 { char c; char ac [4]; } uac4;
46
fsc()47 static __attribute__ ((used))SC fsc () { return SC (); }
fasc1()48 static __attribute__ ((used))SAC1 fasc1 () { return SAC1 (); }
fasc2()49 static __attribute__ ((used))SAC2 fasc2 () { return SAC2 (); }
fasc3()50 static __attribute__ ((used))SAC3 fasc3 () { return SAC3 (); }
fasc4()51 static __attribute__ ((used))SAC4 fasc4 () { return SAC4 (); }
52
53 static __attribute__ ((used))void *r;
54
ptr()55 static __attribute__ ((used))void* ptr () { return 0; }
56
57 static __attribute__ ((used))
test(void * p,int n)58 void test (void *p, int n)
59 {
60 {
61 void *q = p;
62 struct { void *p; } s = { p };
63
64 // Verify that none of function arguments, local or global
65 // variables, or function return values trigger the warning.
66 new (p) char;
67 new (q) char;
68 new (r) char;
69 new (s.p) char;
70 new (ptr ()) char;
71
72 new (p) char [32];
73 new (q) char [32];
74 new (r) char [32];
75 new (s.p) char [32];
76 new (ptr ()) char [32];
77
78 new (&p) char;
79 new (&q) char;
80 new (&r) char;
81
82 // Using address of objects, however, must trigger the warning.
83 new (&p) char [32]; // { dg-warning "placement" }
84 new (&q) char [32]; // { dg-warning "placement" }
85 new (&r) char [32]; // { dg-warning "placement" }
86 }
87
88 enum { N0, N1, N2, N3 };
89
90 new (&c) char;
91
92 // Warn for the common case when constructing at an offset from
93 // the beginning of an array that doesn't leave enough space for
94 // the object.
95 new (&c + 0) char; // okay
96 new (&c + n) char; // okay (n is unknown)
97 new (&c + 1) char; // { dg-warning "placement" }
98 new (&c + N0) char;
99 new (&c + N1) char; // { dg-warning "placement" }
100
101 // No warning is issued when constructing an array in space exactly
102 // its size even though strictly speaking a compiler is allowed to
103 // add a cookie to the array (gcc does not).
104 new (&c) char [1];
105 new (&c) char [sizeof c];
106 new (&c) char [n];
107 new (&c) char [1][1];
108 new (&c) char [1][1][1];
109 new (&c + N1) char [1][1][1]; // { dg-warning "placement" }
110
111 new (&c) char [2]; // { dg-warning "placement" }
112 new (&c) char [sizeof c + 1]; // { dg-warning "placement" }
113 new (&c) char [1][2]; // { dg-warning "placement" }
114 new (&c) char [2][1]; // { dg-warning "placement" }
115 new (&c) char [n][1];
116 new (&c) char [n][2]; // { dg-warning "placement" }
117 new (&c) char [3]; // { dg-warning "placement" }
118 new (&c) char [3][1]; // { dg-warning "placement" }
119 new (&c) char [1][3]; // { dg-warning "placement" }
120 new (&c) char [4][1]; // { dg-warning "placement" }
121 new (&c) char [1][4]; // { dg-warning "placement" }
122
123 // Casts must not suppress it.
124 new ((void*)&c) char [2]; // { dg-warning "placement" }
125 new ((char*)&c) char [3]; // { dg-warning "placement" }
126
127 new (static_cast<void*>(&c)) char [4]; // { dg-warning "placement" }
128 new (reinterpret_cast<char*>(&c)) char [5]; // { dg-warning "placement" }
129
130 new (&c + 0) char [2]; // { dg-warning "placement" }
131 new (&c + 0) char [3]; // { dg-warning "placement" }
132 new (&c + 0) char [4]; // { dg-warning "placement" }
133
134 new (&c + 1) char [2]; // { dg-warning "placement" }
135 new (&c + 1) char [3]; // { dg-warning "placement" }
136 new (&c + 1) char [4]; // { dg-warning "placement" }
137
138 new (&c + N0) char [1];
139 new (&c + N1) char [2]; // { dg-warning "placement" }
140
141 // Warn even though n is unknown since c is too small for char[2]
142 // regardless of the value of n.
143 new (&c + n) char [2]; // { dg-warning "placement" }
144
145 new (ac2) char [1];
146 new (ac2) char [1][1];
147 new (ac2) char [1][2];
148 new (ac2) char [2][1];
149 new (ac2) char [1][3]; // { dg-warning "placement" }
150 new (ac2) char [2][2]; // { dg-warning "placement" }
151 new (ac2) char [3][1]; // { dg-warning "placement" }
152
153 new (ac2 + N0) char [1][1];
154 new (ac2 + N0) char [1][2];
155 new (ac2 + N1) char [1][2]; // { dg-warning "placement" }
156 new (ac2 + N1) char [2][1]; // { dg-warning "placement" }
157 new (ac2 + N2) char [1][1]; // { dg-warning "placement" }
158 new (ac2 + N2) char [1][2]; // { dg-warning "placement" }
159 new (ac2 + N2) char [2][1]; // { dg-warning "placement" }
160 new (ac2 + N2) char [2][2]; // { dg-warning "placement" }
161
162 new (ac8) char [1];
163 new (ac8) char [2][2];
164 new (ac8) char [2][3];
165 new (ac8) char [2][4];
166 new (ac8) char [2][5]; // { dg-warning "placement" }
167 new (ac8) char [2][2][2];
168 new (ac8) char [2][2][3]; // { dg-warning "placement" }
169
170 new (&c) int; // { dg-warning "placement" }
171
172 new (&ac1) int; // { dg-warning "placement" }
173 new (&ac2) int; // { dg-warning "placement" }
174 new (&ac3) int; // { dg-warning "placement" }
175 new (&ac4) int;
176
177 // Constructing at an address of an array element.
178 new (&ac1 [0]) int; // { dg-warning "placement" }
179 new (&ac2 [0]) int; // { dg-warning "placement" }
180 new (&ac3 [0]) int; // { dg-warning "placement" }
181 new (&ac4 [0]) int;
182
183 // ...plus or minus a constant offset.
184 new (&ac1 [0] + 0) int; // { dg-warning "placement" }
185 new (&ac2 [0] + 0) int; // { dg-warning "placement" }
186 new (&ac3 [0] + 0) int; // { dg-warning "placement" }
187 new (&ac4 [0] + 0) int;
188 new (&ac4 [1] + 0) int; // { dg-warning "placement" }
189 new (&ac4 [1] - 1) int;
190 new (&ac4 [2] - 1) int; // { dg-warning "placement" }
191 new (&ac4 [2] - 2) int;
192 new (&ac4 [3] - 1) int; // { dg-warning "placement" }
193 new (&ac4 [3] - 2) int; // { dg-warning "placement" }
194 new (&ac4 [3] - 3) int;
195 new (&ac4 [4] - 1) int; // { dg-warning "placement" }
196 new (&ac4 [4] - 2) int; // { dg-warning "placement" }
197 new (&ac4 [4] - 3) int; // { dg-warning "placement" }
198 new (&ac4 [4] - 4) int;
199
200 new (&ac1 [0] + 1) int; // { dg-warning "placement" }
201 new (&ac2 [0] + 1) int; // { dg-warning "placement" }
202 new (&ac3 [0] + 1) int; // { dg-warning "placement" }
203 new (&ac4 [0] + 1) int; // { dg-warning "placement" }
204
205 new (&ac3 [0] + n) int; // { dg-warning "placement" }
206 new (&ac4 [0] + n) int; // no warning (n could be zero)
207 new (&ac4 [1] + n) int; // no warning (n could be negative)
208 new (&ac4 [2] + n) int; // ditto
209 new (&ac4 [3] + n) int; // ditto
210 new (&ac4 [4] + n) int; // ditto
211 new (&ac4 [4] - n) int; // (or positive)
212
213 new (&c + 0) int; // { dg-warning "placement" }
214 new (&c + 1) int; // { dg-warning "placement" }
215
216 // Constructing at an offset into the address of an array.
217 new (&ac1 + 0) int; // { dg-warning "placement" }
218 new (&ac1 + 1) int; // { dg-warning "placement" }
219 new (&ac1 + n) int; // { dg-warning "placement" }
220 new (&ac2 + 0) int; // { dg-warning "placement" }
221 new (&ac2 + 1) int; // { dg-warning "placement" }
222 new (&ac2 + n) int; // { dg-warning "placement" }
223 new (&ac3 + 0) int; // { dg-warning "placement" }
224 new (&ac3 + 1) int; // { dg-warning "placement" }
225
226 // Even though n below is uknown an array of 3 bytes isn't large
227 // enugh for an int.
228 new (&ac3 + n) int; // { dg-warning "placement" }
229
230 new (&ac4 + 0) int;
231 new (&ac4 + 1) int; // { dg-warning "placement" }
232 new (&ac4 + n) int; // no warning (n could be zero)
233
234 // Constructing in an array object.
235 new (ac1) int; // { dg-warning "placement" }
236 new (ac2) int; // { dg-warning "placement" }
237 new (ac3) int; // { dg-warning "placement" }
238 new (ac4) int;
239 new (ac5) int;
240 new (ac5 + 0) int;
241 new (ac5 + 1) int;
242 new (ac5 + n) int; // no warning (n could be zero)
243 new (ac5 + 2) int; // { dg-warning "placement" }
244 new (ac5 + 3) int; // { dg-warning "placement" }
245 new (ac5 + 4) int; // { dg-warning "placement" }
246 new (ac5 + 5) int; // { dg-warning "placement" }
247
248 new (ac1_1) char;
249 new (ac1_1) char[1];
250 new (ac1_1) char[n]; // no warning (n is unknown)
251 new (ac1_1) char[2]; // { dg-warning "placement" }
252 new (ac1_1) char[3]; // { dg-warning "placement" }
253
254 new (ac1_2) char;
255 new (ac1_2) char[1];
256 new (ac1_2) char[2];
257 new (ac1_2) char[3]; // { dg-warning "placement" }
258
259 new (ac2_1) char;
260 new (ac2_1) char[1];
261 new (ac2_1) char[2];
262 new (ac2_1) char[3]; // { dg-warning "placement" }
263
264 new (ac2_2) char;
265 new (ac2_2) char[1];
266 new (ac2_2) char[2];
267 new (ac2_2) char[2][2];
268
269 // Even though n below is uknown it can't meaningfully be zero
270 // (even if zero-size arrays are allowed as an extension, the size
271 // they are allocated in by placement new is zero).
272 new (ac1_1) char[n][2]; // { dg-warning "placement" }
273 new (ac2_2) char[3];
274 new (ac2_2) char[3][1];
275 new (ac2_2) char[3][2]; // { dg-warning "placement" }
276 new (ac2_2) char[4];
277 new (ac2_2) char[4][1];
278 new (ac2_2) char[4][2]; // { dg-warning "placement" }
279 new (ac2_2) char[5]; // { dg-warning "placement" }
280
281 new (&s) int; // { dg-warning "placement" }
282 new (&as1) int; // { dg-warning "placement" }
283 new (&as2) int;
284
285 new (as1) int; // { dg-warning "placement" }
286 new (as2) int;
287
288 new (&sc.c) int; // { dg-warning "placement" }
289 new (&sac1.ac) int; // { dg-warning "placement" }
290 new (&sac2.ac) int; // { dg-warning "placement" }
291 new (&sac3.ac) int; // { dg-warning "placement" }
292 new (&sac4.ac) int;
293
294 new (sc.pc) char;
295 new (sc.pc) int;
296 new (sc.pc) int[1024];
297 new (sc.pc + 0) int;
298 new (sc.pc + 0) int[2048];
299 new (sc.pv) int;
300 new (sc.pv) char[1024];
301
302 new (sac1.ac) int; // { dg-warning "placement" }
303 new (sac2.ac) int; // { dg-warning "placement" }
304 new (sac3.ac) int; // { dg-warning "placement" }
305 new (sac4.ac) int;
306
307 new (&ssc.sc) SSC; // { dg-warning "placement" }
308 new (&ssac1.sac) int; // { dg-warning "placement" }
309 new (&ssac2.sac) int; // { dg-warning "placement" }
310 new (&ssac3.sac) int; // { dg-warning "placement" }
311 new (&ssac4.sac) int;
312
313 new (&sssac4_2) char[sizeof sssac4_2];
314 new (&sssac4_2) char[sizeof sssac4_2 + 1]; // { dg-warning "placement" }
315
316 // taking the address of a temporary is allowed with -fpermissive
317 new (&fsc ().c) int; // { dg-warning "address|placement" }
318 new (&fasc1 ().ac) int; // { dg-warning "address|placement" }
319 new (&fasc2 ().ac) int; // { dg-warning "address|placement" }
320 new (&fasc3 ().ac) int; // { dg-warning "address|placement" }
321 new (&fasc4 ().ac) int; // { dg-warning "address|placement" }
322
323 new (&uac1) int; // { dg-warning "placement" }
324 new (&uac2) int; // { dg-warning "placement" }
325 new (&uac3) int; // { dg-warning "placement" }
326 new (&uac4) int;
327 new (&uac4 + 1) int; // { dg-warning "placement" }
328
329 new (&uac1.c) int; // { dg-warning "placement" }
330 new (&uac2.c) int; // { dg-warning "placement" }
331 new (&uac3.c) int; // { dg-warning "placement" }
332
333 // Diagnose the following even though the size of uac4.c could be
334 // expected to extend to the end of the union (as it is by Built-in
335 // Object Size and so isn't diagnosed in calls to functions like
336 // memset(&uac4.c, 0, sizeof(int)) when _FORTIFY_SOURCE is non-zero. */
337 new (&uac4.c) int; // { dg-warning "placement" }
338
339 new (&uac4.c + 1) int; // { dg-warning "placement" }
340 }
341
342
343 struct S { char c [2]; };
344
345 // Verify the full text of the warning message.
346 static __attribute__ ((used))
test_message(int i)347 void test_message (int i)
348 {
349 char a [2];
350
351 // The exact sizes of both the buffer and the type are known.
352 new (a + 1) S; // { dg-warning "placement new constructing an object of type .S. and size .2. in a region of type .char \\\[2\\\]. and size .1." }
353
354 // The buffer size is known but only the size of the type whose
355 // objects are being constructed is known, not their number. While
356 // in theory it could be zero, it practice likely never will be so
357 // the potential false positive is acceptable.
358 new (a + 1) S [i]; // { dg-warning "placement new constructing an array of objects of type .S. and size .2. in a region of type .char \\\[2\\\]. and size .1." }
359
360 // The exact amount of space in the buffer isn't known, only its
361 // maximum is. The exact size of the array being created is known.
362 new (a + i) S [2]; // { dg-warning "placement new constructing an object of type .S \\\[2\\\]. and size .4. in a region of type .char \\\[2\\\]. and size at most .2." }
363 }
364
365
366 struct ClassWithMemberNew {
367 struct Object { int i; } *pobj;
368 unsigned nobj;
369
370 ClassWithMemberNew ();
371 void foo ();
372
373 void* operator new (size_t, void*);
374 void* operator new[] (size_t, void*);
375 };
376
foo()377 void ClassWithMemberNew::foo()
378 {
379 for (unsigned i = 0; i != nobj; ++i)
380 new (pobj + i) Object ();
381 }
382
383
384 struct ClassWithGlobalNew {
385 int a [4];
386 ClassWithGlobalNew ();
387 };
388
389 void* operator new (size_t, ClassWithGlobalNew*);
390 void* operator new[] (size_t, ClassWithGlobalNew*);
391
test_user_defined_placement_new()392 void test_user_defined_placement_new ()
393 {
394 {
395 ClassWithMemberNew x;
396
397 // Expect no diagnostics for placement new expressions with types
398 // with their own placement operator new since the semantics of
399 // the operator aren't known.
400 new (&c) ClassWithMemberNew;
401 new (&x) ClassWithMemberNew[2];
402 }
403
404 {
405 ClassWithGlobalNew x;
406
407 new (&c) ClassWithGlobalNew; // { dg-warning "placement" }
408 new (&x) ClassWithGlobalNew[2];
409 }
410 }
411
412 extern char extbuf[];
413
414 template <class> struct TemplateClass { char c; };
415
416 // Declare a specialization but don't provide a definition.
417 template <> struct TemplateClass<void>;
418
419 // Declare an object of an explicit specialization of an unknown size.
420 extern TemplateClass<void> exttempl_void;
421
422 // Verify that no warning is issued when placement new is called with
423 // an extern buffer of unknown size (and the case is handled gracefully
424 // and doesn't cause an ICE).
425 static __attribute__ ((used))
426 void test_extern_buffer_of_unknown_size ()
427 {
428 new (extbuf) int ();
429 new (extbuf) int [1024];
430
431 new (&exttempl_void) int ();
432 new (&exttempl_void) int [1024];
433 }
434
435 extern char extbuf_size_int [sizeof (int)];
436
437 extern TemplateClass<int> exttempl;
438
439 // Verify that a warning is issued as expected when placement new is
440 // called with an extern buffer of known size (and the case is handled
441 // gracefully and doesn't cause an ICE).
442 static __attribute__ ((used))
443 void test_extern_buffer ()
444 {
445 new (extbuf_size_int) int ();
446 new (extbuf_size_int) int [1];
447
448 struct S { int a [2]; };
449
450 new (extbuf_size_int) S; // { dg-warning "placement" }
451 new (extbuf_size_int) int [2]; // { dg-warning "placement" }
452
453 new (&exttempl) int (); // { dg-warning "placement" }
454 new (&exttempl) int [1024]; // { dg-warning "placement" }
455 }
456