478 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s2// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -DCONSTRUCTORS=1 -analyzer-config c++-inlining=constructors -verify %s3 4void clang_analyzer_eval(bool);5void clang_analyzer_checkInlined(bool);6 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}20 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};29 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 an67 // 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}90 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}140 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 CONSTRUCTORS277 DerivedVTBL d2(d);278 clang_analyzer_eval(getX(d2) == 1); // expected-warning{{TRUE}}279 clang_analyzer_eval(getY(d2) == 2); // expected-warning{{TRUE}}280#endif281 }282 283#if CONSTRUCTORS284 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#endif306 }307 308#if CONSTRUCTORS309 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#endif336}337 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 crash356 d.bar(); // basic correctness check357 358 Base &b = d;359 b.foo(); // don't crash360 361 d.value = 42; // don't crash362 clang_analyzer_eval(d.get() == 42); // expected-warning{{TRUE}}363 clang_analyzer_eval(b.get() == 42); // expected-warning{{TRUE}}364 }365};366 367namespace 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 453namespace Bug16309 {454 struct Incomplete;455 456 struct Base { virtual ~Base(); };457 458 struct Derived : public Base { int x; };459 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;465 }466 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}}476 }477}478