diff options
Diffstat (limited to 'test/Analysis/NewDelete-checker-test.cpp')
-rw-r--r-- | test/Analysis/NewDelete-checker-test.cpp | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/test/Analysis/NewDelete-checker-test.cpp b/test/Analysis/NewDelete-checker-test.cpp index 5d134bc..cc97251 100644 --- a/test/Analysis/NewDelete-checker-test.cpp +++ b/test/Analysis/NewDelete-checker-test.cpp @@ -4,6 +4,7 @@ typedef __typeof__(sizeof(int)) size_t; extern "C" void *malloc(size_t); +extern "C" void free (void* ptr); int *global; //------------------ @@ -206,3 +207,154 @@ void testConstEscapePlacementNew() { void *y = new (x) int; escapeVoidPtr(y); } // no-warning + +//============== Test Uninitialized delete delete[]======================== +void testUninitDelete() { + int *x; + int * y = new int; + delete y; + delete x; // expected-warning{{Argument to 'delete' is uninitialized}} +} + +void testUninitDeleteArray() { + int *x; + int * y = new int[5]; + delete[] y; + delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}} +} + +void testUninitFree() { + int *x; + free(x); // expected-warning{{Function call argument is an uninitialized value}} +} + +void testUninitDeleteSink() { + int *x; + delete x; // expected-warning{{Argument to 'delete' is uninitialized}} + (*(volatile int *)0 = 1); // no warn +} + +void testUninitDeleteArraySink() { + int *x; + delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}} + (*(volatile int *)0 = 1); // no warn +} + +namespace reference_count { + class control_block { + unsigned count; + public: + control_block() : count(0) {} + void retain() { ++count; } + int release() { return --count; } + }; + + template <typename T> + class shared_ptr { + T *p; + control_block *control; + + public: + shared_ptr() : p(0), control(0) {} + explicit shared_ptr(T *p) : p(p), control(new control_block) { + control->retain(); + } + shared_ptr(shared_ptr &other) : p(other.p), control(other.control) { + if (control) + control->retain(); + } + ~shared_ptr() { + if (control && control->release() == 0) { + delete p; + delete control; + } + }; + + T &operator *() { + return *p; + }; + + void swap(shared_ptr &other) { + T *tmp = p; + p = other.p; + other.p = tmp; + + control_block *ctrlTmp = control; + control = other.control; + other.control = ctrlTmp; + } + }; + + void testSingle() { + shared_ptr<int> a(new int); + *a = 1; + } + + void testDouble() { + shared_ptr<int> a(new int); + shared_ptr<int> b = a; + *a = 1; + } + + void testInvalidated() { + shared_ptr<int> a(new int); + shared_ptr<int> b = a; + *a = 1; + + extern void use(shared_ptr<int> &); + use(b); + } + + void testNestedScope() { + shared_ptr<int> a(new int); + { + shared_ptr<int> b = a; + } + *a = 1; + } + + void testSwap() { + shared_ptr<int> a(new int); + shared_ptr<int> b; + shared_ptr<int> c = a; + shared_ptr<int>(c).swap(b); + } + + void testUseAfterFree() { + int *p = new int; + { + shared_ptr<int> a(p); + shared_ptr<int> b = a; + } + + // FIXME: We should get a warning here, but we don't because we've + // conservatively modeled ~shared_ptr. + *p = 1; + } +} + +// Test double delete +class DerefClass{ +public: + int *x; + DerefClass() {} + ~DerefClass() {*x = 1;} //expected-warning {{Use of memory after it is freed}} +}; + +void testDoubleDeleteClassInstance() { + DerefClass *foo = new DerefClass(); + delete foo; + delete foo; // FIXME: We should ideally report warning here instead of inside the destructor. +} + +class EmptyClass{ +public: + EmptyClass() {} + ~EmptyClass() {} +}; + +void testDoubleDeleteEmptyClass() { + EmptyClass *foo = new EmptyClass(); + delete foo; + delete foo; //expected-warning {{Attempt to free released memory}} +} |