[NFC][AArch64] Explicitly define undefined bits for instructions (#122129)
[llvm-project.git] / clang / test / Analysis / Checkers / WebKit / uncounted-lambda-captures.cpp
blob2173245bc7af3ebb1759da25b91128e7c99fc5e5
1 // RUN: %clang_analyze_cc1 -analyzer-checker=webkit.UncountedLambdaCapturesChecker -verify %s
3 #include "mock-types.h"
5 namespace WTF {
7 namespace Detail {
9 template<typename Out, typename... In>
10 class CallableWrapperBase {
11 public:
12 virtual ~CallableWrapperBase() { }
13 virtual Out call(In...) = 0;
16 template<typename, typename, typename...> class CallableWrapper;
18 template<typename CallableType, typename Out, typename... In>
19 class CallableWrapper : public CallableWrapperBase<Out, In...> {
20 public:
21 explicit CallableWrapper(CallableType& callable)
22 : m_callable(callable) { }
23 Out call(In... in) final { return m_callable(in...); }
25 private:
26 CallableType m_callable;
29 } // namespace Detail
31 template<typename> class Function;
33 template<typename Out, typename... In> Function<Out(In...)> adopt(Detail::CallableWrapperBase<Out, In...>*);
35 template <typename Out, typename... In>
36 class Function<Out(In...)> {
37 public:
38 using Impl = Detail::CallableWrapperBase<Out, In...>;
40 Function() = default;
42 template<typename FunctionType>
43 Function(FunctionType f)
44 : m_callableWrapper(new Detail::CallableWrapper<FunctionType, Out, In...>(f)) { }
46 Out operator()(In... in) const { return m_callableWrapper->call(in...); }
47 explicit operator bool() const { return !!m_callableWrapper; }
49 private:
50 enum AdoptTag { Adopt };
51 Function(Impl* impl, AdoptTag)
52 : m_callableWrapper(impl)
56 friend Function adopt<Out, In...>(Impl*);
58 std::unique_ptr<Impl> m_callableWrapper;
61 template<typename Out, typename... In> Function<Out(In...)> adopt(Detail::CallableWrapperBase<Out, In...>* impl)
63 return Function<Out(In...)>(impl, Function<Out(In...)>::Adopt);
66 } // namespace WTF
68 struct A {
69 static void b();
72 RefCountable* make_obj();
74 void someFunction();
75 template <typename Callback> void call(Callback callback) {
76 someFunction();
77 callback();
80 void raw_ptr() {
81 RefCountable* ref_countable = make_obj();
82 auto foo1 = [ref_countable](){
83 // expected-warning@-1{{Captured raw-pointer 'ref_countable' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
84 ref_countable->method();
86 auto foo2 = [&ref_countable](){
87 // expected-warning@-1{{Captured raw-pointer 'ref_countable' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
88 ref_countable->method();
90 auto foo3 = [&](){
91 ref_countable->method();
92 // expected-warning@-1{{Implicitly captured raw-pointer 'ref_countable' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
93 ref_countable = nullptr;
96 auto foo4 = [=](){
97 ref_countable->method();
98 // expected-warning@-1{{Implicitly captured raw-pointer 'ref_countable' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
101 call(foo1);
102 call(foo2);
103 call(foo3);
104 call(foo4);
106 // Confirm that the checker respects [[clang::suppress]].
107 RefCountable* suppressed_ref_countable = nullptr;
108 [[clang::suppress]] auto foo5 = [suppressed_ref_countable](){};
109 // no warning.
110 call(foo5);
113 void references() {
114 RefCountable automatic;
115 RefCountable& ref_countable_ref = automatic;
116 auto foo1 = [ref_countable_ref](){ ref_countable_ref.constMethod(); };
117 // expected-warning@-1{{Captured reference 'ref_countable_ref' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
118 auto foo2 = [&ref_countable_ref](){ ref_countable_ref.method(); };
119 // expected-warning@-1{{Captured reference 'ref_countable_ref' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
120 auto foo3 = [&](){ ref_countable_ref.method(); };
121 // expected-warning@-1{{Implicitly captured reference 'ref_countable_ref' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
122 auto foo4 = [=](){ ref_countable_ref.constMethod(); };
123 // expected-warning@-1{{Implicitly captured reference 'ref_countable_ref' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
125 call(foo1);
126 call(foo2);
127 call(foo3);
128 call(foo4);
131 void quiet() {
132 // This code is not expected to trigger any warnings.
134 RefCountable automatic;
135 RefCountable &ref_countable_ref = automatic;
138 auto foo3 = [&]() {};
139 auto foo4 = [=]() {};
141 call(foo3);
142 call(foo4);
144 RefCountable *ref_countable = nullptr;
147 template <typename Callback>
148 void map(RefCountable* start, [[clang::noescape]] Callback&& callback)
150 while (start) {
151 callback(*start);
152 start = start->next();
156 template <typename Callback1, typename Callback2>
157 void doubleMap(RefCountable* start, [[clang::noescape]] Callback1&& callback1, Callback2&& callback2)
159 while (start) {
160 callback1(*start);
161 callback2(*start);
162 start = start->next();
166 void noescape_lambda() {
167 RefCountable* someObj = make_obj();
168 RefCountable* otherObj = make_obj();
169 map(make_obj(), [&](RefCountable& obj) {
170 otherObj->method();
172 doubleMap(make_obj(), [&](RefCountable& obj) {
173 otherObj->method();
174 }, [&](RefCountable& obj) {
175 otherObj->method();
176 // expected-warning@-1{{Implicitly captured raw-pointer 'otherObj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
178 ([&] {
179 someObj->method();
180 })();
183 void lambda_capture_param(RefCountable* obj) {
184 auto someLambda = [&]() {
185 obj->method();
187 someLambda();
188 someLambda();
191 struct RefCountableWithLambdaCapturingThis {
192 void ref() const;
193 void deref() const;
194 void nonTrivial();
196 void method_captures_this_safe() {
197 auto lambda = [&]() {
198 nonTrivial();
200 lambda();
203 void method_captures_this_unsafe() {
204 auto lambda = [&]() {
205 nonTrivial();
206 // expected-warning@-1{{Implicitly captured raw-pointer 'this' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
208 call(lambda);
211 void method_captures_this_unsafe_capture_local_var_explicitly() {
212 RefCountable* x = make_obj();
213 call([this, protectedThis = RefPtr { this }, x]() {
214 // expected-warning@-1{{Captured raw-pointer 'x' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
215 nonTrivial();
216 x->method();
220 void method_captures_this_with_other_protected_var() {
221 RefCountable* x = make_obj();
222 call([this, protectedX = RefPtr { x }]() {
223 // expected-warning@-1{{Captured raw-pointer 'this' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
224 nonTrivial();
225 protectedX->method();
229 void method_captures_this_unsafe_capture_local_var_explicitly_with_deref() {
230 RefCountable* x = make_obj();
231 call([this, protectedThis = Ref { *this }, x]() {
232 // expected-warning@-1{{Captured raw-pointer 'x' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
233 nonTrivial();
234 x->method();
238 void method_captures_this_unsafe_local_var_via_vardecl() {
239 RefCountable* x = make_obj();
240 auto lambda = [this, protectedThis = Ref { *this }, x]() {
241 // expected-warning@-1{{Captured raw-pointer 'x' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
242 nonTrivial();
243 x->method();
245 call(lambda);
248 void method_captures_this_with_guardian() {
249 auto lambda = [this, protectedThis = Ref { *this }]() {
250 nonTrivial();
252 call(lambda);
255 void method_captures_this_with_guardian_refPtr() {
256 auto lambda = [this, protectedThis = RefPtr { &*this }]() {
257 nonTrivial();
259 call(lambda);
264 struct NonRefCountableWithLambdaCapturingThis {
265 void nonTrivial();
267 void method_captures_this_safe() {
268 auto lambda = [&]() {
269 nonTrivial();
271 lambda();
274 void method_captures_this_unsafe() {
275 auto lambda = [&]() {
276 nonTrivial();
278 call(lambda);
282 void trivial_lambda() {
283 RefCountable* ref_countable = make_obj();
284 auto trivial_lambda = [&]() {
285 return ref_countable->trivial();
287 trivial_lambda();
290 void lambda_with_args(RefCountable* obj) {
291 auto trivial_lambda = [&](int v) {
292 obj->method();
294 trivial_lambda(1);
297 void callFunctionOpaque(WTF::Function<void()>&&);
298 void callFunction(WTF::Function<void()>&& function) {
299 someFunction();
300 function();
303 void lambda_converted_to_function(RefCountable* obj)
305 callFunction([&]() {
306 obj->method();
307 // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
309 callFunctionOpaque([&]() {
310 obj->method();
311 // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}