| // RUN: %clang_analyze_cc1 -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-output=text -verify -std=c++11 %s |
| |
| // RUN: %clang_analyze_cc1 -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-config optin.cplusplus.VirtualCall:PureOnly=true -DPUREONLY=1 -analyzer-output=text -verify -std=c++11 %s |
| |
| #include "virtualcall.h" |
| |
| class A { |
| public: |
| A(); |
| |
| ~A(){}; |
| |
| virtual int foo() = 0; |
| virtual void bar() = 0; |
| void f() { |
| foo(); |
| // expected-warning-re@-1 {{{{^}}Call to pure virtual function during construction}} |
| // expected-note-re@-2 {{{{^}}Call to pure virtual function during construction}} |
| } |
| }; |
| |
| class B : public A { |
| public: |
| B() { // expected-note {{Calling default constructor for 'A'}} |
| foo(); |
| #if !PUREONLY |
| // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| // expected-note-re@-3 {{{{^}}This constructor of an object of type 'B' has not returned when the virtual method was called}} |
| // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| #endif |
| } |
| ~B(); |
| |
| virtual int foo(); |
| virtual void bar() { |
| foo(); |
| #if !PUREONLY |
| // expected-warning-re@-2 {{{{^}}Call to virtual function during destruction}} |
| // expected-note-re@-3 {{{{^}}Call to virtual function during destruction}} |
| #endif |
| } |
| }; |
| |
| A::A() { |
| f(); |
| // expected-note-re@-1 {{{{^}}This constructor of an object of type 'A' has not returned when the virtual method was called}} |
| // expected-note-re@-2 {{{{^}}Calling 'A::f'}} |
| } |
| |
| B::~B() { |
| this->B::foo(); // no-warning |
| this->B::bar(); |
| #if !PUREONLY |
| // expected-note-re@-2 {{{{^}}This destructor of an object of type '~B' has not returned when the virtual method was called}} |
| // expected-note-re@-3 {{{{^}}Calling 'B::bar'}} |
| #endif |
| this->foo(); |
| #if !PUREONLY |
| // expected-warning-re@-2 {{{{^}}Call to virtual function during destruction}} |
| // expected-note-re@-3 {{{{^}}This destructor of an object of type '~B' has not returned when the virtual method was called}} |
| // expected-note-re@-4 {{{{^}}Call to virtual function during destruction}} |
| #endif |
| |
| } |
| |
| class C : public B { |
| public: |
| C(); |
| ~C(); |
| |
| virtual int foo(); |
| void f(int i); |
| }; |
| |
| C::C() { |
| f(foo()); |
| #if !PUREONLY |
| // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| // expected-note-re@-3 {{{{^}}This constructor of an object of type 'C' has not returned when the virtual method was called}} |
| // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| #endif |
| } |
| |
| 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(); } |
| #if !PUREONLY |
| // expected-note-re@-2 2{{{{^}}Calling '~B'}} |
| #endif |
| 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(); |
| #if !PUREONLY |
| // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| // expected-note-re@-3 {{{{^}}This constructor of an object of type 'H' has not returned when the virtual method was called}} |
| // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| #endif |
| H &h = *this; |
| h.f(); |
| #if !PUREONLY |
| // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| // expected-note-re@-3 {{{{^}}This constructor of an object of type 'H' has not returned when the virtual method was called}} |
| // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| #endif |
| } |
| }; |
| |
| class X { |
| public: |
| X() { |
| g(); |
| #if !PUREONLY |
| // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| // expected-note-re@-3 {{{{^}}This constructor of an object of type 'X' has not returned when the virtual method was called}} |
| // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| #endif |
| } |
| X(int i) { |
| if (i > 0) { |
| #if !PUREONLY |
| // expected-note-re@-2 {{{{^}}Taking true branch}} |
| // expected-note-re@-3 {{{{^}}Taking false branch}} |
| #endif |
| X x(i - 1); |
| #if !PUREONLY |
| // expected-note-re@-2 {{{{^}}Calling constructor for 'X'}} |
| #endif |
| x.g(); // no warning |
| } |
| g(); |
| #if !PUREONLY |
| // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| // expected-note-re@-3 {{{{^}}This constructor of an object of type 'X' has not returned when the virtual method was called}} |
| // expected-note-re@-4 {{{{^}}Call to virtual function during construction}} |
| #endif |
| } |
| 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); |
| #if !PUREONLY |
| // expected-note-re@-2 {{{{^}}This constructor of an object of type 'M' has not returned when the virtual method was called}} |
| // expected-note-re@-3 {{{{^}}Calling 'N::callFooOfM'}} |
| #endif |
| } |
| virtual void foo(); |
| }; |
| void N::callFooOfM(M *m) { |
| m->foo(); |
| #if !PUREONLY |
| // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| // expected-note-re@-3 {{{{^}}Call to virtual function during construction}} |
| #endif |
| } |
| |
| class Y { |
| public: |
| virtual void foobar(); |
| void fooY() { |
| F f1; |
| foobar(); |
| #if !PUREONLY |
| // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}} |
| // expected-note-re@-3 {{{{^}}Call to virtual function during construction}} |
| #endif |
| } |
| Y() { fooY(); } |
| #if !PUREONLY |
| // expected-note-re@-2 {{{{^}}This constructor of an object of type 'Y' has not returned when the virtual method was called}} |
| // expected-note-re@-3 {{{{^}}Calling 'Y::fooY'}} |
| #endif |
| }; |
| |
| int main() { |
| B b; |
| #if PUREONLY |
| //expected-note-re@-2 {{{{^}}Calling default constructor for 'B'}} |
| #else |
| //expected-note-re@-4 2{{{{^}}Calling default constructor for 'B'}} |
| #endif |
| C c; |
| #if !PUREONLY |
| //expected-note-re@-2 {{{{^}}Calling default constructor for 'C'}} |
| #endif |
| D d; |
| E e; |
| F f; |
| G g; |
| H h; |
| H h1(1); |
| #if !PUREONLY |
| //expected-note-re@-2 {{{{^}}Calling constructor for 'H'}} |
| //expected-note-re@-3 {{{{^}}Calling constructor for 'H'}} |
| #endif |
| X x; |
| #if !PUREONLY |
| //expected-note-re@-2 {{{{^}}Calling default constructor for 'X'}} |
| #endif |
| X x1(1); |
| #if !PUREONLY |
| //expected-note-re@-2 {{{{^}}Calling constructor for 'X'}} |
| #endif |
| M m; |
| #if !PUREONLY |
| //expected-note-re@-2 {{{{^}}Calling default constructor for 'M'}} |
| #endif |
| Y *y = new Y; |
| #if !PUREONLY |
| //expected-note-re@-2 {{{{^}}Calling default constructor for 'Y'}} |
| #endif |
| delete y; |
| header::Z z; |
| #if !PUREONLY |
| // expected-note-re@-2 {{{{^}}Calling default constructor for 'Z'}} |
| #endif |
| } |
| #if !PUREONLY |
| //expected-note-re@-2 2{{{{^}}Calling '~E'}} |
| #endif |
| |
| 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(); } |
| } |