// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.VirtualCall \ // RUN: -analyzer-checker=debug.ExprInspection \ // RUN: -std=c++11 -verify=impure %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.PureVirtualCall \ // RUN: -analyzer-checker=debug.ExprInspection \ // RUN: -std=c++11 -verify=pure -std=c++11 %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.VirtualCall \ // RUN: -analyzer-config \ // RUN: optin.cplusplus.VirtualCall:PureOnly=true \ // RUN: -analyzer-checker=debug.ExprInspection \ // RUN: -std=c++11 -verify=none %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.PureVirtualCall \ // RUN: -analyzer-checker=optin.cplusplus.VirtualCall \ // RUN: -analyzer-checker=debug.ExprInspection \ // RUN: -std=c++11 -verify=pure,impure -std=c++11 %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.PureVirtualCall \ // RUN: -analyzer-checker=optin.cplusplus.VirtualCall \ // RUN: -analyzer-config \ // RUN: optin.cplusplus.VirtualCall:PureOnly=true \ // RUN: -analyzer-checker=debug.ExprInspection \ // RUN: -std=c++11 -verify=pure %s // We expect no diagnostics when all checks are disabled. // none-no-diagnostics #include "virtualcall.h" void clang_analyzer_warnIfReached(); class A { public: A(); ~A(){}; virtual int foo() = 0; virtual void bar() = 0; void f() { foo(); // pure-warning{{Call to pure virtual method 'A::foo' during construction has undefined behavior}} clang_analyzer_warnIfReached(); // no-warning } }; A::A() { f(); } class B { public: B() { foo(); // impure-warning {{Call to virtual method 'B::foo' during construction bypasses virtual dispatch}} } ~B(); virtual int foo(); virtual void bar() { foo(); // impure-warning {{Call to virtual method 'B::foo' during destruction bypasses virtual dispatch}} } }; B::~B() { this->B::foo(); // no-warning this->B::bar(); this->foo(); // impure-warning {{Call to virtual method 'B::foo' during destruction bypasses virtual dispatch}} } class C : public B { public: C(); ~C(); virtual int foo(); void f(int i); }; C::C() { f(foo()); // impure-warning {{Call to virtual method 'C::foo' during construction bypasses virtual dispatch}} } class D : public B { public: D() { foo(); // no-warning } ~D() { bar(); } int foo() final; void bar() final { foo(); } // no-warning }; class E final : public B { public: E() { foo(); // no-warning } ~E() { bar(); } int foo() override; }; class F { public: F() { void (F::*ptr)() = &F::foo; (this->*ptr)(); } void foo(); }; class G { public: G() {} virtual void bar(); void foo() { bar(); // no warning } }; class H { public: H() : initState(0) { init(); } int initState; virtual void f() const; void init() { if (initState) f(); // no warning } H(int i) { G g; g.foo(); g.bar(); // no warning f(); // impure-warning {{Call to virtual method 'H::f' during construction bypasses virtual dispatch}} H &h = *this; h.f(); // impure-warning {{Call to virtual method 'H::f' during construction bypasses virtual dispatch}} } }; class X { public: X() { g(); // impure-warning {{Call to virtual method 'X::g' during construction bypasses virtual dispatch}} } X(int i) { if (i > 0) { X x(i - 1); x.g(); // no warning } g(); // impure-warning {{Call to virtual method 'X::g' during construction bypasses virtual dispatch}} } virtual void g(); }; class M; class N { public: virtual void virtualMethod(); void callFooOfM(M *); }; class M { public: M() { N n; n.virtualMethod(); // no warning n.callFooOfM(this); } virtual void foo(); }; void N::callFooOfM(M *m) { m->foo(); // impure-warning {{Call to virtual method 'M::foo' during construction bypasses virtual dispatch}} } class Y { public: virtual void foobar(); void fooY() { F f1; foobar(); // impure-warning {{Call to virtual method 'Y::foobar' during construction bypasses virtual dispatch}} } Y() { fooY(); } }; int main() { B b; C c; D d; E e; F f; G g; H h; H h1(1); X x; X x1(1); M m; Y *y = new Y; delete y; header::Z z; } namespace PR34451 { struct a { void b() { a c[1]; c->b(); } }; class e { public: void b() const; }; class c { void m_fn2() const; e d[]; }; void c::m_fn2() const { d->b(); } }