blob: b846d2c28bb280b445f59a2bdae9c8530f68bc28 [file] [log] [blame]
Anna Zaksbfa9ab82013-01-24 23:15:30 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
Jordan Rose65f991c2013-02-19 20:28:33 +00002// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -DCONSTRUCTORS=1 -analyzer-config c++-inlining=constructors -verify %s
Jordan Roseb11a3ad2012-08-13 22:11:34 +00003
4void clang_analyzer_eval(bool);
Zhongxing Xu4fd56812010-11-26 08:21:53 +00005
6class A {
7protected:
8 int x;
9};
10
11class B : public A {
12public:
13 void f();
14};
15
16void B::f() {
17 x = 3;
18}
Jordan Rose2c5f8d72012-08-09 21:24:02 +000019
20
21class C : public B {
22public:
23 void g() {
24 // This used to crash because we are upcasting through two bases.
25 x = 5;
26 }
27};
Jordan Roseb11a3ad2012-08-13 22:11:34 +000028
29
30namespace VirtualBaseClasses {
31 class A {
32 protected:
33 int x;
34 };
35
36 class B : public virtual A {
37 public:
38 int getX() { return x; }
39 };
40
41 class C : public virtual A {
42 public:
43 void setX() { x = 42; }
44 };
45
46 class D : public B, public C {};
47 class DV : virtual public B, public C {};
48 class DV2 : public B, virtual public C {};
49
50 void test() {
51 D d;
52 d.setX();
53 clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
54
55 DV dv;
56 dv.setX();
57 clang_analyzer_eval(dv.getX() == 42); // expected-warning{{TRUE}}
58
59 DV2 dv2;
60 dv2.setX();
61 clang_analyzer_eval(dv2.getX() == 42); // expected-warning{{TRUE}}
62 }
63
64
65 // Make sure we're consistent about the offset of the A subobject within an
66 // Intermediate virtual base class.
67 class Padding1 { int unused; };
68 class Padding2 { int unused; };
69 class Intermediate : public Padding1, public A, public Padding2 {};
70
71 class BI : public virtual Intermediate {
72 public:
73 int getX() { return x; }
74 };
75
76 class CI : public virtual Intermediate {
77 public:
78 void setX() { x = 42; }
79 };
80
81 class DI : public BI, public CI {};
82
83 void testIntermediate() {
84 DI d;
85 d.setX();
86 clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
87 }
88}
Jordan Rose0a562982012-08-13 22:11:42 +000089
90
91namespace DynamicVirtualUpcast {
92 class A {
93 public:
94 virtual ~A();
95 };
96
97 class B : virtual public A {};
98 class C : virtual public B {};
99 class D : virtual public C {};
100
101 bool testCast(A *a) {
102 return dynamic_cast<B*>(a) && dynamic_cast<C*>(a);
103 }
104
105 void test() {
106 D d;
107 clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
108 }
109}
110
111namespace DynamicMultipleInheritanceUpcast {
112 class B {
113 public:
114 virtual ~B();
115 };
116 class C {
117 public:
118 virtual ~C();
119 };
120 class D : public B, public C {};
121
122 bool testCast(B *a) {
123 return dynamic_cast<C*>(a);
124 }
125
126 void test() {
127 D d;
128 clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
129 }
130
131
132 class DV : virtual public B, virtual public C {};
133
134 void testVirtual() {
135 DV d;
136 clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
137 }
138}
Jordan Rose65f991c2013-02-19 20:28:33 +0000139
140namespace LazyBindings {
141 struct Base {
142 int x;
143 };
144
145 struct Derived : public Base {
146 int y;
147 };
148
149 struct DoubleDerived : public Derived {
150 int z;
151 };
152
153 int getX(const Base &obj) {
154 return obj.x;
155 }
156
157 int getY(const Derived &obj) {
158 return obj.y;
159 }
160
161 void testDerived() {
162 Derived d;
163 d.x = 1;
164 d.y = 2;
165 clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
166 clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
167
168 Base b(d);
169 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
170
171 Derived d2(d);
172 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
173 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
174 }
175
176 void testDoubleDerived() {
177 DoubleDerived d;
178 d.x = 1;
179 d.y = 2;
180 clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
181 clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
182
183 Base b(d);
184 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
185
186 Derived d2(d);
187 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
188 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
189
190 DoubleDerived d3(d);
191 clang_analyzer_eval(getX(d3) == 1); // expected-warning{{TRUE}}
192 clang_analyzer_eval(getY(d3) == 2); // expected-warning{{TRUE}}
193 }
194
195 namespace WithOffset {
196 struct Offset {
197 int padding;
198 };
199
200 struct OffsetDerived : private Offset, public Base {
201 int y;
202 };
203
204 struct DoubleOffsetDerived : public OffsetDerived {
205 int z;
206 };
207
208 int getY(const OffsetDerived &obj) {
209 return obj.y;
210 }
211
212 void testDerived() {
213 OffsetDerived d;
214 d.x = 1;
215 d.y = 2;
216 clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
217 clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
218
219 Base b(d);
220 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
221
222 OffsetDerived d2(d);
223 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
224 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
225 }
226
227 void testDoubleDerived() {
228 DoubleOffsetDerived d;
229 d.x = 1;
230 d.y = 2;
231 clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
232 clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
233
234 Base b(d);
235 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
236
237 OffsetDerived d2(d);
238 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
239 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
240
241 DoubleOffsetDerived d3(d);
242 clang_analyzer_eval(getX(d3) == 1); // expected-warning{{TRUE}}
243 clang_analyzer_eval(getY(d3) == 2); // expected-warning{{TRUE}}
244 }
245 }
246
247 namespace WithVTable {
248 struct DerivedVTBL : public Base {
249 int y;
250 virtual void method();
251 };
252
253 struct DoubleDerivedVTBL : public DerivedVTBL {
254 int z;
255 };
256
257 int getY(const DerivedVTBL &obj) {
258 return obj.y;
259 }
260
261 int getZ(const DoubleDerivedVTBL &obj) {
262 return obj.z;
263 }
264
265 void testDerived() {
266 DerivedVTBL d;
267 d.x = 1;
268 d.y = 2;
269 clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
270 clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
271
272 Base b(d);
273 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
274
275#if CONSTRUCTORS
276 DerivedVTBL d2(d);
277 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
278 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
279#endif
280 }
281
282#if CONSTRUCTORS
283 void testDoubleDerived() {
284 DoubleDerivedVTBL d;
285 d.x = 1;
286 d.y = 2;
287 d.z = 3;
288 clang_analyzer_eval(getX(d) == 1); // expected-warning{{TRUE}}
289 clang_analyzer_eval(getY(d) == 2); // expected-warning{{TRUE}}
290 clang_analyzer_eval(getZ(d) == 3); // expected-warning{{TRUE}}
291
292 Base b(d);
293 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
294
295 DerivedVTBL d2(d);
296 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
297 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
298
299 DoubleDerivedVTBL d3(d);
300 clang_analyzer_eval(getX(d3) == 1); // expected-warning{{TRUE}}
301 clang_analyzer_eval(getY(d3) == 2); // expected-warning{{TRUE}}
302 clang_analyzer_eval(getZ(d3) == 3); // expected-warning{{TRUE}}
303 }
304#endif
305 }
Jordan Rose11f0cae2013-02-21 01:34:51 +0000306
307#if CONSTRUCTORS
308 namespace Nested {
309 struct NonTrivialCopy {
310 int padding;
311 NonTrivialCopy() {}
312 NonTrivialCopy(const NonTrivialCopy &) {}
313 };
314
315 struct FullyDerived : private NonTrivialCopy, public Derived {
316 int z;
317 };
318
319 struct Wrapper {
320 FullyDerived d;
321 int zz;
322
323 Wrapper(const FullyDerived &d) : d(d), zz(0) {}
324 };
325
326 void test5() {
327 Wrapper w((FullyDerived()));
328 w.d.x = 1;
329
330 Wrapper w2(w);
331 clang_analyzer_eval(getX(w2.d) == 1); // expected-warning{{TRUE}}
332 }
333 }
334#endif
Jordan Rose65f991c2013-02-19 20:28:33 +0000335}
Jordan Roseae7396c2013-02-22 19:33:13 +0000336
337namespace Redeclaration {
338 class Base;
339
340 class Base {
341 public:
342 virtual int foo();
343 int get() { return value; }
344
345 int value;
346 };
347
348 class Derived : public Base {
349 public:
350 virtual int bar();
351 };
352
353 void test(Derived d) {
354 d.foo(); // don't crash
355 d.bar(); // sanity check
356
357 Base &b = d;
358 b.foo(); // don't crash
359
360 d.value = 42; // don't crash
361 clang_analyzer_eval(d.get() == 42); // expected-warning{{TRUE}}
362 clang_analyzer_eval(b.get() == 42); // expected-warning{{TRUE}}
363 }
364};
365