blob: 1f45925561c996d7590f96e561fab48ae0568d48 [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);
Zhongxing Xub13453b2010-11-20 06:53:12 +00004
5class A {
6public:
7 ~A() {
8 int *x = 0;
9 *x = 3; // expected-warning{{Dereference of null pointer}}
10 }
11};
12
13int main() {
14 A a;
15}
Jordan Roseda5fc532012-07-26 20:04:00 +000016
17
18typedef __typeof(sizeof(int)) size_t;
19void *malloc(size_t);
20void free(void *);
21
22class SmartPointer {
23 void *X;
24public:
25 SmartPointer(void *x) : X(x) {}
26 ~SmartPointer() {
27 free(X);
28 }
29};
30
31void testSmartPointer() {
32 char *mem = (char*)malloc(4);
33 {
34 SmartPointer Deleter(mem);
35 // destructor called here
36 }
37 *mem = 0; // expected-warning{{Use of memory after it is freed}}
38}
Jordan Rose183ba8e2012-07-26 20:04:05 +000039
40
41void doSomething();
42void testSmartPointer2() {
43 char *mem = (char*)malloc(4);
44 {
45 SmartPointer Deleter(mem);
46 // Remove dead bindings...
47 doSomething();
48 // destructor called here
49 }
50 *mem = 0; // expected-warning{{Use of memory after it is freed}}
51}
52
53
54class Subclass : public SmartPointer {
55public:
56 Subclass(void *x) : SmartPointer(x) {}
57};
58
59void testSubclassSmartPointer() {
60 char *mem = (char*)malloc(4);
61 {
62 Subclass Deleter(mem);
63 // Remove dead bindings...
64 doSomething();
65 // destructor called here
66 }
67 *mem = 0; // expected-warning{{Use of memory after it is freed}}
68}
69
70
71class MultipleInheritance : public Subclass, public SmartPointer {
72public:
73 MultipleInheritance(void *a, void *b) : Subclass(a), SmartPointer(b) {}
74};
75
76void testMultipleInheritance1() {
77 char *mem = (char*)malloc(4);
78 {
79 MultipleInheritance Deleter(mem, 0);
80 // Remove dead bindings...
81 doSomething();
82 // destructor called here
83 }
84 *mem = 0; // expected-warning{{Use of memory after it is freed}}
85}
86
87void testMultipleInheritance2() {
88 char *mem = (char*)malloc(4);
89 {
90 MultipleInheritance Deleter(0, mem);
91 // Remove dead bindings...
92 doSomething();
93 // destructor called here
94 }
95 *mem = 0; // expected-warning{{Use of memory after it is freed}}
96}
97
98void testMultipleInheritance3() {
99 char *mem = (char*)malloc(4);
100 {
101 MultipleInheritance Deleter(mem, mem);
102 // Remove dead bindings...
103 doSomething();
104 // destructor called here
Jordan Rosee460c462012-07-26 20:04:25 +0000105 // expected-warning@27 {{Attempt to free released memory}}
Jordan Rose183ba8e2012-07-26 20:04:05 +0000106 }
107}
Jordan Rose3a0a9e32012-07-26 20:04:21 +0000108
109
110class SmartPointerMember {
111 SmartPointer P;
112public:
113 SmartPointerMember(void *x) : P(x) {}
114};
115
116void testSmartPointerMember() {
117 char *mem = (char*)malloc(4);
118 {
119 SmartPointerMember Deleter(mem);
120 // Remove dead bindings...
121 doSomething();
122 // destructor called here
123 }
124 *mem = 0; // expected-warning{{Use of memory after it is freed}}
125}
Jordan Rosee460c462012-07-26 20:04:25 +0000126
127
128struct IntWrapper {
129 IntWrapper() : x(0) {}
130 ~IntWrapper();
131 int *x;
132};
133
134void testArrayInvalidation() {
135 int i = 42;
136 int j = 42;
137
138 {
139 IntWrapper arr[2];
140
141 // There should be no undefined value warnings here.
142 // Eventually these should be TRUE as well, but right now
143 // we can't handle array constructors.
144 clang_analyzer_eval(arr[0].x == 0); // expected-warning{{UNKNOWN}}
145 clang_analyzer_eval(arr[1].x == 0); // expected-warning{{UNKNOWN}}
146
147 arr[0].x = &i;
148 arr[1].x = &j;
149 clang_analyzer_eval(*arr[0].x == 42); // expected-warning{{TRUE}}
150 clang_analyzer_eval(*arr[1].x == 42); // expected-warning{{TRUE}}
151 }
152
153 // The destructors should have invalidated i and j.
154 clang_analyzer_eval(i == 42); // expected-warning{{UNKNOWN}}
155 clang_analyzer_eval(j == 42); // expected-warning{{UNKNOWN}}
156}
Jordan Rose1d3ca252012-07-26 20:04:30 +0000157
158
159
160// Don't crash on a default argument inside an initializer.
161struct DefaultArg {
162 DefaultArg(int x = 0) {}
163 ~DefaultArg();
164};
165
166struct InheritsDefaultArg : DefaultArg {
167 InheritsDefaultArg() {}
168 virtual ~InheritsDefaultArg();
169};
170
171void testDefaultArg() {
172 InheritsDefaultArg a;
173 // Force a bug to be emitted.
174 *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
175}
Jordan Rose0ad36ba2012-08-15 00:51:56 +0000176
177
178namespace DestructorVirtualCalls {
179 class A {
180 public:
181 int *out1, *out2, *out3;
182
183 virtual int get() { return 1; }
184
185 ~A() {
186 *out1 = get();
187 }
188 };
189
190 class B : public A {
191 public:
192 virtual int get() { return 2; }
193
194 ~B() {
195 *out2 = get();
196 }
197 };
198
199 class C : public B {
200 public:
201 virtual int get() { return 3; }
202
203 ~C() {
204 *out3 = get();
205 }
206 };
207
208 void test() {
209 int a, b, c;
210
211 // New scope for the C object.
212 {
213 C obj;
214 clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
215
216 // Sanity check for devirtualization.
217 A *base = &obj;
218 clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
219
220 obj.out1 = &a;
221 obj.out2 = &b;
222 obj.out3 = &c;
223 }
224
225 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
226 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
227 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
228 }
229}