1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -verify %s
2 
3 void clang_analyzer_eval(bool);
4 void clang_analyzer_checkInlined(bool);
5 
6 typedef __typeof__(sizeof(int)) size_t;
7 extern "C" void *malloc(size_t);
8 
9 // This is the standard placement new.
10 inline void* operator new(size_t, void* __p) throw()
11 {
12   return __p;
13 }
14 
15 
16 class A {
17 public:
18   int getZero() { return 0; }
19   virtual int getNum() { return 0; }
20 };
21 
22 void 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 
32 class One : public A {
33 public:
34   virtual int getNum() { return 1; }
35 };
36 
37 void 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 
57 
58 namespace 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 
84 namespace 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   }
119 
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   }
130 }
131 
132 namespace PR13569_virtual {
133   class Parent {
134   protected:
135     int m_parent;
136     virtual int impl() const = 0;
137 
138     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 }
179 
180 namespace 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 {
195       // We were accidentally not invalidating under inlining
196       // 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 }
206 
207 namespace 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:
219     static const int value = 40 + 2;
220     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}}
228     clang_analyzer_eval(obj.get() == 42); // expected-warning{{TRUE}}
229     clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}}
230   }
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}}
262   }
263 
264   int defaultReference(const int &input = 42) {
265     return -input;
266   }
267   int defaultReferenceZero(const int &input = 0) {
268     return -input;
269   }
270 
271   void testReference() {
272     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}}
292   }
293 
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   }
302 }
303 
304 namespace 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}}
321     delete obj;
322   }
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 }
334 
335 
336 namespace VirtualWithSisterCasts {
337   // 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.
341   struct Parent {
342     virtual int foo();
343     int x;
344   };
345 
346   struct A : Parent {
347     virtual int foo() { return 42; }
348   };
349 
350   struct B : Parent {
351     virtual int foo();
352   };
353 
354   struct Grandchild : public A {};
355 
356   struct Unrelated {};
357 
358   void testDowncast(Parent *b) {
359     A *a = (A *)(void *)b;
360     clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
361 
362     a->x = 42;
363     clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
364   }
365 
366   void testRelated(B *b) {
367     A *a = (A *)(void *)b;
368     clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
369 
370     a->x = 42;
371     clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
372   }
373 
374   void testUnrelated(Unrelated *b) {
375     A *a = (A *)(void *)b;
376     clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
377 
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();
384     clang_analyzer_eval(g->foo() == 42); // expected-warning{{TRUE}}
385 
386     g->x = 42;
387     clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}}
388   }
389 }
390 
391 
392 namespace 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 }
405 
406 
407 namespace 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 }
432 
433 namespace 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 }
439