Files
TheRock/compiler/amd-llvm/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
derek.holloway 7502bf64a4
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
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

970 lines
25 KiB
C++

// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,optin.cplusplus.UninitializedObject \
// RUN: -analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
// RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
// RUN: -std=c++11 -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,optin.cplusplus.UninitializedObject \
// RUN: -analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
// RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
// RUN: -std=c++11 -verify %s -DHEAP_ALLOCATION
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,optin.cplusplus.UninitializedObject \
// RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
// RUN: -std=c++11 -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,optin.cplusplus.UninitializedObject \
// RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
// RUN: -std=c++11 -verify %s -DHEAP_ALLOCATION
#ifdef HEAP_ALLOCATION
#define INIT(CLS, ARGS) new CLS ARGS
#else
#define INIT(CLS, ARGS) (void) CLS ARGS
#endif
//===----------------------------------------------------------------------===//
// Concrete location tests.
//===----------------------------------------------------------------------===//
struct ConcreteIntLocTest {
int *ptr;
ConcreteIntLocTest() : ptr(reinterpret_cast<int *>(0xDEADBEEF)) {}
};
void fConcreteIntLocTest() {
INIT(ConcreteIntLocTest, ());
}
//===----------------------------------------------------------------------===//
// nonloc::LocAsInteger tests.
//===----------------------------------------------------------------------===//
using intptr_t = unsigned long long;
struct LocAsIntegerTest {
intptr_t ptr; // expected-note{{uninitialized pointee 'reinterpret_cast<char *>(this->ptr)'}}
int dontGetFilteredByNonPedanticMode = 0;
LocAsIntegerTest(void *ptr) : ptr(reinterpret_cast<intptr_t>(ptr)) {} // expected-warning{{1 uninitialized field}}
};
void fLocAsIntegerTest() {
char c;
INIT(LocAsIntegerTest, (&c));
}
//===----------------------------------------------------------------------===//
// Null pointer tests.
//===----------------------------------------------------------------------===//
class NullPtrTest {
struct RecordType {
int x;
int y;
};
float *fptr = nullptr;
int *ptr;
RecordType *recPtr;
public:
NullPtrTest() : ptr(nullptr), recPtr(nullptr) {
// All good!
}
};
void fNullPtrTest() {
INIT(NullPtrTest, ());
}
//===----------------------------------------------------------------------===//
// Alloca tests.
//===----------------------------------------------------------------------===//
struct UntypedAllocaTest {
void *allocaPtr;
int dontGetFilteredByNonPedanticMode = 0;
// expected-warning-re@+3 {{Address of stack memory allocated by call to \
alloca() on line {{[0-9]+}} is still referred to by a temporary object on the \
stack upon returning to the caller. This will be a dangling reference}}
UntypedAllocaTest() : allocaPtr(__builtin_alloca(sizeof(int))) {
// All good!
}
};
void fUntypedAllocaTest() {
UntypedAllocaTest();
}
struct TypedAllocaTest1 {
int *allocaPtr; // expected-note{{uninitialized pointee 'this->allocaPtr'}}
int dontGetFilteredByNonPedanticMode = 0;
TypedAllocaTest1() // expected-warning{{1 uninitialized field}}
: allocaPtr(static_cast<int *>(__builtin_alloca(sizeof(int)))) {}
// expected-warning-re@-2 {{Address of stack memory allocated by call to \
alloca() on line {{[0-9]+}} is still referred to by a temporary object on the \
stack upon returning to the caller. This will be a dangling reference}}
};
void fTypedAllocaTest1() {
TypedAllocaTest1();
}
struct TypedAllocaTest2 {
int *allocaPtr;
int dontGetFilteredByNonPedanticMode = 0;
// expected-warning-re@+5 {{Address of stack memory allocated by call to \
alloca() on line {{[0-9]+}} is still referred to by a temporary object on the \
stack upon returning to the caller. This will be a dangling reference}}
TypedAllocaTest2()
: allocaPtr(static_cast<int *>(__builtin_alloca(sizeof(int)))) {
*allocaPtr = 55555;
// All good!
}
};
void fTypedAllocaTest2() {
TypedAllocaTest2();
}
//===----------------------------------------------------------------------===//
// Heap pointer tests.
//===----------------------------------------------------------------------===//
class HeapPointerTest1 {
struct RecordType {
// TODO: we'd expect the note: {{uninitialized field 'this->recPtr->y'}}
int x; // no-note
// TODO: we'd expect the note: {{uninitialized field 'this->recPtr->y'}}
int y; // no-note
};
// TODO: we'd expect the note: {{uninitialized pointee 'this->fptr'}}
float *fptr = new float; // no-note
// TODO: we'd expect the note: {{uninitialized pointee 'this->ptr'}}
int *ptr; // no-note
RecordType *recPtr;
public:
// TODO: we'd expect the warning: {{4 uninitialized fields}}
HeapPointerTest1() : ptr(new int), recPtr(new RecordType) { // no-note
}
};
void fHeapPointerTest1() {
INIT(HeapPointerTest1, ());
}
class HeapPointerTest2 {
struct RecordType {
int x;
int y;
};
float *fptr = new float(); // initializes to 0
int *ptr;
RecordType *recPtr;
public:
HeapPointerTest2() : ptr(new int{25}), recPtr(new RecordType{26, 27}) {
// All good!
}
};
void fHeapPointerTest2() {
INIT(HeapPointerTest2, ());
}
//===----------------------------------------------------------------------===//
// Stack pointer tests.
//===----------------------------------------------------------------------===//
class StackPointerTest1 {
public:
struct RecordType {
int x;
int y;
};
private:
int *ptr;
RecordType *recPtr;
public:
StackPointerTest1(int *_ptr, StackPointerTest1::RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) {
// All good!
}
};
void fStackPointerTest1() {
int ok_a = 28;
StackPointerTest1::RecordType ok_rec{29, 30};
INIT(StackPointerTest1, (&ok_a, &ok_rec)); // 'a', 'rec.x', 'rec.y' uninitialized
}
#ifdef PEDANTIC
class StackPointerTest2 {
public:
struct RecordType {
int x; // expected-note{{uninitialized field 'this->recPtr->x'}}
int y; // expected-note{{uninitialized field 'this->recPtr->y'}}
};
private:
int *ptr; // expected-note{{uninitialized pointee 'this->ptr'}}
RecordType *recPtr;
public:
StackPointerTest2(int *_ptr, RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) { // expected-warning{{3 uninitialized fields}}
}
};
void fStackPointerTest2() {
int a;
StackPointerTest2::RecordType rec;
INIT(StackPointerTest2, (&a, &rec)); // 'a', 'rec.x', 'rec.y' uninitialized
}
#else
class StackPointerTest2 {
public:
struct RecordType {
int x;
int y;
};
private:
int *ptr;
RecordType *recPtr;
public:
StackPointerTest2(int *_ptr, RecordType *_recPtr) : ptr(_ptr), recPtr(_recPtr) {
}
};
void fStackPointerTest2() {
int a;
StackPointerTest2::RecordType rec;
INIT(StackPointerTest2, (&a, &rec)); // 'a', 'rec.x', 'rec.y' uninitialized
}
#endif // PEDANTIC
class UninitPointerTest {
struct RecordType {
int x;
int y;
};
int *ptr; // expected-note{{uninitialized pointer 'this->ptr'}}
RecordType *recPtr;
public:
UninitPointerTest() : recPtr(new RecordType{13, 13}) { // expected-warning{{1 uninitialized field}}
}
};
void fUninitPointerTest() {
INIT(UninitPointerTest, ());
}
struct CharPointerTest {
const char *str;
int dontGetFilteredByNonPedanticMode = 0;
CharPointerTest() : str("") {}
};
void fCharPointerTest() {
INIT(CharPointerTest, ());
}
struct VectorSizePointer {
VectorSizePointer() {} // expected-warning{{1 uninitialized field}}
__attribute__((__vector_size__(8))) int *x; // expected-note{{uninitialized pointer 'this->x'}}
int dontGetFilteredByNonPedanticMode = 0;
};
void __vector_size__PointerTest() {
INIT(VectorSizePointer, ());
}
struct VectorSizePointee {
using MyVectorType = __attribute__((__vector_size__(8))) int;
MyVectorType *x;
VectorSizePointee(decltype(x) x) : x(x) {}
};
void __vector_size__PointeeTest() {
VectorSizePointee::MyVectorType i;
// TODO: Report v.x's pointee.
INIT(VectorSizePointee, (&i));
}
struct CyclicPointerTest1 {
int *ptr; // expected-note{{object references itself 'this->ptr'}}
int dontGetFilteredByNonPedanticMode = 0;
CyclicPointerTest1() : ptr(reinterpret_cast<int *>(&ptr)) {} // expected-warning{{1 uninitialized field}}
};
void fCyclicPointerTest1() {
INIT(CyclicPointerTest1, ());
}
struct CyclicPointerTest2 {
int **pptr; // expected-note{{object references itself 'this->pptr'}}
int dontGetFilteredByNonPedanticMode = 0;
CyclicPointerTest2() : pptr(reinterpret_cast<int **>(&pptr)) {} // expected-warning{{1 uninitialized field}}
};
void fCyclicPointerTest2() {
INIT(CyclicPointerTest2, ());
}
//===----------------------------------------------------------------------===//
// Void pointer tests.
//===----------------------------------------------------------------------===//
// Void pointer tests are mainly no-crash tests.
typedef __typeof(sizeof(int)) size_t;
void *calloc(size_t nmemb, size_t size);
void free(void *p);
class VoidPointerTest1 {
void *vptr;
public:
VoidPointerTest1(void *vptr, char) : vptr(vptr) {
// All good!
}
};
void fVoidPointerTest1() {
void *vptr = calloc(1, sizeof(int));
INIT(VoidPointerTest1, (vptr, char()));
free(vptr);
}
class VoidPointerTest2 {
void **vpptr;
public:
VoidPointerTest2(void **vpptr, char) : vpptr(vpptr) {
// All good!
}
};
void fVoidPointerTest2() {
void *vptr = calloc(1, sizeof(int));
INIT(VoidPointerTest2, (&vptr, char()));
free(vptr);
}
class VoidPointerRRefTest1 {
void *&&vptrrref; // expected-note {{here}}
public:
// expected-warning@+3 {{Address of stack memory associated with local \
variable 'vptr' is still referred to by a temporary object on the stack \
upon returning to the caller. This will be a dangling reference}}
VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast<void *&&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}}
// All good!
}
};
void fVoidPointerRRefTest1() {
void *vptr = calloc(1, sizeof(int));
VoidPointerRRefTest1(vptr, char());
free(vptr);
}
class VoidPointerRRefTest2 {
void **&&vpptrrref; // expected-note {{here}}
public:
// expected-warning@+3 {{Address of stack memory associated with local \
variable 'vptr' is still referred to by a temporary object on the stack \
upon returning to the caller. This will be a dangling reference}}
VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast<void **&&>(vptr)) { // expected-warning {{binding reference member 'vpptrrref' to stack allocated parameter 'vptr'}}
// All good!
}
};
void fVoidPointerRRefTest2() {
void *vptr = calloc(1, sizeof(int));
VoidPointerRRefTest2(&vptr, char());
free(vptr);
}
class VoidPointerLRefTest {
void *&vptrrref; // expected-note {{here}}
public:
// expected-warning@+3 {{Address of stack memory associated with local \
variable 'vptr' is still referred to by a temporary object on the stack \
upon returning to the caller. This will be a dangling reference}}
VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast<void *&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}}
// All good!
}
};
void fVoidPointerLRefTest() {
void *vptr = calloc(1, sizeof(int));
VoidPointerLRefTest(vptr, char());
free(vptr);
}
struct CyclicVoidPointerTest {
void *vptr; // expected-note{{object references itself 'this->vptr'}}
int dontGetFilteredByNonPedanticMode = 0;
CyclicVoidPointerTest() : vptr(&vptr) {} // expected-warning{{1 uninitialized field}}
};
void fCyclicVoidPointerTest() {
INIT(CyclicVoidPointerTest, ());
}
struct IntDynTypedVoidPointerTest1 {
void *vptr; // expected-note{{uninitialized pointee 'static_cast<int *>(this->vptr)'}}
int dontGetFilteredByNonPedanticMode = 0;
IntDynTypedVoidPointerTest1(void *vptr) : vptr(vptr) {} // expected-warning{{1 uninitialized field}}
};
void fIntDynTypedVoidPointerTest1() {
int a;
INIT(IntDynTypedVoidPointerTest1, (&a));
}
struct RecordDynTypedVoidPointerTest {
struct RecordType {
int x; // expected-note{{uninitialized field 'static_cast<RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
int y; // expected-note{{uninitialized field 'static_cast<RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
};
void *vptr;
int dontGetFilteredByNonPedanticMode = 0;
RecordDynTypedVoidPointerTest(void *vptr) : vptr(vptr) {} // expected-warning{{2 uninitialized fields}}
};
void fRecordDynTypedVoidPointerTest() {
RecordDynTypedVoidPointerTest::RecordType a;
INIT(RecordDynTypedVoidPointerTest, (&a));
}
struct NestedNonVoidDynTypedVoidPointerTest {
struct RecordType {
int x; // expected-note{{uninitialized field 'static_cast<NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
int y; // expected-note{{uninitialized field 'static_cast<NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
void *vptr; // expected-note{{uninitialized pointee 'static_cast<char *>(static_cast<NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->vptr)'}}
};
void *vptr;
int dontGetFilteredByNonPedanticMode = 0;
NestedNonVoidDynTypedVoidPointerTest(void *vptr, void *c) : vptr(vptr) {
static_cast<RecordType *>(vptr)->vptr = c; // expected-warning{{3 uninitialized fields}}
}
};
void fNestedNonVoidDynTypedVoidPointerTest() {
NestedNonVoidDynTypedVoidPointerTest::RecordType a;
char c;
INIT(NestedNonVoidDynTypedVoidPointerTest, (&a, &c));
}
//===----------------------------------------------------------------------===//
// Multipointer tests.
//===----------------------------------------------------------------------===//
#ifdef PEDANTIC
class MultiPointerTest1 {
public:
struct RecordType {
int x;
int y;
};
private:
RecordType **mptr; // expected-note{{uninitialized pointee 'this->mptr'}}
public:
MultiPointerTest1(RecordType **p, int) : mptr(p) { // expected-warning{{1 uninitialized field}}
}
};
void fMultiPointerTest1() {
MultiPointerTest1::RecordType *p1;
MultiPointerTest1::RecordType **mptr = &p1;
INIT(MultiPointerTest1, (mptr, int())); // '*mptr' uninitialized
}
#else
class MultiPointerTest1 {
public:
struct RecordType {
int x;
int y;
};
private:
RecordType **mptr;
public:
MultiPointerTest1(RecordType **p, int) : mptr(p) {}
};
void fMultiPointerTest1() {
MultiPointerTest1::RecordType *p1;
MultiPointerTest1::RecordType **mptr = &p1;
INIT(MultiPointerTest1, (mptr, int())); // '*mptr' uninitialized
}
#endif // PEDANTIC
#ifdef PEDANTIC
class MultiPointerTest2 {
public:
struct RecordType {
int x; // expected-note{{uninitialized field 'this->mptr->x'}}
int y; // expected-note{{uninitialized field 'this->mptr->y'}}
};
private:
RecordType **mptr;
public:
MultiPointerTest2(RecordType **p, int) : mptr(p) { // expected-warning{{2 uninitialized fields}}
}
};
void fMultiPointerTest2() {
MultiPointerTest2::RecordType i;
MultiPointerTest2::RecordType *p1 = &i;
MultiPointerTest2::RecordType **mptr = &p1;
INIT(MultiPointerTest2, (mptr, int())); // '**mptr' uninitialized
}
#else
class MultiPointerTest2 {
public:
struct RecordType {
int x;
int y;
};
private:
RecordType **mptr;
public:
MultiPointerTest2(RecordType **p, int) : mptr(p) {
}
};
void fMultiPointerTest2() {
MultiPointerTest2::RecordType i;
MultiPointerTest2::RecordType *p1 = &i;
MultiPointerTest2::RecordType **mptr = &p1;
INIT(MultiPointerTest2, (mptr, int())); // '**mptr' uninitialized
}
#endif // PEDANTIC
class MultiPointerTest3 {
public:
struct RecordType {
int x;
int y;
};
private:
RecordType **mptr;
public:
MultiPointerTest3(RecordType **p, int) : mptr(p) {
// All good!
}
};
void fMultiPointerTest3() {
MultiPointerTest3::RecordType i{31, 32};
MultiPointerTest3::RecordType *p1 = &i;
MultiPointerTest3::RecordType **mptr = &p1;
INIT(MultiPointerTest3, (mptr, int())); // '**mptr' uninitialized
}
//===----------------------------------------------------------------------===//
// Incomplete pointee tests.
//===----------------------------------------------------------------------===//
class IncompleteType;
struct IncompletePointeeTypeTest {
IncompleteType *pImpl; //no-crash
int dontGetFilteredByNonPedanticMode = 0;
IncompletePointeeTypeTest(IncompleteType *A) : pImpl(A) {}
};
void fIncompletePointeeTypeTest(void *ptr) {
INIT(IncompletePointeeTypeTest, (reinterpret_cast<IncompleteType *>(ptr)));
}
//===----------------------------------------------------------------------===//
// Function pointer tests.
//===----------------------------------------------------------------------===//
struct FunctionPointerWithDifferentDynTypeTest {
using Func1 = void *(*)();
using Func2 = int *(*)();
Func1 f; // no-crash
FunctionPointerWithDifferentDynTypeTest(Func2 f) : f((Func1)f) {}
};
// Note that there isn't a function calling the constructor of
// FunctionPointerWithDifferentDynTypeTest, because a crash could only be
// reproduced without it.
//===----------------------------------------------------------------------===//
// Member pointer tests.
//===----------------------------------------------------------------------===//
struct UsefulFunctions {
int a, b;
void print() {}
void dump() {}
};
#ifdef PEDANTIC
struct PointerToMemberFunctionTest1 {
void (UsefulFunctions::*f)(void); // expected-note{{uninitialized field 'this->f'}}
PointerToMemberFunctionTest1() {}
};
void fPointerToMemberFunctionTest1() {
INIT(PointerToMemberFunctionTest1, ()); // expected-warning{{1 uninitialized field}}
}
struct PointerToMemberFunctionTest2 {
void (UsefulFunctions::*f)(void);
PointerToMemberFunctionTest2(void (UsefulFunctions::*f)(void)) : f(f) {
// All good!
}
};
void fPointerToMemberFunctionTest2() {
void (UsefulFunctions::*f)(void) = &UsefulFunctions::print;
INIT(PointerToMemberFunctionTest2, (f));
}
struct MultiPointerToMemberFunctionTest1 {
void (UsefulFunctions::**f)(void); // expected-note{{uninitialized pointer 'this->f'}}
MultiPointerToMemberFunctionTest1() {}
};
void fMultiPointerToMemberFunctionTest1() {
INIT(MultiPointerToMemberFunctionTest1, ()); // expected-warning{{1 uninitialized field}}
}
struct MultiPointerToMemberFunctionTest2 {
void (UsefulFunctions::**f)(void);
MultiPointerToMemberFunctionTest2(void (UsefulFunctions::**f)(void)) : f(f) {
// All good!
}
};
void fMultiPointerToMemberFunctionTest2() {
void (UsefulFunctions::*f)(void) = &UsefulFunctions::print;
INIT(MultiPointerToMemberFunctionTest2, (&f));
}
struct PointerToMemberDataTest1 {
int UsefulFunctions::*d; // expected-note{{uninitialized field 'this->d'}}
PointerToMemberDataTest1() {}
};
void fPointerToMemberDataTest1() {
INIT(PointerToMemberDataTest1, ()); // expected-warning{{1 uninitialized field}}
}
struct PointerToMemberDataTest2 {
int UsefulFunctions::*d;
PointerToMemberDataTest2(int UsefulFunctions::*d) : d(d) {
// All good!
}
};
void fPointerToMemberDataTest2() {
int UsefulFunctions::*d = &UsefulFunctions::a;
INIT(PointerToMemberDataTest2, (d));
}
struct MultiPointerToMemberDataTest1 {
int UsefulFunctions::**d; // expected-note{{uninitialized pointer 'this->d'}}
MultiPointerToMemberDataTest1() {}
};
void fMultiPointerToMemberDataTest1() {
INIT(MultiPointerToMemberDataTest1, ()); // expected-warning{{1 uninitialized field}}
}
struct MultiPointerToMemberDataTest2 {
int UsefulFunctions::**d;
MultiPointerToMemberDataTest2(int UsefulFunctions::**d) : d(d) {
// All good!
}
};
void fMultiPointerToMemberDataTest2() {
int UsefulFunctions::*d = &UsefulFunctions::a;
INIT(MultiPointerToMemberDataTest2, (&d));
}
#endif // PEDANTIC
//===----------------------------------------------------------------------===//
// Tests for list-like records.
//===----------------------------------------------------------------------===//
class ListTest1 {
public:
struct Node {
Node *next = nullptr; // no crash
int i;
};
private:
Node *head = nullptr;
public:
ListTest1() {
// All good!
}
};
void fListTest1() {
INIT(ListTest1, ());
}
class ListTest2 {
public:
struct Node {
Node *next = nullptr;
int i; // expected-note{{uninitialized field 'this->head->i'}}
};
private:
Node *head = nullptr;
public:
ListTest2(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}}
}
};
void fListTest2() {
ListTest2::Node n;
INIT(ListTest2, (&n, int()));
}
class CyclicList {
public:
struct Node {
Node *next = nullptr;
int i; // expected-note{{uninitialized field 'this->head->i'}}
};
private:
Node *head = nullptr;
public:
CyclicList(Node *node, int) : head(node) { // expected-warning{{1 uninitialized field}}
}
};
void fCyclicList() {
/*
n3
/ \
this -- n1 -- n2
*/
CyclicList::Node n1;
CyclicList::Node n2;
n2.next = &n1;
n2.i = 50;
CyclicList::Node n3;
n3.next = &n2;
n3.i = 50;
n1.next = &n3;
// note that n1.i is uninitialized
INIT(CyclicList, (&n1, int()));
}
struct RingListTest {
RingListTest *next; // no-crash
RingListTest() : next(this) {}
};
void fRingListTest() {
INIT(RingListTest, ());
}
//===----------------------------------------------------------------------===//
// Tests for classes containing references.
//===----------------------------------------------------------------------===//
class ReferenceTest1 {
public:
struct RecordType {
int x;
int y;
};
private:
RecordType &lref;
RecordType &&rref;
public:
ReferenceTest1(RecordType &lref, RecordType &rref) : lref(lref), rref(static_cast<RecordType &&>(rref)) {
// All good!
}
};
void fReferenceTest1() {
ReferenceTest1::RecordType d{33, 34};
INIT(ReferenceTest1, (d, d));
}
#ifdef PEDANTIC
class ReferenceTest2 {
public:
struct RecordType {
int x; // expected-note{{uninitialized field 'this->lref.x'}}
int y; // expected-note{{uninitialized field 'this->lref.y'}}
};
private:
RecordType &lref;
RecordType &&rref;
public:
ReferenceTest2(RecordType &lref, RecordType &rref)
: lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
}
};
void fReferenceTest2() {
ReferenceTest2::RecordType c;
INIT(ReferenceTest2, (c, c));
}
#else
class ReferenceTest2 {
public:
struct RecordType {
int x;
int y;
};
private:
RecordType &lref;
RecordType &&rref;
public:
ReferenceTest2(RecordType &lref, RecordType &rref)
: lref(lref), rref(static_cast<RecordType &&>(rref)) {
}
};
void fReferenceTest2() {
ReferenceTest2::RecordType c;
INIT(ReferenceTest2, (c, c));
}
#endif // PEDANTIC
class ReferenceTest3 {
public:
struct RecordType {
int x; // expected-note{{uninitialized field 'this->lref.x'}}
int y; // expected-note{{uninitialized field 'this->lref.y'}}
};
private:
RecordType &lref;
RecordType &&rref;
public:
ReferenceTest3(RecordType &lref, RecordType &rref)
: lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
}
};
void fReferenceTest3() {
ReferenceTest3::RecordType c, d{35, 36};
INIT(ReferenceTest3, (c, d));
}
class ReferenceTest4 {
public:
struct RecordType {
int x; // expected-note{{uninitialized field 'this->rref.x'}}
int y; // expected-note{{uninitialized field 'this->rref.y'}}
};
private:
RecordType &lref;
RecordType &&rref;
public:
ReferenceTest4(RecordType &lref, RecordType &rref)
: lref(lref), rref(static_cast<RecordType &&>(rref)) { // expected-warning{{2 uninitialized fields}}
}
};
void fReferenceTest5() {
ReferenceTest4::RecordType c, d{37, 38};
INIT(ReferenceTest4, (d, c));
}
//===----------------------------------------------------------------------===//
// Tests for objects containing multiple references to the same object.
//===----------------------------------------------------------------------===//
struct IntMultipleReferenceToSameObjectTest {
int *iptr; // expected-note{{uninitialized pointee 'this->iptr'}}
int &iref; // no-note, pointee of this->iref was already reported
int dontGetFilteredByNonPedanticMode = 0;
IntMultipleReferenceToSameObjectTest(int *i) : iptr(i), iref(*i) {} // expected-warning{{1 uninitialized field}}
};
void fIntMultipleReferenceToSameObjectTest() {
int a;
INIT(IntMultipleReferenceToSameObjectTest, (&a));
}
struct IntReferenceWrapper1 {
int &a; // expected-note{{uninitialized pointee 'this->a'}}
int dontGetFilteredByNonPedanticMode = 0;
IntReferenceWrapper1(int &a) : a(a) {} // expected-warning{{1 uninitialized field}}
};
struct IntReferenceWrapper2 {
int &a; // no-note, pointee of this->a was already reported
int dontGetFilteredByNonPedanticMode = 0;
IntReferenceWrapper2(int &a) : a(a) {} // no-warning
};
void fMultipleObjectsReferencingTheSameObjectTest() {
int a;
INIT(IntReferenceWrapper1, (a));
INIT(IntReferenceWrapper2, (a));
}