xref: /llvm-project/clang/test/Analysis/placement-new.cpp (revision a504ddc8bf9d5c406ea88b84b8495d7aae200d4c)
1 // RUN: %clang_analyze_cc1 -std=c++11 %s \
2 // RUN:   -analyzer-checker=core \
3 // RUN:   -analyzer-checker=cplusplus.NewDelete \
4 // RUN:   -analyzer-checker=cplusplus.PlacementNew \
5 // RUN:   -analyzer-output=text -verify \
6 // RUN:   -triple x86_64-unknown-linux-gnu
7 
8 #include "Inputs/system-header-simulator-cxx.h"
9 
f()10 void f() {
11   short s;                    // expected-note {{'s' declared without an initial value}}
12   long *lp = ::new (&s) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 3 {{}}
13   (void)lp;
14 }
15 
16 namespace testArrayNew {
f()17 void f() {
18   short s;                        // expected-note {{'s' declared without an initial value}}
19   char *buf = ::new (&s) char[8]; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 3 {{}}
20   (void)buf;
21 }
22 } // namespace testArrayNew
23 
24 namespace testBufferInOtherFun {
f(void * place)25 void f(void *place) {
26   long *lp = ::new (place) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
27   (void)lp;
28 }
g()29 void g() {
30   short buf; // expected-note {{'buf' declared without an initial value}}
31   f(&buf);   // expected-note 2 {{}}
32 }
33 } // namespace testBufferInOtherFun
34 
35 namespace testArrayBuffer {
f(void * place)36 void f(void *place) {
37   long *lp = ::new (place) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
38   (void)lp;
39 }
g()40 void g() {
41   char buf[2]; // expected-note {{'buf' initialized here}}
42   f(&buf);     // expected-note 2 {{}}
43 }
44 } // namespace testArrayBuffer
45 
46 namespace testGlobalPtrAsPlace {
47 void *gptr = nullptr;
48 short gs;
f()49 void f() {
50   gptr = &gs; // expected-note {{Value assigned to 'gptr'}}
51 }
g()52 void g() {
53   f();                          // expected-note 2 {{}}
54   long *lp = ::new (gptr) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
55   (void)lp;
56 }
57 } // namespace testGlobalPtrAsPlace
58 
59 namespace testRvalue {
60 short gs;
f()61 void *f() {
62   return &gs;
63 }
g()64 void g() {
65   long *lp = ::new (f()) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
66   (void)lp;
67 }
68 } // namespace testRvalue
69 
70 namespace testNoWarning {
71 void *f();
g()72 void g() {
73   long *lp = ::new (f()) long;
74   (void)lp;
75 }
76 } // namespace testNoWarning
77 
78 namespace testPtrToArrayAsPlace {
f()79 void f() {
80   //char *st = new char [8];
81   char buf[3];                // expected-note {{'buf' initialized here}}
82   void *st = buf;             // expected-note {{'st' initialized here}}
83   long *lp = ::new (st) long; // expected-warning{{Storage provided to placement new is only 3 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
84   (void)lp;
85 }
86 } // namespace testPtrToArrayAsPlace
87 
88 namespace testPtrToArrayWithOffsetAsPlace {
f()89 void f() {
90   int buf[3];                      // expected-note {{'buf' initialized here}}
91   long *lp = ::new (buf + 2) long; // expected-warning{{Storage provided to placement new is only 4 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
92   (void)lp;
93 }
94 } // namespace testPtrToArrayWithOffsetAsPlace
95 
96 namespace testZeroSize {
f()97 void f() {
98   int buf[3];                      // expected-note {{'buf' initialized here}}
99   long *lp = ::new (buf + 3) long; // expected-warning{{Storage provided to placement new is only 0 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
100   (void)lp;
101 }
102 } // namespace testZeroSize
103 
104 namespace testNegativeSize {
f()105 void f() {
106   int buf[3];                      // expected-note {{'buf' initialized here}}
107   long *lp = ::new (buf + 4) long; // expected-warning{{Storage provided to placement new is only -4 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
108   (void)lp;
109 }
110 } // namespace testNegativeSize
111 
112 namespace testHeapAllocatedBuffer {
g2()113 void g2() {
114   char *buf = new char[2];     // expected-note {{'buf' initialized here}}
115                                // FIXME: The message is misleading -- we should
116                                // state that a pointer to an uninitialized value
117                                // is stored.
118                                // expected-note@-4{{Storing uninitialized value}}
119   long *lp = ::new (buf) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
120   (void)lp;
121 }
122 } // namespace testHeapAllocatedBuffer
123 
124 namespace testMultiDimensionalArray {
f()125 void f() {
126   char buf[2][3];              // expected-note {{'buf' initialized here}}
127   long *lp = ::new (buf) long; // expected-warning{{Storage provided to placement new is only 6 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
128   (void)lp;
129 }
130 } // namespace testMultiDimensionalArray
131 
132 namespace testMultiDimensionalArray2 {
f()133 void f() {
134   char buf[2][3];                  // expected-note {{'buf' initialized here}}
135   long *lp = ::new (buf + 1) long; // expected-warning{{Storage provided to placement new is only 3 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
136   (void)lp;
137 }
138 } // namespace testMultiDimensionalArray2
139 
140 namespace testMultiDimensionalArray3 {
f()141 void f() {
142   char buf[2][3];                     // expected-note {{'buf' initialized here}}
143   long *lp = ::new (&buf[1][1]) long; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
144   (void)lp;
145 }
146 } // namespace testMultiDimensionalArray3
147 
148 namespace testHierarchy {
149 struct Base {
150   char a[2];
151 };
152 struct Derived : Base {
153   char x[2];
154   int y;
155 };
f()156 void f() {
157   Base b;                           // expected-note {{'b' initialized here}}
158   Derived *dp = ::new (&b) Derived; // expected-warning{{Storage provided to placement new is only 2 bytes, whereas the allocated type requires 8 bytes}} expected-note 1 {{}}
159   (void)dp;
160 }
161 } // namespace testHierarchy
162 
163 namespace testArrayTypesAllocation {
f1()164 void f1() {
165   struct S {
166     short a;
167   };
168 
169   // bad (not enough space).
170   const unsigned N = 32;
171   alignas(S) unsigned char buffer1[sizeof(S) * N]; // expected-note {{'buffer1' initialized here}}
172   ::new (buffer1) S[N];                            // expected-warning{{Storage provided to placement new is only 64 bytes, whereas the allocated array type requires more space for internal needs}} expected-note 1 {{}}
173 }
174 
f2()175 void f2() {
176   struct S {
177     short a;
178   };
179 
180   // maybe ok but we need to warn.
181   const unsigned N = 32;
182   alignas(S) unsigned char buffer2[sizeof(S) * N + sizeof(int)]; // expected-note {{'buffer2' initialized here}}
183   ::new (buffer2) S[N];                                          // expected-warning{{68 bytes is possibly not enough for array allocation which requires 64 bytes. Current overhead requires the size of 4 bytes}} expected-note 1 {{}}
184 }
185 } // namespace testArrayTypesAllocation
186 
187 namespace testStructAlign {
f1()188 void f1() {
189   struct X {
190     char a[9];
191   } Xi; // expected-note {{'Xi' initialized here}}
192 
193   // bad (struct X is aligned to char).
194   ::new (&Xi.a) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
195 }
196 
f2()197 void f2() {
198   struct X {
199     char a;
200     char b;
201     long c;
202   } Xi;
203 
204   // ok (struct X is aligned to long).
205   ::new (&Xi.a) long;
206 }
207 
f3()208 void f3() {
209   struct X {
210     char a;
211     char b;
212     long c;
213   } Xi; // expected-note {{'Xi' initialized here}}
214 
215   // bad (struct X is aligned to long but field 'b' is aligned to 1 because of its offset)
216   ::new (&Xi.b) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
217 }
218 
f4()219 void f4() {
220   struct X {
221     char a;
222     struct alignas(alignof(short)) Y {
223       char b;
224       char c;
225     } y;
226     long d;
227   } Xi; // expected-note {{'Xi' initialized here}}
228 
229   // bad. 'b' is aligned to short
230   ::new (&Xi.y.b) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
231 }
232 
f5()233 void f5() {
234   short b[10]; // expected-note {{'b' initialized here}}
235 
236   ::new (&b) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
237 }
238 
f6()239 void f6() {
240   short b[10]; // expected-note {{'b' initialized here}}
241 
242   // bad (same as previous but checks ElementRegion case)
243   ::new (&b[0]) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
244 }
245 
f7()246 void f7() {
247   alignas(alignof(long)) short b[10];
248 
249   // ok. aligned to long(ok). offset 4*2(ok)
250   ::new (&b[4]) long;
251 }
252 
f8()253 void f8() {
254   alignas(alignof(long)) short b[10]; // expected-note {{'b' initialized here}}
255 
256   // ok. aligned to long(ok). offset 3*2(ok)
257   ::new (&b[3]) long; // expected-warning{{Storage type is aligned to 6 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
258 }
259 
f9()260 void f9() {
261   struct X {
262     char a;
263     alignas(alignof(long)) char b[20];
264   } Xi; // expected-note {{'Xi' initialized here}}
265 
266   // ok. aligned to long(ok). offset 8*1(ok)
267   ::new (&Xi.b[8]) long;
268 
269   // bad. aligned to long(ok). offset 1*1(ok)
270   ::new (&Xi.b[1]) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
271 }
272 
f10()273 void f10() {
274   struct X {
275     char a[8];
276     alignas(2) char b;
277   } Xi; // expected-note {{'Xi' initialized here}}
278 
279   // bad (struct X is aligned to 2).
280   ::new (&Xi.a) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
281 }
282 
f11()283 void f11() {
284   struct X {
285     char a;
286     char b;
287     struct Y {
288       long c;
289     } d;
290   } Xi;
291 
292   // ok (struct X is aligned to long).
293   ::new (&Xi.a) long;
294 }
295 
f12()296 void f12() {
297   struct alignas(alignof(long)) X {
298     char a;
299     char b;
300   } Xi;
301 
302   // ok (struct X is aligned to long).
303   ::new (&Xi.a) long;
304 }
305 
test13()306 void test13() {
307   struct Y {
308     char a[10];
309   };
310 
311   struct X {
312     Y b[10];
313   } Xi; // expected-note {{'Xi' initialized here}}
314 
315   // bad. X,A are aligned to 'char'
316   ::new (&Xi.b[0].a) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
317 }
318 
test14()319 void test14() {
320   struct Y {
321     char a[10];
322   };
323 
324   struct alignas(alignof(long)) X {
325     Y b[10];
326   } Xi;
327 
328   // ok. X is aligned to 'long' and field 'a' goes with zero offset
329   ::new (&Xi.b[0].a) long;
330 }
331 
test15()332 void test15() {
333   struct alignas(alignof(long)) Y {
334     char a[10];
335   };
336 
337   struct X {
338     Y b[10];
339   } Xi;
340 
341   // ok. X is aligned to 'long' because it contains struct 'Y' which is aligned to 'long'
342   ::new (&Xi.b[0].a) long;
343 }
344 
test16()345 void test16() {
346   struct alignas(alignof(long)) Y {
347     char p;
348     char a[10];
349   };
350 
351   struct X {
352     Y b[10];
353   } Xi; // expected-note {{'Xi' initialized here}}
354 
355   // bad. aligned to long(ok). offset 1(bad)
356   ::new (&Xi.b[0].a) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
357 }
358 
test17()359 void test17() {
360   struct alignas(alignof(long)) Y {
361     char p;
362     char a[10];
363   };
364 
365   struct X {
366     Y b[10];
367   } Xi;
368 
369   // ok. aligned to long(ok). offset 1+7*1(ok)
370   ::new (&Xi.b[0].a[7]) long;
371 }
372 
test18()373 void test18() {
374   struct Y {
375     char p;
376     alignas(alignof(long)) char a[10];
377   };
378 
379   struct X {
380     Y b[10];
381   } Xi; // expected-note {{'Xi' initialized here}}
382 
383   // ok. aligned to long(ok). offset 8*1(ok)
384   ::new (&Xi.b[0].a[8]) long;
385 
386   // bad. aligned to long(ok). offset 1(bad)
387   ::new (&Xi.b[0].a[1]) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
388 }
389 
test19()390 void test19() {
391   struct Z {
392     char p;
393     char c[10];
394   };
395 
396   struct Y {
397     char p;
398     Z b[10];
399   };
400 
401   struct X {
402     Y a[10];
403   } Xi; // expected-note {{'Xi' initialized here}}
404 
405   // bad. all structures X,Y,Z are aligned to char
406   ::new (&Xi.a[1].b[1].c) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
407 }
408 
test20()409 void test20() {
410   struct Z {
411     char p;
412     alignas(alignof(long)) char c[10];
413   };
414 
415   struct Y {
416     char p;
417     Z b[10];
418   };
419 
420   struct X {
421     Y a[10];
422   } Xi;
423 
424   // ok. field 'c' is aligned to 'long'
425   ::new (&Xi.a[1].b[1].c) long;
426 }
427 
test21()428 void test21() {
429   struct Z {
430     char p;
431     char c[10];
432   };
433 
434   struct Y {
435     char p;
436     Z b[10];
437   };
438 
439   struct alignas(alignof(long)) X {
440     Y a[10];
441   } Xi; // expected-note {{'Xi' initialized here}}
442 
443   // ok. aligned to long(ok). offset 1+7*1(ok)
444   ::new (&Xi.a[0].b[0].c[7]) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
445 }
446 
test22()447 void test22() {
448   struct alignas(alignof(long)) Y {
449     char p;
450     char a[10][10];
451   };
452 
453   struct X {
454     Y b[10];
455   } Xi; // expected-note {{'Xi' initialized here}}
456 
457   // ok. aligned to long(ok). offset ok. 1(field 'a' offset) + 0*10(index '0' * first dimension size '10') + 7*1(index '7')
458   ::new (&Xi.b[0].a[0][7]) long;
459 
460   // ok. aligned to long(ok). offset ok. 1(field 'a' offset) + 1*10(index '1' * first dimension size '10') + 5*1(index '5')
461   ::new (&Xi.b[0].a[1][5]) long;
462 
463   // bad. aligned to long(ok). offset ok. 1(field 'a' offset) + 1*10(index '1' * first dimension size '10') + 6*1(index '5')
464   ::new (&Xi.b[0].a[1][6]) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
465 }
466 
467 } // namespace testStructAlign
468