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);
25 // This used to crash because we are upcasting through two bases.
31 namespace VirtualBaseClasses
{
37 class B
: public virtual A
{
39 int getX() { return x
; }
42 class C
: public virtual A
{
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
{};
54 clang_analyzer_eval(d
.getX() == 42); // expected-warning{{TRUE}}
58 clang_analyzer_eval(dv
.getX() == 42); // expected-warning{{TRUE}}
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
{
74 int getX() { return x
; }
77 class CI
: public virtual Intermediate
{
79 void setX() { x
= 42; }
82 class DI
: public BI
, public CI
{};
84 void testIntermediate() {
87 clang_analyzer_eval(d
.getX() == 42); // expected-warning{{TRUE}}
92 namespace DynamicVirtualUpcast
{
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
);
108 clang_analyzer_eval(testCast(&d
)); // expected-warning{{TRUE}}
112 namespace DynamicMultipleInheritanceUpcast
{
121 class D
: public B
, public C
{};
123 bool testCast(B
*a
) {
124 return dynamic_cast<C
*>(a
);
129 clang_analyzer_eval(testCast(&d
)); // expected-warning{{TRUE}}
133 class DV
: virtual public B
, virtual public C
{};
137 clang_analyzer_eval(testCast(&d
)); // expected-warning{{TRUE}}
141 namespace LazyBindings
{
146 struct Derived
: public Base
{
150 struct DoubleDerived
: public Derived
{
154 int getX(const Base
&obj
) {
158 int getY(const Derived
&obj
) {
166 clang_analyzer_eval(getX(d
) == 1); // expected-warning{{TRUE}}
167 clang_analyzer_eval(getY(d
) == 2); // expected-warning{{TRUE}}
170 clang_analyzer_eval(getX(b
) == 1); // expected-warning{{TRUE}}
173 clang_analyzer_eval(getX(d2
) == 1); // expected-warning{{TRUE}}
174 clang_analyzer_eval(getY(d2
) == 2); // expected-warning{{TRUE}}
177 void testDoubleDerived() {
181 clang_analyzer_eval(getX(d
) == 1); // expected-warning{{TRUE}}
182 clang_analyzer_eval(getY(d
) == 2); // expected-warning{{TRUE}}
185 clang_analyzer_eval(getX(b
) == 1); // expected-warning{{TRUE}}
188 clang_analyzer_eval(getX(d2
) == 1); // expected-warning{{TRUE}}
189 clang_analyzer_eval(getY(d2
) == 2); // expected-warning{{TRUE}}
192 clang_analyzer_eval(getX(d3
) == 1); // expected-warning{{TRUE}}
193 clang_analyzer_eval(getY(d3
) == 2); // expected-warning{{TRUE}}
196 namespace WithOffset
{
201 struct OffsetDerived
: private Offset
, public Base
{
205 struct DoubleOffsetDerived
: public OffsetDerived
{
209 int getY(const OffsetDerived
&obj
) {
217 clang_analyzer_eval(getX(d
) == 1); // expected-warning{{TRUE}}
218 clang_analyzer_eval(getY(d
) == 2); // expected-warning{{TRUE}}
221 clang_analyzer_eval(getX(b
) == 1); // expected-warning{{TRUE}}
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
;
232 clang_analyzer_eval(getX(d
) == 1); // expected-warning{{TRUE}}
233 clang_analyzer_eval(getY(d
) == 2); // expected-warning{{TRUE}}
236 clang_analyzer_eval(getX(b
) == 1); // expected-warning{{TRUE}}
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
{
251 virtual void method();
254 struct DoubleDerivedVTBL
: public DerivedVTBL
{
258 int getY(const DerivedVTBL
&obj
) {
262 int getZ(const DoubleDerivedVTBL
&obj
) {
270 clang_analyzer_eval(getX(d
) == 1); // expected-warning{{TRUE}}
271 clang_analyzer_eval(getY(d
) == 2); // expected-warning{{TRUE}}
274 clang_analyzer_eval(getX(b
) == 1); // expected-warning{{TRUE}}
278 clang_analyzer_eval(getX(d2
) == 1); // expected-warning{{TRUE}}
279 clang_analyzer_eval(getY(d2
) == 2); // expected-warning{{TRUE}}
284 void testDoubleDerived() {
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}}
294 clang_analyzer_eval(getX(b
) == 1); // expected-warning{{TRUE}}
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}}
310 struct NonTrivialCopy
{
313 NonTrivialCopy(const NonTrivialCopy
&) {}
316 struct FullyDerived
: private NonTrivialCopy
, public Derived
{
324 Wrapper(const FullyDerived
&d
) : d(d
), zz(0) {}
328 Wrapper
w((FullyDerived()));
332 clang_analyzer_eval(getX(w2
.d
) == 1); // expected-warning{{TRUE}}
338 namespace Redeclaration
{
344 int get() { return value
; }
349 class Derived
: public Base
{
354 void test(Derived d
) {
355 d
.foo(); // don't crash
356 d
.bar(); // basic correctness check
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}}
375 class Derived1
: public Base
{
380 class Derived2
: public Derived1
{
383 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
389 Derived1
*d1p
= reinterpret_cast<Derived1
*>(new Derived2
);
392 clang_analyzer_eval(d1p
->f() == 3); // expected-warning{{TRUE}}
396 namespace VirtualInDerived
{
402 class Derived1
: public Base
{
408 class Derived2
: public Derived1
{
411 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
417 Derived1
*d1p
= reinterpret_cast<Derived1
*>(new Derived2
);
420 clang_analyzer_eval(d1p
->f() == 3); // expected-warning{{TRUE}}
430 class Derived1
: public Base
{
436 class Derived2
: public Derived1
{
439 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
445 Derived1
*d1p
= new Derived2
;
448 clang_analyzer_eval(d1p
->f() == 3); // expected-warning{{TRUE}}
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
);
467 // And check that reinterpret+dynamic casts work correctly after the fix.
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}}