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 
7 class A {
8 public:
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 
22 class B : public A {
23 public:
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 
44 A::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 
50 B::~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 
66 class C : public B {
67 public:
68   C();
69   ~C();
70 
71   virtual int foo();
72   void f(int i);
73 };
74 
75 C::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 
84 class D : public B {
85 public:
86   D() {
87     foo(); // no-warning
88   }
89   ~D() { bar(); }
90   int foo() final;
91   void bar() final { foo(); } // no-warning
92 };
93 
94 class E final : public B {
95 public:
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 
106 class F {
107 public:
108   F() {
109     void (F::*ptr)() = &F::foo;
110     (this->*ptr)();
111   }
112   void foo();
113 };
114 
115 class G {
116 public:
117   G() {}
118   virtual void bar();
119   void foo() {
120     bar(); // no warning
121   }
122 };
123 
124 class H {
125 public:
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 
154 class X {
155 public:
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 
186 class M;
187 class N {
188 public:
189   virtual void virtualMethod();
190   void callFooOfM(M *);
191 };
192 class M {
193 public:
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 };
205 void 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 
213 class Y {
214 public:
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 
231 int 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   delete y;
266   header::Z z;
267 #if !PUREONLY
268 	// expected-note-re@-2 {{{{^}}Calling default constructor for 'Z'}}
269 #endif
270 }
271 #if !PUREONLY
272 	//expected-note-re@-2 2{{{{^}}Calling '~E'}}
273 #endif
274 
275 namespace PR34451 {
276 struct a {
277   void b() {
278     a c[1];
279     c->b();
280   }
281 };
282 
283 class e {
284  public:
285   void b() const;
286 };
287 
288 class c {
289   void m_fn2() const;
290   e d[];
291 };
292 
293 void c::m_fn2() const { d->b(); }
294 }
295