1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
2
3#include "Inputs/system-header-simulator-cxx.h"
4
5void clang_analyzer_eval(bool);
6void clang_analyzer_checkInlined(bool);
7
8// A simplified version of std::move.
9template <typename T>
10T &&move(T &obj) {
11  return static_cast<T &&>(obj);
12}
13
14
15struct Wrapper {
16  __strong id obj;
17};
18
19void test() {
20  Wrapper w;
21  // force a diagnostic
22  *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
23}
24
25
26struct IntWrapper {
27  int x;
28};
29
30void testCopyConstructor() {
31  IntWrapper a;
32  a.x = 42;
33
34  IntWrapper b(a);
35  clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
36}
37
38struct NonPODIntWrapper {
39  int x;
40
41  virtual int get();
42};
43
44void testNonPODCopyConstructor() {
45  NonPODIntWrapper a;
46  a.x = 42;
47
48  NonPODIntWrapper b(a);
49  clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
50}
51
52
53namespace ConstructorVirtualCalls {
54  class A {
55  public:
56    int *out1, *out2, *out3;
57
58    virtual int get() { return 1; }
59
60    A(int *out1) {
61      *out1 = get();
62    }
63  };
64
65  class B : public A {
66  public:
67    virtual int get() { return 2; }
68
69    B(int *out1, int *out2) : A(out1) {
70      *out2 = get();
71    }
72  };
73
74  class C : public B {
75  public:
76    virtual int get() { return 3; }
77
78    C(int *out1, int *out2, int *out3) : B(out1, out2) {
79      *out3 = get();
80    }
81  };
82
83  void test() {
84    int a, b, c;
85
86    C obj(&a, &b, &c);
87    clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
88    clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
89    clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
90
91    clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
92
93    // Sanity check for devirtualization.
94    A *base = &obj;
95    clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
96  }
97}
98
99namespace TemporaryConstructor {
100  class BoolWrapper {
101  public:
102    BoolWrapper() {
103      clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
104      value = true;
105    }
106    bool value;
107  };
108
109  void test() {
110    // PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined.
111    if (BoolWrapper().value)
112      return;
113  }
114}
115
116
117namespace ConstructorUsedAsRValue {
118  using TemporaryConstructor::BoolWrapper;
119
120  bool extractValue(BoolWrapper b) {
121    return b.value;
122  }
123
124  void test() {
125    bool result = extractValue(BoolWrapper());
126    clang_analyzer_eval(result); // expected-warning{{TRUE}}
127  }
128}
129
130namespace PODUninitialized {
131  class POD {
132  public:
133    int x, y;
134  };
135
136  class PODWrapper {
137  public:
138    POD p;
139  };
140
141  class NonPOD {
142  public:
143    int x, y;
144
145    NonPOD() {}
146    NonPOD(const NonPOD &Other)
147      : x(Other.x), y(Other.y) // expected-warning {{undefined}}
148    {
149    }
150    NonPOD(NonPOD &&Other)
151    : x(Other.x), y(Other.y) // expected-warning {{undefined}}
152    {
153    }
154
155    NonPOD &operator=(const NonPOD &Other)
156    {
157      x = Other.x;
158      y = Other.y; // expected-warning {{undefined}}
159      return *this;
160    }
161    NonPOD &operator=(NonPOD &&Other)
162    {
163      x = Other.x;
164      y = Other.y; // expected-warning {{undefined}}
165      return *this;
166    }
167  };
168
169  class NonPODWrapper {
170  public:
171    class Inner {
172    public:
173      int x, y;
174
175      Inner() {}
176      Inner(const Inner &Other)
177        : x(Other.x), y(Other.y) // expected-warning {{undefined}}
178      {
179      }
180      Inner(Inner &&Other)
181      : x(Other.x), y(Other.y) // expected-warning {{undefined}}
182      {
183      }
184
185      Inner &operator=(const Inner &Other)
186      {
187        x = Other.x; // expected-warning {{undefined}}
188        y = Other.y;
189        return *this;
190      }
191      Inner &operator=(Inner &&Other)
192      {
193        x = Other.x; // expected-warning {{undefined}}
194        y = Other.y;
195        return *this;
196      }
197    };
198
199    Inner p;
200  };
201
202  void testPOD() {
203    POD p;
204    p.x = 1;
205    POD p2 = p; // no-warning
206    clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
207    POD p3 = move(p); // no-warning
208    clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
209
210    // Use rvalues as well.
211    clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
212
213    PODWrapper w;
214    w.p.y = 1;
215    PODWrapper w2 = w; // no-warning
216    clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
217    PODWrapper w3 = move(w); // no-warning
218    clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
219
220    // Use rvalues as well.
221    clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
222  }
223
224  void testNonPOD() {
225    NonPOD p;
226    p.x = 1;
227    NonPOD p2 = p;
228  }
229
230  void testNonPODMove() {
231    NonPOD p;
232    p.x = 1;
233    NonPOD p2 = move(p);
234  }
235
236  void testNonPODWrapper() {
237    NonPODWrapper w;
238    w.p.y = 1;
239    NonPODWrapper w2 = w;
240  }
241
242  void testNonPODWrapperMove() {
243    NonPODWrapper w;
244    w.p.y = 1;
245    NonPODWrapper w2 = move(w);
246  }
247
248  // Not strictly about constructors, but trivial assignment operators should
249  // essentially work the same way.
250  namespace AssignmentOperator {
251    void testPOD() {
252      POD p;
253      p.x = 1;
254      POD p2;
255      p2 = p; // no-warning
256      clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
257      POD p3;
258      p3 = move(p); // no-warning
259      clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
260
261      PODWrapper w;
262      w.p.y = 1;
263      PODWrapper w2;
264      w2 = w; // no-warning
265      clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
266      PODWrapper w3;
267      w3 = move(w); // no-warning
268      clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
269    }
270
271    void testReturnValue() {
272      POD p;
273      p.x = 1;
274      POD p2;
275      clang_analyzer_eval(&(p2 = p) == &p2); // expected-warning{{TRUE}}
276
277      PODWrapper w;
278      w.p.y = 1;
279      PODWrapper w2;
280      clang_analyzer_eval(&(w2 = w) == &w2); // expected-warning{{TRUE}}
281    }
282
283    void testNonPOD() {
284      NonPOD p;
285      p.x = 1;
286      NonPOD p2;
287      p2 = p;
288    }
289
290    void testNonPODMove() {
291      NonPOD p;
292      p.x = 1;
293      NonPOD p2;
294      p2 = move(p);
295    }
296
297    void testNonPODWrapper() {
298      NonPODWrapper w;
299      w.p.y = 1;
300      NonPODWrapper w2;
301      w2 = w;
302    }
303
304    void testNonPODWrapperMove() {
305      NonPODWrapper w;
306      w.p.y = 1;
307      NonPODWrapper w2;
308      w2 = move(w);
309    }
310  }
311}
312
313namespace ArrayMembers {
314  struct Primitive {
315    int values[3];
316  };
317
318  void testPrimitive() {
319    Primitive a = { { 1, 2, 3 } };
320
321    clang_analyzer_eval(a.values[0] == 1); // expected-warning{{TRUE}}
322    clang_analyzer_eval(a.values[1] == 2); // expected-warning{{TRUE}}
323    clang_analyzer_eval(a.values[2] == 3); // expected-warning{{TRUE}}
324
325    Primitive b = a;
326
327    clang_analyzer_eval(b.values[0] == 1); // expected-warning{{TRUE}}
328    clang_analyzer_eval(b.values[1] == 2); // expected-warning{{TRUE}}
329    clang_analyzer_eval(b.values[2] == 3); // expected-warning{{TRUE}}
330
331    Primitive c;
332    c = b;
333
334    clang_analyzer_eval(c.values[0] == 1); // expected-warning{{TRUE}}
335    clang_analyzer_eval(c.values[1] == 2); // expected-warning{{TRUE}}
336    clang_analyzer_eval(c.values[2] == 3); // expected-warning{{TRUE}}
337  }
338
339  struct NestedPrimitive {
340    int values[2][3];
341  };
342
343  void testNestedPrimitive() {
344    NestedPrimitive a = { { { 0, 0, 0 }, { 1, 2, 3 } } };
345
346    clang_analyzer_eval(a.values[1][0] == 1); // expected-warning{{TRUE}}
347    clang_analyzer_eval(a.values[1][1] == 2); // expected-warning{{TRUE}}
348    clang_analyzer_eval(a.values[1][2] == 3); // expected-warning{{TRUE}}
349
350    NestedPrimitive b = a;
351
352    clang_analyzer_eval(b.values[1][0] == 1); // expected-warning{{TRUE}}
353    clang_analyzer_eval(b.values[1][1] == 2); // expected-warning{{TRUE}}
354    clang_analyzer_eval(b.values[1][2] == 3); // expected-warning{{TRUE}}
355
356    NestedPrimitive c;
357    c = b;
358
359    clang_analyzer_eval(c.values[1][0] == 1); // expected-warning{{TRUE}}
360    clang_analyzer_eval(c.values[1][1] == 2); // expected-warning{{TRUE}}
361    clang_analyzer_eval(c.values[1][2] == 3); // expected-warning{{TRUE}}
362  }
363
364  struct POD {
365    IntWrapper values[3];
366  };
367
368  void testPOD() {
369    POD a = { { { 1 }, { 2 }, { 3 } } };
370
371    clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
372    clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
373    clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
374
375    POD b = a;
376
377    clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
378    clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
379    clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
380
381    POD c;
382    c = b;
383
384    clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
385    clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
386    clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
387  }
388
389  struct NestedPOD {
390    IntWrapper values[2][3];
391  };
392
393  void testNestedPOD() {
394    NestedPOD a = { { { { 0 }, { 0 }, { 0 } }, { { 1 }, { 2 }, { 3 } } } };
395
396    clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
397    clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
398    clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
399
400    NestedPOD b = a;
401
402    clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{TRUE}}
403    clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{TRUE}}
404    clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{TRUE}}
405
406    NestedPOD c;
407    c = b;
408
409    clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{TRUE}}
410    clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{TRUE}}
411    clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{TRUE}}
412  }
413
414  struct NonPOD {
415    NonPODIntWrapper values[3];
416  };
417
418  void testNonPOD() {
419    NonPOD a;
420    a.values[0].x = 1;
421    a.values[1].x = 2;
422    a.values[2].x = 3;
423
424    clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
425    clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
426    clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
427
428    NonPOD b = a;
429
430    clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}}
431    clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}}
432    clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}}
433
434    NonPOD c;
435    c = b;
436
437    clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}}
438    clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}}
439    clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
440  }
441
442  struct NestedNonPOD {
443    NonPODIntWrapper values[2][3];
444  };
445
446  void testNestedNonPOD() {
447    NestedNonPOD a;
448    a.values[0][0].x = 0;
449    a.values[0][1].x = 0;
450    a.values[0][2].x = 0;
451    a.values[1][0].x = 1;
452    a.values[1][1].x = 2;
453    a.values[1][2].x = 3;
454
455    clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
456    clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
457    clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
458
459    NestedNonPOD b = a;
460
461    clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
462    clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
463    clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
464
465    NestedNonPOD c;
466    c = b;
467
468    clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
469    clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
470    clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
471  }
472
473  struct NonPODDefaulted {
474    NonPODIntWrapper values[3];
475
476    NonPODDefaulted() = default;
477    NonPODDefaulted(const NonPODDefaulted &) = default;
478    NonPODDefaulted &operator=(const NonPODDefaulted &) = default;
479  };
480
481  void testNonPODDefaulted() {
482    NonPODDefaulted a;
483    a.values[0].x = 1;
484    a.values[1].x = 2;
485    a.values[2].x = 3;
486
487    clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
488    clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
489    clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
490
491    NonPODDefaulted b = a;
492
493    clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}}
494    clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}}
495    clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}}
496
497    NonPODDefaulted c;
498    c = b;
499
500    clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}}
501    clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}}
502    clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
503  }
504};
505
506namespace VirtualInheritance {
507  int counter;
508
509  struct base {
510    base() {
511      ++counter;
512    }
513  };
514
515  struct virtual_subclass : public virtual base {
516    virtual_subclass() {}
517  };
518
519  struct double_subclass : public virtual_subclass {
520    double_subclass() {}
521  };
522
523  void test() {
524    counter = 0;
525    double_subclass obj;
526    clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
527  }
528
529  struct double_virtual_subclass : public virtual virtual_subclass {
530    double_virtual_subclass() {}
531  };
532
533  void testVirtual() {
534    counter = 0;
535    double_virtual_subclass obj;
536    clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
537  }
538}
539
540namespace ZeroInitialization {
541  struct raw_pair {
542    int p1;
543    int p2;
544  };
545
546  void testVarDecl() {
547    raw_pair p{};
548    clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
549    clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
550  }
551
552  void testTemporary() {
553    clang_analyzer_eval(raw_pair().p1 == 0); // expected-warning{{TRUE}}
554    clang_analyzer_eval(raw_pair().p2 == 0); // expected-warning{{TRUE}}
555  }
556
557  void testArray() {
558    raw_pair p[2] = {};
559    clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{TRUE}}
560    clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{TRUE}}
561    clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{TRUE}}
562    clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{TRUE}}
563  }
564
565  void testNew() {
566    // FIXME: Pending proper implementation of constructors for 'new'.
567    raw_pair *pp = new raw_pair();
568    clang_analyzer_eval(pp->p1 == 0); // expected-warning{{UNKNOWN}}
569    clang_analyzer_eval(pp->p2 == 0); // expected-warning{{UNKNOWN}}
570  }
571
572  void testArrayNew() {
573    // FIXME: Pending proper implementation of constructors for 'new[]'.
574    raw_pair *p = new raw_pair[2]();
575    clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{UNKNOWN}}
576    clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{UNKNOWN}}
577    clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{UNKNOWN}}
578    clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{UNKNOWN}}
579  }
580
581  struct initializing_pair {
582  public:
583    int x;
584    raw_pair y;
585    initializing_pair() : x(), y() {}
586  };
587
588  void testFieldInitializers() {
589    initializing_pair p;
590    clang_analyzer_eval(p.x == 0); // expected-warning{{TRUE}}
591    clang_analyzer_eval(p.y.p1 == 0); // expected-warning{{TRUE}}
592    clang_analyzer_eval(p.y.p2 == 0); // expected-warning{{TRUE}}
593  }
594
595  struct subclass : public raw_pair {
596    subclass() = default;
597  };
598
599  void testSubclass() {
600    subclass p;
601    clang_analyzer_eval(p.p1 == 0); // expected-warning{{garbage}}
602  }
603
604  struct initializing_subclass : public raw_pair {
605    initializing_subclass() : raw_pair() {}
606  };
607
608  void testInitializingSubclass() {
609    initializing_subclass p;
610    clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
611    clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
612  }
613
614  struct pair_wrapper {
615    pair_wrapper() : p() {}
616    raw_pair p;
617  };
618
619  struct virtual_subclass : public virtual pair_wrapper {
620    virtual_subclass() {}
621  };
622
623  struct double_virtual_subclass : public virtual_subclass {
624    double_virtual_subclass() {
625      // This previously caused a crash because the pair_wrapper subobject was
626      // initialized twice.
627    }
628  };
629
630  class Empty {
631  public:
632    Empty();
633  };
634
635  class PairContainer : public Empty {
636    raw_pair p;
637  public:
638    PairContainer() : Empty(), p() {
639      // This previously caused a crash because the empty base class looked
640      // like an initialization of 'p'.
641    }
642    PairContainer(int) : Empty(), p() {
643      // Test inlining something else here.
644    }
645  };
646
647  class PairContainerContainer {
648    int padding;
649    PairContainer pc;
650  public:
651    PairContainerContainer() : pc(1) {}
652  };
653}
654
655namespace InitializerList {
656  struct List {
657    bool usedInitializerList;
658
659    List() : usedInitializerList(false) {}
660    List(std::initializer_list<int>) : usedInitializerList(true) {}
661  };
662
663  void testStatic() {
664    List defaultCtor;
665    clang_analyzer_eval(!defaultCtor.usedInitializerList); // expected-warning{{TRUE}}
666
667    List list{1, 2};
668    clang_analyzer_eval(list.usedInitializerList); // expected-warning{{TRUE}}
669  }
670
671  void testDynamic() {
672    List *list = new List{1, 2};
673    // FIXME: When we handle constructors with 'new', this will be TRUE.
674    clang_analyzer_eval(list->usedInitializerList); // expected-warning{{UNKNOWN}}
675  }
676}
677