forked from OSchip/llvm-project
138 lines
2.4 KiB
C++
138 lines
2.4 KiB
C++
// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -verify %s
|
|
|
|
void clang_analyzer_eval(bool);
|
|
|
|
class A {
|
|
protected:
|
|
int x;
|
|
};
|
|
|
|
class B : public A {
|
|
public:
|
|
void f();
|
|
};
|
|
|
|
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}}
|
|
}
|
|
}
|