1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s 2 3 #include "mock-types.h" 4 5 RefCountable* provide() { return nullptr; } 6 void consume_refcntbl(RefCountable*) {} 7 8 namespace simple { 9 void foo() { 10 consume_refcntbl(provide()); 11 // expected-warning@-1{{Call argument is uncounted and unsafe}} 12 } 13 } 14 15 namespace multi_arg { 16 void consume_refcntbl(int, RefCountable* foo, bool) {} 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 { 24 Ref<RefCountable> provide_ref_counted() { return Ref<RefCountable>{}; } 25 void consume_ref_counted(Ref<RefCountable>) {} 26 27 void foo() { 28 consume_refcntbl(provide_ref_counted().get()); 29 // no warning 30 } 31 } 32 33 namespace methods { 34 struct Consumer { 35 void consume_ptr(RefCountable* ptr) {} 36 void consume_ref(const RefCountable& ref) {} 37 }; 38 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 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 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 { 70 RefCountable* downcast(RefCountable*) { return nullptr; } 71 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 { 105 void foo_ref() { 106 consume_refcntbl(nullptr); 107 consume_refcntbl(0); 108 } 109 } 110 111 namespace ref_counted_lookalike { 112 struct Decoy { 113 RefCountable* get() { return nullptr; } 114 }; 115 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; 127 Ref(T*) { } 128 T* get() { return nullptr; } 129 operator T& () { return t; } 130 T t; 131 }; 132 133 void consume_ref(RefCountable&) {} 134 135 void foo() { 136 Ref<RefCountable> bar; 137 consume_ref(bar); 138 } 139 } 140 141 namespace param_formarding_function { 142 void consume_ref_countable_ref(RefCountable&) {} 143 void consume_ref_countable_ptr(RefCountable*) {} 144 145 namespace ptr { 146 void foo(RefCountable* param) { 147 consume_ref_countable_ptr(param); 148 } 149 } 150 151 namespace ref { 152 void foo(RefCountable& param) { 153 consume_ref_countable_ref(param); 154 } 155 } 156 157 namespace ref_deref_operators { 158 void foo_ref(RefCountable& param) { 159 consume_ref_countable_ptr(¶m); 160 } 161 162 void foo_ptr(RefCountable* param) { 163 consume_ref_countable_ref(*param); 164 } 165 } 166 167 namespace casts { 168 169 RefCountable* downcast(RefCountable*) { return nullptr; } 170 171 template<class T> 172 T* bitwise_cast(T*) { return nullptr; } 173 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 { 182 auto consume_ref_countable_ref = [](RefCountable&) {}; 183 auto consume_ref_countable_ptr = [](RefCountable*) {}; 184 185 namespace ptr { 186 void foo(RefCountable* param) { 187 consume_ref_countable_ptr(param); 188 } 189 } 190 191 namespace ref { 192 void foo(RefCountable& param) { 193 consume_ref_countable_ref(param); 194 } 195 } 196 197 namespace ref_deref_operators { 198 void foo_ref(RefCountable& param) { 199 consume_ref_countable_ptr(¶m); 200 } 201 202 void foo_ptr(RefCountable* param) { 203 consume_ref_countable_ref(*param); 204 } 205 } 206 207 namespace casts { 208 209 RefCountable* downcast(RefCountable*) { return nullptr; } 210 211 template<class T> 212 T* bitwise_cast(T*) { return nullptr; } 213 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 { 223 void consume_ref_countable_ref(RefCountable&) {}; 224 static void consume_ref_countable_ptr(RefCountable*) {}; 225 }; 226 227 namespace ptr { 228 void foo(RefCountable* param) { 229 methodclass::consume_ref_countable_ptr(param); 230 } 231 } 232 233 namespace ref { 234 void foo(RefCountable& param) { 235 methodclass mc; 236 mc.consume_ref_countable_ref(param); 237 } 238 } 239 240 namespace ref_deref_operators { 241 void foo_ref(RefCountable& param) { 242 methodclass::consume_ref_countable_ptr(¶m); 243 } 244 245 void foo_ptr(RefCountable* param) { 246 methodclass mc; 247 mc.consume_ref_countable_ref(*param); 248 } 249 } 250 251 namespace casts { 252 253 RefCountable* downcast(RefCountable*) { return nullptr; } 254 255 template<class T> 256 T* bitwise_cast(T*) { return nullptr; } 257 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 { 266 void makeRef(RefCountable*) {} 267 void makeRefPtr(RefCountable*) {} 268 void makeWeakPtr(RefCountable*) {} 269 void makeWeakPtr(RefCountable&) {} 270 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 { 282 void consume_ref_countable(RefCountable*) {} 283 RefCountable* downcast(RefCountable*) { return nullptr; } 284 285 void foo() { 286 RefPtr<RefCountable> bar; 287 consume_ref_countable( downcast(bar.get()) ); 288 } 289 } 290 291 namespace string_impl { 292 struct String { 293 RefCountable* impl() { return nullptr; } 294 }; 295 296 struct AtomString { 297 RefCountable rc; 298 RefCountable& impl() { return rc; } 299 }; 300 301 void consume_ptr(RefCountable*) {} 302 void consume_ref(RefCountable&) {} 303 304 namespace simple { 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 317 void function_with_default_arg(RefCountable* param = global) {} 318 // expected-warning@-1{{Call argument for parameter 'param' is uncounted and unsafe}} 319 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 { 328 Foo& operator+(RefCountable* bad) { return *this; } 329 friend Foo& operator-(Foo& lhs, RefCountable* bad) { return lhs; } 330 void operator()(RefCountable* bad) { } 331 }; 332 333 RefCountable* global; 334 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