• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5
6#include "Inputs/system-header-simulator-cxx.h"
7
8void clang_analyzer_eval(bool);
9void clang_analyzer_checkInlined(bool);
10
11// A simplified version of std::move.
12template <typename T>
13T &&move(T &obj) {
14  return static_cast<T &&>(obj);
15}
16
17
18struct Wrapper {
19  __strong id obj;
20};
21
22void test() {
23  Wrapper w;
24  // force a diagnostic
25  *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
26}
27
28
29struct IntWrapper {
30  int x;
31};
32
33void testCopyConstructor() {
34  IntWrapper a;
35  a.x = 42;
36
37  IntWrapper b(a);
38  clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
39}
40
41struct NonPODIntWrapper {
42  int x;
43
44  virtual int get();
45};
46
47void testNonPODCopyConstructor() {
48  NonPODIntWrapper a;
49  a.x = 42;
50
51  NonPODIntWrapper b(a);
52  clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
53}
54
55
56namespace ConstructorVirtualCalls {
57  class A {
58  public:
59    int *out1, *out2, *out3;
60
61    virtual int get() { return 1; }
62
63    A(int *out1) {
64      *out1 = get();
65    }
66  };
67
68  class B : public A {
69  public:
70    virtual int get() { return 2; }
71
72    B(int *out1, int *out2) : A(out1) {
73      *out2 = get();
74    }
75  };
76
77  class C : public B {
78  public:
79    virtual int get() { return 3; }
80
81    C(int *out1, int *out2, int *out3) : B(out1, out2) {
82      *out3 = get();
83    }
84  };
85
86  void test() {
87    int a, b, c;
88
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}}
93
94    clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
95
96    // Sanity check for devirtualization.
97    A *base = &obj;
98    clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
99  }
100}
101
102namespace TemporaryConstructor {
103  class BoolWrapper {
104  public:
105    BoolWrapper() {
106      clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
107      value = true;
108    }
109    bool value;
110  };
111
112  void test() {
113    // PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined.
114    if (BoolWrapper().value)
115      return;
116  }
117}
118
119
120namespace ConstructorUsedAsRValue {
121  using TemporaryConstructor::BoolWrapper;
122
123  bool extractValue(BoolWrapper b) {
124    return b.value;
125  }
126
127  void test() {
128    bool result = extractValue(BoolWrapper());
129    clang_analyzer_eval(result); // expected-warning{{TRUE}}
130  }
131}
132
133namespace PODUninitialized {
134  class POD {
135  public:
136    int x, y;
137  };
138
139  class PODWrapper {
140  public:
141    POD p;
142  };
143
144  class NonPOD {
145  public:
146    int x, y;
147
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    }
157
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  };
171
172  class NonPODWrapper {
173  public:
174    class Inner {
175    public:
176      int x, y;
177
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      }
187
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    };
201
202    Inner p;
203  };
204
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}}
212
213    // Use rvalues as well.
214    clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
215
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    // FIXME: Element region gets in the way, so these aren't the same symbols
222    // as they should be.
223    clang_analyzer_eval(pp.x == p4.x); // expected-warning{{UNKNOWN}}
224
225    PODWrapper w;
226    w.p.y = 1;
227    PODWrapper w2 = w; // no-warning
228    clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
229    PODWrapper w3 = move(w); // no-warning
230    clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
231
232    // Use rvalues as well.
233    clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
234  }
235
236  void testNonPOD() {
237    NonPOD p;
238    p.x = 1;
239    NonPOD p2 = p;
240  }
241
242  void testNonPODMove() {
243    NonPOD p;
244    p.x = 1;
245    NonPOD p2 = move(p);
246  }
247
248  void testNonPODWrapper() {
249    NonPODWrapper w;
250    w.p.y = 1;
251    NonPODWrapper w2 = w;
252  }
253
254  void testNonPODWrapperMove() {
255    NonPODWrapper w;
256    w.p.y = 1;
257    NonPODWrapper w2 = move(w);
258  }
259
260  // Not strictly about constructors, but trivial assignment operators should
261  // essentially work the same way.
262  namespace AssignmentOperator {
263    void testPOD() {
264      POD p;
265      p.x = 1;
266      POD p2;
267      p2 = p; // no-warning
268      clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
269      POD p3;
270      p3 = move(p); // no-warning
271      clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
272
273      PODWrapper w;
274      w.p.y = 1;
275      PODWrapper w2;
276      w2 = w; // no-warning
277      clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
278      PODWrapper w3;
279      w3 = move(w); // no-warning
280      clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
281    }
282
283    void testReturnValue() {
284      POD p;
285      p.x = 1;
286      POD p2;
287      clang_analyzer_eval(&(p2 = p) == &p2); // expected-warning{{TRUE}}
288
289      PODWrapper w;
290      w.p.y = 1;
291      PODWrapper w2;
292      clang_analyzer_eval(&(w2 = w) == &w2); // expected-warning{{TRUE}}
293    }
294
295    void testNonPOD() {
296      NonPOD p;
297      p.x = 1;
298      NonPOD p2;
299      p2 = p;
300    }
301
302    void testNonPODMove() {
303      NonPOD p;
304      p.x = 1;
305      NonPOD p2;
306      p2 = move(p);
307    }
308
309    void testNonPODWrapper() {
310      NonPODWrapper w;
311      w.p.y = 1;
312      NonPODWrapper w2;
313      w2 = w;
314    }
315
316    void testNonPODWrapperMove() {
317      NonPODWrapper w;
318      w.p.y = 1;
319      NonPODWrapper w2;
320      w2 = move(w);
321    }
322  }
323}
324
325namespace ArrayMembers {
326  struct Primitive {
327    int values[3];
328  };
329
330  void testPrimitive() {
331    Primitive a = { { 1, 2, 3 } };
332
333    clang_analyzer_eval(a.values[0] == 1); // expected-warning{{TRUE}}
334    clang_analyzer_eval(a.values[1] == 2); // expected-warning{{TRUE}}
335    clang_analyzer_eval(a.values[2] == 3); // expected-warning{{TRUE}}
336
337    Primitive b = a;
338
339    clang_analyzer_eval(b.values[0] == 1); // expected-warning{{TRUE}}
340    clang_analyzer_eval(b.values[1] == 2); // expected-warning{{TRUE}}
341    clang_analyzer_eval(b.values[2] == 3); // expected-warning{{TRUE}}
342
343    Primitive c;
344    c = b;
345
346    clang_analyzer_eval(c.values[0] == 1); // expected-warning{{TRUE}}
347    clang_analyzer_eval(c.values[1] == 2); // expected-warning{{TRUE}}
348    clang_analyzer_eval(c.values[2] == 3); // expected-warning{{TRUE}}
349  }
350
351  struct NestedPrimitive {
352    int values[2][3];
353  };
354
355  void testNestedPrimitive() {
356    NestedPrimitive a = { { { 0, 0, 0 }, { 1, 2, 3 } } };
357
358    clang_analyzer_eval(a.values[1][0] == 1); // expected-warning{{TRUE}}
359    clang_analyzer_eval(a.values[1][1] == 2); // expected-warning{{TRUE}}
360    clang_analyzer_eval(a.values[1][2] == 3); // expected-warning{{TRUE}}
361
362    NestedPrimitive b = a;
363
364    clang_analyzer_eval(b.values[1][0] == 1); // expected-warning{{TRUE}}
365    clang_analyzer_eval(b.values[1][1] == 2); // expected-warning{{TRUE}}
366    clang_analyzer_eval(b.values[1][2] == 3); // expected-warning{{TRUE}}
367
368    NestedPrimitive c;
369    c = b;
370
371    clang_analyzer_eval(c.values[1][0] == 1); // expected-warning{{TRUE}}
372    clang_analyzer_eval(c.values[1][1] == 2); // expected-warning{{TRUE}}
373    clang_analyzer_eval(c.values[1][2] == 3); // expected-warning{{TRUE}}
374  }
375
376  struct POD {
377    IntWrapper values[3];
378  };
379
380  void testPOD() {
381    POD a = { { { 1 }, { 2 }, { 3 } } };
382
383    clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
384    clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
385    clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
386
387    POD b = a;
388
389    clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
390    clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
391    clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
392
393    POD c;
394    c = b;
395
396    clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
397    clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
398    clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
399  }
400
401  struct NestedPOD {
402    IntWrapper values[2][3];
403  };
404
405  void testNestedPOD() {
406    NestedPOD a = { { { { 0 }, { 0 }, { 0 } }, { { 1 }, { 2 }, { 3 } } } };
407
408    clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
409    clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
410    clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
411
412    NestedPOD b = a;
413
414    clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{TRUE}}
415    clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{TRUE}}
416    clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{TRUE}}
417
418    NestedPOD c;
419    c = b;
420
421    clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{TRUE}}
422    clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{TRUE}}
423    clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{TRUE}}
424  }
425
426  struct NonPOD {
427    NonPODIntWrapper values[3];
428  };
429
430  void testNonPOD() {
431    NonPOD a;
432    a.values[0].x = 1;
433    a.values[1].x = 2;
434    a.values[2].x = 3;
435
436    clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
437    clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
438    clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
439
440    NonPOD b = a;
441
442    clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}}
443    clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}}
444    clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}}
445
446    NonPOD c;
447    c = b;
448
449    clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}}
450    clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}}
451    clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
452  }
453
454  struct NestedNonPOD {
455    NonPODIntWrapper values[2][3];
456  };
457
458  void testNestedNonPOD() {
459    NestedNonPOD a;
460    a.values[0][0].x = 0;
461    a.values[0][1].x = 0;
462    a.values[0][2].x = 0;
463    a.values[1][0].x = 1;
464    a.values[1][1].x = 2;
465    a.values[1][2].x = 3;
466
467    clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
468    clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
469    clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
470
471    NestedNonPOD b = a;
472
473    clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
474    clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
475    clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
476
477    NestedNonPOD c;
478    c = b;
479
480    clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
481    clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
482    clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
483  }
484
485  struct NonPODDefaulted {
486    NonPODIntWrapper values[3];
487
488    NonPODDefaulted() = default;
489    NonPODDefaulted(const NonPODDefaulted &) = default;
490    NonPODDefaulted &operator=(const NonPODDefaulted &) = default;
491  };
492
493  void testNonPODDefaulted() {
494    NonPODDefaulted a;
495    a.values[0].x = 1;
496    a.values[1].x = 2;
497    a.values[2].x = 3;
498
499    clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
500    clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
501    clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
502
503    NonPODDefaulted b = a;
504
505    clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}}
506    clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}}
507    clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}}
508
509    NonPODDefaulted c;
510    c = b;
511
512    clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}}
513    clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}}
514    clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
515  }
516};
517
518namespace VirtualInheritance {
519  int counter;
520
521  struct base {
522    base() {
523      ++counter;
524    }
525  };
526
527  struct virtual_subclass : public virtual base {
528    virtual_subclass() {}
529  };
530
531  struct double_subclass : public virtual_subclass {
532    double_subclass() {}
533  };
534
535  void test() {
536    counter = 0;
537    double_subclass obj;
538    clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
539  }
540
541  struct double_virtual_subclass : public virtual virtual_subclass {
542    double_virtual_subclass() {}
543  };
544
545  void testVirtual() {
546    counter = 0;
547    double_virtual_subclass obj;
548    clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
549  }
550}
551
552namespace ZeroInitialization {
553  struct raw_pair {
554    int p1;
555    int p2;
556  };
557
558  void testVarDecl() {
559    raw_pair p{};
560    clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
561    clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
562  }
563
564  void testTemporary() {
565    clang_analyzer_eval(raw_pair().p1 == 0); // expected-warning{{TRUE}}
566    clang_analyzer_eval(raw_pair().p2 == 0); // expected-warning{{TRUE}}
567  }
568
569  void testArray() {
570    raw_pair p[2] = {};
571    clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{TRUE}}
572    clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{TRUE}}
573    clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{TRUE}}
574    clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{TRUE}}
575  }
576
577  void testNew() {
578    raw_pair *pp = new raw_pair();
579    clang_analyzer_eval(pp->p1 == 0); // expected-warning{{TRUE}}
580    clang_analyzer_eval(pp->p2 == 0); // expected-warning{{TRUE}}
581  }
582
583  void testArrayNew() {
584    // FIXME: Pending proper implementation of constructors for 'new[]'.
585    raw_pair *p = new raw_pair[2]();
586    clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{UNKNOWN}}
587    clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{UNKNOWN}}
588    clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{UNKNOWN}}
589    clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{UNKNOWN}}
590  }
591
592  struct initializing_pair {
593  public:
594    int x;
595    raw_pair y;
596    initializing_pair() : x(), y() {}
597  };
598
599  void testFieldInitializers() {
600    initializing_pair p;
601    clang_analyzer_eval(p.x == 0); // expected-warning{{TRUE}}
602    clang_analyzer_eval(p.y.p1 == 0); // expected-warning{{TRUE}}
603    clang_analyzer_eval(p.y.p2 == 0); // expected-warning{{TRUE}}
604  }
605
606  struct subclass : public raw_pair {
607    subclass() = default;
608  };
609
610  void testSubclass() {
611    subclass p;
612    clang_analyzer_eval(p.p1 == 0); // expected-warning{{garbage}}
613  }
614
615  struct initializing_subclass : public raw_pair {
616    initializing_subclass() : raw_pair() {}
617  };
618
619  void testInitializingSubclass() {
620    initializing_subclass p;
621    clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
622    clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
623  }
624
625  struct pair_wrapper {
626    pair_wrapper() : p() {}
627    raw_pair p;
628  };
629
630  struct virtual_subclass : public virtual pair_wrapper {
631    virtual_subclass() {}
632  };
633
634  struct double_virtual_subclass : public virtual_subclass {
635    double_virtual_subclass() {
636      // This previously caused a crash because the pair_wrapper subobject was
637      // initialized twice.
638    }
639  };
640
641  class Empty {
642  public:
643    static int glob;
644    Empty(); // No body.
645    Empty(int x); // Body below.
646  };
647
648  class PairContainer : public Empty {
649  public:
650    raw_pair p;
651    int q;
652    PairContainer() : Empty(), p() {
653      // This previously caused a crash because the empty base class looked
654      // like an initialization of 'p'.
655    }
656    PairContainer(int) : Empty(), p() {
657      // Test inlining something else here.
658    }
659    PairContainer(double): Empty(1), p() {
660      clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
661      clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
662
663      clang_analyzer_eval(q == 1); // expected-warning{{TRUE}}
664
665      // This one's indeed UNKNOWN. Definitely not TRUE.
666      clang_analyzer_eval(p.p2 == glob); // expected-warning{{UNKNOWN}}
667    }
668  };
669
670  Empty::Empty(int x) {
671    static_cast<PairContainer *>(this)->p.p1 = x;
672    static_cast<PairContainer *>(this)->q = x;
673    // Our static member will store the old garbage values of fields that aren't
674    // yet initialized. It's not certainly garbage though (i.e. the constructor
675    // could have been called on an initialized piece of memory), so no
676    // uninitialized value warning here, and it should be a symbol, not
677    // undefined value, for later comparison.
678    glob = static_cast<PairContainer *>(this)->p.p2;
679  }
680
681	class Empty2 {
682	public:
683		static int glob_p1, glob_p2;
684		Empty2(); // Body below.
685	};
686
687	class PairDoubleEmptyContainer: public Empty, public Empty2 {
688	public:
689    raw_pair p;
690		PairDoubleEmptyContainer(): Empty(), Empty2(), p() {
691      clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
692      clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
693
694      // This is indeed UNKNOWN.
695      clang_analyzer_eval(p.p1 == glob_p1); // expected-warning{{UNKNOWN}}
696      clang_analyzer_eval(p.p2 == glob_p2); // expected-warning{{UNKNOWN}}
697		}
698	};
699
700	Empty2::Empty2() {
701    glob_p1 = static_cast<PairDoubleEmptyContainer *>(this)->p.p1;
702    glob_p2 = static_cast<PairDoubleEmptyContainer *>(this)->p.p2;
703	}
704
705  class PairContainerContainer {
706    int padding;
707    PairContainer pc;
708  public:
709    PairContainerContainer() : pc(1) {}
710  };
711}
712
713namespace InitializerList {
714  struct List {
715    bool usedInitializerList;
716
717    List() : usedInitializerList(false) {}
718    List(std::initializer_list<int>) : usedInitializerList(true) {}
719  };
720
721  void testStatic() {
722    List defaultCtor;
723    clang_analyzer_eval(!defaultCtor.usedInitializerList); // expected-warning{{TRUE}}
724
725    List list{1, 2};
726    clang_analyzer_eval(list.usedInitializerList); // expected-warning{{TRUE}}
727  }
728
729  void testDynamic() {
730    List *list = new List{1, 2};
731    clang_analyzer_eval(list->usedInitializerList); // expected-warning{{TRUE}}
732  }
733}
734
735namespace PR19579 {
736  class C {};
737
738  void f() {
739    C();
740    int a;
741
742    extern void use(int);
743    use(a); // expected-warning{{uninitialized}}
744  }
745
746  void g() {
747    struct S {
748      C c;
749      int i;
750    };
751
752    // This order triggers the initialization of the inner "a" after the
753    // constructor for "C" is run, which used to confuse the analyzer
754    // (is "C()" the initialization of "a"?).
755    struct S s = {
756      C(),
757      ({
758        int a, b = 0;
759        0;
760      })
761    };
762  }
763}
764
765namespace NoCrashOnEmptyBaseOptimization {
766  struct NonEmptyBase {
767    int X;
768    explicit NonEmptyBase(int X) : X(X) {}
769  };
770
771  struct EmptyBase {};
772
773  struct S : NonEmptyBase, EmptyBase {
774    S() : NonEmptyBase(0), EmptyBase() {}
775  };
776
777  void testSCtorNoCrash() {
778    S s;
779  }
780}
781
782namespace EmptyBaseAssign {
783struct B1 {};
784struct B2 { int x; };
785struct D: public B1, public B2 {
786const D &operator=(const D &d) {
787  *((B2 *)this) = d;
788  *((B1 *)this) = d;
789  return *this;
790}
791};
792
793void test() {
794  D d1;
795  d1.x = 1;
796  D d2;
797  d2 = d1;
798  clang_analyzer_eval(d2.x == 1); // expected-warning{{TRUE}}
799}
800}
801
802namespace vbase_zero_init {
803class A {
804  virtual void foo();
805};
806
807class B {
808  virtual void bar();
809public:
810  static int glob_y, glob_z, glob_w;
811  int x;
812  B(); // Body below.
813};
814
815class C : virtual public A {
816public:
817  int y;
818};
819
820class D : public B, public C {
821public:
822  // 'z', unlike 'w', resides in an area that would have been within padding of
823  // base class 'C' if it wasn't part of 'D', but only on 64-bit systems.
824  int z, w;
825  // Initialization order: A(), B(), C().
826  D() : A(), C() {
827    clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
828    clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
829#ifdef I386
830    clang_analyzer_eval(z == 3); // expected-warning{{TRUE}}
831#else
832    // FIXME: Should be TRUE. Initialized in B().
833    clang_analyzer_eval(z == 3); // expected-warning{{UNKNOWN}}
834#endif
835    clang_analyzer_eval(w == 4); // expected-warning{{TRUE}}
836
837    // FIXME: Should be UNKNOWN. Changed in B() since glob_y was assigned.
838    clang_analyzer_eval(y == glob_y); // expected-warning{{TRUE}}
839
840#ifdef I386
841    clang_analyzer_eval(z == glob_z); // expected-warning{{UNKNOWN}}
842#else
843    // FIXME: Should be UNKNOWN. Changed in B() since glob_z was assigned.
844    clang_analyzer_eval(z == glob_z); // expected-warning{{TRUE}}
845#endif
846
847    clang_analyzer_eval(w == glob_w); // expected-warning{{UNKNOWN}}
848  } // no-crash
849};
850
851B::B() : x(1) {
852  // Our static members will store the old garbage values of fields that aren't
853  // yet initialized. These aren't certainly garbage though (i.e. the
854  // constructor could have been called on an initialized piece of memory),
855  // so no uninitialized value warning here, and these should be symbols, not
856  // undefined values, for later comparison.
857  glob_y = static_cast<D *>(this)->y;
858  glob_z = static_cast<D *>(this)->z;
859  glob_w = static_cast<D *>(this)->w;
860  static_cast<D *>(this)->y = 2;
861  static_cast<D *>(this)->z = 3;
862  static_cast<D *>(this)->w = 4;
863}
864}
865