]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/MismatchedDeallocator-checker-test.mm
Vendor import of clang trunk r338150:
[FreeBSD/FreeBSD.git] / test / Analysis / MismatchedDeallocator-checker-test.mm
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -fblocks -verify %s
2 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.MismatchedDeallocator -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s
3
4 #include "Inputs/system-header-simulator-objc.h"
5 #include "Inputs/system-header-simulator-cxx.h"
6
7 typedef __typeof__(sizeof(int)) size_t;
8 void *malloc(size_t);
9 void *realloc(void *ptr, size_t size);
10 void *calloc(size_t nmemb, size_t size);
11 char *strdup(const char *s);
12 void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
13
14 void free(void *);
15 void __attribute((ownership_takes(malloc, 1))) my_free(void *);
16
17 //---------------------------------------------------------------
18 // Test if an allocation function matches deallocation function
19 //---------------------------------------------------------------
20
21 //--------------- test malloc family
22 void testMalloc1() {
23   int *p = (int *)malloc(sizeof(int));
24   delete p; // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not 'delete'}}
25 }
26
27 void testMalloc2() {
28   int *p = (int *)malloc(8);
29   int *q = (int *)realloc(p, 16);
30   delete q; // expected-warning{{Memory allocated by realloc() should be deallocated by free(), not 'delete'}}
31 }
32
33 void testMalloc3() {
34   int *p = (int *)calloc(1, sizeof(int));
35   delete p; // expected-warning{{Memory allocated by calloc() should be deallocated by free(), not 'delete'}}
36 }
37
38 void testMalloc4(const char *s) {
39   char *p = strdup(s);
40   delete p; // expected-warning{{Memory allocated by strdup() should be deallocated by free(), not 'delete'}}
41 }
42
43 void testMalloc5() {
44   int *p = (int *)my_malloc(sizeof(int));
45   delete p; // expected-warning{{Memory allocated by my_malloc() should be deallocated by free(), not 'delete'}}
46 }
47
48 void testMalloc6() {
49   int *p = (int *)malloc(sizeof(int));
50   operator delete(p); // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not operator delete}}
51 }
52
53 void testMalloc7() {
54   int *p = (int *)malloc(sizeof(int));
55   delete[] p; // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not 'delete[]'}}
56 }
57
58 void testMalloc8() {
59   int *p = (int *)malloc(sizeof(int));
60   operator delete[](p); // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not operator delete[]}}
61 }
62
63 void testAlloca() {
64   int *p = (int *)__builtin_alloca(sizeof(int));
65   delete p; // expected-warning{{Memory allocated by alloca() should not be deallocated}}
66 }
67
68 //--------------- test new family
69 void testNew1() {
70   int *p = new int;
71   free(p); // expected-warning{{Memory allocated by 'new' should be deallocated by 'delete', not free()}}
72 }
73
74 void testNew2() {
75   int *p = (int *)operator new(0);
76   free(p); // expected-warning{{Memory allocated by operator new should be deallocated by 'delete', not free()}}
77 }
78
79 void testNew3() {
80   int *p = new int[1];
81   free(p); // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not free()}}
82 }
83
84 void testNew4() {
85   int *p = new int;
86   realloc(p, sizeof(long)); // expected-warning{{Memory allocated by 'new' should be deallocated by 'delete', not realloc()}}
87 }
88
89 void testNew5() {
90   int *p = (int *)operator new(0);
91   realloc(p, sizeof(long)); // expected-warning{{Memory allocated by operator new should be deallocated by 'delete', not realloc()}}
92 }
93
94 void testNew6() {
95   int *p = new int[1];
96   realloc(p, sizeof(long)); // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not realloc()}}
97 }
98
99 int *allocInt() {
100   return new int;
101 }
102 void testNew7() {
103   int *p = allocInt();
104   delete[] p; // expected-warning{{Memory allocated by 'new' should be deallocated by 'delete', not 'delete[]'}}
105 }
106
107 void testNew8() {
108   int *p = (int *)operator new(0);
109   delete[] p; // expected-warning{{Memory allocated by operator new should be deallocated by 'delete', not 'delete[]'}}
110 }
111
112 int *allocIntArray(unsigned c) {
113   return new int[c];
114 }
115
116 void testNew9() {
117   int *p = allocIntArray(1);
118   delete p; // expected-warning{{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}}
119 }
120
121 void testNew10() {
122   int *p = (int *)operator new[](0);
123   delete p; // expected-warning{{Memory allocated by operator new[] should be deallocated by 'delete[]', not 'delete'}}
124 }
125
126 void testNew11(NSUInteger dataLength) {
127   int *p = new int;
128   NSData *d = [NSData dataWithBytesNoCopy:p length:sizeof(int) freeWhenDone:1]; // expected-warning{{+dataWithBytesNoCopy:length:freeWhenDone: cannot take ownership of memory allocated by 'new'}}
129 }
130
131 //-------------------------------------------------------
132 // Check for intersection with unix.Malloc bounded with 
133 // unix.MismatchedDeallocator
134 //-------------------------------------------------------
135
136 // new/delete oparators are subjects of cplusplus.NewDelete.
137 void testNewDeleteNoWarn() {
138   int i;
139   delete &i; // no-warning
140
141   int *p1 = new int;
142   delete ++p1; // no-warning
143
144   int *p2 = new int;
145   delete p2;
146   delete p2; // no-warning
147
148   int *p3 = new int; // no-warning
149 }
150
151 void testDeleteOpAfterFree() {
152   int *p = (int *)malloc(sizeof(int));
153   free(p);
154   operator delete(p); // no-warning
155 }
156
157 void testDeleteAfterFree() {
158   int *p = (int *)malloc(sizeof(int));
159   free(p);
160   delete p; // no-warning
161 }
162
163 void testStandardPlacementNewAfterFree() {
164   int *p = (int *)malloc(sizeof(int));
165   free(p);
166   p = new(p) int; // no-warning
167 }
168
169 //---------------------------------------------------------------
170 // Check for intersection with cplusplus.NewDelete bounded with 
171 // unix.MismatchedDeallocator
172 //---------------------------------------------------------------
173
174 // malloc()/free() are subjects of unix.Malloc and unix.MallocWithAnnotations
175 void testMallocFreeNoWarn() {
176   int i;
177   free(&i); // no-warning
178
179   int *p1 = (int *)malloc(sizeof(int));
180   free(++p1); // no-warning
181
182   int *p2 = (int *)malloc(sizeof(int));
183   free(p2);
184   free(p2); // no-warning
185
186   int *p3 = (int *)malloc(sizeof(int)); // no-warning
187 }
188
189 void testFreeAfterDelete() {
190   int *p = new int;  
191   delete p;
192   free(p); // no-warning
193 }
194
195 void testStandardPlacementNewAfterDelete() {
196   int *p = new int;  
197   delete p;
198   p = new(p) int; // no-warning
199 }
200
201
202 // Smart pointer example
203 template <typename T>
204 struct SimpleSmartPointer {
205   T *ptr;
206
207   explicit SimpleSmartPointer(T *p = 0) : ptr(p) {}
208   ~SimpleSmartPointer() {
209     delete ptr;
210     // expected-warning@-1 {{Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'}}
211     // expected-warning@-2 {{Memory allocated by malloc() should be deallocated by free(), not 'delete'}}
212   }
213 };
214
215 void testSimpleSmartPointerArrayNew() {
216   {
217     SimpleSmartPointer<int> a(new int);
218   } // no-warning
219
220   {
221     SimpleSmartPointer<int> a(new int[4]);
222   }
223 }
224
225 void testSimpleSmartPointerMalloc() {
226   {
227     SimpleSmartPointer<int> a(new int);
228   } // no-warning
229
230   {
231     SimpleSmartPointer<int> a((int *)malloc(4));
232   }
233 }