diff options
Diffstat (limited to 'test/Analysis/derived-to-base.cpp')
-rw-r--r-- | test/Analysis/derived-to-base.cpp | 124 |
1 files changed, 123 insertions, 1 deletions
diff --git a/test/Analysis/derived-to-base.cpp b/test/Analysis/derived-to-base.cpp index f65b9db..f833678 100644 --- a/test/Analysis/derived-to-base.cpp +++ b/test/Analysis/derived-to-base.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify %s + +void clang_analyzer_eval(bool); class A { protected: @@ -13,3 +15,123 @@ public: void B::f() { x = 3; } + + +class C : public B { +public: + void g() { + // This used to crash because we are upcasting through two bases. + x = 5; + } +}; + + +namespace VirtualBaseClasses { + class A { + protected: + int x; + }; + + class B : public virtual A { + public: + int getX() { return x; } + }; + + class C : public virtual A { + public: + void setX() { x = 42; } + }; + + class D : public B, public C {}; + class DV : virtual public B, public C {}; + class DV2 : public B, virtual public C {}; + + void test() { + D d; + d.setX(); + clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}} + + DV dv; + dv.setX(); + clang_analyzer_eval(dv.getX() == 42); // expected-warning{{TRUE}} + + DV2 dv2; + dv2.setX(); + clang_analyzer_eval(dv2.getX() == 42); // expected-warning{{TRUE}} + } + + + // Make sure we're consistent about the offset of the A subobject within an + // Intermediate virtual base class. + class Padding1 { int unused; }; + class Padding2 { int unused; }; + class Intermediate : public Padding1, public A, public Padding2 {}; + + class BI : public virtual Intermediate { + public: + int getX() { return x; } + }; + + class CI : public virtual Intermediate { + public: + void setX() { x = 42; } + }; + + class DI : public BI, public CI {}; + + void testIntermediate() { + DI d; + d.setX(); + clang_analyzer_eval(d.getX() == 42); // expected-warning{{TRUE}} + } +} + + +namespace DynamicVirtualUpcast { + class A { + public: + virtual ~A(); + }; + + class B : virtual public A {}; + class C : virtual public B {}; + class D : virtual public C {}; + + bool testCast(A *a) { + return dynamic_cast<B*>(a) && dynamic_cast<C*>(a); + } + + void test() { + D d; + clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}} + } +} + +namespace DynamicMultipleInheritanceUpcast { + class B { + public: + virtual ~B(); + }; + class C { + public: + virtual ~C(); + }; + class D : public B, public C {}; + + bool testCast(B *a) { + return dynamic_cast<C*>(a); + } + + void test() { + D d; + clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}} + } + + + class DV : virtual public B, virtual public C {}; + + void testVirtual() { + DV d; + clang_analyzer_eval(testCast(&d)); // expected-warning{{TRUE}} + } +} |