| // 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(); } |
| } |