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