derived-to-base.cpp revision bfa9ab8183e2fdc74f8633d758cb0c6201314320
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
2
3void clang_analyzer_eval(bool);
4
5class A {
6protected:
7  int x;
8};
9
10class B : public A {
11public:
12  void f();
13};
14
15void B::f() {
16  x = 3;
17}
18
19
20class C : public B {
21public:
22  void g() {
23    // This used to crash because we are upcasting through two bases.
24    x = 5;
25  }
26};
27
28
29namespace VirtualBaseClasses {
30  class A {
31  protected:
32    int x;
33  };
34
35  class B : public virtual A {
36  public:
37    int getX() { return x; }
38  };
39
40  class C : public virtual A {
41  public:
42    void setX() { x = 42; }
43  };
44
45  class D : public B, public C {};
46  class DV : virtual public B, public C {};
47  class DV2 : public B, virtual public C {};
48
49  void test() {
50    D d;
51    d.setX();
52    clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
53
54    DV dv;
55    dv.setX();
56    clang_analyzer_eval(dv.getX() == 42); // expected-warning{{TRUE}}
57
58    DV2 dv2;
59    dv2.setX();
60    clang_analyzer_eval(dv2.getX() == 42); // expected-warning{{TRUE}}
61  }
62
63
64  // Make sure we're consistent about the offset of the A subobject within an
65  // Intermediate virtual base class.
66  class Padding1 { int unused; };
67  class Padding2 { int unused; };
68  class Intermediate : public Padding1, public A, public Padding2 {};
69
70  class BI : public virtual Intermediate {
71  public:
72    int getX() { return x; }
73  };
74
75  class CI : public virtual Intermediate {
76  public:
77    void setX() { x = 42; }
78  };
79
80  class DI : public BI, public CI {};
81
82  void testIntermediate() {
83    DI d;
84    d.setX();
85    clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
86  }
87}
88
89
90namespace DynamicVirtualUpcast {
91  class A {
92  public:
93    virtual ~A();
94  };
95
96  class B : virtual public A {};
97  class C : virtual public B {};
98  class D : virtual public C {};
99
100  bool testCast(A *a) {
101    return dynamic_cast<B*>(a) && dynamic_cast<C*>(a);
102  }
103
104  void test() {
105    D d;
106    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
107  }
108}
109
110namespace DynamicMultipleInheritanceUpcast {
111  class B {
112  public:
113    virtual ~B();
114  };
115  class C {
116  public:
117    virtual ~C();
118  };
119  class D : public B, public C {};
120
121  bool testCast(B *a) {
122    return dynamic_cast<C*>(a);
123  }
124
125  void test() {
126    D d;
127    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
128  }
129
130
131  class DV : virtual public B, virtual public C {};
132
133  void testVirtual() {
134    DV d;
135    clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
136  }
137}
138