• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -analyzer-config c++-allocator-inlining=true -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.
operator new(size_t,void * __p)10 inline void* operator new(size_t, void* __p) throw()
11 {
12   clang_analyzer_checkInlined(true);// expected-warning{{TRUE}}
13   return __p;
14 }
15 
16 
17 class A {
18 public:
getZero()19   int getZero() { return 0; }
getNum()20   virtual int getNum() { return 0; }
21 };
22 
test(A & a)23 void 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 
33 class One : public A {
34 public:
getNum()35   virtual int getNum() { return 1; }
36 };
37 
testPathSensitivity(int x)38 void 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 
58 
59 namespace PureVirtualParent {
60   class Parent {
61   public:
62     virtual int pureVirtual() const = 0;
callVirtual() const63     int callVirtual() const {
64       return pureVirtual();
65     }
66   };
67 
68   class Child : public Parent {
69   public:
pureVirtual() const70     virtual int pureVirtual() const {
71       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
72       return 42;
73     }
74   };
75 
testVirtual()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 
85 namespace PR13569 {
86   class Parent {
87   protected:
88     int m_parent;
89     virtual int impl() const = 0;
90 
Parent()91     Parent() : m_parent(0) {}
92 
93   public:
interface() const94     int interface() const {
95       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
96       return impl();
97     }
98   };
99 
100   class Child : public Parent {
101   protected:
impl() const102     virtual int impl() const {
103       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
104       return m_parent + m_child;
105     }
106 
107   public:
Child()108     Child() : m_child(0) {}
109 
110     int m_child;
111   };
112 
testVirtual()113   void testVirtual() {
114     Child x;
115     x.m_child = 42;
116 
117     // Don't crash when inlining and devirtualizing.
118     x.interface();
119   }
120 
121 
122   class Grandchild : public Child {};
123 
testDevirtualizeToMiddle()124   void testDevirtualizeToMiddle() {
125     Grandchild x;
126     x.m_child = 42;
127 
128     // Don't crash when inlining and devirtualizing.
129     x.interface();
130   }
131 }
132 
133 namespace PR13569_virtual {
134   class Parent {
135   protected:
136     int m_parent;
137     virtual int impl() const = 0;
138 
Parent()139     Parent() : m_parent(0) {}
140 
141   public:
interface() const142     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:
impl() const150     virtual int impl() const {
151       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
152       return m_parent + m_child;
153     }
154 
155   public:
Child()156     Child() : m_child(0) {}
157 
158     int m_child;
159   };
160 
testVirtual()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 
testDevirtualizeToMiddle()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 }
180 
181 namespace Invalidation {
182   struct X {
touchInvalidation::X183     void touch(int &x) const {
184       x = 0;
185     }
186 
187     void touch2(int &x) const;
188 
touchVInvalidation::X189     virtual void touchV(int &x) const {
190       x = 0;
191     }
192 
193     virtual void touchV2(int &x) const;
194 
testInvalidation::X195     int test() const {
196       // We were accidentally not invalidating under inlining
197       // 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 }
207 
208 namespace DefaultArgs {
takesDefaultArgs(int i=42)209   int takesDefaultArgs(int i = 42) {
210     return -i;
211   }
212 
testFunction()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:
220     static const int value = 40 + 2;
get(int i=value)221     int get(int i = value) {
222       return i;
223     }
224   };
225 
testMethod()226   void testMethod() {
227     Secret obj;
228     clang_analyzer_eval(obj.get(1) == 1); // expected-warning{{TRUE}}
229     clang_analyzer_eval(obj.get() == 42); // expected-warning{{TRUE}}
230     clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}}
231   }
232 
233   enum ABC {
234     A = 0,
235     B = 1,
236     C = 2
237   };
238 
enumUser(ABC input=B)239   int enumUser(ABC input = B) {
240     return static_cast<int>(input);
241   }
242 
testEnum()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 
exprUser(int input=2* 4)249   int exprUser(int input = 2 * 4) {
250     return input;
251   }
252 
complicatedExprUser(int input=2* Secret::value)253   int complicatedExprUser(int input = 2 * Secret::value) {
254     return input;
255   }
256 
testExprs()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}}
263   }
264 
defaultReference(const int & input=42)265   int defaultReference(const int &input = 42) {
266     return -input;
267   }
defaultReferenceZero(const int & input=0)268   int defaultReferenceZero(const int &input = 0) {
269     return -input;
270   }
271 
testReference()272   void testReference() {
273     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 
defaultFloatReference(const double & i=42)280   double defaultFloatReference(const double &i = 42) {
281     return -i;
282   }
defaultFloatReferenceZero(const double & i=0)283   double defaultFloatReferenceZero(const double &i = 0) {
284     return -i;
285   }
286 
testFloatReference()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}}
293   }
294 
defaultString(const char * s="abc")295   char defaultString(const char *s = "abc") {
296     return s[1];
297   }
298 
testString()299   void testString() {
300     clang_analyzer_eval(defaultString("xyz") == 'y'); // expected-warning{{TRUE}}
301     clang_analyzer_eval(defaultString() == 'b'); // expected-warning{{TRUE}}
302   }
303 
304   const void * const void_string = "abc";
305 
testBitcastedString()306   void testBitcastedString() {
307     clang_analyzer_eval(0 != void_string); // expected-warning{{TRUE}}
308     clang_analyzer_eval('b' == ((char *)void_string)[1]); // expected-warning{{TRUE}}
309   }
310 }
311 
312 namespace OperatorNew {
313   class IntWrapper {
314   public:
315     int value;
316 
IntWrapper(int input)317     IntWrapper(int input) : value(input) {
318       // We don't want this constructor to be inlined unless we can actually
319       // use the proper region for operator new.
320       // See PR12014 and <rdar://problem/12180598>.
321       clang_analyzer_checkInlined(false); // no-warning
322     }
323   };
324 
test()325   void test() {
326     IntWrapper *obj = new IntWrapper(42);
327     // should be TRUE
328     clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
329     delete obj;
330   }
331 
testPlacement()332   void testPlacement() {
333     IntWrapper *obj = static_cast<IntWrapper *>(malloc(sizeof(IntWrapper)));
334     IntWrapper *alias = new (obj) IntWrapper(42);
335 
336     clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}}
337 
338     // should be TRUE
339     clang_analyzer_eval(obj->value == 42); // expected-warning{{UNKNOWN}}
340   }
341 }
342 
343 
344 namespace VirtualWithSisterCasts {
345   // This entire set of tests exercises casts from sister classes and
346   // from classes outside the hierarchy, which can very much confuse
347   // code that uses DynamicTypeInfo or needs to construct CXXBaseObjectRegions.
348   // These examples used to cause crashes in +Asserts builds.
349   struct Parent {
350     virtual int foo();
351     int x;
352   };
353 
354   struct A : Parent {
fooVirtualWithSisterCasts::A355     virtual int foo() { return 42; }
356   };
357 
358   struct B : Parent {
359     virtual int foo();
360   };
361 
362   struct Grandchild : public A {};
363 
364   struct Unrelated {};
365 
testDowncast(Parent * b)366   void testDowncast(Parent *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 
testRelated(B * b)374   void testRelated(B *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 
testUnrelated(Unrelated * b)382   void testUnrelated(Unrelated *b) {
383     A *a = (A *)(void *)b;
384     clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
385 
386     a->x = 42;
387     clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
388   }
389 
testCastViaNew(B * b)390   void testCastViaNew(B *b) {
391     Grandchild *g = new (b) Grandchild();
392     clang_analyzer_eval(g->foo() == 42); // expected-warning{{TRUE}}
393 
394     g->x = 42;
395     clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}}
396   }
397 }
398 
399 
400 namespace QualifiedCalls {
test(One * object)401   void test(One *object) {
402     // This uses the One class from the top of the file.
403     clang_analyzer_eval(object->getNum() == 1); // expected-warning{{UNKNOWN}}
404     clang_analyzer_eval(object->One::getNum() == 1); // expected-warning{{TRUE}}
405     clang_analyzer_eval(object->A::getNum() == 0); // expected-warning{{TRUE}}
406 
407     // getZero is non-virtual.
408     clang_analyzer_eval(object->getZero() == 0); // expected-warning{{TRUE}}
409     clang_analyzer_eval(object->One::getZero() == 0); // expected-warning{{TRUE}}
410     clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}}
411 }
412 }
413 
414 
415 namespace rdar12409977  {
416   struct Base {
417     int x;
418   };
419 
420   struct Parent : public Base {
421     virtual Parent *vGetThis();
getThisrdar12409977::Parent422     Parent *getThis() { return vGetThis(); }
423   };
424 
425   struct Child : public Parent {
vGetThisrdar12409977::Child426     virtual Child *vGetThis() { return this; }
427   };
428 
test()429   void test() {
430     Child obj;
431     obj.x = 42;
432 
433     // Originally, calling a devirtualized method with a covariant return type
434     // caused a crash because the return value had the wrong type. When we then
435     // go to layer a CXXBaseObjectRegion on it, the base isn't a direct base of
436     // the object region and we get an assertion failure.
437     clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}}
438   }
439 }
440 
441 namespace bug16307 {
one_argument(int a)442   void one_argument(int a) { }
call_with_less()443   void call_with_less() {
444     reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument}}
445   }
446 }
447