1 // RUN: %clang_analyze_cc1 -analyzer-checker=webkit.UncountedLambdaCapturesChecker -verify %s
3 #include "mock-types.h"
9 template<typename Out
, typename
... In
>
10 class CallableWrapperBase
{
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
...> {
21 explicit CallableWrapper(CallableType
& callable
)
22 : m_callable(callable
) { }
23 Out
call(In
... in
) final
{ return m_callable(in
...); }
26 CallableType m_callable
;
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
...)> {
38 using Impl
= Detail::CallableWrapperBase
<Out
, In
...>;
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
; }
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
);
72 RefCountable
* make_obj();
75 template <typename Callback
> void call(Callback callback
) {
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();
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;
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]}}
106 // Confirm that the checker respects [[clang::suppress]].
107 RefCountable
* suppressed_ref_countable
= nullptr;
108 [[clang::suppress
]] auto foo5
= [suppressed_ref_countable
](){};
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]}}
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
= [=]() {};
144 RefCountable
*ref_countable
= nullptr;
147 template <typename Callback
>
148 void map(RefCountable
* start
, [[clang::noescape
]] Callback
&& callback
)
152 start
= start
->next();
156 template <typename Callback1
, typename Callback2
>
157 void doubleMap(RefCountable
* start
, [[clang::noescape
]] Callback1
&& callback1
, Callback2
&& callback2
)
162 start
= start
->next();
166 void noescape_lambda() {
167 RefCountable
* someObj
= make_obj();
168 RefCountable
* otherObj
= make_obj();
169 map(make_obj(), [&](RefCountable
& obj
) {
172 doubleMap(make_obj(), [&](RefCountable
& obj
) {
174 }, [&](RefCountable
& obj
) {
176 // expected-warning@-1{{Implicitly captured raw-pointer 'otherObj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
183 void lambda_capture_param(RefCountable
* obj
) {
184 auto someLambda
= [&]() {
191 struct RefCountableWithLambdaCapturingThis
{
196 void method_captures_this_safe() {
197 auto lambda
= [&]() {
203 void method_captures_this_unsafe() {
204 auto lambda
= [&]() {
206 // expected-warning@-1{{Implicitly captured raw-pointer 'this' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
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]}}
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]}}
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]}}
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]}}
248 void method_captures_this_with_guardian() {
249 auto lambda
= [this, protectedThis
= Ref
{ *this }]() {
255 void method_captures_this_with_guardian_refPtr() {
256 auto lambda
= [this, protectedThis
= RefPtr
{ &*this }]() {
264 struct NonRefCountableWithLambdaCapturingThis
{
267 void method_captures_this_safe() {
268 auto lambda
= [&]() {
274 void method_captures_this_unsafe() {
275 auto lambda
= [&]() {
282 void trivial_lambda() {
283 RefCountable
* ref_countable
= make_obj();
284 auto trivial_lambda
= [&]() {
285 return ref_countable
->trivial();
290 void lambda_with_args(RefCountable
* obj
) {
291 auto trivial_lambda
= [&](int v
) {
297 void callFunctionOpaque(WTF::Function
<void()>&&);
298 void callFunction(WTF::Function
<void()>&& function
) {
303 void lambda_converted_to_function(RefCountable
* obj
)
307 // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}
309 callFunctionOpaque([&]() {
311 // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}}