xref: /minix3/external/bsd/llvm/dist/clang/test/Analysis/derived-to-base.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
2*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -DCONSTRUCTORS=1 -analyzer-config c++-inlining=constructors -verify %s
3*f4a2713aSLionel Sambuc 
4*f4a2713aSLionel Sambuc void clang_analyzer_eval(bool);
5*f4a2713aSLionel Sambuc void clang_analyzer_checkInlined(bool);
6*f4a2713aSLionel Sambuc 
7*f4a2713aSLionel Sambuc class A {
8*f4a2713aSLionel Sambuc protected:
9*f4a2713aSLionel Sambuc   int x;
10*f4a2713aSLionel Sambuc };
11*f4a2713aSLionel Sambuc 
12*f4a2713aSLionel Sambuc class B : public A {
13*f4a2713aSLionel Sambuc public:
14*f4a2713aSLionel Sambuc   void f();
15*f4a2713aSLionel Sambuc };
16*f4a2713aSLionel Sambuc 
f()17*f4a2713aSLionel Sambuc void B::f() {
18*f4a2713aSLionel Sambuc   x = 3;
19*f4a2713aSLionel Sambuc }
20*f4a2713aSLionel Sambuc 
21*f4a2713aSLionel Sambuc 
22*f4a2713aSLionel Sambuc class C : public B {
23*f4a2713aSLionel Sambuc public:
g()24*f4a2713aSLionel Sambuc   void g() {
25*f4a2713aSLionel Sambuc     // This used to crash because we are upcasting through two bases.
26*f4a2713aSLionel Sambuc     x = 5;
27*f4a2713aSLionel Sambuc   }
28*f4a2713aSLionel Sambuc };
29*f4a2713aSLionel Sambuc 
30*f4a2713aSLionel Sambuc 
31*f4a2713aSLionel Sambuc namespace VirtualBaseClasses {
32*f4a2713aSLionel Sambuc   class A {
33*f4a2713aSLionel Sambuc   protected:
34*f4a2713aSLionel Sambuc     int x;
35*f4a2713aSLionel Sambuc   };
36*f4a2713aSLionel Sambuc 
37*f4a2713aSLionel Sambuc   class B : public virtual A {
38*f4a2713aSLionel Sambuc   public:
getX()39*f4a2713aSLionel Sambuc     int getX() { return x; }
40*f4a2713aSLionel Sambuc   };
41*f4a2713aSLionel Sambuc 
42*f4a2713aSLionel Sambuc   class C : public virtual A {
43*f4a2713aSLionel Sambuc   public:
setX()44*f4a2713aSLionel Sambuc     void setX() { x = 42; }
45*f4a2713aSLionel Sambuc   };
46*f4a2713aSLionel Sambuc 
47*f4a2713aSLionel Sambuc   class D : public B, public C {};
48*f4a2713aSLionel Sambuc   class DV : virtual public B, public C {};
49*f4a2713aSLionel Sambuc   class DV2 : public B, virtual public C {};
50*f4a2713aSLionel Sambuc 
test()51*f4a2713aSLionel Sambuc   void test() {
52*f4a2713aSLionel Sambuc     D d;
53*f4a2713aSLionel Sambuc     d.setX();
54*f4a2713aSLionel Sambuc     clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
55*f4a2713aSLionel Sambuc 
56*f4a2713aSLionel Sambuc     DV dv;
57*f4a2713aSLionel Sambuc     dv.setX();
58*f4a2713aSLionel Sambuc     clang_analyzer_eval(dv.getX() == 42); // expected-warning{{TRUE}}
59*f4a2713aSLionel Sambuc 
60*f4a2713aSLionel Sambuc     DV2 dv2;
61*f4a2713aSLionel Sambuc     dv2.setX();
62*f4a2713aSLionel Sambuc     clang_analyzer_eval(dv2.getX() == 42); // expected-warning{{TRUE}}
63*f4a2713aSLionel Sambuc   }
64*f4a2713aSLionel Sambuc 
65*f4a2713aSLionel Sambuc 
66*f4a2713aSLionel Sambuc   // Make sure we're consistent about the offset of the A subobject within an
67*f4a2713aSLionel Sambuc   // Intermediate virtual base class.
68*f4a2713aSLionel Sambuc   class Padding1 { int unused; };
69*f4a2713aSLionel Sambuc   class Padding2 { int unused; };
70*f4a2713aSLionel Sambuc   class Intermediate : public Padding1, public A, public Padding2 {};
71*f4a2713aSLionel Sambuc 
72*f4a2713aSLionel Sambuc   class BI : public virtual Intermediate {
73*f4a2713aSLionel Sambuc   public:
getX()74*f4a2713aSLionel Sambuc     int getX() { return x; }
75*f4a2713aSLionel Sambuc   };
76*f4a2713aSLionel Sambuc 
77*f4a2713aSLionel Sambuc   class CI : public virtual Intermediate {
78*f4a2713aSLionel Sambuc   public:
setX()79*f4a2713aSLionel Sambuc     void setX() { x = 42; }
80*f4a2713aSLionel Sambuc   };
81*f4a2713aSLionel Sambuc 
82*f4a2713aSLionel Sambuc   class DI : public BI, public CI {};
83*f4a2713aSLionel Sambuc 
testIntermediate()84*f4a2713aSLionel Sambuc   void testIntermediate() {
85*f4a2713aSLionel Sambuc     DI d;
86*f4a2713aSLionel Sambuc     d.setX();
87*f4a2713aSLionel Sambuc     clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
88*f4a2713aSLionel Sambuc   }
89*f4a2713aSLionel Sambuc }
90*f4a2713aSLionel Sambuc 
91*f4a2713aSLionel Sambuc 
92*f4a2713aSLionel Sambuc namespace DynamicVirtualUpcast {
93*f4a2713aSLionel Sambuc   class A {
94*f4a2713aSLionel Sambuc   public:
95*f4a2713aSLionel Sambuc     virtual ~A();
96*f4a2713aSLionel Sambuc   };
97*f4a2713aSLionel Sambuc 
98*f4a2713aSLionel Sambuc   class B : virtual public A {};
99*f4a2713aSLionel Sambuc   class C : virtual public B {};
100*f4a2713aSLionel Sambuc   class D : virtual public C {};
101*f4a2713aSLionel Sambuc 
testCast(A * a)102*f4a2713aSLionel Sambuc   bool testCast(A *a) {
103*f4a2713aSLionel Sambuc     return dynamic_cast<B*>(a) && dynamic_cast<C*>(a);
104*f4a2713aSLionel Sambuc   }
105*f4a2713aSLionel Sambuc 
test()106*f4a2713aSLionel Sambuc   void test() {
107*f4a2713aSLionel Sambuc     D d;
108*f4a2713aSLionel Sambuc     clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
109*f4a2713aSLionel Sambuc   }
110*f4a2713aSLionel Sambuc }
111*f4a2713aSLionel Sambuc 
112*f4a2713aSLionel Sambuc namespace DynamicMultipleInheritanceUpcast {
113*f4a2713aSLionel Sambuc   class B {
114*f4a2713aSLionel Sambuc   public:
115*f4a2713aSLionel Sambuc     virtual ~B();
116*f4a2713aSLionel Sambuc   };
117*f4a2713aSLionel Sambuc   class C {
118*f4a2713aSLionel Sambuc   public:
119*f4a2713aSLionel Sambuc     virtual ~C();
120*f4a2713aSLionel Sambuc   };
121*f4a2713aSLionel Sambuc   class D : public B, public C {};
122*f4a2713aSLionel Sambuc 
testCast(B * a)123*f4a2713aSLionel Sambuc   bool testCast(B *a) {
124*f4a2713aSLionel Sambuc     return dynamic_cast<C*>(a);
125*f4a2713aSLionel Sambuc   }
126*f4a2713aSLionel Sambuc 
test()127*f4a2713aSLionel Sambuc   void test() {
128*f4a2713aSLionel Sambuc     D d;
129*f4a2713aSLionel Sambuc     clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
130*f4a2713aSLionel Sambuc   }
131*f4a2713aSLionel Sambuc 
132*f4a2713aSLionel Sambuc 
133*f4a2713aSLionel Sambuc   class DV : virtual public B, virtual public C {};
134*f4a2713aSLionel Sambuc 
testVirtual()135*f4a2713aSLionel Sambuc   void testVirtual() {
136*f4a2713aSLionel Sambuc     DV d;
137*f4a2713aSLionel Sambuc     clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
138*f4a2713aSLionel Sambuc   }
139*f4a2713aSLionel Sambuc }
140*f4a2713aSLionel Sambuc 
141*f4a2713aSLionel Sambuc namespace LazyBindings {
142*f4a2713aSLionel Sambuc   struct Base {
143*f4a2713aSLionel Sambuc     int x;
144*f4a2713aSLionel Sambuc   };
145*f4a2713aSLionel Sambuc 
146*f4a2713aSLionel Sambuc   struct Derived : public Base {
147*f4a2713aSLionel Sambuc     int y;
148*f4a2713aSLionel Sambuc   };
149*f4a2713aSLionel Sambuc 
150*f4a2713aSLionel Sambuc   struct DoubleDerived : public Derived {
151*f4a2713aSLionel Sambuc     int z;
152*f4a2713aSLionel Sambuc   };
153*f4a2713aSLionel Sambuc 
getX(const Base & obj)154*f4a2713aSLionel Sambuc   int getX(const Base &obj) {
155*f4a2713aSLionel Sambuc     return obj.x;
156*f4a2713aSLionel Sambuc   }
157*f4a2713aSLionel Sambuc 
getY(const Derived & obj)158*f4a2713aSLionel Sambuc   int getY(const Derived &obj) {
159*f4a2713aSLionel Sambuc     return obj.y;
160*f4a2713aSLionel Sambuc   }
161*f4a2713aSLionel Sambuc 
testDerived()162*f4a2713aSLionel Sambuc   void testDerived() {
163*f4a2713aSLionel Sambuc     Derived d;
164*f4a2713aSLionel Sambuc     d.x = 1;
165*f4a2713aSLionel Sambuc     d.y = 2;
166*f4a2713aSLionel Sambuc     clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
167*f4a2713aSLionel Sambuc     clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
168*f4a2713aSLionel Sambuc 
169*f4a2713aSLionel Sambuc     Base b(d);
170*f4a2713aSLionel Sambuc     clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
171*f4a2713aSLionel Sambuc 
172*f4a2713aSLionel Sambuc     Derived d2(d);
173*f4a2713aSLionel Sambuc     clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
174*f4a2713aSLionel Sambuc     clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
175*f4a2713aSLionel Sambuc   }
176*f4a2713aSLionel Sambuc 
testDoubleDerived()177*f4a2713aSLionel Sambuc   void testDoubleDerived() {
178*f4a2713aSLionel Sambuc     DoubleDerived d;
179*f4a2713aSLionel Sambuc     d.x = 1;
180*f4a2713aSLionel Sambuc     d.y = 2;
181*f4a2713aSLionel Sambuc     clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
182*f4a2713aSLionel Sambuc     clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
183*f4a2713aSLionel Sambuc 
184*f4a2713aSLionel Sambuc     Base b(d);
185*f4a2713aSLionel Sambuc     clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
186*f4a2713aSLionel Sambuc 
187*f4a2713aSLionel Sambuc     Derived d2(d);
188*f4a2713aSLionel Sambuc     clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
189*f4a2713aSLionel Sambuc     clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
190*f4a2713aSLionel Sambuc 
191*f4a2713aSLionel Sambuc     DoubleDerived d3(d);
192*f4a2713aSLionel Sambuc     clang_analyzer_eval(getX(d3) == 1); // expected-warning{{TRUE}}
193*f4a2713aSLionel Sambuc     clang_analyzer_eval(getY(d3) == 2); // expected-warning{{TRUE}}
194*f4a2713aSLionel Sambuc   }
195*f4a2713aSLionel Sambuc 
196*f4a2713aSLionel Sambuc   namespace WithOffset {
197*f4a2713aSLionel Sambuc     struct Offset {
198*f4a2713aSLionel Sambuc       int padding;
199*f4a2713aSLionel Sambuc     };
200*f4a2713aSLionel Sambuc 
201*f4a2713aSLionel Sambuc     struct OffsetDerived : private Offset, public Base {
202*f4a2713aSLionel Sambuc       int y;
203*f4a2713aSLionel Sambuc     };
204*f4a2713aSLionel Sambuc 
205*f4a2713aSLionel Sambuc     struct DoubleOffsetDerived : public OffsetDerived {
206*f4a2713aSLionel Sambuc       int z;
207*f4a2713aSLionel Sambuc     };
208*f4a2713aSLionel Sambuc 
getY(const OffsetDerived & obj)209*f4a2713aSLionel Sambuc     int getY(const OffsetDerived &obj) {
210*f4a2713aSLionel Sambuc       return obj.y;
211*f4a2713aSLionel Sambuc     }
212*f4a2713aSLionel Sambuc 
testDerived()213*f4a2713aSLionel Sambuc     void testDerived() {
214*f4a2713aSLionel Sambuc       OffsetDerived d;
215*f4a2713aSLionel Sambuc       d.x = 1;
216*f4a2713aSLionel Sambuc       d.y = 2;
217*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
218*f4a2713aSLionel Sambuc       clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
219*f4a2713aSLionel Sambuc 
220*f4a2713aSLionel Sambuc       Base b(d);
221*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
222*f4a2713aSLionel Sambuc 
223*f4a2713aSLionel Sambuc       OffsetDerived d2(d);
224*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
225*f4a2713aSLionel Sambuc       clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
226*f4a2713aSLionel Sambuc     }
227*f4a2713aSLionel Sambuc 
testDoubleDerived()228*f4a2713aSLionel Sambuc     void testDoubleDerived() {
229*f4a2713aSLionel Sambuc       DoubleOffsetDerived d;
230*f4a2713aSLionel Sambuc       d.x = 1;
231*f4a2713aSLionel Sambuc       d.y = 2;
232*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
233*f4a2713aSLionel Sambuc       clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
234*f4a2713aSLionel Sambuc 
235*f4a2713aSLionel Sambuc       Base b(d);
236*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
237*f4a2713aSLionel Sambuc 
238*f4a2713aSLionel Sambuc       OffsetDerived d2(d);
239*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
240*f4a2713aSLionel Sambuc       clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
241*f4a2713aSLionel Sambuc 
242*f4a2713aSLionel Sambuc       DoubleOffsetDerived d3(d);
243*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(d3) == 1); // expected-warning{{TRUE}}
244*f4a2713aSLionel Sambuc       clang_analyzer_eval(getY(d3) == 2); // expected-warning{{TRUE}}
245*f4a2713aSLionel Sambuc     }
246*f4a2713aSLionel Sambuc   }
247*f4a2713aSLionel Sambuc 
248*f4a2713aSLionel Sambuc   namespace WithVTable {
249*f4a2713aSLionel Sambuc     struct DerivedVTBL : public Base {
250*f4a2713aSLionel Sambuc       int y;
251*f4a2713aSLionel Sambuc       virtual void method();
252*f4a2713aSLionel Sambuc     };
253*f4a2713aSLionel Sambuc 
254*f4a2713aSLionel Sambuc     struct DoubleDerivedVTBL : public DerivedVTBL {
255*f4a2713aSLionel Sambuc       int z;
256*f4a2713aSLionel Sambuc     };
257*f4a2713aSLionel Sambuc 
getY(const DerivedVTBL & obj)258*f4a2713aSLionel Sambuc     int getY(const DerivedVTBL &obj) {
259*f4a2713aSLionel Sambuc       return obj.y;
260*f4a2713aSLionel Sambuc     }
261*f4a2713aSLionel Sambuc 
getZ(const DoubleDerivedVTBL & obj)262*f4a2713aSLionel Sambuc     int getZ(const DoubleDerivedVTBL &obj) {
263*f4a2713aSLionel Sambuc       return obj.z;
264*f4a2713aSLionel Sambuc     }
265*f4a2713aSLionel Sambuc 
testDerived()266*f4a2713aSLionel Sambuc     void testDerived() {
267*f4a2713aSLionel Sambuc       DerivedVTBL d;
268*f4a2713aSLionel Sambuc       d.x = 1;
269*f4a2713aSLionel Sambuc       d.y = 2;
270*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
271*f4a2713aSLionel Sambuc       clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
272*f4a2713aSLionel Sambuc 
273*f4a2713aSLionel Sambuc       Base b(d);
274*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
275*f4a2713aSLionel Sambuc 
276*f4a2713aSLionel Sambuc #if CONSTRUCTORS
277*f4a2713aSLionel Sambuc       DerivedVTBL d2(d);
278*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
279*f4a2713aSLionel Sambuc       clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
280*f4a2713aSLionel Sambuc #endif
281*f4a2713aSLionel Sambuc     }
282*f4a2713aSLionel Sambuc 
283*f4a2713aSLionel Sambuc #if CONSTRUCTORS
testDoubleDerived()284*f4a2713aSLionel Sambuc     void testDoubleDerived() {
285*f4a2713aSLionel Sambuc       DoubleDerivedVTBL d;
286*f4a2713aSLionel Sambuc       d.x = 1;
287*f4a2713aSLionel Sambuc       d.y = 2;
288*f4a2713aSLionel Sambuc       d.z = 3;
289*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
290*f4a2713aSLionel Sambuc       clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
291*f4a2713aSLionel Sambuc       clang_analyzer_eval(getZ(d) == 3); // expected-warning{{TRUE}}
292*f4a2713aSLionel Sambuc 
293*f4a2713aSLionel Sambuc       Base b(d);
294*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
295*f4a2713aSLionel Sambuc 
296*f4a2713aSLionel Sambuc       DerivedVTBL d2(d);
297*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
298*f4a2713aSLionel Sambuc       clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
299*f4a2713aSLionel Sambuc 
300*f4a2713aSLionel Sambuc       DoubleDerivedVTBL d3(d);
301*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(d3) == 1); // expected-warning{{TRUE}}
302*f4a2713aSLionel Sambuc       clang_analyzer_eval(getY(d3) == 2); // expected-warning{{TRUE}}
303*f4a2713aSLionel Sambuc       clang_analyzer_eval(getZ(d3) == 3); // expected-warning{{TRUE}}
304*f4a2713aSLionel Sambuc     }
305*f4a2713aSLionel Sambuc #endif
306*f4a2713aSLionel Sambuc   }
307*f4a2713aSLionel Sambuc 
308*f4a2713aSLionel Sambuc #if CONSTRUCTORS
309*f4a2713aSLionel Sambuc   namespace Nested {
310*f4a2713aSLionel Sambuc     struct NonTrivialCopy {
311*f4a2713aSLionel Sambuc       int padding;
NonTrivialCopyLazyBindings::Nested::NonTrivialCopy312*f4a2713aSLionel Sambuc       NonTrivialCopy() {}
NonTrivialCopyLazyBindings::Nested::NonTrivialCopy313*f4a2713aSLionel Sambuc       NonTrivialCopy(const NonTrivialCopy &) {}
314*f4a2713aSLionel Sambuc     };
315*f4a2713aSLionel Sambuc 
316*f4a2713aSLionel Sambuc     struct FullyDerived : private NonTrivialCopy, public Derived {
317*f4a2713aSLionel Sambuc       int z;
318*f4a2713aSLionel Sambuc     };
319*f4a2713aSLionel Sambuc 
320*f4a2713aSLionel Sambuc     struct Wrapper {
321*f4a2713aSLionel Sambuc       FullyDerived d;
322*f4a2713aSLionel Sambuc       int zz;
323*f4a2713aSLionel Sambuc 
WrapperLazyBindings::Nested::Wrapper324*f4a2713aSLionel Sambuc       Wrapper(const FullyDerived &d) : d(d), zz(0) {}
325*f4a2713aSLionel Sambuc     };
326*f4a2713aSLionel Sambuc 
test5()327*f4a2713aSLionel Sambuc     void test5() {
328*f4a2713aSLionel Sambuc       Wrapper w((FullyDerived()));
329*f4a2713aSLionel Sambuc       w.d.x = 1;
330*f4a2713aSLionel Sambuc 
331*f4a2713aSLionel Sambuc       Wrapper w2(w);
332*f4a2713aSLionel Sambuc       clang_analyzer_eval(getX(w2.d) == 1); // expected-warning{{TRUE}}
333*f4a2713aSLionel Sambuc     }
334*f4a2713aSLionel Sambuc   }
335*f4a2713aSLionel Sambuc #endif
336*f4a2713aSLionel Sambuc }
337*f4a2713aSLionel Sambuc 
338*f4a2713aSLionel Sambuc namespace Redeclaration {
339*f4a2713aSLionel Sambuc   class Base;
340*f4a2713aSLionel Sambuc 
341*f4a2713aSLionel Sambuc   class Base {
342*f4a2713aSLionel Sambuc   public:
343*f4a2713aSLionel Sambuc     virtual int foo();
get()344*f4a2713aSLionel Sambuc     int get() { return value; }
345*f4a2713aSLionel Sambuc 
346*f4a2713aSLionel Sambuc     int value;
347*f4a2713aSLionel Sambuc   };
348*f4a2713aSLionel Sambuc 
349*f4a2713aSLionel Sambuc   class Derived : public Base {
350*f4a2713aSLionel Sambuc   public:
351*f4a2713aSLionel Sambuc     virtual int bar();
352*f4a2713aSLionel Sambuc   };
353*f4a2713aSLionel Sambuc 
test(Derived d)354*f4a2713aSLionel Sambuc   void test(Derived d) {
355*f4a2713aSLionel Sambuc     d.foo(); // don't crash
356*f4a2713aSLionel Sambuc     d.bar(); // sanity check
357*f4a2713aSLionel Sambuc 
358*f4a2713aSLionel Sambuc     Base &b = d;
359*f4a2713aSLionel Sambuc     b.foo(); // don't crash
360*f4a2713aSLionel Sambuc 
361*f4a2713aSLionel Sambuc     d.value = 42; // don't crash
362*f4a2713aSLionel Sambuc     clang_analyzer_eval(d.get() == 42); // expected-warning{{TRUE}}
363*f4a2713aSLionel Sambuc     clang_analyzer_eval(b.get() == 42); // expected-warning{{TRUE}}
364*f4a2713aSLionel Sambuc   }
365*f4a2713aSLionel Sambuc };
366*f4a2713aSLionel Sambuc 
367*f4a2713aSLionel Sambuc namespace PR15394 {
368*f4a2713aSLionel Sambuc   namespace Original {
369*f4a2713aSLionel Sambuc     class Base {
370*f4a2713aSLionel Sambuc     public:
371*f4a2713aSLionel Sambuc       virtual int f() = 0;
372*f4a2713aSLionel Sambuc       int i;
373*f4a2713aSLionel Sambuc     };
374*f4a2713aSLionel Sambuc 
375*f4a2713aSLionel Sambuc     class Derived1 : public Base {
376*f4a2713aSLionel Sambuc     public:
377*f4a2713aSLionel Sambuc       int j;
378*f4a2713aSLionel Sambuc     };
379*f4a2713aSLionel Sambuc 
380*f4a2713aSLionel Sambuc     class Derived2 : public Derived1 {
381*f4a2713aSLionel Sambuc     public:
f()382*f4a2713aSLionel Sambuc       virtual int f() {
383*f4a2713aSLionel Sambuc         clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
384*f4a2713aSLionel Sambuc         return i + j;
385*f4a2713aSLionel Sambuc       }
386*f4a2713aSLionel Sambuc     };
387*f4a2713aSLionel Sambuc 
testXXX()388*f4a2713aSLionel Sambuc     void testXXX() {
389*f4a2713aSLionel Sambuc       Derived1 *d1p = reinterpret_cast<Derived1*>(new Derived2);
390*f4a2713aSLionel Sambuc       d1p->i = 1;
391*f4a2713aSLionel Sambuc       d1p->j = 2;
392*f4a2713aSLionel Sambuc       clang_analyzer_eval(d1p->f() == 3); // expected-warning{{TRUE}}
393*f4a2713aSLionel Sambuc     }
394*f4a2713aSLionel Sambuc   }
395*f4a2713aSLionel Sambuc 
396*f4a2713aSLionel Sambuc   namespace VirtualInDerived {
397*f4a2713aSLionel Sambuc     class Base {
398*f4a2713aSLionel Sambuc     public:
399*f4a2713aSLionel Sambuc       int i;
400*f4a2713aSLionel Sambuc     };
401*f4a2713aSLionel Sambuc 
402*f4a2713aSLionel Sambuc     class Derived1 : public Base {
403*f4a2713aSLionel Sambuc     public:
404*f4a2713aSLionel Sambuc       virtual int f() = 0;
405*f4a2713aSLionel Sambuc       int j;
406*f4a2713aSLionel Sambuc     };
407*f4a2713aSLionel Sambuc 
408*f4a2713aSLionel Sambuc     class Derived2 : public Derived1 {
409*f4a2713aSLionel Sambuc     public:
f()410*f4a2713aSLionel Sambuc       virtual int f() {
411*f4a2713aSLionel Sambuc         clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
412*f4a2713aSLionel Sambuc         return i + j;
413*f4a2713aSLionel Sambuc       }
414*f4a2713aSLionel Sambuc     };
415*f4a2713aSLionel Sambuc 
test()416*f4a2713aSLionel Sambuc     void test() {
417*f4a2713aSLionel Sambuc       Derived1 *d1p = reinterpret_cast<Derived1*>(new Derived2);
418*f4a2713aSLionel Sambuc       d1p->i = 1;
419*f4a2713aSLionel Sambuc       d1p->j = 2;
420*f4a2713aSLionel Sambuc       clang_analyzer_eval(d1p->f() == 3); // expected-warning{{TRUE}}
421*f4a2713aSLionel Sambuc     }
422*f4a2713aSLionel Sambuc   }
423*f4a2713aSLionel Sambuc 
424*f4a2713aSLionel Sambuc   namespace NoCast {
425*f4a2713aSLionel Sambuc     class Base {
426*f4a2713aSLionel Sambuc     public:
427*f4a2713aSLionel Sambuc       int i;
428*f4a2713aSLionel Sambuc     };
429*f4a2713aSLionel Sambuc 
430*f4a2713aSLionel Sambuc     class Derived1 : public Base {
431*f4a2713aSLionel Sambuc     public:
432*f4a2713aSLionel Sambuc       virtual int f() = 0;
433*f4a2713aSLionel Sambuc       int j;
434*f4a2713aSLionel Sambuc     };
435*f4a2713aSLionel Sambuc 
436*f4a2713aSLionel Sambuc     class Derived2 : public Derived1 {
437*f4a2713aSLionel Sambuc     public:
f()438*f4a2713aSLionel Sambuc       virtual int f() {
439*f4a2713aSLionel Sambuc         clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
440*f4a2713aSLionel Sambuc         return i + j;
441*f4a2713aSLionel Sambuc       }
442*f4a2713aSLionel Sambuc     };
443*f4a2713aSLionel Sambuc 
test()444*f4a2713aSLionel Sambuc     void test() {
445*f4a2713aSLionel Sambuc       Derived1 *d1p = new Derived2;
446*f4a2713aSLionel Sambuc       d1p->i = 1;
447*f4a2713aSLionel Sambuc       d1p->j = 2;
448*f4a2713aSLionel Sambuc       clang_analyzer_eval(d1p->f() == 3); // expected-warning{{TRUE}}
449*f4a2713aSLionel Sambuc     }
450*f4a2713aSLionel Sambuc   }
451*f4a2713aSLionel Sambuc };
452*f4a2713aSLionel Sambuc 
453*f4a2713aSLionel Sambuc namespace Bug16309 {
454*f4a2713aSLionel Sambuc   struct Incomplete;
455*f4a2713aSLionel Sambuc 
456*f4a2713aSLionel Sambuc   struct Base { virtual ~Base(); };
457*f4a2713aSLionel Sambuc 
458*f4a2713aSLionel Sambuc   struct Derived : public Base { int x; };
459*f4a2713aSLionel Sambuc 
f(Incomplete * i)460*f4a2713aSLionel Sambuc   void* f(Incomplete *i) {
461*f4a2713aSLionel Sambuc     Base *b = reinterpret_cast<Base *>(i);
462*f4a2713aSLionel Sambuc     // This used to crash because of the reinterpret_cast above.
463*f4a2713aSLionel Sambuc     Derived *d = dynamic_cast<Derived *>(b);
464*f4a2713aSLionel Sambuc     return d;
465*f4a2713aSLionel Sambuc   }
466*f4a2713aSLionel Sambuc 
467*f4a2713aSLionel Sambuc   // And check that reinterpret+dynamic casts work correctly after the fix.
g()468*f4a2713aSLionel Sambuc   void g() {
469*f4a2713aSLionel Sambuc     Derived d;
470*f4a2713aSLionel Sambuc     d.x = 47;
471*f4a2713aSLionel Sambuc     Base *b = &d;
472*f4a2713aSLionel Sambuc     Incomplete *i = reinterpret_cast<Incomplete *>(b);
473*f4a2713aSLionel Sambuc     Base *b2 = reinterpret_cast<Base *>(i);
474*f4a2713aSLionel Sambuc     Derived *d2 = dynamic_cast<Derived *>(b2);
475*f4a2713aSLionel Sambuc     clang_analyzer_eval(d2->x == 47); // expected-warning{{TRUE}}
476*f4a2713aSLionel Sambuc   }
477*f4a2713aSLionel Sambuc }
478