// RUN: %clang_analyze_cc1 -analyzer-checker=core,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,optin.cplusplus.UninitializedObject \ // RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \ // RUN: -std=c++11 -verify %s //===----------------------------------------------------------------------===// // Concrete location tests. //===----------------------------------------------------------------------===// struct ConcreteIntLocTest { int *ptr; ConcreteIntLocTest() : ptr(reinterpret_cast(0xDEADBEEF)) {} }; void fConcreteIntLocTest() { ConcreteIntLocTest(); } //===----------------------------------------------------------------------===// // nonloc::LocAsInteger tests. //===----------------------------------------------------------------------===// using intptr_t = unsigned long long; struct LocAsIntegerTest { intptr_t ptr; // expected-note{{uninitialized pointee 'reinterpret_cast(this->ptr)'}} int dontGetFilteredByNonPedanticMode = 0; LocAsIntegerTest(void *ptr) : ptr(reinterpret_cast(ptr)) {} // expected-warning{{1 uninitialized field}} }; void fLocAsIntegerTest() { char c; LocAsIntegerTest t(&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() { NullPtrTest(); } //===----------------------------------------------------------------------===// // Alloca tests. //===----------------------------------------------------------------------===// struct UntypedAllocaTest { void *allocaPtr; int dontGetFilteredByNonPedanticMode = 0; 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(__builtin_alloca(sizeof(int)))) {} }; void fTypedAllocaTest1() { TypedAllocaTest1(); } struct TypedAllocaTest2 { int *allocaPtr; int dontGetFilteredByNonPedanticMode = 0; TypedAllocaTest2() : allocaPtr(static_cast(__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() { 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() { 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}; 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; 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; 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() { UninitPointerTest(); } struct CharPointerTest { const char *str; int dontGetFilteredByNonPedanticMode = 0; CharPointerTest() : str("") {} }; void fCharPointerTest() { 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() { VectorSizePointer v; } 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. VectorSizePointee v(&i); } struct CyclicPointerTest1 { int *ptr; // expected-note{{object references itself 'this->ptr'}} int dontGetFilteredByNonPedanticMode = 0; CyclicPointerTest1() : ptr(reinterpret_cast(&ptr)) {} // expected-warning{{1 uninitialized field}} }; void fCyclicPointerTest1() { CyclicPointerTest1(); } struct CyclicPointerTest2 { int **pptr; // expected-note{{object references itself 'this->pptr'}} int dontGetFilteredByNonPedanticMode = 0; CyclicPointerTest2() : pptr(reinterpret_cast(&pptr)) {} // expected-warning{{1 uninitialized field}} }; void fCyclicPointerTest2() { CyclicPointerTest2(); } //===----------------------------------------------------------------------===// // Void pointer tests. //===----------------------------------------------------------------------===// // Void pointer tests are mainly no-crash tests. void *malloc(int size); class VoidPointerTest1 { void *vptr; public: VoidPointerTest1(void *vptr, char) : vptr(vptr) { // All good! } }; void fVoidPointerTest1() { void *vptr = malloc(sizeof(int)); VoidPointerTest1(vptr, char()); } class VoidPointerTest2 { void **vpptr; public: VoidPointerTest2(void **vpptr, char) : vpptr(vpptr) { // All good! } }; void fVoidPointerTest2() { void *vptr = malloc(sizeof(int)); VoidPointerTest2(&vptr, char()); } class VoidPointerRRefTest1 { void *&&vptrrref; // expected-note {{here}} public: VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}} // All good! } }; void fVoidPointerRRefTest1() { void *vptr = malloc(sizeof(int)); VoidPointerRRefTest1(vptr, char()); } class VoidPointerRRefTest2 { void **&&vpptrrref; // expected-note {{here}} public: VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vpptrrref' to stack allocated parameter 'vptr'}} // All good! } }; void fVoidPointerRRefTest2() { void *vptr = malloc(sizeof(int)); VoidPointerRRefTest2(&vptr, char()); } class VoidPointerLRefTest { void *&vptrrref; // expected-note {{here}} public: VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}} // All good! } }; void fVoidPointerLRefTest() { void *vptr = malloc(sizeof(int)); VoidPointerLRefTest(vptr, char()); } struct CyclicVoidPointerTest { void *vptr; // expected-note{{object references itself 'this->vptr'}} int dontGetFilteredByNonPedanticMode = 0; CyclicVoidPointerTest() : vptr(&vptr) {} // expected-warning{{1 uninitialized field}} }; void fCyclicVoidPointerTest() { CyclicVoidPointerTest(); } struct IntDynTypedVoidPointerTest1 { void *vptr; // expected-note{{uninitialized pointee 'static_cast(this->vptr)'}} int dontGetFilteredByNonPedanticMode = 0; IntDynTypedVoidPointerTest1(void *vptr) : vptr(vptr) {} // expected-warning{{1 uninitialized field}} }; void fIntDynTypedVoidPointerTest1() { int a; IntDynTypedVoidPointerTest1 tmp(&a); } struct RecordDynTypedVoidPointerTest { struct RecordType { int x; // expected-note{{uninitialized field 'static_cast(this->vptr)->x'}} int y; // expected-note{{uninitialized field 'static_cast(this->vptr)->y'}} }; void *vptr; int dontGetFilteredByNonPedanticMode = 0; RecordDynTypedVoidPointerTest(void *vptr) : vptr(vptr) {} // expected-warning{{2 uninitialized fields}} }; void fRecordDynTypedVoidPointerTest() { RecordDynTypedVoidPointerTest::RecordType a; RecordDynTypedVoidPointerTest tmp(&a); } struct NestedNonVoidDynTypedVoidPointerTest { struct RecordType { int x; // expected-note{{uninitialized field 'static_cast(this->vptr)->x'}} int y; // expected-note{{uninitialized field 'static_cast(this->vptr)->y'}} void *vptr; // expected-note{{uninitialized pointee 'static_cast(static_cast(this->vptr)->vptr)'}} }; void *vptr; int dontGetFilteredByNonPedanticMode = 0; NestedNonVoidDynTypedVoidPointerTest(void *vptr, void *c) : vptr(vptr) { static_cast(vptr)->vptr = c; // expected-warning{{3 uninitialized fields}} } }; void fNestedNonVoidDynTypedVoidPointerTest() { NestedNonVoidDynTypedVoidPointerTest::RecordType a; char c; NestedNonVoidDynTypedVoidPointerTest tmp(&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; 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; 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; 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; 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; 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) { IncompletePointeeTypeTest(reinterpret_cast(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() { 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; PointerToMemberFunctionTest2 a(f); } struct MultiPointerToMemberFunctionTest1 { void (UsefulFunctions::**f)(void); // expected-note{{uninitialized pointer 'this->f'}} MultiPointerToMemberFunctionTest1() {} }; void fMultiPointerToMemberFunctionTest1() { 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; MultiPointerToMemberFunctionTest2 a(&f); } struct PointerToMemberDataTest1 { int UsefulFunctions::*d; // expected-note{{uninitialized field 'this->d'}} PointerToMemberDataTest1() {} }; void fPointerToMemberDataTest1() { 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; PointerToMemberDataTest2 a(d); } struct MultiPointerToMemberDataTest1 { int UsefulFunctions::**d; // expected-note{{uninitialized pointer 'this->d'}} MultiPointerToMemberDataTest1() {} }; void fMultiPointerToMemberDataTest1() { 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; MultiPointerToMemberDataTest2 a(&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() { 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; 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 CyclicList(&n1, int()); } struct RingListTest { RingListTest *next; // no-crash RingListTest() : next(this) {} }; void fRingListTest() { 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(rref)) { // All good! } }; void fReferenceTest1() { ReferenceTest1::RecordType d{33, 34}; 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(rref)) { // expected-warning{{2 uninitialized fields}} } }; void fReferenceTest2() { ReferenceTest2::RecordType c; 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(rref)) { } }; void fReferenceTest2() { ReferenceTest2::RecordType c; 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(rref)) { // expected-warning{{2 uninitialized fields}} } }; void fReferenceTest3() { ReferenceTest3::RecordType c, d{35, 36}; 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(rref)) { // expected-warning{{2 uninitialized fields}} } }; void fReferenceTest5() { ReferenceTest4::RecordType c, d{37, 38}; 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; IntMultipleReferenceToSameObjectTest Test(&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; IntReferenceWrapper1 T1(a); IntReferenceWrapper2 T2(a); }