brintos

brintos / llvm-project-archived public Read only

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