[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Analysis / derived-to-base.cpp
blobef30f97aadf707e0876221fddfe7eba71d9b2c2d
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
2 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -DCONSTRUCTORS=1 -analyzer-config c++-inlining=constructors -verify %s
4 void clang_analyzer_eval(bool);
5 void clang_analyzer_checkInlined(bool);
7 class A {
8 protected:
9 int x;
12 class B : public A {
13 public:
14 void f();
17 void B::f() {
18 x = 3;
22 class C : public B {
23 public:
24 void g() {
25 // This used to crash because we are upcasting through two bases.
26 x = 5;
31 namespace VirtualBaseClasses {
32 class A {
33 protected:
34 int x;
37 class B : public virtual A {
38 public:
39 int getX() { return x; }
42 class C : public virtual A {
43 public:
44 void setX() { x = 42; }
47 class D : public B, public C {};
48 class DV : virtual public B, public C {};
49 class DV2 : public B, virtual public C {};
51 void test() {
52 D d;
53 d.setX();
54 clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
56 DV dv;
57 dv.setX();
58 clang_analyzer_eval(dv.getX() == 42); // expected-warning{{TRUE}}
60 DV2 dv2;
61 dv2.setX();
62 clang_analyzer_eval(dv2.getX() == 42); // expected-warning{{TRUE}}
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 {};
72 class BI : public virtual Intermediate {
73 public:
74 int getX() { return x; }
77 class CI : public virtual Intermediate {
78 public:
79 void setX() { x = 42; }
82 class DI : public BI, public CI {};
84 void testIntermediate() {
85 DI d;
86 d.setX();
87 clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}}
92 namespace DynamicVirtualUpcast {
93 class A {
94 public:
95 virtual ~A();
98 class B : virtual public A {};
99 class C : virtual public B {};
100 class D : virtual public C {};
102 bool testCast(A *a) {
103 return dynamic_cast<B*>(a) && dynamic_cast<C*>(a);
106 void test() {
107 D d;
108 clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
112 namespace DynamicMultipleInheritanceUpcast {
113 class B {
114 public:
115 virtual ~B();
117 class C {
118 public:
119 virtual ~C();
121 class D : public B, public C {};
123 bool testCast(B *a) {
124 return dynamic_cast<C*>(a);
127 void test() {
128 D d;
129 clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
133 class DV : virtual public B, virtual public C {};
135 void testVirtual() {
136 DV d;
137 clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}}
141 namespace LazyBindings {
142 struct Base {
143 int x;
146 struct Derived : public Base {
147 int y;
150 struct DoubleDerived : public Derived {
151 int z;
154 int getX(const Base &obj) {
155 return obj.x;
158 int getY(const Derived &obj) {
159 return obj.y;
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}}
169 Base b(d);
170 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
172 Derived d2(d);
173 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
174 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
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}}
184 Base b(d);
185 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
187 Derived d2(d);
188 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
189 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
191 DoubleDerived d3(d);
192 clang_analyzer_eval(getX(d3) == 1); // expected-warning{{TRUE}}
193 clang_analyzer_eval(getY(d3) == 2); // expected-warning{{TRUE}}
196 namespace WithOffset {
197 struct Offset {
198 int padding;
201 struct OffsetDerived : private Offset, public Base {
202 int y;
205 struct DoubleOffsetDerived : public OffsetDerived {
206 int z;
209 int getY(const OffsetDerived &obj) {
210 return obj.y;
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}}
220 Base b(d);
221 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
223 OffsetDerived d2(d);
224 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
225 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
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}}
235 Base b(d);
236 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
238 OffsetDerived d2(d);
239 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
240 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
242 DoubleOffsetDerived d3(d);
243 clang_analyzer_eval(getX(d3) == 1); // expected-warning{{TRUE}}
244 clang_analyzer_eval(getY(d3) == 2); // expected-warning{{TRUE}}
248 namespace WithVTable {
249 struct DerivedVTBL : public Base {
250 int y;
251 virtual void method();
254 struct DoubleDerivedVTBL : public DerivedVTBL {
255 int z;
258 int getY(const DerivedVTBL &obj) {
259 return obj.y;
262 int getZ(const DoubleDerivedVTBL &obj) {
263 return obj.z;
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}}
273 Base b(d);
274 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
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
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}}
293 Base b(d);
294 clang_analyzer_eval(getX(b) == 1); // expected-warning{{TRUE}}
296 DerivedVTBL d2(d);
297 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}
298 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}
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}}
305 #endif
308 #if CONSTRUCTORS
309 namespace Nested {
310 struct NonTrivialCopy {
311 int padding;
312 NonTrivialCopy() {}
313 NonTrivialCopy(const NonTrivialCopy &) {}
316 struct FullyDerived : private NonTrivialCopy, public Derived {
317 int z;
320 struct Wrapper {
321 FullyDerived d;
322 int zz;
324 Wrapper(const FullyDerived &d) : d(d), zz(0) {}
327 void test5() {
328 Wrapper w((FullyDerived()));
329 w.d.x = 1;
331 Wrapper w2(w);
332 clang_analyzer_eval(getX(w2.d) == 1); // expected-warning{{TRUE}}
335 #endif
338 namespace Redeclaration {
339 class Base;
341 class Base {
342 public:
343 virtual int foo();
344 int get() { return value; }
346 int value;
349 class Derived : public Base {
350 public:
351 virtual int bar();
354 void test(Derived d) {
355 d.foo(); // don't crash
356 d.bar(); // basic correctness check
358 Base &b = d;
359 b.foo(); // don't crash
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}}
367 namespace PR15394 {
368 namespace Original {
369 class Base {
370 public:
371 virtual int f() = 0;
372 int i;
375 class Derived1 : public Base {
376 public:
377 int j;
380 class Derived2 : public Derived1 {
381 public:
382 virtual int f() {
383 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
384 return i + j;
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}}
396 namespace VirtualInDerived {
397 class Base {
398 public:
399 int i;
402 class Derived1 : public Base {
403 public:
404 virtual int f() = 0;
405 int j;
408 class Derived2 : public Derived1 {
409 public:
410 virtual int f() {
411 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
412 return i + j;
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}}
424 namespace NoCast {
425 class Base {
426 public:
427 int i;
430 class Derived1 : public Base {
431 public:
432 virtual int f() = 0;
433 int j;
436 class Derived2 : public Derived1 {
437 public:
438 virtual int f() {
439 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
440 return i + j;
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}}
453 namespace Bug16309 {
454 struct Incomplete;
456 struct Base { virtual ~Base(); };
458 struct Derived : public Base { int x; };
460 void* f(Incomplete *i) {
461 Base *b = reinterpret_cast<Base *>(i);
462 // This used to crash because of the reinterpret_cast above.
463 Derived *d = dynamic_cast<Derived *>(b);
464 return d;
467 // And check that reinterpret+dynamic casts work correctly after the fix.
468 void g() {
469 Derived d;
470 d.x = 47;
471 Base *b = &d;
472 Incomplete *i = reinterpret_cast<Incomplete *>(b);
473 Base *b2 = reinterpret_cast<Base *>(i);
474 Derived *d2 = dynamic_cast<Derived *>(b2);
475 clang_analyzer_eval(d2->x == 47); // expected-warning{{TRUE}}