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