NewDelete-checker-test.cpp revision 68eb4c25e961d18f82b47a0a385f90d7af09bcc3
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s 2// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s 3#include "Inputs/system-header-simulator-cxx.h" 4 5typedef __typeof__(sizeof(int)) size_t; 6extern "C" void *malloc(size_t); 7int *global; 8 9//------------------ 10// check for leaks 11//------------------ 12 13//----- Standard non-placement operators 14void testGlobalOpNew() { 15 void *p = operator new(0); 16} 17#ifdef LEAKS 18// expected-warning@-2{{Potential leak of memory pointed to by 'p'}} 19#endif 20 21void testGlobalOpNewArray() { 22 void *p = operator new[](0); 23} 24#ifdef LEAKS 25// expected-warning@-2{{Potential leak of memory pointed to by 'p'}} 26#endif 27 28void testGlobalNewExpr() { 29 int *p = new int; 30} 31#ifdef LEAKS 32// expected-warning@-2{{Potential leak of memory pointed to by 'p'}} 33#endif 34 35void testGlobalNewExprArray() { 36 int *p = new int[0]; 37} 38#ifdef LEAKS 39// expected-warning@-2{{Potential leak of memory pointed to by 'p'}} 40#endif 41 42//----- Standard nothrow placement operators 43void testGlobalNoThrowPlacementOpNewBeforeOverload() { 44 void *p = operator new(0, std::nothrow); 45} 46#ifdef LEAKS 47// expected-warning@-2{{Potential leak of memory pointed to by 'p'}} 48#endif 49 50void testGlobalNoThrowPlacementExprNewBeforeOverload() { 51 int *p = new(std::nothrow) int; 52} 53#ifdef LEAKS 54// expected-warning@-2{{Potential leak of memory pointed to by 'p'}} 55#endif 56 57 58//----- Standard pointer placement operators 59void testGlobalPointerPlacementNew() { 60 int i; 61 62 void *p1 = operator new(0, &i); // no warn 63 64 void *p2 = operator new[](0, &i); // no warn 65 66 int *p3 = new(&i) int; // no warn 67 68 int *p4 = new(&i) int[0]; // no warn 69} 70 71//----- Other cases 72void testNewMemoryIsInHeap() { 73 int *p = new int; 74 if (global != p) // condition is always true as 'p' wraps a heap region that 75 // is different from a region wrapped by 'global' 76 global = p; // pointer escapes 77} 78 79struct PtrWrapper { 80 int *x; 81 82 PtrWrapper(int *input) : x(input) {} 83}; 84 85void testNewInvalidationPlacement(PtrWrapper *w) { 86 // Ensure that we don't consider this a leak. 87 new (w) PtrWrapper(new int); // no warn 88} 89 90//--------------- 91// other checks 92//--------------- 93 94void f(int *); 95 96void testUseAfterDelete() { 97 int *p = new int; 98 delete p; 99 f(p); // expected-warning{{Use of memory after it is freed}} 100} 101 102void testDeleteAlloca() { 103 int *p = (int *)__builtin_alloca(sizeof(int)); 104 delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}} 105} 106 107void testDoubleDelete() { 108 int *p = new int; 109 delete p; 110 delete p; // expected-warning{{Attempt to free released memory}} 111} 112 113void testExprDeleteArg() { 114 int i; 115 delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}} 116} 117 118void testExprDeleteArrArg() { 119 int i; 120 delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}} 121} 122 123void testAllocDeallocNames() { 124 int *p = new(std::nothrow) int[1]; 125 delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}} 126} 127 128//-------------------------------- 129// Test escape of newed const pointer. Note, a const pointer can be deleted. 130//-------------------------------- 131struct StWithConstPtr { 132 const int *memp; 133}; 134void escape(const int &x); 135void escapeStruct(const StWithConstPtr &x); 136void escapePtr(const StWithConstPtr *x); 137void escapeVoidPtr(const void *x); 138 139void testConstEscape() { 140 int *p = new int(1); 141 escape(*p); 142} // no-warning 143 144void testConstEscapeStruct() { 145 StWithConstPtr *St = new StWithConstPtr(); 146 escapeStruct(*St); 147} // no-warning 148 149void testConstEscapeStructPtr() { 150 StWithConstPtr *St = new StWithConstPtr(); 151 escapePtr(St); 152} // no-warning 153 154void testConstEscapeMember() { 155 StWithConstPtr St; 156 St.memp = new int(2); 157 escapeVoidPtr(St.memp); 158} // no-warning 159 160void testConstEscapePlacementNew() { 161 int *x = (int *)malloc(sizeof(int)); 162 void *y = new (x) int; 163 escapeVoidPtr(y); 164} // no-warning 165