blob: ca126ddf7f389d76b306fc241f746542c0132ef7 [file] [log] [blame]
Anna Zaks6bab4ef2013-01-24 23:15:30 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -verify %s
Jordan Rosed66bee32012-07-12 00:16:25 +00002
3void clang_analyzer_eval(bool);
Jordan Rose51bcb222012-08-10 22:26:43 +00004void clang_analyzer_checkInlined(bool);
Jordan Rosed66bee32012-07-12 00:16:25 +00005
Jordan Rose561919e2012-08-27 18:39:22 +00006typedef __typeof__(sizeof(int)) size_t;
7extern "C" void *malloc(size_t);
8
9// This is the standard placement new.
10inline void* operator new(size_t, void* __p) throw()
11{
12 return __p;
13}
14
15
Jordan Rosed66bee32012-07-12 00:16:25 +000016class A {
17public:
18 int getZero() { return 0; }
19 virtual int getNum() { return 0; }
20};
21
22void test(A &a) {
23 clang_analyzer_eval(a.getZero() == 0); // expected-warning{{TRUE}}
24 clang_analyzer_eval(a.getNum() == 0); // expected-warning{{UNKNOWN}}
25
26 A copy(a);
27 clang_analyzer_eval(copy.getZero() == 0); // expected-warning{{TRUE}}
28 clang_analyzer_eval(copy.getNum() == 0); // expected-warning{{TRUE}}
29}
30
31
32class One : public A {
33public:
34 virtual int getNum() { return 1; }
35};
36
37void testPathSensitivity(int x) {
38 A a;
39 One b;
40
41 A *ptr;
42 switch (x) {
43 case 0:
44 ptr = &a;
45 break;
46 case 1:
47 ptr = &b;
48 break;
49 default:
50 return;
51 }
52
53 // This should be true on both branches.
54 clang_analyzer_eval(ptr->getNum() == x); // expected-warning {{TRUE}}
55}
56
Jordan Rose51bcb222012-08-10 22:26:43 +000057
58namespace PureVirtualParent {
59 class Parent {
60 public:
61 virtual int pureVirtual() const = 0;
62 int callVirtual() const {
63 return pureVirtual();
64 }
65 };
66
67 class Child : public Parent {
68 public:
69 virtual int pureVirtual() const {
70 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
71 return 42;
72 }
73 };
74
75 void testVirtual() {
76 Child x;
77
78 clang_analyzer_eval(x.pureVirtual() == 42); // expected-warning{{TRUE}}
79 clang_analyzer_eval(x.callVirtual() == 42); // expected-warning{{TRUE}}
80 }
81}
82
83
Jordan Rose02e53092012-08-10 22:26:46 +000084namespace PR13569 {
85 class Parent {
86 protected:
87 int m_parent;
88 virtual int impl() const = 0;
89
90 Parent() : m_parent(0) {}
91
92 public:
93 int interface() const {
94 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
95 return impl();
96 }
97 };
98
99 class Child : public Parent {
100 protected:
101 virtual int impl() const {
102 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
103 return m_parent + m_child;
104 }
105
106 public:
107 Child() : m_child(0) {}
108
109 int m_child;
110 };
111
112 void testVirtual() {
113 Child x;
114 x.m_child = 42;
115
116 // Don't crash when inlining and devirtualizing.
117 x.interface();
118 }
Jordan Rose710f6b12012-08-13 23:46:01 +0000119
120
121 class Grandchild : public Child {};
122
123 void testDevirtualizeToMiddle() {
124 Grandchild x;
125 x.m_child = 42;
126
127 // Don't crash when inlining and devirtualizing.
128 x.interface();
129 }
Jordan Rose02e53092012-08-10 22:26:46 +0000130}
131
Jordan Rose710f6b12012-08-13 23:46:01 +0000132namespace PR13569_virtual {
133 class Parent {
134 protected:
135 int m_parent;
136 virtual int impl() const = 0;
Jordan Rose02e53092012-08-10 22:26:46 +0000137
Jordan Rose710f6b12012-08-13 23:46:01 +0000138 Parent() : m_parent(0) {}
139
140 public:
141 int interface() const {
142 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
143 return impl();
144 }
145 };
146
147 class Child : virtual public Parent {
148 protected:
149 virtual int impl() const {
150 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
151 return m_parent + m_child;
152 }
153
154 public:
155 Child() : m_child(0) {}
156
157 int m_child;
158 };
159
160 void testVirtual() {
161 Child x;
162 x.m_child = 42;
163
164 // Don't crash when inlining and devirtualizing.
165 x.interface();
166 }
167
168
169 class Grandchild : virtual public Child {};
170
171 void testDevirtualizeToMiddle() {
172 Grandchild x;
173 x.m_child = 42;
174
175 // Don't crash when inlining and devirtualizing.
176 x.interface();
177 }
178}
Jordan Rosee9753b02012-08-15 21:05:15 +0000179
180namespace Invalidation {
181 struct X {
182 void touch(int &x) const {
183 x = 0;
184 }
185
186 void touch2(int &x) const;
187
188 virtual void touchV(int &x) const {
189 x = 0;
190 }
191
192 virtual void touchV2(int &x) const;
193
194 int test() const {
Anna Zaks6bab4ef2013-01-24 23:15:30 +0000195 // We were accidentally not invalidating under inlining
Jordan Rosee9753b02012-08-15 21:05:15 +0000196 // at one point for virtual methods with visible definitions.
197 int a, b, c, d;
198 touch(a);
199 touch2(b);
200 touchV(c);
201 touchV2(d);
202 return a + b + c + d; // no-warning
203 }
204 };
205}
Jordan Rosee5d53932012-08-23 18:10:53 +0000206
207namespace DefaultArgs {
208 int takesDefaultArgs(int i = 42) {
209 return -i;
210 }
211
212 void testFunction() {
213 clang_analyzer_eval(takesDefaultArgs(1) == -1); // expected-warning{{TRUE}}
214 clang_analyzer_eval(takesDefaultArgs() == -42); // expected-warning{{TRUE}}
215 }
216
217 class Secret {
218 public:
Jordan Rose42b130b2013-02-13 03:11:06 +0000219 static const int value = 40 + 2;
Jordan Rosee5d53932012-08-23 18:10:53 +0000220 int get(int i = value) {
221 return i;
222 }
223 };
224
225 void testMethod() {
226 Secret obj;
227 clang_analyzer_eval(obj.get(1) == 1); // expected-warning{{TRUE}}
Jordan Rose42b130b2013-02-13 03:11:06 +0000228 clang_analyzer_eval(obj.get() == 42); // expected-warning{{TRUE}}
Jordan Rosee5d53932012-08-23 18:10:53 +0000229 clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}}
Jordan Rose42b130b2013-02-13 03:11:06 +0000230 }
231
232 enum ABC {
233 A = 0,
234 B = 1,
235 C = 2
236 };
237
238 int enumUser(ABC input = B) {
239 return static_cast<int>(input);
240 }
241
242 void testEnum() {
243 clang_analyzer_eval(enumUser(C) == 2); // expected-warning{{TRUE}}
244 clang_analyzer_eval(enumUser() == 1); // expected-warning{{TRUE}}
245 }
246
247
248 int exprUser(int input = 2 * 4) {
249 return input;
250 }
251
252 int complicatedExprUser(int input = 2 * Secret::value) {
253 return input;
254 }
255
256 void testExprs() {
257 clang_analyzer_eval(exprUser(1) == 1); // expected-warning{{TRUE}}
258 clang_analyzer_eval(exprUser() == 8); // expected-warning{{TRUE}}
259
260 clang_analyzer_eval(complicatedExprUser(1) == 1); // expected-warning{{TRUE}}
261 clang_analyzer_eval(complicatedExprUser() == 84); // expected-warning{{TRUE}}
Jordan Rosee5d53932012-08-23 18:10:53 +0000262 }
Jordan Rose77cdb532013-02-25 19:45:34 +0000263
264 int defaultReference(const int &input = 42) {
Jordan Rosec76d7e32013-05-02 19:51:20 +0000265 return -input;
266 }
267 int defaultReferenceZero(const int &input = 0) {
268 return -input;
Jordan Rose77cdb532013-02-25 19:45:34 +0000269 }
270
271 void testReference() {
Jordan Rosec76d7e32013-05-02 19:51:20 +0000272 clang_analyzer_eval(defaultReference(1) == -1); // expected-warning{{TRUE}}
273 clang_analyzer_eval(defaultReference() == -42); // expected-warning{{TRUE}}
274
275 clang_analyzer_eval(defaultReferenceZero(1) == -1); // expected-warning{{TRUE}}
276 clang_analyzer_eval(defaultReferenceZero() == 0); // expected-warning{{TRUE}}
277}
278
279 double defaultFloatReference(const double &i = 42) {
280 return -i;
281 }
282 double defaultFloatReferenceZero(const double &i = 0) {
283 return -i;
284 }
285
286 void testFloatReference() {
287 clang_analyzer_eval(defaultFloatReference(1) == -1); // expected-warning{{UNKNOWN}}
288 clang_analyzer_eval(defaultFloatReference() == -42); // expected-warning{{UNKNOWN}}
289
290 clang_analyzer_eval(defaultFloatReferenceZero(1) == -1); // expected-warning{{UNKNOWN}}
291 clang_analyzer_eval(defaultFloatReferenceZero() == 0); // expected-warning{{UNKNOWN}}
Jordan Rose77cdb532013-02-25 19:45:34 +0000292 }
Jordan Rose5fded082013-07-17 17:16:38 +0000293
294 char defaultString(const char *s = "abc") {
295 return s[1];
296 }
297
298 void testString() {
299 clang_analyzer_eval(defaultString("xyz") == 'y'); // expected-warning{{TRUE}}
300 clang_analyzer_eval(defaultString() == 'b'); // expected-warning{{TRUE}}
301 }
Jordan Rosee5d53932012-08-23 18:10:53 +0000302}
Jordan Rose561919e2012-08-27 18:39:22 +0000303
304namespace OperatorNew {
305 class IntWrapper {
306 public:
307 int value;
308
309 IntWrapper(int input) : value(input) {
310 // We don't want this constructor to be inlined unless we can actually
311 // use the proper region for operator new.
312 // See PR12014 and <rdar://problem/12180598>.
313 clang_analyzer_checkInlined(false); // no-warning
314 }
315 };
316
317 void test() {
318 IntWrapper *obj = new IntWrapper(42);
319 // should be TRUE
320 clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
Anton Yartsev13df0362013-03-25 01:35:45 +0000321 delete obj;
Jordan Rose561919e2012-08-27 18:39:22 +0000322 }
323
324 void testPlacement() {
325 IntWrapper *obj = static_cast<IntWrapper *>(malloc(sizeof(IntWrapper)));
326 IntWrapper *alias = new (obj) IntWrapper(42);
327
328 clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}}
329
330 // should be TRUE
331 clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
332 }
333}
Jordan Rose81456d92012-09-07 01:19:42 +0000334
335
336namespace VirtualWithSisterCasts {
Jordan Roseaaf83182012-09-08 01:24:38 +0000337 // This entire set of tests exercises casts from sister classes and
338 // from classes outside the hierarchy, which can very much confuse
339 // code that uses DynamicTypeInfo or needs to construct CXXBaseObjectRegions.
340 // These examples used to cause crashes in +Asserts builds.
Jordan Rose81456d92012-09-07 01:19:42 +0000341 struct Parent {
342 virtual int foo();
Jordan Roseaaf83182012-09-08 01:24:38 +0000343 int x;
Jordan Rose81456d92012-09-07 01:19:42 +0000344 };
345
346 struct A : Parent {
347 virtual int foo() { return 42; }
348 };
349
350 struct B : Parent {
351 virtual int foo();
352 };
353
Jordan Roseaaf83182012-09-08 01:24:38 +0000354 struct Grandchild : public A {};
355
Jordan Rose81456d92012-09-07 01:19:42 +0000356 struct Unrelated {};
357
358 void testDowncast(Parent *b) {
359 A *a = (A *)(void *)b;
360 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
Jordan Roseaaf83182012-09-08 01:24:38 +0000361
362 a->x = 42;
363 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
Jordan Rose81456d92012-09-07 01:19:42 +0000364 }
365
366 void testRelated(B *b) {
367 A *a = (A *)(void *)b;
368 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
Jordan Roseaaf83182012-09-08 01:24:38 +0000369
370 a->x = 42;
371 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
Jordan Rose81456d92012-09-07 01:19:42 +0000372 }
373
374 void testUnrelated(Unrelated *b) {
375 A *a = (A *)(void *)b;
376 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
Jordan Roseaaf83182012-09-08 01:24:38 +0000377
378 a->x = 42;
379 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
380 }
381
382 void testCastViaNew(B *b) {
383 Grandchild *g = new (b) Grandchild();
Jordan Rose34376692013-04-22 21:36:44 +0000384 clang_analyzer_eval(g->foo() == 42); // expected-warning{{TRUE}}
Jordan Roseaaf83182012-09-08 01:24:38 +0000385
386 g->x = 42;
387 clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}}
Jordan Rose81456d92012-09-07 01:19:42 +0000388 }
389}
Jordan Rose12f669e2012-09-11 00:31:02 +0000390
391
392namespace QualifiedCalls {
393 void test(One *object) {
394 // This uses the One class from the top of the file.
395 clang_analyzer_eval(object->getNum() == 1); // expected-warning{{UNKNOWN}}
396 clang_analyzer_eval(object->One::getNum() == 1); // expected-warning{{TRUE}}
397 clang_analyzer_eval(object->A::getNum() == 0); // expected-warning{{TRUE}}
398
399 // getZero is non-virtual.
400 clang_analyzer_eval(object->getZero() == 0); // expected-warning{{TRUE}}
401 clang_analyzer_eval(object->One::getZero() == 0); // expected-warning{{TRUE}}
402 clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}}
403}
404}
Jordan Rose1dd2afd2012-10-03 01:08:35 +0000405
406
407namespace rdar12409977 {
408 struct Base {
409 int x;
410 };
411
412 struct Parent : public Base {
413 virtual Parent *vGetThis();
414 Parent *getThis() { return vGetThis(); }
415 };
416
417 struct Child : public Parent {
418 virtual Child *vGetThis() { return this; }
419 };
420
421 void test() {
422 Child obj;
423 obj.x = 42;
424
425 // Originally, calling a devirtualized method with a covariant return type
426 // caused a crash because the return value had the wrong type. When we then
427 // go to layer a CXXBaseObjectRegion on it, the base isn't a direct base of
428 // the object region and we get an assertion failure.
429 clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}}
430 }
431}
Pavel Labath963f91b2013-06-19 08:19:56 +0000432
433namespace bug16307 {
434 void one_argument(int a) { }
435 void call_with_less() {
436 reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument}}
437 }
438}