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