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 | #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 | |
278 | namespace PR34451 { |
279 | struct a { |
280 | void b() { |
281 | a c[1]; |
282 | c->b(); |
283 | } |
284 | }; |
285 | |
286 | class e { |
287 | public: |
288 | void b() const; |
289 | }; |
290 | |
291 | class c { |
292 | void m_fn2() const; |
293 | e d[]; |
294 | }; |
295 | |
296 | void c::m_fn2() const { d->b(); } |
297 | } |
298 | |