| // 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,cplusplus.PureVirtualCall \ | |
| // RUN: -analyzer-checker=optin.cplusplus.VirtualCall \ | |
| // RUN: -analyzer-checker=debug.ExprInspection \ | |
| // RUN: -std=c++11 -verify=pure,impure -std=c++11 %s | |
| // Verify no warnings for virtual calls in system headers. | |
| // RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.VirtualCall \ | |
| // RUN: -std=c++11 -verify=system,impure %s | |
| #include "virtualcall.h" | |
| #include "Inputs/virtualcall-system-header.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(); } | |
| } |