1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -verify %s
2 
3 void clang_analyzer_eval(bool);
4 
5 class A {
6 protected:
7   int x;
8 };
9 
10 class B : public A {
11 public:
12   void f();
13 };
14 
15 void B::f() {
16   x = 3;
17 }
18 
19 
20 class C : public B {
21 public:
22   void g() {
23     // This used to crash because we are upcasting through two bases.
24     x = 5;
25   }
26 };
27 
28 
29 namespace 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 
90 namespace 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 
110 namespace 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