Clang Project

clang_source_code/test/Analysis/inline.cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config ipa=inlining -analyzer-config c++-allocator-inlining=true -verify -analyzer-config eagerly-assume=false %s
2
3void clang_analyzer_eval(bool);
4void clang_analyzer_checkInlined(bool);
5
6typedef __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  clang_analyzer_checkInlined(true);// expected-warning{{TRUE}}
13  return __p;
14}
15
16
17class 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
58
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
85namespace 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  }
120
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  }
131}
132
133namespace PR13569_virtual {
134  class Parent {
135  protected:
136    int m_parent;
137    virtual int impl() const = 0;
138
139    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}
180
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 {
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
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:
220    static const int value = 40 + 2;
221    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}}
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
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}}
263  }
264
265  int defaultReference(const int &input = 42) {
266    return -input;
267  }
268  int defaultReferenceZero(const int &input = 0) {
269    return -input;
270  }
271
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
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}}
293  }
294
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  }
303
304  const void * const void_string = "abc";
305
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
312namespace OperatorNew {
313  class IntWrapper {
314  public:
315    int value;
316
317    IntWrapper(int input) : value(input) {
318      clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
319    }
320  };
321
322  void test() {
323    IntWrapper *obj = new IntWrapper(42);
324    clang_analyzer_eval(obj->value == 42); // expected-warning{{TRUE}}
325    delete obj;
326  }
327
328  void testPlacement() {
329    IntWrapper *obj = static_cast<IntWrapper *>(malloc(sizeof(IntWrapper)));
330    IntWrapper *alias = new (obj) IntWrapper(42);
331
332    clang_analyzer_eval(alias == obj); // expected-warning{{TRUE}}
333
334    clang_analyzer_eval(obj->value == 42); // expected-warning{{TRUE}}
335    // Because malloc() was never free()d:
336    // expected-warning@-2{{Potential leak of memory pointed to by 'alias'}}
337  }
338}
339
340
341namespace VirtualWithSisterCasts {
342  // This entire set of tests exercises casts from sister classes and
343  // from classes outside the hierarchy, which can very much confuse
344  // code that uses DynamicTypeInfo or needs to construct CXXBaseObjectRegions.
345  // These examples used to cause crashes in +Asserts builds.
346  struct Parent {
347    virtual int foo();
348    int x;
349  };
350
351  struct A : Parent {
352    virtual int foo() { return 42; }
353  };
354
355  struct B : Parent {
356    virtual int foo();
357  };
358
359  struct Grandchild : public A {};
360
361  struct Unrelated {};
362
363  void testDowncast(Parent *b) {
364    A *a = (A *)(void *)b;
365    clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
366
367    a->x = 42;
368    clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
369  }
370
371  void testRelated(B *b) {
372    A *a = (A *)(void *)b;
373    clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
374
375    a->x = 42;
376    clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
377  }
378
379  void testUnrelated(Unrelated *b) {
380    A *a = (A *)(void *)b;
381    clang_analyzer_eval(a->foo() == 42); // expected-warning{{UNKNOWN}}
382
383    a->x = 42;
384    clang_analyzer_eval(a->x == 42); // expected-warning{{TRUE}}
385  }
386
387  void testCastViaNew(B *b) {
388    Grandchild *g = new (b) Grandchild();
389    clang_analyzer_eval(g->foo() == 42); // expected-warning{{TRUE}}
390
391    g->x = 42;
392    clang_analyzer_eval(g->x == 42); // expected-warning{{TRUE}}
393  }
394}
395
396
397namespace QualifiedCalls {
398  void test(One *object) {
399    // This uses the One class from the top of the file.
400    clang_analyzer_eval(object->getNum() == 1); // expected-warning{{UNKNOWN}}
401    clang_analyzer_eval(object->One::getNum() == 1); // expected-warning{{TRUE}}
402    clang_analyzer_eval(object->A::getNum() == 0); // expected-warning{{TRUE}}
403
404    // getZero is non-virtual.
405    clang_analyzer_eval(object->getZero() == 0); // expected-warning{{TRUE}}
406    clang_analyzer_eval(object->One::getZero() == 0); // expected-warning{{TRUE}}
407    clang_analyzer_eval(object->A::getZero() == 0); // expected-warning{{TRUE}}
408}
409}
410
411
412namespace rdar12409977  {
413  struct Base {
414    int x;
415  };
416
417  struct Parent : public Base {
418    virtual Parent *vGetThis();
419    Parent *getThis() { return vGetThis(); }
420  };
421
422  struct Child : public Parent {
423    virtual Child *vGetThis() { return this; }
424  };
425
426  void test() {
427    Child obj;
428    obj.x = 42;
429
430    // Originally, calling a devirtualized method with a covariant return type
431    // caused a crash because the return value had the wrong type. When we then
432    // go to layer a CXXBaseObjectRegion on it, the base isn't a direct base of
433    // the object region and we get an assertion failure.
434    clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}}
435  }
436}
437
438namespace bug16307 {
439  void one_argument(int a) { }
440  void call_with_less() {
441    reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument is called with fewer (0)}}
442  }
443}
444