Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / Analysis / ctor.mm
blobfb385833df9c7690aa320c35cf6980924d3e1268
1 // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DI386 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -analyzer-config eagerly-assume=false %s
2 // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -DI386 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -DTEST_INLINABLE_ALLOCATORS -analyzer-config eagerly-assume=false %s
3 // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin12 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -analyzer-config eagerly-assume=false %s
4 // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin12 -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify -DTEST_INLINABLE_ALLOCATORS -analyzer-config eagerly-assume=false %s
6 #include "Inputs/system-header-simulator-cxx.h"
8 void clang_analyzer_eval(bool);
9 void clang_analyzer_checkInlined(bool);
11 // A simplified version of std::move.
12 template <typename T>
13 T &&move(T &obj) {
14   return static_cast<T &&>(obj);
18 struct Wrapper {
19   __strong id obj;
22 void test() {
23   Wrapper w;
24   // force a diagnostic
25   *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
29 struct IntWrapper {
30   int x;
33 void testCopyConstructor() {
34   IntWrapper a;
35   a.x = 42;
37   IntWrapper b(a);
38   clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
41 struct NonPODIntWrapper {
42   int x;
44   virtual int get();
47 void testNonPODCopyConstructor() {
48   NonPODIntWrapper a;
49   a.x = 42;
51   NonPODIntWrapper b(a);
52   clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
56 namespace ConstructorVirtualCalls {
57   class A {
58   public:
59     int *out1, *out2, *out3;
61     virtual int get() { return 1; }
63     A(int *out1) {
64       *out1 = get();
65     }
66   };
68   class B : public A {
69   public:
70     virtual int get() { return 2; }
72     B(int *out1, int *out2) : A(out1) {
73       *out2 = get();
74     }
75   };
77   class C : public B {
78   public:
79     virtual int get() { return 3; }
81     C(int *out1, int *out2, int *out3) : B(out1, out2) {
82       *out3 = get();
83     }
84   };
86   void test() {
87     int a, b, c;
89     C obj(&a, &b, &c);
90     clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
91     clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
92     clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
94     clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
96     // Correctness check for devirtualization.
97     A *base = &obj;
98     clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
99   }
102 namespace TemporaryConstructor {
103   class BoolWrapper {
104   public:
105     BoolWrapper() {
106       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
107       value = true;
108     }
109     bool value;
110   };
112   void test() {
113     // PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined.
114     if (BoolWrapper().value)
115       return;
116   }
120 namespace ConstructorUsedAsRValue {
121   using TemporaryConstructor::BoolWrapper;
123   bool extractValue(BoolWrapper b) {
124     return b.value;
125   }
127   void test() {
128     bool result = extractValue(BoolWrapper());
129     clang_analyzer_eval(result); // expected-warning{{TRUE}}
130   }
133 namespace PODUninitialized {
134   class POD {
135   public:
136     int x, y;
137   };
139   class PODWrapper {
140   public:
141     POD p;
142   };
144   class NonPOD {
145   public:
146     int x, y;
148     NonPOD() {}
149     NonPOD(const NonPOD &Other)
150       : x(Other.x), y(Other.y) // expected-warning {{undefined}}
151     {
152     }
153     NonPOD(NonPOD &&Other)
154     : x(Other.x), y(Other.y) // expected-warning {{undefined}}
155     {
156     }
158     NonPOD &operator=(const NonPOD &Other)
159     {
160       x = Other.x;
161       y = Other.y; // expected-warning {{undefined}}
162       return *this;
163     }
164     NonPOD &operator=(NonPOD &&Other)
165     {
166       x = Other.x;
167       y = Other.y; // expected-warning {{undefined}}
168       return *this;
169     }
170   };
172   class NonPODWrapper {
173   public:
174     class Inner {
175     public:
176       int x, y;
178       Inner() {}
179       Inner(const Inner &Other)
180         : x(Other.x), y(Other.y) // expected-warning {{undefined}}
181       {
182       }
183       Inner(Inner &&Other)
184       : x(Other.x), y(Other.y) // expected-warning {{undefined}}
185       {
186       }
188       Inner &operator=(const Inner &Other)
189       {
190         x = Other.x; // expected-warning {{undefined}}
191         y = Other.y;
192         return *this;
193       }
194       Inner &operator=(Inner &&Other)
195       {
196         x = Other.x; // expected-warning {{undefined}}
197         y = Other.y;
198         return *this;
199       }
200     };
202     Inner p;
203   };
205   void testPOD(const POD &pp) {
206     POD p;
207     p.x = 1;
208     POD p2 = p; // no-warning
209     clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
210     POD p3 = move(p); // no-warning
211     clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
213     // Use rvalues as well.
214     clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
216     // Copy from symbolic references correctly.
217     POD p4 = pp;
218     // Make sure that p4.x contains a symbol after copy.
219     if (p4.x > 0)
220       clang_analyzer_eval(p4.x > 0); // expected-warning{{TRUE}}
221     clang_analyzer_eval(pp.x == p4.x); // expected-warning{{TRUE}}
223     PODWrapper w;
224     w.p.y = 1;
225     PODWrapper w2 = w; // no-warning
226     clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
227     PODWrapper w3 = move(w); // no-warning
228     clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
230     // Use rvalues as well.
231     clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
232   }
234   void testNonPOD() {
235     NonPOD p;
236     p.x = 1;
237     NonPOD p2 = p;
238   }
240   void testNonPODMove() {
241     NonPOD p;
242     p.x = 1;
243     NonPOD p2 = move(p);
244   }
246   void testNonPODWrapper() {
247     NonPODWrapper w;
248     w.p.y = 1;
249     NonPODWrapper w2 = w;
250   }
252   void testNonPODWrapperMove() {
253     NonPODWrapper w;
254     w.p.y = 1;
255     NonPODWrapper w2 = move(w);
256   }
258   // Not strictly about constructors, but trivial assignment operators should
259   // essentially work the same way.
260   namespace AssignmentOperator {
261     void testPOD() {
262       POD p;
263       p.x = 1;
264       POD p2;
265       p2 = p; // no-warning
266       clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
267       POD p3;
268       p3 = move(p); // no-warning
269       clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
271       PODWrapper w;
272       w.p.y = 1;
273       PODWrapper w2;
274       w2 = w; // no-warning
275       clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
276       PODWrapper w3;
277       w3 = move(w); // no-warning
278       clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
279     }
281     void testReturnValue() {
282       POD p;
283       p.x = 1;
284       POD p2;
285       clang_analyzer_eval(&(p2 = p) == &p2); // expected-warning{{TRUE}}
287       PODWrapper w;
288       w.p.y = 1;
289       PODWrapper w2;
290       clang_analyzer_eval(&(w2 = w) == &w2); // expected-warning{{TRUE}}
291     }
293     void testNonPOD() {
294       NonPOD p;
295       p.x = 1;
296       NonPOD p2;
297       p2 = p;
298     }
300     void testNonPODMove() {
301       NonPOD p;
302       p.x = 1;
303       NonPOD p2;
304       p2 = move(p);
305     }
307     void testNonPODWrapper() {
308       NonPODWrapper w;
309       w.p.y = 1;
310       NonPODWrapper w2;
311       w2 = w;
312     }
314     void testNonPODWrapperMove() {
315       NonPODWrapper w;
316       w.p.y = 1;
317       NonPODWrapper w2;
318       w2 = move(w);
319     }
320   }
323 namespace ArrayMembers {
324   struct Primitive {
325     int values[3];
326   };
328   void testPrimitive() {
329     Primitive a = { { 1, 2, 3 } };
331     clang_analyzer_eval(a.values[0] == 1); // expected-warning{{TRUE}}
332     clang_analyzer_eval(a.values[1] == 2); // expected-warning{{TRUE}}
333     clang_analyzer_eval(a.values[2] == 3); // expected-warning{{TRUE}}
335     Primitive b = a;
337     clang_analyzer_eval(b.values[0] == 1); // expected-warning{{TRUE}}
338     clang_analyzer_eval(b.values[1] == 2); // expected-warning{{TRUE}}
339     clang_analyzer_eval(b.values[2] == 3); // expected-warning{{TRUE}}
341     Primitive c;
342     c = b;
344     clang_analyzer_eval(c.values[0] == 1); // expected-warning{{TRUE}}
345     clang_analyzer_eval(c.values[1] == 2); // expected-warning{{TRUE}}
346     clang_analyzer_eval(c.values[2] == 3); // expected-warning{{TRUE}}
347   }
349   struct NestedPrimitive {
350     int values[2][3];
351   };
353   void testNestedPrimitive() {
354     NestedPrimitive a = { { { 0, 0, 0 }, { 1, 2, 3 } } };
356     clang_analyzer_eval(a.values[1][0] == 1); // expected-warning{{TRUE}}
357     clang_analyzer_eval(a.values[1][1] == 2); // expected-warning{{TRUE}}
358     clang_analyzer_eval(a.values[1][2] == 3); // expected-warning{{TRUE}}
360     NestedPrimitive b = a;
362     clang_analyzer_eval(b.values[1][0] == 1); // expected-warning{{TRUE}}
363     clang_analyzer_eval(b.values[1][1] == 2); // expected-warning{{TRUE}}
364     clang_analyzer_eval(b.values[1][2] == 3); // expected-warning{{TRUE}}
366     NestedPrimitive c;
367     c = b;
369     clang_analyzer_eval(c.values[1][0] == 1); // expected-warning{{TRUE}}
370     clang_analyzer_eval(c.values[1][1] == 2); // expected-warning{{TRUE}}
371     clang_analyzer_eval(c.values[1][2] == 3); // expected-warning{{TRUE}}
372   }
374   struct POD {
375     IntWrapper values[3];
376   };
378   void testPOD() {
379     POD a = { { { 1 }, { 2 }, { 3 } } };
381     clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
382     clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
383     clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
385     POD b = a;
387     clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
388     clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
389     clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
391     POD c;
392     c = b;
394     clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
395     clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
396     clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
397   }
399   struct NestedPOD {
400     IntWrapper values[2][3];
401   };
403   void testNestedPOD() {
404     NestedPOD a = { { { { 0 }, { 0 }, { 0 } }, { { 1 }, { 2 }, { 3 } } } };
406     clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
407     clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
408     clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
410     NestedPOD b = a;
412     clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{TRUE}}
413     clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{TRUE}}
414     clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{TRUE}}
416     NestedPOD c;
417     c = b;
419     clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{TRUE}}
420     clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{TRUE}}
421     clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{TRUE}}
422   }
424   struct NonPOD {
425     NonPODIntWrapper values[3];
426   };
428   void testNonPOD() {
429     NonPOD a;
430     a.values[0].x = 1;
431     a.values[1].x = 2;
432     a.values[2].x = 3;
434     clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
435     clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
436     clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
438     NonPOD b = a;
440     clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
441     clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
442     clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
444     NonPOD c;
445     c = b;
447     clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
448     clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
449     clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
450   }
452   struct NestedNonPOD {
453     NonPODIntWrapper values[2][3];
454   };
456   void testNestedNonPOD() {
457     NestedNonPOD a;
458     a.values[0][0].x = 0;
459     a.values[0][1].x = 0;
460     a.values[0][2].x = 0;
461     a.values[1][0].x = 1;
462     a.values[1][1].x = 2;
463     a.values[1][2].x = 3;
465     clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
466     clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
467     clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
469     NestedNonPOD b = a;
471     clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
472     clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
473     clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
475     NestedNonPOD c;
476     c = b;
478     clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
479     clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
480     clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
481   }
482   
483   struct NonPODDefaulted {
484     NonPODIntWrapper values[3];
486     NonPODDefaulted() = default;
487     NonPODDefaulted(const NonPODDefaulted &) = default;
488     NonPODDefaulted &operator=(const NonPODDefaulted &) = default;
489   };
491   void testNonPODDefaulted() {
492     NonPODDefaulted a;
493     a.values[0].x = 1;
494     a.values[1].x = 2;
495     a.values[2].x = 3;
497     clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
498     clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
499     clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
501     NonPODDefaulted b = a;
503     clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
504     clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
505     clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
507     NonPODDefaulted c;
508     c = b;
510     clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
511     clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
512     clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
513   }
516 namespace VirtualInheritance {
517   int counter;
519   struct base {
520     base() {
521       ++counter;
522     }
523   };
525   struct virtual_subclass : public virtual base {
526     virtual_subclass() {}
527   };
529   struct double_subclass : public virtual_subclass {
530     double_subclass() {}
531   };
533   void test() {
534     counter = 0;
535     double_subclass obj;
536     clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
537   }
539   struct double_virtual_subclass : public virtual virtual_subclass {
540     double_virtual_subclass() {}
541   };
543   void testVirtual() {
544     counter = 0;
545     double_virtual_subclass obj;
546     clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
547   }
550 namespace ZeroInitialization {
551   struct raw_pair {
552     int p1;
553     int p2;
554   };
556   void testVarDecl() {
557     raw_pair p{};
558     clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
559     clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
560   }
562   void testTemporary() {
563     clang_analyzer_eval(raw_pair().p1 == 0); // expected-warning{{TRUE}}
564     clang_analyzer_eval(raw_pair().p2 == 0); // expected-warning{{TRUE}}
565   }
567   void testArray() {
568     raw_pair p[2] = {};
569     clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{TRUE}}
570     clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{TRUE}}
571     clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{TRUE}}
572     clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{TRUE}}
573   }
575   void testNew() {
576     raw_pair *pp = new raw_pair();
577     clang_analyzer_eval(pp->p1 == 0); // expected-warning{{TRUE}}
578     clang_analyzer_eval(pp->p2 == 0); // expected-warning{{TRUE}}
579   }
581   void testArrayNew() {
582     raw_pair *p = new raw_pair[2]();
583     clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{TRUE}}
584     clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{TRUE}}
585     clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{TRUE}}
586     clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{TRUE}}
587   }
589   struct initializing_pair {
590   public:
591     int x;
592     raw_pair y;
593     initializing_pair() : x(), y() {}
594   };
595   
596   void testFieldInitializers() {
597     initializing_pair p;
598     clang_analyzer_eval(p.x == 0); // expected-warning{{TRUE}}
599     clang_analyzer_eval(p.y.p1 == 0); // expected-warning{{TRUE}}
600     clang_analyzer_eval(p.y.p2 == 0); // expected-warning{{TRUE}}
601   }
603   struct subclass : public raw_pair {
604     subclass() = default;
605   };
607   void testSubclass() {
608     subclass p;
609     clang_analyzer_eval(p.p1 == 0); // expected-warning{{garbage}}
610   }
612   struct initializing_subclass : public raw_pair {
613     initializing_subclass() : raw_pair() {}
614   };
616   void testInitializingSubclass() {
617     initializing_subclass p;
618     clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
619     clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
620   }
622   struct pair_wrapper {
623     pair_wrapper() : p() {}
624     raw_pair p;
625   };
627   struct virtual_subclass : public virtual pair_wrapper {
628     virtual_subclass() {}
629   };
631   struct double_virtual_subclass : public virtual_subclass {
632     double_virtual_subclass() {
633       // This previously caused a crash because the pair_wrapper subobject was
634       // initialized twice.
635     }
636   };
638   class Empty {
639   public:
640     static int glob;
641     Empty(); // No body.
642     Empty(int x); // Body below.
643   };
645   class PairContainer : public Empty {
646   public:
647     raw_pair p;
648     int q;
649     PairContainer() : Empty(), p() {
650       // This previously caused a crash because the empty base class looked
651       // like an initialization of 'p'.
652     }
653     PairContainer(int) : Empty(), p() {
654       // Test inlining something else here.
655     }
656     PairContainer(double): Empty(1), p() {
657       clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
658       clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
660       clang_analyzer_eval(q == 1); // expected-warning{{TRUE}}
662       // This one's indeed UNKNOWN. Definitely not TRUE.
663       clang_analyzer_eval(p.p2 == glob); // expected-warning{{UNKNOWN}}
664     }
665   };
667   Empty::Empty(int x) {
668     static_cast<PairContainer *>(this)->p.p1 = x;
669     static_cast<PairContainer *>(this)->q = x;
670     // Our static member will store the old garbage values of fields that aren't
671     // yet initialized. It's not certainly garbage though (i.e. the constructor
672     // could have been called on an initialized piece of memory), so no
673     // uninitialized value warning here, and it should be a symbol, not
674     // undefined value, for later comparison.
675     glob = static_cast<PairContainer *>(this)->p.p2;
676   }
678         class Empty2 {
679         public:
680                 static int glob_p1, glob_p2;
681                 Empty2(); // Body below.
682         };
684         class PairDoubleEmptyContainer: public Empty, public Empty2 {
685         public:
686     raw_pair p;
687                 PairDoubleEmptyContainer(): Empty(), Empty2(), p() {
688       clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
689       clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
691       // This is indeed UNKNOWN.
692       clang_analyzer_eval(p.p1 == glob_p1); // expected-warning{{UNKNOWN}}
693       clang_analyzer_eval(p.p2 == glob_p2); // expected-warning{{UNKNOWN}}
694                 }
695         };
697         Empty2::Empty2() {
698     glob_p1 = static_cast<PairDoubleEmptyContainer *>(this)->p.p1;
699     glob_p2 = static_cast<PairDoubleEmptyContainer *>(this)->p.p2;
700         }
702   class PairContainerContainer {
703     int padding;
704     PairContainer pc;
705   public:
706     PairContainerContainer() : pc(1) {}
707   };
710 namespace InitializerList {
711   struct List {
712     bool usedInitializerList;
714     List() : usedInitializerList(false) {}
715     List(std::initializer_list<int>) : usedInitializerList(true) {}
716   };
718   void testStatic() {
719     List defaultCtor;
720     clang_analyzer_eval(!defaultCtor.usedInitializerList); // expected-warning{{TRUE}}
722     List list{1, 2};
723     clang_analyzer_eval(list.usedInitializerList); // expected-warning{{TRUE}}
724   }
726   void testDynamic() {
727     List *list = new List{1, 2};
728     clang_analyzer_eval(list->usedInitializerList); // expected-warning{{TRUE}}
729   }
732 namespace PR19579 {
733   class C {};
735   void f() {
736     C();
737     int a;
739     extern void use(int);
740     use(a); // expected-warning{{uninitialized}}
741   }
743   void g() {
744     struct S {
745       C c;
746       int i;
747     };
748     
749     // This order triggers the initialization of the inner "a" after the
750     // constructor for "C" is run, which used to confuse the analyzer
751     // (is "C()" the initialization of "a"?).
752     struct S s = {
753       C(),
754       ({
755         int a, b = 0;
756         0;
757       })
758     };
759   }
762 namespace NoCrashOnEmptyBaseOptimization {
763   struct NonEmptyBase {
764     int X;
765     explicit NonEmptyBase(int X) : X(X) {}
766   };
768   struct EmptyBase {};
770   struct S : NonEmptyBase, EmptyBase {
771     S() : NonEmptyBase(0), EmptyBase() {}
772   };
774   void testSCtorNoCrash() {
775     S s;
776   }
779 namespace EmptyBaseAssign {
780 struct B1 {};
781 struct B2 { int x; };
782 struct D: public B1, public B2 {
783 const D &operator=(const D &d) {
784   *((B2 *)this) = d;
785   *((B1 *)this) = d;
786   return *this;
790 void test() {
791   D d1;
792   d1.x = 1;
793   D d2;
794   d2 = d1;
795   clang_analyzer_eval(d2.x == 1); // expected-warning{{TRUE}}
799 namespace vbase_zero_init {
800 class A {
801   virtual void foo();
804 class B {
805   virtual void bar();
806 public:
807   static int glob_y, glob_z, glob_w;
808   int x;
809   B(); // Body below.
812 class C : virtual public A {
813 public:
814   int y;
817 class D : public B, public C {
818 public:
819   // 'z', unlike 'w', resides in an area that would have been within padding of
820   // base class 'C' if it wasn't part of 'D', but only on 64-bit systems.
821   int z, w;
822   // Initialization order: A(), B(), C().
823   D() : A(), C() {
824     clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
825     clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
826 #ifdef I386
827     clang_analyzer_eval(z == 3); // expected-warning{{TRUE}}
828 #else
829     // FIXME: Should be TRUE. Initialized in B().
830     clang_analyzer_eval(z == 3); // expected-warning{{UNKNOWN}}
831 #endif
832     clang_analyzer_eval(w == 4); // expected-warning{{TRUE}}
834     // FIXME: Should be UNKNOWN. Changed in B() since glob_y was assigned.
835     clang_analyzer_eval(y == glob_y); // expected-warning{{TRUE}}
837 #ifdef I386
838     clang_analyzer_eval(z == glob_z); // expected-warning{{UNKNOWN}}
839 #else
840     // FIXME: Should be UNKNOWN. Changed in B() since glob_z was assigned.
841     clang_analyzer_eval(z == glob_z); // expected-warning{{TRUE}}
842 #endif
844     clang_analyzer_eval(w == glob_w); // expected-warning{{UNKNOWN}}
845   } // no-crash
848 B::B() : x(1) {
849   // Our static members will store the old garbage values of fields that aren't
850   // yet initialized. These aren't certainly garbage though (i.e. the
851   // constructor could have been called on an initialized piece of memory),
852   // so no uninitialized value warning here, and these should be symbols, not
853   // undefined values, for later comparison.
854   glob_y = static_cast<D *>(this)->y;
855   glob_z = static_cast<D *>(this)->z;
856   glob_w = static_cast<D *>(this)->w;
857   static_cast<D *>(this)->y = 2;
858   static_cast<D *>(this)->z = 3;
859   static_cast<D *>(this)->w = 4;