2017-08-28 16:44:43 +08:00
|
|
|
// RUN: %clang_analyze_cc1 -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-output=text -verify -std=c++11 %s
|
2016-12-10 09:16:09 +08:00
|
|
|
|
2017-08-28 16:44:43 +08:00
|
|
|
// 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
|
2016-12-10 09:16:09 +08:00
|
|
|
|
2017-08-28 16:44:43 +08:00
|
|
|
#include "virtualcall.h"
|
2012-01-04 07:18:57 +08:00
|
|
|
|
|
|
|
class A {
|
|
|
|
public:
|
|
|
|
A();
|
2016-12-10 09:16:09 +08:00
|
|
|
|
2017-08-28 16:44:43 +08:00
|
|
|
~A(){};
|
|
|
|
|
|
|
|
virtual int foo() = 0;
|
2012-01-04 07:18:57 +08:00
|
|
|
virtual void bar() = 0;
|
|
|
|
void f() {
|
2016-12-10 09:16:09 +08:00
|
|
|
foo();
|
2017-08-28 16:44:43 +08:00
|
|
|
// expected-warning-re@-1 {{{{^}}Call to pure virtual function during construction}}
|
|
|
|
// expected-note-re@-2 {{{{^}}Call to pure virtual function during construction}}
|
2012-01-04 07:18:57 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class B : public A {
|
|
|
|
public:
|
2017-08-28 16:44:43 +08:00
|
|
|
B() { // expected-note {{Calling default constructor for 'A'}}
|
|
|
|
foo();
|
2016-12-10 09:16:09 +08:00
|
|
|
#if !PUREONLY
|
2017-08-28 16:44:43 +08:00
|
|
|
// 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}}
|
2016-12-10 09:16:09 +08:00
|
|
|
#endif
|
2012-01-04 07:18:57 +08:00
|
|
|
}
|
|
|
|
~B();
|
2017-08-28 16:44:43 +08:00
|
|
|
|
2012-01-04 07:18:57 +08:00
|
|
|
virtual int foo();
|
2017-08-28 16:44:43 +08:00
|
|
|
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}}
|
2016-12-10 09:16:09 +08:00
|
|
|
#endif
|
2017-08-28 16:44:43 +08:00
|
|
|
}
|
2012-01-04 07:18:57 +08:00
|
|
|
};
|
|
|
|
|
2017-08-28 16:44:43 +08:00
|
|
|
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'}}
|
2016-12-10 09:16:09 +08:00
|
|
|
}
|
|
|
|
|
2012-01-04 07:18:57 +08:00
|
|
|
B::~B() {
|
|
|
|
this->B::foo(); // no-warning
|
|
|
|
this->B::bar();
|
2016-12-10 09:16:09 +08:00
|
|
|
#if !PUREONLY
|
2017-08-28 16:44:43 +08:00
|
|
|
// 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'}}
|
2016-12-10 09:16:09 +08:00
|
|
|
#endif
|
2017-08-28 16:44:43 +08:00
|
|
|
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}}
|
2016-12-10 09:16:09 +08:00
|
|
|
#endif
|
2017-08-28 16:44:43 +08:00
|
|
|
|
2012-01-04 07:18:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
class C : public B {
|
|
|
|
public:
|
|
|
|
C();
|
|
|
|
~C();
|
2017-08-28 16:44:43 +08:00
|
|
|
|
2012-01-04 07:18:57 +08:00
|
|
|
virtual int foo();
|
|
|
|
void f(int i);
|
|
|
|
};
|
|
|
|
|
|
|
|
C::C() {
|
2017-08-28 16:44:43 +08:00
|
|
|
f(foo());
|
2016-12-10 09:16:09 +08:00
|
|
|
#if !PUREONLY
|
2017-08-28 16:44:43 +08:00
|
|
|
// 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}}
|
2016-12-10 09:16:09 +08:00
|
|
|
#endif
|
2012-01-04 07:18:57 +08:00
|
|
|
}
|
|
|
|
|
2014-08-21 18:25:03 +08:00
|
|
|
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(); }
|
2017-08-28 16:44:43 +08:00
|
|
|
#if !PUREONLY
|
|
|
|
// expected-note-re@-2 2{{{{^}}Calling '~B'}}
|
|
|
|
#endif
|
2014-08-21 18:25:03 +08:00
|
|
|
int foo() override;
|
|
|
|
};
|
|
|
|
|
2017-01-31 13:23:20 +08:00
|
|
|
class F {
|
|
|
|
public:
|
|
|
|
F() {
|
2017-08-28 16:44:43 +08:00
|
|
|
void (F::*ptr)() = &F::foo;
|
2017-01-31 13:23:20 +08:00
|
|
|
(this->*ptr)();
|
|
|
|
}
|
|
|
|
void foo();
|
|
|
|
};
|
|
|
|
|
2017-08-28 16:44:43 +08:00
|
|
|
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
|
2012-01-04 07:18:57 +08:00
|
|
|
}
|
2012-10-11 01:55:40 +08:00
|
|
|
|
2017-08-28 16:44:43 +08:00
|
|
|
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
|
|
|
|
};
|
2012-10-11 01:55:40 +08:00
|
|
|
|
2017-08-28 16:44:43 +08:00
|
|
|
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;
|
2018-01-25 04:59:40 +08:00
|
|
|
#if !PUREONLY
|
|
|
|
//expected-note-re@-2 {{{{^}}Calling default constructor for 'Y'}}
|
|
|
|
#endif
|
2017-08-28 16:44:43 +08:00
|
|
|
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
|
2017-09-21 16:18:59 +08:00
|
|
|
|
|
|
|
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(); }
|
|
|
|
}
|