new.cpp revision b061720ddf88b4a1934dbbb1b874a424716cd7d7
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -verify %s 2#include "Inputs/system-header-simulator-cxx.h" 3 4void clang_analyzer_eval(bool); 5 6typedef __typeof__(sizeof(int)) size_t; 7extern "C" void *malloc(size_t); 8extern "C" void free(void *); 9 10int someGlobal; 11void testImplicitlyDeclaredGlobalNew() { 12 if (someGlobal != 0) 13 return; 14 15 // This used to crash because the global operator new is being implicitly 16 // declared and it does not have a valid source location. (PR13090) 17 void *x = ::operator new(0); 18 ::operator delete(x); 19 20 // Check that the new/delete did not invalidate someGlobal; 21 clang_analyzer_eval(someGlobal == 0); // expected-warning{{TRUE}} 22} 23 24void *testPlacementNew() { 25 int *x = (int *)malloc(sizeof(int)); 26 *x = 1; 27 clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}}; 28 29 void *y = new (x) int; 30 clang_analyzer_eval(x == y); // expected-warning{{TRUE}}; 31 clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}}; 32 33 return y; 34} 35 36void *operator new(size_t, size_t, int *); 37void *testCustomNew() { 38 int x[1] = {1}; 39 clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}}; 40 41 void *y = new (0, x) int; 42 clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}}; 43 44 return y; // no-warning 45} 46 47void *operator new(size_t, void *, void *); 48void *testCustomNewMalloc() { 49 int *x = (int *)malloc(sizeof(int)); 50 51 // Should be no-warning (the custom allocator could have freed x). 52 void *y = new (0, x) int; // no-warning 53 54 return y; 55} 56 57void testScalarInitialization() { 58 int *n = new int(3); 59 clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}} 60 61 new (n) int(); 62 clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}} 63 64 new (n) int{3}; 65 clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}} 66 67 new (n) int{}; 68 clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}} 69} 70 71struct PtrWrapper { 72 int *x; 73 74 PtrWrapper(int *input) : x(input) {} 75}; 76 77PtrWrapper *testNewInvalidation() { 78 // Ensure that we don't consider this a leak. 79 return new PtrWrapper(static_cast<int *>(malloc(4))); // no-warning 80} 81 82void testNewInvalidationPlacement(PtrWrapper *w) { 83 // Ensure that we don't consider this a leak. 84 new (w) PtrWrapper(static_cast<int *>(malloc(4))); // no-warning 85} 86 87int **testNewInvalidationScalar() { 88 // Ensure that we don't consider this a leak. 89 return new (int *)(static_cast<int *>(malloc(4))); // no-warning 90} 91 92void testNewInvalidationScalarPlacement(int **p) { 93 // Ensure that we don't consider this a leak. 94 new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning 95} 96 97//-------------------------------------------------------------------- 98// Check for intersection with other checkers from MallocChecker.cpp 99// bounded with unix.Malloc 100//-------------------------------------------------------------------- 101 102// new/delete oparators are subjects of cplusplus.NewDelete. 103void testNewDeleteNoWarn() { 104 int i; 105 delete &i; // no-warning 106 107 int *p1 = new int; 108 delete ++p1; // no-warning 109 110 int *p2 = new int; 111 delete p2; 112 delete p2; // no-warning 113 114 int *p3 = new int; // no-warning 115} 116 117// unix.Malloc does not know about operators new/delete. 118void testDeleteMallocked() { 119 int *x = (int *)malloc(sizeof(int)); 120 delete x; // FIXME: Shoud detect pointer escape and keep silent after 'delete' is modeled properly. 121} // expected-warning{{Memory is never released; potential leak}} 122 123void testDeleteOpAfterFree() { 124 int *p = (int *)malloc(sizeof(int)); 125 free(p); 126 operator delete(p); // expected-warning{{Use of memory after it is freed}} 127} 128 129void testDeleteAfterFree() { 130 int *p = (int *)malloc(sizeof(int)); 131 free(p); 132 delete p; // expected-warning{{Use of memory after it is freed}} 133} 134 135void testStandardPlacementNewAfterFree() { 136 int *p = (int *)malloc(sizeof(int)); 137 free(p); 138 p = new(p) int; // expected-warning{{Use of memory after it is freed}} 139} 140 141void testCustomPlacementNewAfterFree() { 142 int *p = (int *)malloc(sizeof(int)); 143 free(p); 144 p = new(0, p) int; // expected-warning{{Use of memory after it is freed}} 145} 146 147//-------------------------------- 148// Incorrectly-modelled behavior 149//-------------------------------- 150 151int testNoInitialization() { 152 int *n = new int; 153 154 // Should warn that *n is uninitialized. 155 if (*n) { // no-warning 156 delete n; 157 return 0; 158 } 159 delete n; 160 return 1; 161} 162 163int testNoInitializationPlacement() { 164 int n; 165 new (&n) int; 166 167 // Should warn that n is uninitialized. 168 if (n) { // no-warning 169 return 0; 170 } 171 return 1; 172} 173