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