• Home
  • History
  • Annotate
  • 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