Bug 1814798 - pt 1. Add bool to enable/disable PHC at runtime r=glandium
[gecko.git] / build / clang-plugin / tests / TestNoRefcountedInsideLambdas.cpp
blobaedc5af096cd9225fb8d7f1d637dadaf32de9d43
1 #include <mozilla/StaticAnalysisFunctions.h>
3 #include <functional>
4 #define MOZ_STRONG_REF
5 #define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
7 // Ensure that warnings about returning stack addresses of local variables are
8 // errors, so our `expected-error` annotations below work correctly.
9 #pragma GCC diagnostic error "-Wreturn-stack-address"
11 struct RefCountedBase {
12 void AddRef();
13 void Release();
16 template <class T>
17 struct SmartPtr {
18 SmartPtr();
19 MOZ_IMPLICIT SmartPtr(T*);
20 T* MOZ_STRONG_REF t;
21 T* operator->() const;
24 struct R : RefCountedBase {
25 void method();
26 private:
27 void privateMethod();
30 void take(...);
31 void foo() {
32 R* ptr;
33 SmartPtr<R> sp;
34 take([&](R* argptr) {
35 R* localptr;
36 ptr->method();
37 argptr->method();
38 localptr->method();
39 });
40 take([&](SmartPtr<R> argsp) {
41 SmartPtr<R> localsp;
42 sp->method();
43 argsp->method();
44 localsp->method();
45 });
46 take([&](R* argptr) {
47 R* localptr;
48 take(ptr);
49 take(argptr);
50 take(localptr);
51 });
52 take([&](SmartPtr<R> argsp) {
53 SmartPtr<R> localsp;
54 take(sp);
55 take(argsp);
56 take(localsp);
57 });
58 take([=](R* argptr) {
59 R* localptr;
60 ptr->method();
61 argptr->method();
62 localptr->method();
63 });
64 take([=](SmartPtr<R> argsp) {
65 SmartPtr<R> localsp;
66 sp->method();
67 argsp->method();
68 localsp->method();
69 });
70 take([=](R* argptr) {
71 R* localptr;
72 take(ptr);
73 take(argptr);
74 take(localptr);
75 });
76 take([=](SmartPtr<R> argsp) {
77 SmartPtr<R> localsp;
78 take(sp);
79 take(argsp);
80 take(localsp);
81 });
82 take([ptr](R* argptr) {
83 R* localptr;
84 ptr->method();
85 argptr->method();
86 localptr->method();
87 });
88 take([sp](SmartPtr<R> argsp) {
89 SmartPtr<R> localsp;
90 sp->method();
91 argsp->method();
92 localsp->method();
93 });
94 take([ptr](R* argptr) {
95 R* localptr;
96 take(ptr);
97 take(argptr);
98 take(localptr);
99 });
100 take([sp](SmartPtr<R> argsp) {
101 SmartPtr<R> localsp;
102 take(sp);
103 take(argsp);
104 take(localsp);
106 take([&ptr](R* argptr) {
107 R* localptr;
108 ptr->method();
109 argptr->method();
110 localptr->method();
112 take([&sp](SmartPtr<R> argsp) {
113 SmartPtr<R> localsp;
114 sp->method();
115 argsp->method();
116 localsp->method();
118 take([&ptr](R* argptr) {
119 R* localptr;
120 take(ptr);
121 take(argptr);
122 take(localptr);
124 take([&sp](SmartPtr<R> argsp) {
125 SmartPtr<R> localsp;
126 take(sp);
127 take(argsp);
128 take(localsp);
132 void b() {
133 R* ptr;
134 SmartPtr<R> sp;
135 std::function<void(R*)>([&](R* argptr) {
136 R* localptr;
137 ptr->method();
138 argptr->method();
139 localptr->method();
141 std::function<void(SmartPtr<R>)>([&](SmartPtr<R> argsp) {
142 SmartPtr<R> localsp;
143 sp->method();
144 argsp->method();
145 localsp->method();
147 std::function<void(R*)>([&](R* argptr) {
148 R* localptr;
149 take(ptr);
150 take(argptr);
151 take(localptr);
153 std::function<void(SmartPtr<R>)>([&](SmartPtr<R> argsp) {
154 SmartPtr<R> localsp;
155 take(sp);
156 take(argsp);
157 take(localsp);
159 std::function<void(R*)>([=](R* argptr) {
160 R* localptr;
161 ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
162 argptr->method();
163 localptr->method();
165 std::function<void(SmartPtr<R>)>([=](SmartPtr<R> argsp) {
166 SmartPtr<R> localsp;
167 sp->method();
168 argsp->method();
169 localsp->method();
171 std::function<void(R*)>([=](R* argptr) {
172 R* localptr;
173 take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
174 take(argptr);
175 take(localptr);
177 std::function<void(SmartPtr<R>)>([=](SmartPtr<R> argsp) {
178 SmartPtr<R> localsp;
179 take(sp);
180 take(argsp);
181 take(localsp);
183 std::function<void(R*)>([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
184 R* localptr;
185 ptr->method();
186 argptr->method();
187 localptr->method();
189 std::function<void(SmartPtr<R>)>([sp](SmartPtr<R> argsp) {
190 SmartPtr<R> localsp;
191 sp->method();
192 argsp->method();
193 localsp->method();
195 std::function<void(R*)>([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
196 R* localptr;
197 take(ptr);
198 take(argptr);
199 take(localptr);
201 std::function<void(SmartPtr<R>)>([sp](SmartPtr<R> argsp) {
202 SmartPtr<R> localsp;
203 take(sp);
204 take(argsp);
205 take(localsp);
207 std::function<void(R*)>([&ptr](R* argptr) {
208 R* localptr;
209 ptr->method();
210 argptr->method();
211 localptr->method();
213 std::function<void(SmartPtr<R>)>([&sp](SmartPtr<R> argsp) {
214 SmartPtr<R> localsp;
215 sp->method();
216 argsp->method();
217 localsp->method();
219 std::function<void(R*)>([&ptr](R* argptr) {
220 R* localptr;
221 take(ptr);
222 take(argptr);
223 take(localptr);
225 std::function<void(SmartPtr<R>)>([&sp](SmartPtr<R> argsp) {
226 SmartPtr<R> localsp;
227 take(sp);
228 take(argsp);
229 take(localsp);
233 // These tests would check c++14 deduced return types, if they were supported in
234 // our codebase. They are being kept here for convenience in the future if we do
235 // add support for c++14 deduced return types
236 #if 0
237 auto d1() {
238 R* ptr;
239 SmartPtr<R> sp;
240 return ([&](R* argptr) {
241 R* localptr;
242 ptr->method();
243 argptr->method();
244 localptr->method();
247 auto d2() {
248 R* ptr;
249 SmartPtr<R> sp;
250 return ([&](SmartPtr<R> argsp) {
251 SmartPtr<R> localsp;
252 sp->method();
253 argsp->method();
254 localsp->method();
257 auto d3() {
258 R* ptr;
259 SmartPtr<R> sp;
260 return ([&](R* argptr) {
261 R* localptr;
262 take(ptr);
263 take(argptr);
264 take(localptr);
267 auto d4() {
268 R* ptr;
269 SmartPtr<R> sp;
270 return ([&](SmartPtr<R> argsp) {
271 SmartPtr<R> localsp;
272 take(sp);
273 take(argsp);
274 take(localsp);
277 auto d5() {
278 R* ptr;
279 SmartPtr<R> sp;
280 return ([=](R* argptr) {
281 R* localptr;
282 ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
283 argptr->method();
284 localptr->method();
287 auto d6() {
288 R* ptr;
289 SmartPtr<R> sp;
290 return ([=](SmartPtr<R> argsp) {
291 SmartPtr<R> localsp;
292 sp->method();
293 argsp->method();
294 localsp->method();
297 auto d8() {
298 R* ptr;
299 SmartPtr<R> sp;
300 return ([=](R* argptr) {
301 R* localptr;
302 take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
303 take(argptr);
304 take(localptr);
307 auto d9() {
308 R* ptr;
309 SmartPtr<R> sp;
310 return ([=](SmartPtr<R> argsp) {
311 SmartPtr<R> localsp;
312 take(sp);
313 take(argsp);
314 take(localsp);
317 auto d10() {
318 R* ptr;
319 SmartPtr<R> sp;
320 return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
321 R* localptr;
322 ptr->method();
323 argptr->method();
324 localptr->method();
327 auto d11() {
328 R* ptr;
329 SmartPtr<R> sp;
330 return ([sp](SmartPtr<R> argsp) {
331 SmartPtr<R> localsp;
332 sp->method();
333 argsp->method();
334 localsp->method();
337 auto d12() {
338 R* ptr;
339 SmartPtr<R> sp;
340 return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
341 R* localptr;
342 take(ptr);
343 take(argptr);
344 take(localptr);
347 auto d13() {
348 R* ptr;
349 SmartPtr<R> sp;
350 return ([sp](SmartPtr<R> argsp) {
351 SmartPtr<R> localsp;
352 take(sp);
353 take(argsp);
354 take(localsp);
357 auto d14() {
358 R* ptr;
359 SmartPtr<R> sp;
360 return ([&ptr](R* argptr) {
361 R* localptr;
362 ptr->method();
363 argptr->method();
364 localptr->method();
367 auto d15() {
368 R* ptr;
369 SmartPtr<R> sp;
370 return ([&sp](SmartPtr<R> argsp) {
371 SmartPtr<R> localsp;
372 sp->method();
373 argsp->method();
374 localsp->method();
377 auto d16() {
378 R* ptr;
379 SmartPtr<R> sp;
380 return ([&ptr](R* argptr) {
381 R* localptr;
382 take(ptr);
383 take(argptr);
384 take(localptr);
387 auto d17() {
388 R* ptr;
389 SmartPtr<R> sp;
390 return ([&sp](SmartPtr<R> argsp) {
391 SmartPtr<R> localsp;
392 take(sp);
393 take(argsp);
394 take(localsp);
397 #endif
399 void e() {
400 auto e1 = []() {
401 R* ptr;
402 SmartPtr<R> sp;
403 return ([&](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}}
404 R* localptr;
405 #if __clang_major__ >= 12
406 ptr->method(); // expected-note{{implicitly captured by reference due to use here}}
407 #else
408 ptr->method();
409 #endif
410 argptr->method();
411 localptr->method();
414 auto e2 = []() {
415 R* ptr;
416 SmartPtr<R> sp;
417 return ([&](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}}
418 SmartPtr<R> localsp;
419 #if __clang_major__ >= 12
420 sp->method(); // expected-note{{implicitly captured by reference due to use here}}
421 #else
422 sp->method();
423 #endif
424 argsp->method();
425 localsp->method();
428 auto e3 = []() {
429 R* ptr;
430 SmartPtr<R> sp;
431 return ([&](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}}
432 R* localptr;
433 #if __clang_major__ >= 12
434 take(ptr); // expected-note{{implicitly captured by reference due to use here}}
435 #else
436 take(ptr);
437 #endif
438 take(argptr);
439 take(localptr);
442 auto e4 = []() {
443 R* ptr;
444 SmartPtr<R> sp;
445 return ([&](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}}
446 SmartPtr<R> localsp;
447 #if __clang_major__ >= 12
448 take(sp); // expected-note{{implicitly captured by reference due to use here}}
449 #else
450 take(sp);
451 #endif
452 take(argsp);
453 take(localsp);
456 auto e5 = []() {
457 R* ptr;
458 SmartPtr<R> sp;
459 return ([=](R* argptr) {
460 R* localptr;
461 ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
462 argptr->method();
463 localptr->method();
466 auto e6 = []() {
467 R* ptr;
468 SmartPtr<R> sp;
469 return ([=](SmartPtr<R> argsp) {
470 SmartPtr<R> localsp;
471 sp->method();
472 argsp->method();
473 localsp->method();
476 auto e8 = []() {
477 R* ptr;
478 SmartPtr<R> sp;
479 return ([=](R* argptr) {
480 R* localptr;
481 take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
482 take(argptr);
483 take(localptr);
486 auto e9 = []() {
487 R* ptr;
488 SmartPtr<R> sp;
489 return ([=](SmartPtr<R> argsp) {
490 SmartPtr<R> localsp;
491 take(sp);
492 take(argsp);
493 take(localsp);
496 auto e10 = []() {
497 R* ptr;
498 SmartPtr<R> sp;
499 return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
500 R* localptr;
501 ptr->method();
502 argptr->method();
503 localptr->method();
506 auto e11 = []() {
507 R* ptr;
508 SmartPtr<R> sp;
509 return ([sp](SmartPtr<R> argsp) {
510 SmartPtr<R> localsp;
511 sp->method();
512 argsp->method();
513 localsp->method();
516 auto e12 = []() {
517 R* ptr;
518 SmartPtr<R> sp;
519 return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
520 R* localptr;
521 take(ptr);
522 take(argptr);
523 take(localptr);
526 auto e13 = []() {
527 R* ptr;
528 SmartPtr<R> sp;
529 return ([sp](SmartPtr<R> argsp) {
530 SmartPtr<R> localsp;
531 take(sp);
532 take(argsp);
533 take(localsp);
536 auto e14 = []() {
537 R* ptr;
538 SmartPtr<R> sp;
539 #if __clang_major__ >= 12
540 return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}} expected-note{{captured by reference here}}
541 R* localptr;
542 ptr->method();
543 argptr->method();
544 localptr->method();
546 #else
547 return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}}
548 R* localptr;
549 ptr->method();
550 argptr->method();
551 localptr->method();
553 #endif
555 auto e15 = []() {
556 R* ptr;
557 SmartPtr<R> sp;
558 #if __clang_major__ >= 12
559 return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}} expected-note{{captured by reference here}}
560 SmartPtr<R> localsp;
561 sp->method();
562 argsp->method();
563 localsp->method();
565 #else
566 return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}}
567 SmartPtr<R> localsp;
568 sp->method();
569 argsp->method();
570 localsp->method();
572 #endif
574 auto e16 = []() {
575 R* ptr;
576 SmartPtr<R> sp;
577 #if __clang_major__ >= 12
578 return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}} expected-note{{captured by reference here}}
579 R* localptr;
580 take(ptr);
581 take(argptr);
582 take(localptr);
584 #else
585 return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}}
586 R* localptr;
587 take(ptr);
588 take(argptr);
589 take(localptr);
591 #endif
593 auto e17 = []() {
594 R* ptr;
595 SmartPtr<R> sp;
596 #if __clang_major__ >= 12
597 return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}} expected-note{{captured by reference here}}
598 SmartPtr<R> localsp;
599 take(sp);
600 take(argsp);
601 take(localsp);
603 #else
604 return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}}
605 SmartPtr<R> localsp;
606 take(sp);
607 take(argsp);
608 take(localsp);
610 #endif
614 void
615 R::privateMethod() {
616 SmartPtr<R> self = this;
617 std::function<void()>([&]() {
618 self->method();
620 std::function<void()>([&]() {
621 self->privateMethod();
623 std::function<void()>([&]() {
624 this->method();
626 std::function<void()>([&]() {
627 this->privateMethod();
629 std::function<void()>([=]() {
630 self->method();
632 std::function<void()>([=]() {
633 self->privateMethod();
635 std::function<void()>([=]() {
636 this->method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
638 std::function<void()>([=]() {
639 this->privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
641 std::function<void()>([self]() {
642 self->method();
644 std::function<void()>([self]() {
645 self->privateMethod();
647 std::function<void()>([this]() {
648 this->method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
650 std::function<void()>([this]() {
651 this->privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
653 std::function<void()>([this]() {
654 method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
656 std::function<void()>([this]() {
657 privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
659 std::function<void()>([=]() {
660 method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
662 std::function<void()>([=]() {
663 privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
665 std::function<void()>([&]() {
666 method();
668 std::function<void()>([&]() {
669 privateMethod();
672 std::function<void()>(
673 [instance = MOZ_KnownLive(this)]() { instance->privateMethod(); });
675 // It should be OK to go through `this` if we have captured a reference to it.
676 std::function<void()>([this, self]() {
677 this->method();
678 this->privateMethod();
679 method();
680 privateMethod();