blob: 183df16e124d18ffaafea3fe248bb4a0a71f4082 [file] [log] [blame]
Stephen Hines651f13c2014-04-23 16:59:28 -07001// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -analyzer-config c++-allocator-inlining=true -verify %s
Jordan Rosec36b30c2012-07-12 00:16:25 +00002
3void clang_analyzer_eval(bool);
Jordan Rose9584f672012-08-10 22:26:43 +00004void clang_analyzer_checkInlined(bool);
Jordan Rosec36b30c2012-07-12 00:16:25 +00005
Jordan Rose6fe4dfb2012-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{
Stephen Hines651f13c2014-04-23 16:59:28 -070012 clang_analyzer_checkInlined(true);// expected-warning{{TRUE}}
Jordan Rose6fe4dfb2012-08-27 18:39:22 +000013 return __p;
14}
15
16
Jordan Rosec36b30c2012-07-12 00:16:25 +000017class A {
18public:
19 int getZero() { return 0; }
20 virtual int getNum() { return 0; }
21};
22
23void test(A &a) {
24 clang_analyzer_eval(a.getZero() == 0); // expected-warning{{TRUE}}
25 clang_analyzer_eval(a.getNum() == 0); // expected-warning{{UNKNOWN}}
26
27 A copy(a);
28 clang_analyzer_eval(copy.getZero() == 0); // expected-warning{{TRUE}}
29 clang_analyzer_eval(copy.getNum() == 0); // expected-warning{{TRUE}}
30}
31
32
33class One : public A {
34public:
35 virtual int getNum() { return 1; }
36};
37
38void testPathSensitivity(int x) {
39 A a;
40 One b;
41
42 A *ptr;
43 switch (x) {
44 case 0:
45 ptr = &a;
46 break;
47 case 1:
48 ptr = &b;
49 break;
50 default:
51 return;
52 }
53
54 // This should be true on both branches.
55 clang_analyzer_eval(ptr->getNum() == x); // expected-warning {{TRUE}}
56}
57
Jordan Rose9584f672012-08-10 22:26:43 +000058
59namespace PureVirtualParent {
60 class Parent {
61 public:
62 virtual int pureVirtual() const = 0;
63 int callVirtual() const {
64 return pureVirtual();
65 }
66 };
67
68 class Child : public Parent {
69 public:
70 virtual int pureVirtual() const {
71 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
72 return 42;
73 }
74 };
75
76 void testVirtual() {
77 Child x;
78
79 clang_analyzer_eval(x.pureVirtual() == 42); // expected-warning{{TRUE}}
80 clang_analyzer_eval(x.callVirtual() == 42); // expected-warning{{TRUE}}
81 }
82}
83
84
Jordan Roseb6d2bea2012-08-10 22:26:46 +000085namespace PR13569 {
86 class Parent {
87 protected:
88 int m_parent;
89 virtual int impl() const = 0;
90
91 Parent() : m_parent(0) {}
92
93 public:
94 int interface() const {
95 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
96 return impl();
97 }
98 };
99
100 class Child : public Parent {
101 protected:
102 virtual int impl() const {
103 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
104 return m_parent + m_child;
105 }
106
107 public:
108 Child() : m_child(0) {}
109
110 int m_child;
111 };
112
113 void testVirtual() {
114 Child x;
115 x.m_child = 42;
116
117 // Don't crash when inlining and devirtualizing.
118 x.interface();
119 }
Jordan Rose8ec104b2012-08-13 23:46:01 +0000120
121
122 class Grandchild : public Child {};
123
124 void testDevirtualizeToMiddle() {
125 Grandchild x;
126 x.m_child = 42;
127
128 // Don't crash when inlining and devirtualizing.
129 x.interface();
130 }
Jordan Roseb6d2bea2012-08-10 22:26:46 +0000131}
132
Jordan Rose8ec104b2012-08-13 23:46:01 +0000133namespace PR13569_virtual {
134 class Parent {
135 protected:
136 int m_parent;
137 virtual int impl() const = 0;
Jordan Roseb6d2bea2012-08-10 22:26:46 +0000138
Jordan Rose8ec104b2012-08-13 23:46:01 +0000139 Parent() : m_parent(0) {}
140
141 public:
142 int interface() const {
143 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
144 return impl();
145 }
146 };
147
148 class Child : virtual public Parent {
149 protected:
150 virtual int impl() const {
151 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
152 return m_parent + m_child;
153 }
154
155 public:
156 Child() : m_child(0) {}
157
158 int m_child;
159 };
160
161 void testVirtual() {
162 Child x;
163 x.m_child = 42;
164
165 // Don't crash when inlining and devirtualizing.
166 x.interface();
167 }
168
169
170 class Grandchild : virtual public Child {};
171
172 void testDevirtualizeToMiddle() {
173 Grandchild x;
174 x.m_child = 42;
175
176 // Don't crash when inlining and devirtualizing.
177 x.interface();
178 }
179}
Jordan Roseda29ac52012-08-15 21:05:15 +0000180
181namespace Invalidation {
182 struct X {
183 void touch(int &x) const {
184 x = 0;
185 }
186
187 void touch2(int &x) const;
188
189 virtual void touchV(int &x) const {
190 x = 0;
191 }
192
193 virtual void touchV2(int &x) const;
194
195 int test() const {
Anna Zaksbfa9ab82013-01-24 23:15:30 +0000196 // We were accidentally not invalidating under inlining
Jordan Roseda29ac52012-08-15 21:05:15 +0000197 // at one point for virtual methods with visible definitions.
198 int a, b, c, d;
199 touch(a);
200 touch2(b);
201 touchV(c);
202 touchV2(d);
203 return a + b + c + d; // no-warning
204 }
205 };
206}
Jordan Roseb66529d2012-08-23 18:10:53 +0000207
208namespace DefaultArgs {
209 int takesDefaultArgs(int i = 42) {
210 return -i;
211 }
212
213 void testFunction() {
214 clang_analyzer_eval(takesDefaultArgs(1) == -1); // expected-warning{{TRUE}}
215 clang_analyzer_eval(takesDefaultArgs() == -42); // expected-warning{{TRUE}}
216 }
217
218 class Secret {
219 public:
Jordan Rose38f68ef2013-02-13 03:11:06 +0000220 static const int value = 40 + 2;
Jordan Roseb66529d2012-08-23 18:10:53 +0000221 int get(int i = value) {
222 return i;
223 }
224 };
225
226 void testMethod() {
227 Secret obj;
228 clang_analyzer_eval(obj.get(1) == 1); // expected-warning{{TRUE}}
Jordan Rose38f68ef2013-02-13 03:11:06 +0000229 clang_analyzer_eval(obj.get() == 42); // expected-warning{{TRUE}}
Jordan Roseb66529d2012-08-23 18:10:53 +0000230 clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}}
Jordan Rose38f68ef2013-02-13 03:11:06 +0000231 }
232
233 enum ABC {
234 A = 0,
235 B = 1,
236 C = 2
237 };
238
239 int enumUser(ABC input = B) {
240 return static_cast<int>(input);
241 }
242
243 void testEnum() {
244 clang_analyzer_eval(enumUser(C) == 2); // expected-warning{{TRUE}}
245 clang_analyzer_eval(enumUser() == 1); // expected-warning{{TRUE}}
246 }
247
248
249 int exprUser(int input = 2 * 4) {
250 return input;
251 }
252
253 int complicatedExprUser(int input = 2 * Secret::value) {
254 return input;
255 }
256
257 void testExprs() {
258 clang_analyzer_eval(exprUser(1) == 1); // expected-warning{{TRUE}}
259 clang_analyzer_eval(exprUser() == 8); // expected-warning{{TRUE}}
260
261 clang_analyzer_eval(complicatedExprUser(1) == 1); // expected-warning{{TRUE}}
262 clang_analyzer_eval(complicatedExprUser() == 84); // expected-warning{{TRUE}}
Jordan Roseb66529d2012-08-23 18:10:53 +0000263 }
Jordan Rosefbdbed32013-02-25 19:45:34 +0000264
265 int defaultReference(const int &input = 42) {
Jordan Rose4b750852013-05-02 19:51:20 +0000266 return -input;
267 }
268 int defaultReferenceZero(const int &input = 0) {
269 return -input;
Jordan Rosefbdbed32013-02-25 19:45:34 +0000270 }
271
272 void testReference() {
Jordan Rose4b750852013-05-02 19:51:20 +0000273 clang_analyzer_eval(defaultReference(1) == -1); // expected-warning{{TRUE}}
274 clang_analyzer_eval(defaultReference() == -42); // expected-warning{{TRUE}}
275
276 clang_analyzer_eval(defaultReferenceZero(1) == -1); // expected-warning{{TRUE}}
277 clang_analyzer_eval(defaultReferenceZero() == 0); // expected-warning{{TRUE}}
278}
279
280 double defaultFloatReference(const double &i = 42) {
281 return -i;
282 }
283 double defaultFloatReferenceZero(const double &i = 0) {
284 return -i;
285 }
286
287 void testFloatReference() {
288 clang_analyzer_eval(defaultFloatReference(1) == -1); // expected-warning{{UNKNOWN}}
289 clang_analyzer_eval(defaultFloatReference() == -42); // expected-warning{{UNKNOWN}}
290
291 clang_analyzer_eval(defaultFloatReferenceZero(1) == -1); // expected-warning{{UNKNOWN}}
292 clang_analyzer_eval(defaultFloatReferenceZero() == 0); // expected-warning{{UNKNOWN}}
Jordan Rosefbdbed32013-02-25 19:45:34 +0000293 }
Jordan Rosedf707002013-07-17 17:16:38 +0000294
295 char defaultString(const char *s = "abc") {
296 return s[1];
297 }
298
299 void testString() {
300 clang_analyzer_eval(defaultString("xyz") == 'y'); // expected-warning{{TRUE}}
301 clang_analyzer_eval(defaultString() == 'b'); // expected-warning{{TRUE}}
302 }
Jordan Roseb66529d2012-08-23 18:10:53 +0000303}
Jordan Rose6fe4dfb2012-08-27 18:39:22 +0000304
305namespace OperatorNew {
306 class IntWrapper {
307 public:
308 int value;
309
310 IntWrapper(int input) : value(input) {
311 // We don't want this constructor to be inlined unless we can actually
312 // use the proper region for operator new.
313 // See PR12014 and <rdar://problem/12180598>.
314 clang_analyzer_checkInlined(false); // no-warning
315 }
316 };
317
318 void test() {
319 IntWrapper *obj = new IntWrapper(42);
320 // should be TRUE
321 clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
Anton Yartsev2de19ed2013-03-25 01:35:45 +0000322 delete obj;
Jordan Rose6fe4dfb2012-08-27 18:39:22 +0000323 }
324
325 void testPlacement() {
326 IntWrapper *obj = static_cast<IntWrapper *>(malloc(sizeof(IntWrapper)));
327 IntWrapper *alias = new (obj) IntWrapper(42);
328
329 clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}}
330
331 // should be TRUE
332 clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
333 }
334}
Jordan Rose8f0d0fe2012-09-07 01:19:42 +0000335
336
337namespace VirtualWithSisterCasts {
Jordan Rose9874f592012-09-08 01:24:38 +0000338 // This entire set of tests exercises casts from sister classes and
339 // from classes outside the hierarchy, which can very much confuse
340 // code that uses DynamicTypeInfo or needs to construct CXXBaseObjectRegions.
341 // These examples used to cause crashes in +Asserts builds.
Jordan Rose8f0d0fe2012-09-07 01:19:42 +0000342 struct Parent {
343 virtual int foo();
Jordan Rose9874f592012-09-08 01:24:38 +0000344 int x;
Jordan Rose8f0d0fe2012-09-07 01:19:42 +0000345 };
346
347 struct A : Parent {
348 virtual int foo() { return 42; }
349 };
350
351 struct B : Parent {
352 virtual int foo();
353 };
354
Jordan Rose9874f592012-09-08 01:24:38 +0000355 struct Grandchild : public A {};
356
Jordan Rose8f0d0fe2012-09-07 01:19:42 +0000357 struct Unrelated {};
358
359 void testDowncast(Parent *b) {
360 A *a = (A *)(void *)b;
361 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
Jordan Rose9874f592012-09-08 01:24:38 +0000362
363 a->x = 42;
364 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
Jordan Rose8f0d0fe2012-09-07 01:19:42 +0000365 }
366
367 void testRelated(B *b) {
368 A *a = (A *)(void *)b;
369 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
Jordan Rose9874f592012-09-08 01:24:38 +0000370
371 a->x = 42;
372 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
Jordan Rose8f0d0fe2012-09-07 01:19:42 +0000373 }
374
375 void testUnrelated(Unrelated *b) {
376 A *a = (A *)(void *)b;
377 clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
Jordan Rose9874f592012-09-08 01:24:38 +0000378
379 a->x = 42;
380 clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
381 }
382
383 void testCastViaNew(B *b) {
384 Grandchild *g = new (b) Grandchild();
Jordan Rosefbc44442013-04-22 21:36:44 +0000385 clang_analyzer_eval(g->foo() == 42); // expected-warning{{TRUE}}
Jordan Rose9874f592012-09-08 01:24:38 +0000386
387 g->x = 42;
388 clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}}
Jordan Rose8f0d0fe2012-09-07 01:19:42 +0000389 }
390}
Jordan Rose00b4f642012-09-11 00:31:02 +0000391
392
393namespace QualifiedCalls {
394 void test(One *object) {
395 // This uses the One class from the top of the file.
396 clang_analyzer_eval(object->getNum() == 1); // expected-warning{{UNKNOWN}}
397 clang_analyzer_eval(object->One::getNum() == 1); // expected-warning{{TRUE}}
398 clang_analyzer_eval(object->A::getNum() == 0); // expected-warning{{TRUE}}
399
400 // getZero is non-virtual.
401 clang_analyzer_eval(object->getZero() == 0); // expected-warning{{TRUE}}
402 clang_analyzer_eval(object->One::getZero() == 0); // expected-warning{{TRUE}}
403 clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}}
404}
405}
Jordan Rose48314cf2012-10-03 01:08:35 +0000406
407
408namespace rdar12409977 {
409 struct Base {
410 int x;
411 };
412
413 struct Parent : public Base {
414 virtual Parent *vGetThis();
415 Parent *getThis() { return vGetThis(); }
416 };
417
418 struct Child : public Parent {
419 virtual Child *vGetThis() { return this; }
420 };
421
422 void test() {
423 Child obj;
424 obj.x = 42;
425
426 // Originally, calling a devirtualized method with a covariant return type
427 // caused a crash because the return value had the wrong type. When we then
428 // go to layer a CXXBaseObjectRegion on it, the base isn't a direct base of
429 // the object region and we get an assertion failure.
430 clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}}
431 }
432}
Pavel Labath37926da2013-06-19 08:19:56 +0000433
434namespace bug16307 {
435 void one_argument(int a) { }
436 void call_with_less() {
437 reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument}}
438 }
439}