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.cpp145
1 files changed, 145 insertions, 0 deletions
diff --git a/test/Analysis/NewDelete-checker-test.cpp b/test/Analysis/NewDelete-checker-test.cpp
new file mode 100644
index 0000000..c31d7f3
--- /dev/null
+++ b/test/Analysis/NewDelete-checker-test.cpp
@@ -0,0 +1,145 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -fblocks -verify %s
+#include "Inputs/system-header-simulator-cxx.h"
+
+typedef __typeof__(sizeof(int)) size_t;
+extern "C" void *malloc(size_t);
+int *global;
+
+//------------------
+// check for leaks
+//------------------
+
+//----- Standard non-placement operators
+void testGlobalOpNew() {
+ void *p = operator new(0);
+} // expected-warning{{Memory is never released; potential leak}}
+
+void testGlobalOpNewArray() {
+ void *p = operator new[](0);
+} // expected-warning{{Memory is never released; potential leak}}
+
+void testGlobalNewExpr() {
+ int *p = new int;
+} // expected-warning{{Memory is never released; potential leak}}
+
+void testGlobalNewExprArray() {
+ int *p = new int[0];
+} // expected-warning{{Memory is never released; potential leak}}
+
+//----- Standard nothrow placement operators
+void testGlobalNoThrowPlacementOpNewBeforeOverload() {
+ void *p = operator new(0, std::nothrow);
+} // expected-warning{{Memory is never released; potential leak}}
+
+void testGlobalNoThrowPlacementExprNewBeforeOverload() {
+ int *p = new(std::nothrow) int;
+} // expected-warning{{Memory is never released; potential leak}}
+
+
+//----- Standard pointer placement operators
+void testGlobalPointerPlacementNew() {
+ int i;
+
+ void *p1 = operator new(0, &i); // no warn
+
+ void *p2 = operator new[](0, &i); // no warn
+
+ int *p3 = new(&i) int; // no warn
+
+ int *p4 = new(&i) int[0]; // no warn
+}
+
+//----- Other cases
+void testNewMemoryIsInHeap() {
+ int *p = new int;
+ if (global != p) // condition is always true as 'p' wraps a heap region that
+ // is different from a region wrapped by 'global'
+ global = p; // pointer escapes
+}
+
+struct PtrWrapper {
+ int *x;
+
+ PtrWrapper(int *input) : x(input) {}
+};
+
+void testNewInvalidationPlacement(PtrWrapper *w) {
+ // Ensure that we don't consider this a leak.
+ new (w) PtrWrapper(new int); // no warn
+}
+
+//---------------
+// other checks
+//---------------
+
+void f(int *);
+
+void testUseAfterDelete() {
+ int *p = new int;
+ delete p;
+ f(p); // expected-warning{{Use of memory after it is freed}}
+}
+
+void testDeleteAlloca() {
+ int *p = (int *)__builtin_alloca(sizeof(int));
+ delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}}
+}
+
+void testDoubleDelete() {
+ int *p = new int;
+ delete p;
+ delete p; // expected-warning{{Attempt to free released memory}}
+}
+
+void testExprDeleteArg() {
+ int i;
+ delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
+}
+
+void testExprDeleteArrArg() {
+ int i;
+ delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
+}
+
+void testAllocDeallocNames() {
+ int *p = new(std::nothrow) int[1];
+ delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
+}
+
+//--------------------------------
+// Test escape of newed const pointer. Note, a const pointer can be deleted.
+//--------------------------------
+struct StWithConstPtr {
+ const int *memp;
+};
+void escape(const int &x);
+void escapeStruct(const StWithConstPtr &x);
+void escapePtr(const StWithConstPtr *x);
+void escapeVoidPtr(const void *x);
+
+void testConstEscape() {
+ int *p = new int(1);
+ escape(*p);
+} // no-warning
+
+void testConstEscapeStruct() {
+ StWithConstPtr *St = new StWithConstPtr();
+ escapeStruct(*St);
+} // no-warning
+
+void testConstEscapeStructPtr() {
+ StWithConstPtr *St = new StWithConstPtr();
+ escapePtr(St);
+} // no-warning
+
+void testConstEscapeMember() {
+ StWithConstPtr St;
+ St.memp = new int(2);
+ escapeVoidPtr(St.memp);
+} // no-warning
+
+void testConstEscapePlacementNew() {
+ int *x = (int *)malloc(sizeof(int));
+ void *y = new (x) int;
+ escapeVoidPtr(y);
+} // no-warning
OpenPOWER on IntegriCloud