1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedLocalVarsChecker -verify %s
3 #include "mock-types.h"
4 #include "mock-system-header.h"
11 // FIXME: later on we might warn on uninitialized vars too
14 void bar(RefCountable
*) {}
15 } // namespace raw_ptr
19 RefCountable automatic
;
20 RefCountable
&bar
= automatic
;
21 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
26 void foo_ref_trivial() {
27 RefCountable automatic
;
28 RefCountable
&bar
= automatic
;
31 void bar_ref(RefCountable
&) {}
32 } // namespace reference
34 namespace guardian_scopes
{
36 RefPtr
<RefCountable
> foo
;
37 { RefCountable
*bar
= foo
.get(); }
41 RefPtr
<RefCountable
> foo
;
42 // missing embedded scope here
43 RefCountable
*bar
= foo
.get();
44 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
50 RefPtr
<RefCountable
> foo
;
52 { RefCountable
*bar
= foo
.get(); }
58 RefPtr
<RefCountable
> foo
;
59 { RefCountable
*bar
= foo
.get(); }
64 RefPtr
<RefCountable
> foo
;
65 auto* bar
= foo
.get();
70 RefPtr
<RefCountable
> foo
;
71 auto* bar
= foo
.get();
72 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
76 struct SelfReferencingStruct
{
77 SelfReferencingStruct
* ptr
;
78 RefCountable
* obj
{ nullptr };
81 void foo7(RefCountable
* obj
) {
82 SelfReferencingStruct bar
= { &bar
, obj
};
86 void foo8(RefCountable
* obj
) {
87 RefPtr
<RefCountable
> foo
;
89 RefCountable
*bar
= foo
.get();
90 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
94 RefPtr
<RefCountable
> baz
;
96 RefCountable
*bar
= baz
.get();
97 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
103 RefCountable
*bar
= foo
.get();
104 // No warning. It's okay to mutate RefPtr in an outer scope.
109 RefCountable
*bar
= foo
.get();
110 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
111 foo
.releaseNonNull();
115 RefCountable
*bar
= foo
.get();
116 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
117 foo
= obj
? obj
: nullptr;
121 RefCountable
*bar
= foo
->trivial() ? foo
.get() : nullptr;
122 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
128 void foo9(RefCountable
& o
) {
129 Ref
<RefCountable
> guardian(o
);
131 RefCountable
&bar
= guardian
.get();
132 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
133 guardian
= o
; // We don't detect that we're setting it to the same value.
137 RefCountable
*bar
= guardian
.ptr();
138 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
139 Ref
<RefCountable
> other(*bar
); // We don't detect other has the same value as guardian.
140 guardian
.swap(other
);
144 RefCountable
*bar
= guardian
.ptr();
145 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
146 Ref
<RefCountable
> other(static_cast<Ref
<RefCountable
>&&>(guardian
));
150 RefCountable
*bar
= guardian
.ptr();
151 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
156 RefCountable
*bar
= guardian
.ptr();
157 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
158 guardian
= o
.trivial() ? o
: *bar
;
163 } // namespace guardian_scopes
165 namespace auto_keyword
{
167 RefCountable
*provide_ref_ctnbl();
170 RefCountable
*bar
= provide_ref_ctnbl();
171 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
172 auto *baz
= provide_ref_ctnbl();
173 // expected-warning@-1{{Local variable 'baz' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
174 auto *baz2
= this->provide_ref_ctnbl();
175 // expected-warning@-1{{Local variable 'baz2' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
176 [[clang::suppress
]] auto *baz_suppressed
= provide_ref_ctnbl(); // no-warning
180 RefCountable
*bar
= provide_ref_ctnbl();
181 // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
186 } // namespace auto_keyword
188 namespace guardian_casts
{
190 RefPtr
<RefCountable
> foo
;
192 RefCountable
*bar
= downcast
<RefCountable
>(foo
.get());
199 RefPtr
<RefCountable
> foo
;
202 static_cast<RefCountable
*>(downcast
<RefCountable
>(foo
.get()));
206 } // namespace guardian_casts
208 namespace guardian_ref_conversion_operator
{
210 Ref
<RefCountable
> rc
;
212 RefCountable
&rr
= rc
;
217 } // namespace guardian_ref_conversion_operator
219 namespace ignore_for_if
{
220 RefCountable
*provide_ref_ctnbl() { return nullptr; }
224 if (RefCountable
*a
= provide_ref_ctnbl())
226 for (RefCountable
*b
= provide_ref_ctnbl(); b
!= nullptr;)
228 RefCountable
*array
[1];
229 for (RefCountable
*c
: array
)
231 while (RefCountable
*d
= provide_ref_ctnbl())
234 RefCountable
*e
= provide_ref_ctnbl();
241 if (RefCountable
*a
= provide_ref_ctnbl()) {
242 // expected-warning@-1{{Local variable 'a' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
245 for (RefCountable
*b
= provide_ref_ctnbl(); b
!= nullptr;) {
246 // expected-warning@-1{{Local variable 'b' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
249 RefCountable
*array
[1];
250 for (RefCountable
*c
: array
) {
251 // expected-warning@-1{{Local variable 'c' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
255 while (RefCountable
*d
= provide_ref_ctnbl()) {
256 // expected-warning@-1{{Local variable 'd' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
260 RefCountable
*e
= provide_ref_ctnbl();
261 // expected-warning@-1{{Local variable 'e' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
267 } // namespace ignore_for_if
269 namespace ignore_system_headers
{
271 RefCountable
*provide_ref_ctnbl();
273 void system_header() {
274 localVar
<RefCountable
>(provide_ref_ctnbl
);
277 } // ignore_system_headers
279 namespace conditional_op
{
280 RefCountable
*provide_ref_ctnbl();
284 RefCountable
*a
= bar() ? nullptr : provide_ref_ctnbl();
285 // expected-warning@-1{{Local variable 'a' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
286 RefPtr
<RefCountable
> b
= provide_ref_ctnbl();
288 RefCountable
* c
= bar() ? nullptr : b
.get();
290 RefCountable
* d
= bar() ? b
.get() : nullptr;
295 } // namespace conditional_op
297 namespace local_assignment_basic
{
299 RefCountable
*provide_ref_cntbl();
301 void foo(RefCountable
* a
) {
303 // expected-warning@-1{{Local variable 'b' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
305 b
= provide_ref_cntbl();
308 void bar(RefCountable
* a
) {
310 // expected-warning@-1{{Local variable 'b' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
311 b
= provide_ref_cntbl();
315 RefPtr a
= provide_ref_cntbl();
317 RefCountable
* b
= a
.get();
318 // expected-warning@-1{{Local variable 'b' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
319 b
= provide_ref_cntbl();
323 } // namespace local_assignment_basic
325 namespace local_assignment_to_parameter
{
327 RefCountable
*provide_ref_cntbl();
330 void foo(RefCountable
* a
) {
331 a
= provide_ref_cntbl();
332 // expected-warning@-1{{Assignment to an uncounted parameter 'a' is unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
337 } // namespace local_assignment_to_parameter
339 namespace local_assignment_to_static_local
{
341 RefCountable
*provide_ref_cntbl();
345 static RefCountable
* a
= nullptr;
346 // expected-warning@-1{{Static local variable 'a' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
347 a
= provide_ref_cntbl();
352 } // namespace local_assignment_to_static_local
354 namespace local_assignment_to_global
{
356 RefCountable
*provide_ref_cntbl();
359 RefCountable
* g_a
= nullptr;
360 // expected-warning@-1{{Global variable 'local_assignment_to_global::g_a' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
363 g_a
= provide_ref_cntbl();
368 } // namespace local_assignment_to_global
370 namespace local_refcountable_checkable_object
{
372 RefCountableAndCheckable
* provide_obj();
374 void local_raw_ptr() {
375 RefCountableAndCheckable
* a
= nullptr;
376 // expected-warning@-1{{Local variable 'a' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
381 void local_checked_ptr() {
382 CheckedPtr
<RefCountableAndCheckable
> a
= nullptr;
387 void local_var_with_guardian_checked_ptr() {
388 CheckedPtr
<RefCountableAndCheckable
> a
= provide_obj();
395 void local_var_with_guardian_checked_ptr_with_assignment() {
396 CheckedPtr
<RefCountableAndCheckable
> a
= provide_obj();
398 RefCountableAndCheckable
* b
= a
.get();
399 // expected-warning@-1{{Local variable 'b' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
405 void local_var_with_guardian_checked_ref() {
406 CheckedRef
<RefCountableAndCheckable
> a
= *provide_obj();
408 RefCountableAndCheckable
& b
= a
;
414 static RefCountableAndCheckable
* a
= nullptr;
415 // expected-warning@-1{{Static local variable 'a' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
419 } // namespace local_refcountable_checkable_object
421 namespace local_var_in_recursive_function
{
424 Ref
<TreeNode
> create() { return Ref(*new TreeNode
); }
426 void ref() const { ++refCount
; }
433 int recursiveWeight();
437 mutable unsigned refCount
{ 0 };
438 TreeNode
* nextSibling
{ nullptr };
439 TreeNode
* firstChild
{ nullptr };
442 int TreeNode::recursiveCost() {
444 unsigned totalCost
= cost
;
445 for (TreeNode
* node
= firstChild
; node
; node
= node
->nextSibling
)
446 totalCost
+= recursiveCost();
450 int TreeNode::recursiveWeight() {
451 unsigned totalCost
= weight();
452 for (TreeNode
* node
= firstChild
; node
; node
= node
->nextSibling
)
453 // expected-warning@-1{{Local variable 'node' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
454 totalCost
+= recursiveWeight();
458 } // namespace local_var_in_recursive_function
460 namespace local_var_for_singleton
{
461 RefCountable
*singleton();
462 RefCountable
*otherSingleton();
464 RefCountable
* bar
= singleton();
465 RefCountable
* baz
= otherSingleton();