Clang Project

clang_source_code/test/Analysis/virtualcall.cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-output=text -verify -std=c++11 %s
2
3// 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
4
5#include "virtualcall.h"
6
7class A {
8public:
9  A();
10
11  ~A(){};
12
13  virtual int foo() = 0;
14  virtual void bar() = 0;
15  void f() {
16    foo();
17 // expected-warning-re@-1 {{{{^}}Call to pure virtual function during construction}}
18 // expected-note-re@-2 {{{{^}}Call to pure virtual function during construction}}
19  }
20};
21
22class B : public A {
23public:
24  B() { // expected-note {{Calling default constructor for 'A'}}
25    foo(); 
26#if !PUREONLY
27   // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
28 // expected-note-re@-3 {{{{^}}This constructor of an object of type 'B' has not returned when the virtual method was called}}
29   // expected-note-re@-4 {{{{^}}Call to virtual function during construction}}
30#endif
31  }
32  ~B();
33
34  virtual int foo();
35  virtual void bar() {
36    foo(); 
37#if !PUREONLY
38   // expected-warning-re@-2 {{{{^}}Call to virtual function during destruction}}
39   // expected-note-re@-3 {{{{^}}Call to virtual function during destruction}}
40#endif
41  } 
42};
43
44A::A() { 
45  f(); 
46// expected-note-re@-1 {{{{^}}This constructor of an object of type 'A' has not returned when the virtual method was called}}
47// expected-note-re@-2 {{{{^}}Calling 'A::f'}}
48}
49
50B::~B() {
51  this->B::foo(); // no-warning
52  this->B::bar();
53#if !PUREONLY
54   // expected-note-re@-2 {{{{^}}This destructor of an object of type '~B' has not returned when the virtual method was called}}
55   // expected-note-re@-3 {{{{^}}Calling 'B::bar'}}
56#endif
57  this->foo(); 
58#if !PUREONLY
59   // expected-warning-re@-2 {{{{^}}Call to virtual function during destruction}}
60   // expected-note-re@-3 {{{{^}}This destructor of an object of type '~B' has not returned when the virtual method was called}}
61   // expected-note-re@-4 {{{{^}}Call to virtual function during destruction}}
62#endif
63
64}
65
66class C : public B {
67public:
68  C();
69  ~C();
70
71  virtual int foo();
72  void f(int i);
73};
74
75C::C() {
76  f(foo()); 
77#if !PUREONLY
78   // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
79 // expected-note-re@-3 {{{{^}}This constructor of an object of type 'C' has not returned when the virtual method was called}}
80   // expected-note-re@-4 {{{{^}}Call to virtual function during construction}}
81#endif
82}
83
84class D : public B {
85public:
86  D() {
87    foo(); // no-warning
88  }
89  ~D() { bar(); }
90  int foo() final;
91  void bar() final { foo(); } // no-warning
92};
93
94class E final : public B {
95public:
96  E() {
97    foo(); // no-warning
98  }
99  ~E() { bar(); }
100#if !PUREONLY
101   // expected-note-re@-2 2{{{{^}}Calling '~B'}}
102#endif
103  int foo() override;
104};
105
106class F {
107public:
108  F() {
109    void (F::*ptr)() = &F::foo;
110    (this->*ptr)();
111  }
112  void foo();
113};
114
115class G {
116public:
117  G() {}
118  virtual void bar();
119  void foo() {
120    bar(); // no warning
121  }
122};
123
124class H {
125public:
126  H() : initState(0) { init(); }
127  int initState;
128  virtual void f() const;
129  void init() {
130    if (initState)
131      f(); // no warning
132  }
133
134  H(int i) {
135    G g;
136    g.foo();
137    g.bar(); // no warning
138    f();     
139#if !PUREONLY
140   // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
141 // expected-note-re@-3 {{{{^}}This constructor of an object of type 'H' has not returned when the virtual method was called}}
142   // expected-note-re@-4 {{{{^}}Call to virtual function during construction}}
143#endif
144    H &h = *this;
145    h.f(); 
146#if !PUREONLY
147   // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
148   // expected-note-re@-3 {{{{^}}This constructor of an object of type 'H' has not returned when the virtual method was called}}
149   // expected-note-re@-4 {{{{^}}Call to virtual function during construction}}
150#endif
151  }
152};
153
154class X {
155public:
156  X() {
157    g(); 
158#if !PUREONLY
159   // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
160 // expected-note-re@-3 {{{{^}}This constructor of an object of type 'X' has not returned when the virtual method was called}}
161   // expected-note-re@-4 {{{{^}}Call to virtual function during construction}}
162#endif
163  }
164  X(int i) {
165    if (i > 0) {
166#if !PUREONLY
167 // expected-note-re@-2 {{{{^}}Taking true branch}}
168 // expected-note-re@-3 {{{{^}}Taking false branch}}
169#endif
170      X x(i - 1);
171#if !PUREONLY
172 // expected-note-re@-2 {{{{^}}Calling constructor for 'X'}}
173#endif
174      x.g(); // no warning
175    }
176    g(); 
177#if !PUREONLY
178   // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
179 // expected-note-re@-3 {{{{^}}This constructor of an object of type 'X' has not returned when the virtual method was called}}
180   // expected-note-re@-4 {{{{^}}Call to virtual function during construction}}
181#endif
182  }
183  virtual void g();
184};
185
186class M;
187class N {
188public:
189  virtual void virtualMethod();
190  void callFooOfM(M *);
191};
192class M {
193public:
194  M() {
195    N n;
196    n.virtualMethod(); // no warning
197    n.callFooOfM(this);
198#if !PUREONLY
199   // expected-note-re@-2 {{{{^}}This constructor of an object of type 'M' has not returned when the virtual method was called}}
200 // expected-note-re@-3 {{{{^}}Calling 'N::callFooOfM'}}
201#endif
202  }
203  virtual void foo();
204};
205void N::callFooOfM(M *m) {
206  m->foo(); 
207#if !PUREONLY
208   // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
209   // expected-note-re@-3 {{{{^}}Call to virtual function during construction}}
210#endif
211}
212
213class Y {
214public:
215  virtual void foobar();
216  void fooY() {
217    F f1;
218    foobar(); 
219#if !PUREONLY
220   // expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
221   // expected-note-re@-3 {{{{^}}Call to virtual function during construction}}
222#endif
223  }
224  Y() { fooY(); }
225#if !PUREONLY
226   // expected-note-re@-2 {{{{^}}This constructor of an object of type 'Y' has not returned when the virtual method was called}}
227   // expected-note-re@-3 {{{{^}}Calling 'Y::fooY'}}
228#endif
229};
230
231int main() {
232  B b;
233#if PUREONLY
234 //expected-note-re@-2 {{{{^}}Calling default constructor for 'B'}}
235#else 
236 //expected-note-re@-4 2{{{{^}}Calling default constructor for 'B'}}
237#endif
238  C c;
239#if !PUREONLY
240 //expected-note-re@-2 {{{{^}}Calling default constructor for 'C'}}
241#endif
242  D d;
243  E e;
244  F f;
245  G g;
246  H h;
247  H h1(1);
248#if !PUREONLY
249 //expected-note-re@-2 {{{{^}}Calling constructor for 'H'}}
250 //expected-note-re@-3 {{{{^}}Calling constructor for 'H'}}
251#endif
252  X x; 
253#if !PUREONLY
254 //expected-note-re@-2 {{{{^}}Calling default constructor for 'X'}}
255#endif
256  X x1(1);
257#if !PUREONLY
258 //expected-note-re@-2 {{{{^}}Calling constructor for 'X'}}
259#endif
260  M m;
261#if !PUREONLY
262 //expected-note-re@-2 {{{{^}}Calling default constructor for 'M'}}
263#endif
264  Y *y = new Y;
265#if !PUREONLY
266  //expected-note-re@-2 {{{{^}}Calling default constructor for 'Y'}}
267#endif
268  delete y;
269  header::Z z;
270#if !PUREONLY
271 // expected-note-re@-2 {{{{^}}Calling default constructor for 'Z'}}
272#endif
273}
274#if !PUREONLY
275 //expected-note-re@-2 2{{{{^}}Calling '~E'}}
276#endif
277
278namespace PR34451 {
279struct a {
280  void b() {
281    a c[1];
282    c->b();
283  }
284};
285
286class e {
287 public:
288  void b() const;
289};
290
291class c {
292  void m_fn2() const;
293  e d[];
294};
295
296void c::m_fn2() const { d->b(); }
297}
298