blob: d6f66c3845fe3dca4488b2f51d7c8fac7849aaf9 [file] [log] [blame]
Jordan Rosee1ce7832012-07-31 18:04:59 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -analyzer-ipa=inlining -cfg-add-implicit-dtors -Wno-null-dereference -verify %s
Jordan Rosee460c462012-07-26 20:04:25 +00002
3void clang_analyzer_eval(bool);
Jordan Rose632e5022012-08-28 20:52:13 +00004void clang_analyzer_checkInlined(bool);
Zhongxing Xub13453b2010-11-20 06:53:12 +00005
6class A {
7public:
8 ~A() {
9 int *x = 0;
10 *x = 3; // expected-warning{{Dereference of null pointer}}
11 }
12};
13
14int main() {
15 A a;
16}
Jordan Roseda5fc532012-07-26 20:04:00 +000017
18
19typedef __typeof(sizeof(int)) size_t;
20void *malloc(size_t);
21void free(void *);
22
23class SmartPointer {
24 void *X;
25public:
26 SmartPointer(void *x) : X(x) {}
27 ~SmartPointer() {
28 free(X);
29 }
30};
31
32void testSmartPointer() {
33 char *mem = (char*)malloc(4);
34 {
35 SmartPointer Deleter(mem);
36 // destructor called here
37 }
38 *mem = 0; // expected-warning{{Use of memory after it is freed}}
39}
Jordan Rose183ba8e2012-07-26 20:04:05 +000040
41
42void doSomething();
43void testSmartPointer2() {
44 char *mem = (char*)malloc(4);
45 {
46 SmartPointer Deleter(mem);
47 // Remove dead bindings...
48 doSomething();
49 // destructor called here
50 }
51 *mem = 0; // expected-warning{{Use of memory after it is freed}}
52}
53
54
55class Subclass : public SmartPointer {
56public:
57 Subclass(void *x) : SmartPointer(x) {}
58};
59
60void testSubclassSmartPointer() {
61 char *mem = (char*)malloc(4);
62 {
63 Subclass Deleter(mem);
64 // Remove dead bindings...
65 doSomething();
66 // destructor called here
67 }
68 *mem = 0; // expected-warning{{Use of memory after it is freed}}
69}
70
71
72class MultipleInheritance : public Subclass, public SmartPointer {
73public:
74 MultipleInheritance(void *a, void *b) : Subclass(a), SmartPointer(b) {}
75};
76
77void testMultipleInheritance1() {
78 char *mem = (char*)malloc(4);
79 {
80 MultipleInheritance Deleter(mem, 0);
81 // Remove dead bindings...
82 doSomething();
83 // destructor called here
84 }
85 *mem = 0; // expected-warning{{Use of memory after it is freed}}
86}
87
88void testMultipleInheritance2() {
89 char *mem = (char*)malloc(4);
90 {
91 MultipleInheritance Deleter(0, mem);
92 // Remove dead bindings...
93 doSomething();
94 // destructor called here
95 }
96 *mem = 0; // expected-warning{{Use of memory after it is freed}}
97}
98
99void testMultipleInheritance3() {
100 char *mem = (char*)malloc(4);
101 {
102 MultipleInheritance Deleter(mem, mem);
103 // Remove dead bindings...
104 doSomething();
105 // destructor called here
Jordan Rose632e5022012-08-28 20:52:13 +0000106 // expected-warning@28 {{Attempt to free released memory}}
Jordan Rose183ba8e2012-07-26 20:04:05 +0000107 }
108}
Jordan Rose3a0a9e32012-07-26 20:04:21 +0000109
110
111class SmartPointerMember {
112 SmartPointer P;
113public:
114 SmartPointerMember(void *x) : P(x) {}
115};
116
117void testSmartPointerMember() {
118 char *mem = (char*)malloc(4);
119 {
120 SmartPointerMember Deleter(mem);
121 // Remove dead bindings...
122 doSomething();
123 // destructor called here
124 }
125 *mem = 0; // expected-warning{{Use of memory after it is freed}}
126}
Jordan Rosee460c462012-07-26 20:04:25 +0000127
128
129struct IntWrapper {
130 IntWrapper() : x(0) {}
131 ~IntWrapper();
132 int *x;
133};
134
135void testArrayInvalidation() {
136 int i = 42;
137 int j = 42;
138
139 {
140 IntWrapper arr[2];
141
142 // There should be no undefined value warnings here.
143 // Eventually these should be TRUE as well, but right now
144 // we can't handle array constructors.
145 clang_analyzer_eval(arr[0].x == 0); // expected-warning{{UNKNOWN}}
146 clang_analyzer_eval(arr[1].x == 0); // expected-warning{{UNKNOWN}}
147
148 arr[0].x = &i;
149 arr[1].x = &j;
150 clang_analyzer_eval(*arr[0].x == 42); // expected-warning{{TRUE}}
151 clang_analyzer_eval(*arr[1].x == 42); // expected-warning{{TRUE}}
152 }
153
154 // The destructors should have invalidated i and j.
155 clang_analyzer_eval(i == 42); // expected-warning{{UNKNOWN}}
156 clang_analyzer_eval(j == 42); // expected-warning{{UNKNOWN}}
157}
Jordan Rose1d3ca252012-07-26 20:04:30 +0000158
159
160
161// Don't crash on a default argument inside an initializer.
162struct DefaultArg {
163 DefaultArg(int x = 0) {}
164 ~DefaultArg();
165};
166
167struct InheritsDefaultArg : DefaultArg {
168 InheritsDefaultArg() {}
169 virtual ~InheritsDefaultArg();
170};
171
172void testDefaultArg() {
173 InheritsDefaultArg a;
174 // Force a bug to be emitted.
175 *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
176}
Jordan Rose0ad36ba2012-08-15 00:51:56 +0000177
178
179namespace DestructorVirtualCalls {
180 class A {
181 public:
182 int *out1, *out2, *out3;
183
184 virtual int get() { return 1; }
185
186 ~A() {
187 *out1 = get();
188 }
189 };
190
191 class B : public A {
192 public:
193 virtual int get() { return 2; }
194
195 ~B() {
196 *out2 = get();
197 }
198 };
199
200 class C : public B {
201 public:
202 virtual int get() { return 3; }
203
204 ~C() {
205 *out3 = get();
206 }
207 };
208
209 void test() {
210 int a, b, c;
211
212 // New scope for the C object.
213 {
214 C obj;
215 clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
216
217 // Sanity check for devirtualization.
218 A *base = &obj;
219 clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
220
221 obj.out1 = &a;
222 obj.out2 = &b;
223 obj.out3 = &c;
224 }
225
226 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
227 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
228 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
229 }
230}
Jordan Rose632e5022012-08-28 20:52:13 +0000231
232
233namespace DestructorsShouldNotAffectReturnValues {
234 class Dtor {
235 public:
236 ~Dtor() {
237 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
238 }
239 };
240
241 void *allocate() {
242 Dtor d;
243 return malloc(4); // no-warning
244 }
245
246 void test() {
247 // At one point we had an issue where the statements inside an
248 // inlined destructor kept us from finding the return statement,
249 // leading the analyzer to believe that the malloc'd memory had leaked.
250 void *p = allocate();
251 free(p); // no-warning
252 }
253}