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 {{{{^}}'i' is > 0}}
168 	// expected-note-re@-3 {{{{^}}Taking true branch}}
169 	// expected-note-re@-4 {{{{^}}'i' is <= 0}}
170 	// expected-note-re@-5 {{{{^}}Taking false branch}}
171 #endif
172       X x(i - 1);
173 #if !PUREONLY
174 	// expected-note-re@-2 {{{{^}}Calling constructor for 'X'}}
175 #endif
176       x.g(); // no warning
177     }
178     g();
179 #if !PUREONLY
180   	// expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
181 	// expected-note-re@-3 {{{{^}}This constructor of an object of type 'X' has not returned when the virtual method was called}}
182   	// expected-note-re@-4 {{{{^}}Call to virtual function during construction}}
183 #endif
184   }
185   virtual void g();
186 };
187 
188 class M;
189 class N {
190 public:
191   virtual void virtualMethod();
192   void callFooOfM(M *);
193 };
194 class M {
195 public:
196   M() {
197     N n;
198     n.virtualMethod(); // no warning
199     n.callFooOfM(this);
200 #if !PUREONLY
201   	// expected-note-re@-2 {{{{^}}This constructor of an object of type 'M' has not returned when the virtual method was called}}
202 	// expected-note-re@-3 {{{{^}}Calling 'N::callFooOfM'}}
203 #endif
204   }
205   virtual void foo();
206 };
207 void N::callFooOfM(M *m) {
208   m->foo();
209 #if !PUREONLY
210   	// expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
211   	// expected-note-re@-3 {{{{^}}Call to virtual function during construction}}
212 #endif
213 }
214 
215 class Y {
216 public:
217   virtual void foobar();
218   void fooY() {
219     F f1;
220     foobar();
221 #if !PUREONLY
222   	// expected-warning-re@-2 {{{{^}}Call to virtual function during construction}}
223   	// expected-note-re@-3 {{{{^}}Call to virtual function during construction}}
224 #endif
225   }
226   Y() { fooY(); }
227 #if !PUREONLY
228   	// expected-note-re@-2 {{{{^}}This constructor of an object of type 'Y' has not returned when the virtual method was called}}
229   	// expected-note-re@-3 {{{{^}}Calling 'Y::fooY'}}
230 #endif
231 };
232 
233 int main() {
234   B b;
235 #if PUREONLY
236 	//expected-note-re@-2 {{{{^}}Calling default constructor for 'B'}}
237 #else
238 	//expected-note-re@-4 2{{{{^}}Calling default constructor for 'B'}}
239 #endif
240   C c;
241 #if !PUREONLY
242 	//expected-note-re@-2 {{{{^}}Calling default constructor for 'C'}}
243 #endif
244   D d;
245   E e;
246   F f;
247   G g;
248   H h;
249   H h1(1);
250 #if !PUREONLY
251 	//expected-note-re@-2 {{{{^}}Calling constructor for 'H'}}
252 	//expected-note-re@-3 {{{{^}}Calling constructor for 'H'}}
253 #endif
254   X x;
255 #if !PUREONLY
256 	//expected-note-re@-2 {{{{^}}Calling default constructor for 'X'}}
257 #endif
258   X x1(1);
259 #if !PUREONLY
260 	//expected-note-re@-2 {{{{^}}Calling constructor for 'X'}}
261 #endif
262   M m;
263 #if !PUREONLY
264 	//expected-note-re@-2 {{{{^}}Calling default constructor for 'M'}}
265 #endif
266   Y *y = new Y;
267 #if !PUREONLY
268   //expected-note-re@-2 {{{{^}}Calling default constructor for 'Y'}}
269 #endif
270   delete y;
271   header::Z z;
272 #if !PUREONLY
273 	// expected-note-re@-2 {{{{^}}Calling default constructor for 'Z'}}
274 #endif
275 }
276 #if !PUREONLY
277 	//expected-note-re@-2 2{{{{^}}Calling '~E'}}
278 #endif
279 
280 namespace PR34451 {
281 struct a {
282   void b() {
283     a c[1];
284     c->b();
285   }
286 };
287 
288 class e {
289  public:
290   void b() const;
291 };
292 
293 class c {
294   void m_fn2() const;
295   e d[];
296 };
297 
298 void c::m_fn2() const { d->b(); }
299 }
300