488 lines · cpp
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-gnu7 8#include "Inputs/system-header-simulator-cxx.h"9 10void 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 16namespace testArrayNew {17void 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 testArrayNew23 24namespace testBufferInOtherFun {25void 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}29void g() {30 short buf; // expected-note {{'buf' declared without an initial value}}31 f(&buf); // expected-note 2 {{}}32}33} // namespace testBufferInOtherFun34 35namespace testArrayBuffer {36void 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}40void g() {41 char buf[2]; // expected-note {{'buf' initialized here}}42 f(&buf); // expected-note 2 {{}}43}44} // namespace testArrayBuffer45 46namespace testGlobalPtrAsPlace {47void *gptr = nullptr;48short gs;49void f() {50 gptr = &gs; // expected-note {{Value assigned to 'gptr'}}51}52void 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 testGlobalPtrAsPlace58 59namespace testRvalue {60short gs;61void *f() {62 return &gs;63}64void 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 testRvalue69 70namespace testNoWarning {71void *f();72void g() {73 long *lp = ::new (f()) long;74 (void)lp;75}76} // namespace testNoWarning77 78namespace testPtrToArrayAsPlace {79void 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 testPtrToArrayAsPlace87 88namespace testPtrToArrayWithOffsetAsPlace {89void 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 testPtrToArrayWithOffsetAsPlace95 96namespace testZeroSize {97void 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 testZeroSize103 104namespace testNegativeSize {105void 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 testNegativeSize111 112namespace testHeapAllocatedBuffer {113void g2() {114 char *buf = new char[2]; // expected-note {{'buf' initialized here}}115 // FIXME: The message is misleading -- we should116 // state that a pointer to an uninitialized value117 // 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 testHeapAllocatedBuffer123 124namespace testMultiDimensionalArray {125void 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 testMultiDimensionalArray131 132namespace testMultiDimensionalArray2 {133void 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 testMultiDimensionalArray2139 140namespace testMultiDimensionalArray3 {141void 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 testMultiDimensionalArray3147 148namespace testHierarchy {149struct Base {150 char a[2];151};152struct Derived : Base {153 char x[2];154 int y;155};156void 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 testHierarchy162 163namespace testArrayTypesAllocation {164void f1() {165 struct S {166 short a;167 };168 169 // On some systems, (notably before MSVC 16.7), a non-allocating placement170 // array new could allocate more memory than the nominal size of the array.171 172 // Since CWG 2382 (implemented in MSVC 16.7), overhead was disallowed for non-allocating placement new.173 // See:174 // https://learn.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=msvc-170175 // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1969r0.html#2382176 177 // However, as of 17.1, there is a regression when the type comes from a template178 // parameter where MSVC reintroduces overhead.179 // See:180 // https://developercommunity.visualstudio.com/t/10777485181 // https://godbolt.org/z/E1z1Tsfvj182 183 // The checker doesn't warn here because this behavior only affects older184 // MSVC versions (<16.7) or certain specific versions (17.1).185 // Suppressing warnings avoids false positives on standard-compliant compilers186 // and modern MSVC versions, but users of affected MSVC versions should be187 // aware of potential buffer size issues.188 189 const unsigned N = 32;190 alignas(S) unsigned char buffer1[sizeof(S) * N]; 191 ::new (buffer1) S[N]; // no-warning: See comments above192}193 194void f2() {195 struct S {196 short a;197 };198 199 // On some systems, placement array new could allocate more memory than the nominal size of the array.200 // See the comment at f1() above for more details.201 const unsigned N = 32;202 alignas(S) unsigned char buffer2[sizeof(S) * N + sizeof(int)]; 203 ::new (buffer2) S[N]; // no-warning: See comments above204}205} // namespace testArrayTypesAllocation206 207namespace testStructAlign {208void f1() {209 struct X {210 char a[9];211 } Xi; // expected-note {{'Xi' initialized here}}212 213 // bad (struct X is aligned to char).214 ::new (&Xi.a) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}215}216 217void f2() {218 struct X {219 char a;220 char b;221 long c;222 } Xi;223 224 // ok (struct X is aligned to long).225 ::new (&Xi.a) long;226}227 228void f3() {229 struct X {230 char a;231 char b;232 long c;233 } Xi; // expected-note {{'Xi' initialized here}}234 235 // bad (struct X is aligned to long but field 'b' is aligned to 1 because of its offset)236 ::new (&Xi.b) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}237}238 239void f4() {240 struct X {241 char a;242 struct alignas(alignof(short)) Y {243 char b;244 char c;245 } y;246 long d;247 } Xi; // expected-note {{'Xi' initialized here}}248 249 // bad. 'b' is aligned to short250 ::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 {{}}251}252 253void f5() {254 short b[10]; // expected-note {{'b' initialized here}}255 256 ::new (&b) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}257}258 259void f6() {260 short b[10]; // expected-note {{'b' initialized here}}261 262 // bad (same as previous but checks ElementRegion case)263 ::new (&b[0]) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}264}265 266void f7() {267 alignas(alignof(long)) short b[10];268 269 // ok. aligned to long(ok). offset 4*2(ok)270 ::new (&b[4]) long;271}272 273void f8() {274 alignas(alignof(long)) short b[10]; // expected-note {{'b' initialized here}}275 276 // ok. aligned to long(ok). offset 3*2(ok)277 ::new (&b[3]) long; // expected-warning{{Storage type is aligned to 6 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}278}279 280void f9() {281 struct X {282 char a;283 alignas(alignof(long)) char b[20];284 } Xi; // expected-note {{'Xi' initialized here}}285 286 // ok. aligned to long(ok). offset 8*1(ok)287 ::new (&Xi.b[8]) long;288 289 // bad. aligned to long(ok). offset 1*1(ok)290 ::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 {{}}291}292 293void f10() {294 struct X {295 char a[8];296 alignas(2) char b;297 } Xi; // expected-note {{'Xi' initialized here}}298 299 // bad (struct X is aligned to 2).300 ::new (&Xi.a) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}301}302 303void f11() {304 struct X {305 char a;306 char b;307 struct Y {308 long c;309 } d;310 } Xi;311 312 // ok (struct X is aligned to long).313 ::new (&Xi.a) long;314}315 316void f12() {317 struct alignas(alignof(long)) X {318 char a;319 char b;320 } Xi;321 322 // ok (struct X is aligned to long).323 ::new (&Xi.a) long;324}325 326void test13() {327 struct Y {328 char a[10];329 };330 331 struct X {332 Y b[10];333 } Xi; // expected-note {{'Xi' initialized here}}334 335 // bad. X,A are aligned to 'char'336 ::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 {{}}337}338 339void test14() {340 struct Y {341 char a[10];342 };343 344 struct alignas(alignof(long)) X {345 Y b[10];346 } Xi;347 348 // ok. X is aligned to 'long' and field 'a' goes with zero offset349 ::new (&Xi.b[0].a) long;350}351 352void test15() {353 struct alignas(alignof(long)) Y {354 char a[10];355 };356 357 struct X {358 Y b[10];359 } Xi;360 361 // ok. X is aligned to 'long' because it contains struct 'Y' which is aligned to 'long'362 ::new (&Xi.b[0].a) long;363}364 365void test16() {366 struct alignas(alignof(long)) Y {367 char p;368 char a[10];369 };370 371 struct X {372 Y b[10];373 } Xi; // expected-note {{'Xi' initialized here}}374 375 // bad. aligned to long(ok). offset 1(bad)376 ::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 {{}}377}378 379void test17() {380 struct alignas(alignof(long)) Y {381 char p;382 char a[10];383 };384 385 struct X {386 Y b[10];387 } Xi;388 389 // ok. aligned to long(ok). offset 1+7*1(ok)390 ::new (&Xi.b[0].a[7]) long;391}392 393void test18() {394 struct Y {395 char p;396 alignas(alignof(long)) char a[10];397 };398 399 struct X {400 Y b[10];401 } Xi; // expected-note {{'Xi' initialized here}}402 403 // ok. aligned to long(ok). offset 8*1(ok)404 ::new (&Xi.b[0].a[8]) long;405 406 // bad. aligned to long(ok). offset 1(bad)407 ::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 {{}}408}409 410void test19() {411 struct Z {412 char p;413 char c[10];414 };415 416 struct Y {417 char p;418 Z b[10];419 };420 421 struct X {422 Y a[10];423 } Xi; // expected-note {{'Xi' initialized here}}424 425 // bad. all structures X,Y,Z are aligned to char426 ::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 {{}}427}428 429void test20() {430 struct Z {431 char p;432 alignas(alignof(long)) char c[10];433 };434 435 struct Y {436 char p;437 Z b[10];438 };439 440 struct X {441 Y a[10];442 } Xi;443 444 // ok. field 'c' is aligned to 'long'445 ::new (&Xi.a[1].b[1].c) long;446}447 448void test21() {449 struct Z {450 char p;451 char c[10];452 };453 454 struct Y {455 char p;456 Z b[10];457 };458 459 struct alignas(alignof(long)) X {460 Y a[10];461 } Xi; // expected-note {{'Xi' initialized here}}462 463 // ok. aligned to long(ok). offset 1+7*1(ok)464 ::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 {{}}465}466 467void test22() {468 struct alignas(alignof(long)) Y {469 char p;470 char a[10][10];471 };472 473 struct X {474 Y b[10];475 } Xi; // expected-note {{'Xi' initialized here}}476 477 // ok. aligned to long(ok). offset ok. 1(field 'a' offset) + 0*10(index '0' * first dimension size '10') + 7*1(index '7')478 ::new (&Xi.b[0].a[0][7]) long;479 480 // ok. aligned to long(ok). offset ok. 1(field 'a' offset) + 1*10(index '1' * first dimension size '10') + 5*1(index '5')481 ::new (&Xi.b[0].a[1][5]) long;482 483 // bad. aligned to long(ok). offset ok. 1(field 'a' offset) + 1*10(index '1' * first dimension size '10') + 6*1(index '5')484 ::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 {{}}485}486 487} // namespace testStructAlign488