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