1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s 2 3 #include "mock-types.h" 4 provide()5RefCountable* provide() { return nullptr; } consume_refcntbl(RefCountable *)6void consume_refcntbl(RefCountable*) {} 7 8 namespace simple { foo()9 void foo() { 10 consume_refcntbl(provide()); 11 // expected-warning@-1{{Call argument is uncounted and unsafe}} 12 } 13 } 14 15 namespace multi_arg { consume_refcntbl(int,RefCountable * foo,bool)16 void consume_refcntbl(int, RefCountable* foo, bool) {} foo()17 void foo() { 18 consume_refcntbl(42, provide(), true); 19 // expected-warning@-1{{Call argument for parameter 'foo' is uncounted and unsafe}} 20 } 21 } 22 23 namespace ref_counted { provide_ref_counted()24 Ref<RefCountable> provide_ref_counted() { return Ref<RefCountable>{}; } consume_ref_counted(Ref<RefCountable>)25 void consume_ref_counted(Ref<RefCountable>) {} 26 foo()27 void foo() { 28 consume_refcntbl(provide_ref_counted().get()); 29 // no warning 30 } 31 } 32 33 namespace methods { 34 struct Consumer { consume_ptrmethods::Consumer35 void consume_ptr(RefCountable* ptr) {} consume_refmethods::Consumer36 void consume_ref(const RefCountable& ref) {} 37 }; 38 foo()39 void foo() { 40 Consumer c; 41 42 c.consume_ptr(provide()); 43 // expected-warning@-1{{Call argument for parameter 'ptr' is uncounted and unsafe}} 44 c.consume_ref(*provide()); 45 // expected-warning@-1{{Call argument for parameter 'ref' is uncounted and unsafe}} 46 } 47 foo2()48 void foo2() { 49 struct Consumer { 50 void consume(RefCountable*) { } 51 void whatever() { 52 consume(provide()); 53 // expected-warning@-1{{Call argument is uncounted and unsafe}} 54 } 55 }; 56 } 57 foo3()58 void foo3() { 59 struct Consumer { 60 void consume(RefCountable*) { } 61 void whatever() { 62 this->consume(provide()); 63 // expected-warning@-1{{Call argument is uncounted and unsafe}} 64 } 65 }; 66 } 67 } 68 69 namespace casts { downcast(RefCountable *)70 RefCountable* downcast(RefCountable*) { return nullptr; } 71 foo()72 void foo() { 73 consume_refcntbl(provide()); 74 // expected-warning@-1{{Call argument is uncounted and unsafe}} 75 76 consume_refcntbl(static_cast<RefCountable*>(provide())); 77 // expected-warning@-1{{Call argument is uncounted and unsafe}} 78 79 consume_refcntbl(dynamic_cast<RefCountable*>(provide())); 80 // expected-warning@-1{{Call argument is uncounted and unsafe}} 81 82 consume_refcntbl(const_cast<RefCountable*>(provide())); 83 // expected-warning@-1{{Call argument is uncounted and unsafe}} 84 85 consume_refcntbl(reinterpret_cast<RefCountable*>(provide())); 86 // expected-warning@-1{{Call argument is uncounted and unsafe}} 87 88 consume_refcntbl(downcast(provide())); 89 // expected-warning@-1{{Call argument is uncounted and unsafe}} 90 91 consume_refcntbl( 92 static_cast<RefCountable*>( 93 downcast( 94 static_cast<RefCountable*>( 95 provide() 96 ) 97 ) 98 ) 99 ); 100 // expected-warning@-8{{Call argument is uncounted and unsafe}} 101 } 102 } 103 104 namespace null_ptr { foo_ref()105 void foo_ref() { 106 consume_refcntbl(nullptr); 107 consume_refcntbl(0); 108 } 109 } 110 111 namespace ref_counted_lookalike { 112 struct Decoy { getref_counted_lookalike::Decoy113 RefCountable* get() { return nullptr; } 114 }; 115 foo()116 void foo() { 117 Decoy D; 118 119 consume_refcntbl(D.get()); 120 // expected-warning@-1{{Call argument is uncounted and unsafe}} 121 } 122 } 123 124 namespace Ref_to_reference_conversion_operator { 125 template<typename T> struct Ref { 126 Ref() = default; RefRef_to_reference_conversion_operator::Ref127 Ref(T*) { } getRef_to_reference_conversion_operator::Ref128 T* get() { return nullptr; } operator T&Ref_to_reference_conversion_operator::Ref129 operator T& () { return t; } 130 T t; 131 }; 132 consume_ref(RefCountable &)133 void consume_ref(RefCountable&) {} 134 foo()135 void foo() { 136 Ref<RefCountable> bar; 137 consume_ref(bar); 138 } 139 } 140 141 namespace param_formarding_function { consume_ref_countable_ref(RefCountable &)142 void consume_ref_countable_ref(RefCountable&) {} consume_ref_countable_ptr(RefCountable *)143 void consume_ref_countable_ptr(RefCountable*) {} 144 145 namespace ptr { foo(RefCountable * param)146 void foo(RefCountable* param) { 147 consume_ref_countable_ptr(param); 148 } 149 } 150 151 namespace ref { foo(RefCountable & param)152 void foo(RefCountable& param) { 153 consume_ref_countable_ref(param); 154 } 155 } 156 157 namespace ref_deref_operators { foo_ref(RefCountable & param)158 void foo_ref(RefCountable& param) { 159 consume_ref_countable_ptr(¶m); 160 } 161 foo_ptr(RefCountable * param)162 void foo_ptr(RefCountable* param) { 163 consume_ref_countable_ref(*param); 164 } 165 } 166 167 namespace casts { 168 downcast(RefCountable *)169 RefCountable* downcast(RefCountable*) { return nullptr; } 170 171 template<class T> bitwise_cast(T *)172 T* bitwise_cast(T*) { return nullptr; } 173 foo(RefCountable * param)174 void foo(RefCountable* param) { 175 consume_ref_countable_ptr(downcast(param)); 176 consume_ref_countable_ptr(bitwise_cast(param)); 177 } 178 } 179 } 180 181 namespace param_formarding_lambda { __anondd0dcd640102(RefCountable&) 182 auto consume_ref_countable_ref = [](RefCountable&) {}; __anondd0dcd640202(RefCountable*) 183 auto consume_ref_countable_ptr = [](RefCountable*) {}; 184 185 namespace ptr { foo(RefCountable * param)186 void foo(RefCountable* param) { 187 consume_ref_countable_ptr(param); 188 } 189 } 190 191 namespace ref { foo(RefCountable & param)192 void foo(RefCountable& param) { 193 consume_ref_countable_ref(param); 194 } 195 } 196 197 namespace ref_deref_operators { foo_ref(RefCountable & param)198 void foo_ref(RefCountable& param) { 199 consume_ref_countable_ptr(¶m); 200 } 201 foo_ptr(RefCountable * param)202 void foo_ptr(RefCountable* param) { 203 consume_ref_countable_ref(*param); 204 } 205 } 206 207 namespace casts { 208 downcast(RefCountable *)209 RefCountable* downcast(RefCountable*) { return nullptr; } 210 211 template<class T> bitwise_cast(T *)212 T* bitwise_cast(T*) { return nullptr; } 213 foo(RefCountable * param)214 void foo(RefCountable* param) { 215 consume_ref_countable_ptr(downcast(param)); 216 consume_ref_countable_ptr(bitwise_cast(param)); 217 } 218 } 219 } 220 221 namespace param_forwarding_method { 222 struct methodclass { consume_ref_countable_refparam_forwarding_method::methodclass223 void consume_ref_countable_ref(RefCountable&) {}; consume_ref_countable_ptrparam_forwarding_method::methodclass224 static void consume_ref_countable_ptr(RefCountable*) {}; 225 }; 226 227 namespace ptr { foo(RefCountable * param)228 void foo(RefCountable* param) { 229 methodclass::consume_ref_countable_ptr(param); 230 } 231 } 232 233 namespace ref { foo(RefCountable & param)234 void foo(RefCountable& param) { 235 methodclass mc; 236 mc.consume_ref_countable_ref(param); 237 } 238 } 239 240 namespace ref_deref_operators { foo_ref(RefCountable & param)241 void foo_ref(RefCountable& param) { 242 methodclass::consume_ref_countable_ptr(¶m); 243 } 244 foo_ptr(RefCountable * param)245 void foo_ptr(RefCountable* param) { 246 methodclass mc; 247 mc.consume_ref_countable_ref(*param); 248 } 249 } 250 251 namespace casts { 252 downcast(RefCountable *)253 RefCountable* downcast(RefCountable*) { return nullptr; } 254 255 template<class T> bitwise_cast(T *)256 T* bitwise_cast(T*) { return nullptr; } 257 foo(RefCountable * param)258 void foo(RefCountable* param) { 259 methodclass::consume_ref_countable_ptr(downcast(param)); 260 methodclass::consume_ref_countable_ptr(bitwise_cast(param)); 261 } 262 } 263 } 264 265 namespace make_ref { makeRef(RefCountable *)266 void makeRef(RefCountable*) {} makeRefPtr(RefCountable *)267 void makeRefPtr(RefCountable*) {} makeWeakPtr(RefCountable *)268 void makeWeakPtr(RefCountable*) {} makeWeakPtr(RefCountable &)269 void makeWeakPtr(RefCountable&) {} 270 foo()271 void foo() { 272 makeRef(provide()); 273 makeRefPtr(provide()); 274 RefPtr<RefCountable> a(provide()); 275 Ref<RefCountable> b(provide()); 276 makeWeakPtr(provide()); 277 makeWeakPtr(*provide()); 278 } 279 } 280 281 namespace downcast { consume_ref_countable(RefCountable *)282 void consume_ref_countable(RefCountable*) {} downcast(RefCountable *)283 RefCountable* downcast(RefCountable*) { return nullptr; } 284 foo()285 void foo() { 286 RefPtr<RefCountable> bar; 287 consume_ref_countable( downcast(bar.get()) ); 288 } 289 } 290 291 namespace string_impl { 292 struct String { implstring_impl::String293 RefCountable* impl() { return nullptr; } 294 }; 295 296 struct AtomString { 297 RefCountable rc; implstring_impl::AtomString298 RefCountable& impl() { return rc; } 299 }; 300 consume_ptr(RefCountable *)301 void consume_ptr(RefCountable*) {} consume_ref(RefCountable &)302 void consume_ref(RefCountable&) {} 303 304 namespace simple { foo()305 void foo() { 306 String s; 307 AtomString as; 308 consume_ptr(s.impl()); 309 consume_ref(as.impl()); 310 } 311 } 312 } 313 314 namespace default_arg { 315 RefCountable* global; 316 function_with_default_arg(RefCountable * param=global)317 void function_with_default_arg(RefCountable* param = global) {} 318 // expected-warning@-1{{Call argument for parameter 'param' is uncounted and unsafe}} 319 foo()320 void foo() { 321 function_with_default_arg(); 322 } 323 } 324 325 namespace cxx_member_operator_call { 326 // The hidden this-pointer argument without a corresponding parameter caused couple bugs in parameter <-> argument attribution. 327 struct Foo { operator +cxx_member_operator_call::Foo328 Foo& operator+(RefCountable* bad) { return *this; } operator -(Foo & lhs,RefCountable * bad)329 friend Foo& operator-(Foo& lhs, RefCountable* bad) { return lhs; } operator ()cxx_member_operator_call::Foo330 void operator()(RefCountable* bad) { } 331 }; 332 333 RefCountable* global; 334 foo()335 void foo() { 336 Foo f; 337 f + global; 338 // expected-warning@-1{{Call argument for parameter 'bad' is uncounted and unsafe}} 339 f - global; 340 // expected-warning@-1{{Call argument for parameter 'bad' is uncounted and unsafe}} 341 f(global); 342 // expected-warning@-1{{Call argument for parameter 'bad' is uncounted and unsafe}} 343 } 344 } 345