Home | History | Annotate | Download | only in Analysis
      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 
      5 void clang_analyzer_eval(bool);
      6 void clang_analyzer_checkInlined(bool);
      7 
      8 // A simplified version of std::move.
      9 template <typename T>
     10 T &&move(T &obj) {
     11   return static_cast<T &&>(obj);
     12 }
     13 
     14 
     15 struct Wrapper {
     16   __strong id obj;
     17 };
     18 
     19 void test() {
     20   Wrapper w;
     21   // force a diagnostic
     22   *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
     23 }
     24 
     25 
     26 struct IntWrapper {
     27   int x;
     28 };
     29 
     30 void 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 
     38 struct NonPODIntWrapper {
     39   int x;
     40 
     41   virtual int get();
     42 };
     43 
     44 void 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 
     53 namespace 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 
     99 namespace 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 
    117 namespace 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 
    130 namespace 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 
    313 namespace 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 
    506 namespace 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 
    540 namespace 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 
    655 namespace 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 
    678 namespace PR19579 {
    679   class C {};
    680 
    681   void f() {
    682     C();
    683     int a;
    684 
    685     extern void use(int);
    686     use(a); // expected-warning{{uninitialized}}
    687   }
    688 
    689   void g() {
    690     struct S {
    691       C c;
    692       int i;
    693     };
    694     
    695     // This order triggers the initialization of the inner "a" after the
    696     // constructor for "C" is run, which used to confuse the analyzer
    697     // (is "C()" the initialization of "a"?).
    698     struct S s = {
    699       C(),
    700       ({
    701         int a, b = 0;
    702         0;
    703       })
    704     };
    705   }
    706 }
    707