summaryrefslogtreecommitdiffstats
path: root/test/Analysis/NewDelete-checker-test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/Analysis/NewDelete-checker-test.cpp')
-rw-r--r--test/Analysis/NewDelete-checker-test.cpp152
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}}
+}
OpenPOWER on IntegriCloud