CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
488 lines
14 KiB
C++
488 lines
14 KiB
C++
// RUN: %clang_analyze_cc1 -std=c++11 %s \
|
|
// RUN: -analyzer-checker=core \
|
|
// RUN: -analyzer-checker=cplusplus.NewDelete \
|
|
// RUN: -analyzer-checker=cplusplus.PlacementNew \
|
|
// RUN: -analyzer-output=text -verify \
|
|
// RUN: -triple x86_64-unknown-linux-gnu
|
|
|
|
#include "Inputs/system-header-simulator-cxx.h"
|
|
|
|
void f() {
|
|
short s; // expected-note {{'s' declared without an initial value}}
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
|
|
namespace testArrayNew {
|
|
void f() {
|
|
short s; // expected-note {{'s' declared without an initial value}}
|
|
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 {{}}
|
|
(void)buf;
|
|
}
|
|
} // namespace testArrayNew
|
|
|
|
namespace testBufferInOtherFun {
|
|
void f(void *place) {
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
void g() {
|
|
short buf; // expected-note {{'buf' declared without an initial value}}
|
|
f(&buf); // expected-note 2 {{}}
|
|
}
|
|
} // namespace testBufferInOtherFun
|
|
|
|
namespace testArrayBuffer {
|
|
void f(void *place) {
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
void g() {
|
|
char buf[2]; // expected-note {{'buf' initialized here}}
|
|
f(&buf); // expected-note 2 {{}}
|
|
}
|
|
} // namespace testArrayBuffer
|
|
|
|
namespace testGlobalPtrAsPlace {
|
|
void *gptr = nullptr;
|
|
short gs;
|
|
void f() {
|
|
gptr = &gs; // expected-note {{Value assigned to 'gptr'}}
|
|
}
|
|
void g() {
|
|
f(); // expected-note 2 {{}}
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testGlobalPtrAsPlace
|
|
|
|
namespace testRvalue {
|
|
short gs;
|
|
void *f() {
|
|
return &gs;
|
|
}
|
|
void g() {
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testRvalue
|
|
|
|
namespace testNoWarning {
|
|
void *f();
|
|
void g() {
|
|
long *lp = ::new (f()) long;
|
|
(void)lp;
|
|
}
|
|
} // namespace testNoWarning
|
|
|
|
namespace testPtrToArrayAsPlace {
|
|
void f() {
|
|
//char *st = new char [8];
|
|
char buf[3]; // expected-note {{'buf' initialized here}}
|
|
void *st = buf; // expected-note {{'st' initialized here}}
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testPtrToArrayAsPlace
|
|
|
|
namespace testPtrToArrayWithOffsetAsPlace {
|
|
void f() {
|
|
int buf[3]; // expected-note {{'buf' initialized here}}
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testPtrToArrayWithOffsetAsPlace
|
|
|
|
namespace testZeroSize {
|
|
void f() {
|
|
int buf[3]; // expected-note {{'buf' initialized here}}
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testZeroSize
|
|
|
|
namespace testNegativeSize {
|
|
void f() {
|
|
int buf[3]; // expected-note {{'buf' initialized here}}
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testNegativeSize
|
|
|
|
namespace testHeapAllocatedBuffer {
|
|
void g2() {
|
|
char *buf = new char[2]; // expected-note {{'buf' initialized here}}
|
|
// FIXME: The message is misleading -- we should
|
|
// state that a pointer to an uninitialized value
|
|
// is stored.
|
|
// expected-note@-4{{Storing uninitialized value}}
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testHeapAllocatedBuffer
|
|
|
|
namespace testMultiDimensionalArray {
|
|
void f() {
|
|
char buf[2][3]; // expected-note {{'buf' initialized here}}
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testMultiDimensionalArray
|
|
|
|
namespace testMultiDimensionalArray2 {
|
|
void f() {
|
|
char buf[2][3]; // expected-note {{'buf' initialized here}}
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testMultiDimensionalArray2
|
|
|
|
namespace testMultiDimensionalArray3 {
|
|
void f() {
|
|
char buf[2][3]; // expected-note {{'buf' initialized here}}
|
|
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 {{}}
|
|
(void)lp;
|
|
}
|
|
} // namespace testMultiDimensionalArray3
|
|
|
|
namespace testHierarchy {
|
|
struct Base {
|
|
char a[2];
|
|
};
|
|
struct Derived : Base {
|
|
char x[2];
|
|
int y;
|
|
};
|
|
void f() {
|
|
Base b; // expected-note {{'b' initialized here}}
|
|
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 {{}}
|
|
(void)dp;
|
|
}
|
|
} // namespace testHierarchy
|
|
|
|
namespace testArrayTypesAllocation {
|
|
void f1() {
|
|
struct S {
|
|
short a;
|
|
};
|
|
|
|
// On some systems, (notably before MSVC 16.7), a non-allocating placement
|
|
// array new could allocate more memory than the nominal size of the array.
|
|
|
|
// Since CWG 2382 (implemented in MSVC 16.7), overhead was disallowed for non-allocating placement new.
|
|
// See:
|
|
// https://learn.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=msvc-170
|
|
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1969r0.html#2382
|
|
|
|
// However, as of 17.1, there is a regression when the type comes from a template
|
|
// parameter where MSVC reintroduces overhead.
|
|
// See:
|
|
// https://developercommunity.visualstudio.com/t/10777485
|
|
// https://godbolt.org/z/E1z1Tsfvj
|
|
|
|
// The checker doesn't warn here because this behavior only affects older
|
|
// MSVC versions (<16.7) or certain specific versions (17.1).
|
|
// Suppressing warnings avoids false positives on standard-compliant compilers
|
|
// and modern MSVC versions, but users of affected MSVC versions should be
|
|
// aware of potential buffer size issues.
|
|
|
|
const unsigned N = 32;
|
|
alignas(S) unsigned char buffer1[sizeof(S) * N];
|
|
::new (buffer1) S[N]; // no-warning: See comments above
|
|
}
|
|
|
|
void f2() {
|
|
struct S {
|
|
short a;
|
|
};
|
|
|
|
// On some systems, placement array new could allocate more memory than the nominal size of the array.
|
|
// See the comment at f1() above for more details.
|
|
const unsigned N = 32;
|
|
alignas(S) unsigned char buffer2[sizeof(S) * N + sizeof(int)];
|
|
::new (buffer2) S[N]; // no-warning: See comments above
|
|
}
|
|
} // namespace testArrayTypesAllocation
|
|
|
|
namespace testStructAlign {
|
|
void f1() {
|
|
struct X {
|
|
char a[9];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad (struct X is aligned to char).
|
|
::new (&Xi.a) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f2() {
|
|
struct X {
|
|
char a;
|
|
char b;
|
|
long c;
|
|
} Xi;
|
|
|
|
// ok (struct X is aligned to long).
|
|
::new (&Xi.a) long;
|
|
}
|
|
|
|
void f3() {
|
|
struct X {
|
|
char a;
|
|
char b;
|
|
long c;
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad (struct X is aligned to long but field 'b' is aligned to 1 because of its offset)
|
|
::new (&Xi.b) long; // expected-warning{{Storage type is aligned to 1 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f4() {
|
|
struct X {
|
|
char a;
|
|
struct alignas(alignof(short)) Y {
|
|
char b;
|
|
char c;
|
|
} y;
|
|
long d;
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad. 'b' is aligned to short
|
|
::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 {{}}
|
|
}
|
|
|
|
void f5() {
|
|
short b[10]; // expected-note {{'b' initialized here}}
|
|
|
|
::new (&b) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f6() {
|
|
short b[10]; // expected-note {{'b' initialized here}}
|
|
|
|
// bad (same as previous but checks ElementRegion case)
|
|
::new (&b[0]) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f7() {
|
|
alignas(alignof(long)) short b[10];
|
|
|
|
// ok. aligned to long(ok). offset 4*2(ok)
|
|
::new (&b[4]) long;
|
|
}
|
|
|
|
void f8() {
|
|
alignas(alignof(long)) short b[10]; // expected-note {{'b' initialized here}}
|
|
|
|
// ok. aligned to long(ok). offset 3*2(ok)
|
|
::new (&b[3]) long; // expected-warning{{Storage type is aligned to 6 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f9() {
|
|
struct X {
|
|
char a;
|
|
alignas(alignof(long)) char b[20];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// ok. aligned to long(ok). offset 8*1(ok)
|
|
::new (&Xi.b[8]) long;
|
|
|
|
// bad. aligned to long(ok). offset 1*1(ok)
|
|
::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 {{}}
|
|
}
|
|
|
|
void f10() {
|
|
struct X {
|
|
char a[8];
|
|
alignas(2) char b;
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad (struct X is aligned to 2).
|
|
::new (&Xi.a) long; // expected-warning{{Storage type is aligned to 2 bytes but allocated type is aligned to 8 bytes}} expected-note 1 {{}}
|
|
}
|
|
|
|
void f11() {
|
|
struct X {
|
|
char a;
|
|
char b;
|
|
struct Y {
|
|
long c;
|
|
} d;
|
|
} Xi;
|
|
|
|
// ok (struct X is aligned to long).
|
|
::new (&Xi.a) long;
|
|
}
|
|
|
|
void f12() {
|
|
struct alignas(alignof(long)) X {
|
|
char a;
|
|
char b;
|
|
} Xi;
|
|
|
|
// ok (struct X is aligned to long).
|
|
::new (&Xi.a) long;
|
|
}
|
|
|
|
void test13() {
|
|
struct Y {
|
|
char a[10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad. X,A are aligned to 'char'
|
|
::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 {{}}
|
|
}
|
|
|
|
void test14() {
|
|
struct Y {
|
|
char a[10];
|
|
};
|
|
|
|
struct alignas(alignof(long)) X {
|
|
Y b[10];
|
|
} Xi;
|
|
|
|
// ok. X is aligned to 'long' and field 'a' goes with zero offset
|
|
::new (&Xi.b[0].a) long;
|
|
}
|
|
|
|
void test15() {
|
|
struct alignas(alignof(long)) Y {
|
|
char a[10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi;
|
|
|
|
// ok. X is aligned to 'long' because it contains struct 'Y' which is aligned to 'long'
|
|
::new (&Xi.b[0].a) long;
|
|
}
|
|
|
|
void test16() {
|
|
struct alignas(alignof(long)) Y {
|
|
char p;
|
|
char a[10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad. aligned to long(ok). offset 1(bad)
|
|
::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 {{}}
|
|
}
|
|
|
|
void test17() {
|
|
struct alignas(alignof(long)) Y {
|
|
char p;
|
|
char a[10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi;
|
|
|
|
// ok. aligned to long(ok). offset 1+7*1(ok)
|
|
::new (&Xi.b[0].a[7]) long;
|
|
}
|
|
|
|
void test18() {
|
|
struct Y {
|
|
char p;
|
|
alignas(alignof(long)) char a[10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// ok. aligned to long(ok). offset 8*1(ok)
|
|
::new (&Xi.b[0].a[8]) long;
|
|
|
|
// bad. aligned to long(ok). offset 1(bad)
|
|
::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 {{}}
|
|
}
|
|
|
|
void test19() {
|
|
struct Z {
|
|
char p;
|
|
char c[10];
|
|
};
|
|
|
|
struct Y {
|
|
char p;
|
|
Z b[10];
|
|
};
|
|
|
|
struct X {
|
|
Y a[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// bad. all structures X,Y,Z are aligned to char
|
|
::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 {{}}
|
|
}
|
|
|
|
void test20() {
|
|
struct Z {
|
|
char p;
|
|
alignas(alignof(long)) char c[10];
|
|
};
|
|
|
|
struct Y {
|
|
char p;
|
|
Z b[10];
|
|
};
|
|
|
|
struct X {
|
|
Y a[10];
|
|
} Xi;
|
|
|
|
// ok. field 'c' is aligned to 'long'
|
|
::new (&Xi.a[1].b[1].c) long;
|
|
}
|
|
|
|
void test21() {
|
|
struct Z {
|
|
char p;
|
|
char c[10];
|
|
};
|
|
|
|
struct Y {
|
|
char p;
|
|
Z b[10];
|
|
};
|
|
|
|
struct alignas(alignof(long)) X {
|
|
Y a[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// ok. aligned to long(ok). offset 1+7*1(ok)
|
|
::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 {{}}
|
|
}
|
|
|
|
void test22() {
|
|
struct alignas(alignof(long)) Y {
|
|
char p;
|
|
char a[10][10];
|
|
};
|
|
|
|
struct X {
|
|
Y b[10];
|
|
} Xi; // expected-note {{'Xi' initialized here}}
|
|
|
|
// ok. aligned to long(ok). offset ok. 1(field 'a' offset) + 0*10(index '0' * first dimension size '10') + 7*1(index '7')
|
|
::new (&Xi.b[0].a[0][7]) long;
|
|
|
|
// ok. aligned to long(ok). offset ok. 1(field 'a' offset) + 1*10(index '1' * first dimension size '10') + 5*1(index '5')
|
|
::new (&Xi.b[0].a[1][5]) long;
|
|
|
|
// bad. aligned to long(ok). offset ok. 1(field 'a' offset) + 1*10(index '1' * first dimension size '10') + 6*1(index '5')
|
|
::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 {{}}
|
|
}
|
|
|
|
} // namespace testStructAlign
|