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