1ef353b02SRyosuke Niwa // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncheckedCallArgsChecker -verify %s 2ef353b02SRyosuke Niwa 3ef353b02SRyosuke Niwa #include "mock-types.h" 4ef353b02SRyosuke Niwa 5ef353b02SRyosuke Niwa CheckedObj* provide(); 6ef353b02SRyosuke Niwa void consume_refcntbl(CheckedObj*); 7ef353b02SRyosuke Niwa void some_function(); 8ef353b02SRyosuke Niwa 9ef353b02SRyosuke Niwa namespace simple { 10ef353b02SRyosuke Niwa void foo() { 11ef353b02SRyosuke Niwa consume_refcntbl(provide()); 12ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument is unchecked and unsafe}} 13ef353b02SRyosuke Niwa } 14ef353b02SRyosuke Niwa 15ef353b02SRyosuke Niwa // Test that the checker works with [[clang::suppress]]. 16ef353b02SRyosuke Niwa void foo_suppressed() { 17ef353b02SRyosuke Niwa [[clang::suppress]] 18ef353b02SRyosuke Niwa consume_refcntbl(provide()); // no-warning 19ef353b02SRyosuke Niwa } 20ef353b02SRyosuke Niwa } 21ef353b02SRyosuke Niwa 22ef353b02SRyosuke Niwa namespace multi_arg { 23ef353b02SRyosuke Niwa void consume_refcntbl(int, CheckedObj* foo, bool); 24ef353b02SRyosuke Niwa void foo() { 25ef353b02SRyosuke Niwa consume_refcntbl(42, provide(), true); 26ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument for parameter 'foo' is unchecked and unsafe}} 27ef353b02SRyosuke Niwa } 28ef353b02SRyosuke Niwa } 29ef353b02SRyosuke Niwa 30ef353b02SRyosuke Niwa namespace ref_counted { 31ef353b02SRyosuke Niwa CheckedRef<CheckedObj> provide_ref_counted() { return CheckedRef<CheckedObj>{}; } 32ef353b02SRyosuke Niwa void consume_ref_counted(CheckedRef<CheckedObj>) {} 33ef353b02SRyosuke Niwa 34ef353b02SRyosuke Niwa void foo() { 35ef353b02SRyosuke Niwa consume_refcntbl(provide_ref_counted().ptr()); 36ef353b02SRyosuke Niwa // no warning 37ef353b02SRyosuke Niwa } 38ef353b02SRyosuke Niwa } 39ef353b02SRyosuke Niwa 40ef353b02SRyosuke Niwa namespace methods { 41ef353b02SRyosuke Niwa struct Consumer { 42ef353b02SRyosuke Niwa void consume_ptr(CheckedObj* ptr); 43ef353b02SRyosuke Niwa void consume_ref(const CheckedObj& ref); 44ef353b02SRyosuke Niwa }; 45ef353b02SRyosuke Niwa 46ef353b02SRyosuke Niwa void foo() { 47ef353b02SRyosuke Niwa Consumer c; 48ef353b02SRyosuke Niwa 49ef353b02SRyosuke Niwa c.consume_ptr(provide()); 50ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument for parameter 'ptr' is unchecked and unsafe}} 51ef353b02SRyosuke Niwa c.consume_ref(*provide()); 52ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument for parameter 'ref' is unchecked and unsafe}} 53ef353b02SRyosuke Niwa } 54ef353b02SRyosuke Niwa 55ef353b02SRyosuke Niwa void foo2() { 56ef353b02SRyosuke Niwa struct Consumer { 57ef353b02SRyosuke Niwa void consume(CheckedObj*) { some_function(); } 58ef353b02SRyosuke Niwa void whatever() { 59ef353b02SRyosuke Niwa consume(provide()); 60ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument is unchecked and unsafe}} 61ef353b02SRyosuke Niwa } 62ef353b02SRyosuke Niwa }; 63ef353b02SRyosuke Niwa } 64ef353b02SRyosuke Niwa 65ef353b02SRyosuke Niwa void foo3() { 66ef353b02SRyosuke Niwa struct Consumer { 67ef353b02SRyosuke Niwa void consume(CheckedObj*) { some_function(); } 68ef353b02SRyosuke Niwa void whatever() { 69ef353b02SRyosuke Niwa this->consume(provide()); 70ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument is unchecked and unsafe}} 71ef353b02SRyosuke Niwa } 72ef353b02SRyosuke Niwa }; 73ef353b02SRyosuke Niwa } 74ef353b02SRyosuke Niwa } 75ef353b02SRyosuke Niwa 76ef353b02SRyosuke Niwa namespace casts { 77ef353b02SRyosuke Niwa CheckedObj* downcast(CheckedObj*); 78ef353b02SRyosuke Niwa 79ef353b02SRyosuke Niwa void foo() { 80ef353b02SRyosuke Niwa consume_refcntbl(provide()); 81ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument is unchecked and unsafe}} 82ef353b02SRyosuke Niwa 83ef353b02SRyosuke Niwa consume_refcntbl(static_cast<CheckedObj*>(provide())); 84ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument is unchecked and unsafe}} 85ef353b02SRyosuke Niwa 86ef353b02SRyosuke Niwa consume_refcntbl(dynamic_cast<CheckedObj*>(provide())); 87ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument is unchecked and unsafe}} 88ef353b02SRyosuke Niwa 89ef353b02SRyosuke Niwa consume_refcntbl(const_cast<CheckedObj*>(provide())); 90ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument is unchecked and unsafe}} 91ef353b02SRyosuke Niwa 92ef353b02SRyosuke Niwa consume_refcntbl(reinterpret_cast<CheckedObj*>(provide())); 93ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument is unchecked and unsafe}} 94ef353b02SRyosuke Niwa 95ef353b02SRyosuke Niwa consume_refcntbl(downcast(provide())); 96ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument is unchecked and unsafe}} 97ef353b02SRyosuke Niwa 98ef353b02SRyosuke Niwa consume_refcntbl( 99ef353b02SRyosuke Niwa static_cast<CheckedObj*>( 100ef353b02SRyosuke Niwa downcast( 101ef353b02SRyosuke Niwa static_cast<CheckedObj*>( 102ef353b02SRyosuke Niwa provide() 103ef353b02SRyosuke Niwa ) 104ef353b02SRyosuke Niwa ) 105ef353b02SRyosuke Niwa ) 106ef353b02SRyosuke Niwa ); 107ef353b02SRyosuke Niwa // expected-warning@-8{{Call argument is unchecked and unsafe}} 108ef353b02SRyosuke Niwa } 109ef353b02SRyosuke Niwa } 110ef353b02SRyosuke Niwa 111ef353b02SRyosuke Niwa namespace null_ptr { 112ef353b02SRyosuke Niwa void foo_ref() { 113ef353b02SRyosuke Niwa consume_refcntbl(nullptr); 114ef353b02SRyosuke Niwa consume_refcntbl(0); 115ef353b02SRyosuke Niwa } 116ef353b02SRyosuke Niwa } 117ef353b02SRyosuke Niwa 118ef353b02SRyosuke Niwa namespace ref_counted_lookalike { 119ef353b02SRyosuke Niwa struct Decoy { 120*05860f9bSRyosuke Niwa CheckedObj* get(); 121ef353b02SRyosuke Niwa }; 122ef353b02SRyosuke Niwa 123ef353b02SRyosuke Niwa void foo() { 124ef353b02SRyosuke Niwa Decoy D; 125ef353b02SRyosuke Niwa 126ef353b02SRyosuke Niwa consume_refcntbl(D.get()); 127ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument is unchecked and unsafe}} 128ef353b02SRyosuke Niwa } 129ef353b02SRyosuke Niwa } 130ef353b02SRyosuke Niwa 131ef353b02SRyosuke Niwa namespace Ref_to_reference_conversion_operator { 132ef353b02SRyosuke Niwa template<typename T> struct Ref { 133ef353b02SRyosuke Niwa Ref() = default; 134ef353b02SRyosuke Niwa Ref(T*) { } 135ef353b02SRyosuke Niwa T* get() { return nullptr; } 136ef353b02SRyosuke Niwa operator T& () { return t; } 137ef353b02SRyosuke Niwa T t; 138ef353b02SRyosuke Niwa }; 139ef353b02SRyosuke Niwa 140ef353b02SRyosuke Niwa void consume_ref(CheckedObj&) {} 141ef353b02SRyosuke Niwa 142ef353b02SRyosuke Niwa void foo() { 143ef353b02SRyosuke Niwa CheckedRef<CheckedObj> bar; 144ef353b02SRyosuke Niwa consume_ref(bar); 145ef353b02SRyosuke Niwa } 146ef353b02SRyosuke Niwa } 147ef353b02SRyosuke Niwa 148ef353b02SRyosuke Niwa namespace param_formarding_function { 149ef353b02SRyosuke Niwa void consume_ref_countable_ref(CheckedObj&); 150ef353b02SRyosuke Niwa void consume_ref_countable_ptr(CheckedObj*); 151ef353b02SRyosuke Niwa 152ef353b02SRyosuke Niwa namespace ptr { 153ef353b02SRyosuke Niwa void foo(CheckedObj* param) { 154ef353b02SRyosuke Niwa consume_ref_countable_ptr(param); 155ef353b02SRyosuke Niwa } 156ef353b02SRyosuke Niwa } 157ef353b02SRyosuke Niwa 158ef353b02SRyosuke Niwa namespace ref { 159ef353b02SRyosuke Niwa void foo(CheckedObj& param) { 160ef353b02SRyosuke Niwa consume_ref_countable_ref(param); 161ef353b02SRyosuke Niwa } 162ef353b02SRyosuke Niwa } 163ef353b02SRyosuke Niwa 164ef353b02SRyosuke Niwa namespace ref_deref_operators { 165ef353b02SRyosuke Niwa void foo_ref(CheckedObj& param) { 166ef353b02SRyosuke Niwa consume_ref_countable_ptr(¶m); 167ef353b02SRyosuke Niwa } 168ef353b02SRyosuke Niwa 169ef353b02SRyosuke Niwa void foo_ptr(CheckedObj* param) { 170ef353b02SRyosuke Niwa consume_ref_countable_ref(*param); 171ef353b02SRyosuke Niwa } 172ef353b02SRyosuke Niwa } 173ef353b02SRyosuke Niwa 174ef353b02SRyosuke Niwa namespace casts { 175ef353b02SRyosuke Niwa 176ef353b02SRyosuke Niwa CheckedObj* downcast(CheckedObj*) { return nullptr; } 177ef353b02SRyosuke Niwa 178ef353b02SRyosuke Niwa template<class T> 179ef353b02SRyosuke Niwa T* bitwise_cast(T*) { return nullptr; } 180ef353b02SRyosuke Niwa 181ef353b02SRyosuke Niwa void foo(CheckedObj* param) { 182ef353b02SRyosuke Niwa consume_ref_countable_ptr(downcast(param)); 183ef353b02SRyosuke Niwa consume_ref_countable_ptr(bitwise_cast(param)); 184ef353b02SRyosuke Niwa } 185ef353b02SRyosuke Niwa } 186ef353b02SRyosuke Niwa } 187ef353b02SRyosuke Niwa 188ef353b02SRyosuke Niwa namespace param_formarding_lambda { 189ef353b02SRyosuke Niwa auto consume_ref_countable_ref = [](CheckedObj&) { some_function(); }; 190ef353b02SRyosuke Niwa auto consume_ref_countable_ptr = [](CheckedObj*) { some_function(); }; 191ef353b02SRyosuke Niwa 192ef353b02SRyosuke Niwa namespace ptr { 193ef353b02SRyosuke Niwa void foo(CheckedObj* param) { 194ef353b02SRyosuke Niwa consume_ref_countable_ptr(param); 195ef353b02SRyosuke Niwa } 196ef353b02SRyosuke Niwa } 197ef353b02SRyosuke Niwa 198ef353b02SRyosuke Niwa namespace ref { 199ef353b02SRyosuke Niwa void foo(CheckedObj& param) { 200ef353b02SRyosuke Niwa consume_ref_countable_ref(param); 201ef353b02SRyosuke Niwa } 202ef353b02SRyosuke Niwa } 203ef353b02SRyosuke Niwa 204ef353b02SRyosuke Niwa namespace ref_deref_operators { 205ef353b02SRyosuke Niwa void foo_ref(CheckedObj& param) { 206ef353b02SRyosuke Niwa consume_ref_countable_ptr(¶m); 207ef353b02SRyosuke Niwa } 208ef353b02SRyosuke Niwa 209ef353b02SRyosuke Niwa void foo_ptr(CheckedObj* param) { 210ef353b02SRyosuke Niwa consume_ref_countable_ref(*param); 211ef353b02SRyosuke Niwa } 212ef353b02SRyosuke Niwa } 213ef353b02SRyosuke Niwa 214ef353b02SRyosuke Niwa namespace casts { 215ef353b02SRyosuke Niwa 216ef353b02SRyosuke Niwa CheckedObj* downcast(CheckedObj*) { return nullptr; } 217ef353b02SRyosuke Niwa 218ef353b02SRyosuke Niwa template<class T> 219ef353b02SRyosuke Niwa T* bitwise_cast(T*) { return nullptr; } 220ef353b02SRyosuke Niwa 221ef353b02SRyosuke Niwa void foo(CheckedObj* param) { 222ef353b02SRyosuke Niwa consume_ref_countable_ptr(downcast(param)); 223ef353b02SRyosuke Niwa consume_ref_countable_ptr(bitwise_cast(param)); 224ef353b02SRyosuke Niwa } 225ef353b02SRyosuke Niwa } 226ef353b02SRyosuke Niwa } 227ef353b02SRyosuke Niwa 228ef353b02SRyosuke Niwa namespace param_forwarding_method { 229ef353b02SRyosuke Niwa struct methodclass { 230ef353b02SRyosuke Niwa void consume_ref_countable_ref(CheckedObj&) {}; 231ef353b02SRyosuke Niwa static void consume_ref_countable_ptr(CheckedObj*) {}; 232ef353b02SRyosuke Niwa }; 233ef353b02SRyosuke Niwa 234ef353b02SRyosuke Niwa namespace ptr { 235ef353b02SRyosuke Niwa void foo(CheckedObj* param) { 236ef353b02SRyosuke Niwa methodclass::consume_ref_countable_ptr(param); 237ef353b02SRyosuke Niwa } 238ef353b02SRyosuke Niwa } 239ef353b02SRyosuke Niwa 240ef353b02SRyosuke Niwa namespace ref { 241ef353b02SRyosuke Niwa void foo(CheckedObj& param) { 242ef353b02SRyosuke Niwa methodclass mc; 243ef353b02SRyosuke Niwa mc.consume_ref_countable_ref(param); 244ef353b02SRyosuke Niwa } 245ef353b02SRyosuke Niwa } 246ef353b02SRyosuke Niwa 247ef353b02SRyosuke Niwa namespace ref_deref_operators { 248ef353b02SRyosuke Niwa void foo_ref(CheckedObj& param) { 249ef353b02SRyosuke Niwa methodclass::consume_ref_countable_ptr(¶m); 250ef353b02SRyosuke Niwa } 251ef353b02SRyosuke Niwa 252ef353b02SRyosuke Niwa void foo_ptr(CheckedObj* param) { 253ef353b02SRyosuke Niwa methodclass mc; 254ef353b02SRyosuke Niwa mc.consume_ref_countable_ref(*param); 255ef353b02SRyosuke Niwa } 256ef353b02SRyosuke Niwa } 257ef353b02SRyosuke Niwa 258ef353b02SRyosuke Niwa namespace casts { 259ef353b02SRyosuke Niwa 260ef353b02SRyosuke Niwa CheckedObj* downcast(CheckedObj*) { return nullptr; } 261ef353b02SRyosuke Niwa 262ef353b02SRyosuke Niwa template<class T> 263ef353b02SRyosuke Niwa T* bitwise_cast(T*) { return nullptr; } 264ef353b02SRyosuke Niwa 265ef353b02SRyosuke Niwa void foo(CheckedObj* param) { 266ef353b02SRyosuke Niwa methodclass::consume_ref_countable_ptr(downcast(param)); 267ef353b02SRyosuke Niwa methodclass::consume_ref_countable_ptr(bitwise_cast(param)); 268ef353b02SRyosuke Niwa } 269ef353b02SRyosuke Niwa } 270ef353b02SRyosuke Niwa } 271ef353b02SRyosuke Niwa 272ef353b02SRyosuke Niwa namespace downcast { 273ef353b02SRyosuke Niwa void consume_ref_countable(CheckedObj*) {} 274ef353b02SRyosuke Niwa CheckedObj* downcast(CheckedObj*) { return nullptr; } 275ef353b02SRyosuke Niwa 276ef353b02SRyosuke Niwa void foo() { 277ef353b02SRyosuke Niwa CheckedPtr<CheckedObj> bar; 278ef353b02SRyosuke Niwa consume_ref_countable( downcast(bar.get()) ); 279ef353b02SRyosuke Niwa } 280ef353b02SRyosuke Niwa } 281ef353b02SRyosuke Niwa 282ef353b02SRyosuke Niwa namespace string_impl { 283ef353b02SRyosuke Niwa struct String { 284ef353b02SRyosuke Niwa CheckedObj* impl() { return nullptr; } 285ef353b02SRyosuke Niwa }; 286ef353b02SRyosuke Niwa 287ef353b02SRyosuke Niwa struct AtomString { 288ef353b02SRyosuke Niwa CheckedObj rc; 289ef353b02SRyosuke Niwa CheckedObj& impl() { return rc; } 290ef353b02SRyosuke Niwa }; 291ef353b02SRyosuke Niwa 292ef353b02SRyosuke Niwa void consume_ptr(CheckedObj*) {} 293ef353b02SRyosuke Niwa void consume_ref(CheckedObj&) {} 294ef353b02SRyosuke Niwa 295ef353b02SRyosuke Niwa namespace simple { 296ef353b02SRyosuke Niwa void foo() { 297ef353b02SRyosuke Niwa String s; 298ef353b02SRyosuke Niwa AtomString as; 299ef353b02SRyosuke Niwa consume_ptr(s.impl()); 300ef353b02SRyosuke Niwa consume_ref(as.impl()); 301ef353b02SRyosuke Niwa } 302ef353b02SRyosuke Niwa } 303ef353b02SRyosuke Niwa } 304ef353b02SRyosuke Niwa 305ef353b02SRyosuke Niwa namespace default_arg { 306ef353b02SRyosuke Niwa CheckedObj* global; 307ef353b02SRyosuke Niwa 308ef353b02SRyosuke Niwa void function_with_default_arg(CheckedObj* param = global); 309ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument for parameter 'param' is unchecked and unsafe}} 310ef353b02SRyosuke Niwa 311ef353b02SRyosuke Niwa void foo() { 312ef353b02SRyosuke Niwa function_with_default_arg(); 313ef353b02SRyosuke Niwa } 314ef353b02SRyosuke Niwa } 315ef353b02SRyosuke Niwa 316ef353b02SRyosuke Niwa namespace cxx_member_func { 317ef353b02SRyosuke Niwa CheckedRef<CheckedObj> provideProtected(); 318ef353b02SRyosuke Niwa void foo() { 319ef353b02SRyosuke Niwa provide()->trivial(); 320ef353b02SRyosuke Niwa provide()->method(); 321ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument for 'this' parameter is unchecked and unsafe}} 322ef353b02SRyosuke Niwa provideProtected()->method(); 323ef353b02SRyosuke Niwa (provideProtected())->method(); 324ef353b02SRyosuke Niwa }; 325ef353b02SRyosuke Niwa } 326ef353b02SRyosuke Niwa 327ef353b02SRyosuke Niwa namespace cxx_member_operator_call { 328ef353b02SRyosuke Niwa // The hidden this-pointer argument without a corresponding parameter caused couple bugs in parameter <-> argument attribution. 329ef353b02SRyosuke Niwa struct Foo { 330ef353b02SRyosuke Niwa Foo& operator+(CheckedObj* bad); 331ef353b02SRyosuke Niwa friend Foo& operator-(Foo& lhs, CheckedObj* bad); 332ef353b02SRyosuke Niwa void operator()(CheckedObj* bad); 333ef353b02SRyosuke Niwa }; 334ef353b02SRyosuke Niwa 335ef353b02SRyosuke Niwa CheckedObj* global; 336ef353b02SRyosuke Niwa 337ef353b02SRyosuke Niwa void foo() { 338ef353b02SRyosuke Niwa Foo f; 339ef353b02SRyosuke Niwa f + global; 340ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument for parameter 'bad' is unchecked and unsafe}} 341ef353b02SRyosuke Niwa f - global; 342ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument for parameter 'bad' is unchecked and unsafe}} 343ef353b02SRyosuke Niwa f(global); 344ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument for parameter 'bad' is unchecked and unsafe}} 345ef353b02SRyosuke Niwa } 346ef353b02SRyosuke Niwa } 347ef353b02SRyosuke Niwa 348ef353b02SRyosuke Niwa namespace call_with_ptr_on_ref { 349ef353b02SRyosuke Niwa CheckedRef<CheckedObj> provideProtected(); 350ef353b02SRyosuke Niwa void bar(CheckedObj* bad); 351ef353b02SRyosuke Niwa bool baz(); 352ef353b02SRyosuke Niwa void foo(bool v) { 353ef353b02SRyosuke Niwa bar(v ? nullptr : provideProtected().ptr()); 354ef353b02SRyosuke Niwa bar(baz() ? provideProtected().ptr() : nullptr); 355ef353b02SRyosuke Niwa bar(v ? provide() : provideProtected().ptr()); 356ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument for parameter 'bad' is unchecked and unsafe}} 357ef353b02SRyosuke Niwa bar(v ? provideProtected().ptr() : provide()); 358ef353b02SRyosuke Niwa // expected-warning@-1{{Call argument for parameter 'bad' is unchecked and unsafe}} 359ef353b02SRyosuke Niwa } 360ef353b02SRyosuke Niwa } 361ef353b02SRyosuke Niwa 362ef353b02SRyosuke Niwa namespace call_with_explicit_temporary_obj { 363ef353b02SRyosuke Niwa void foo() { 364ef353b02SRyosuke Niwa CheckedRef { *provide() }->method(); 365ef353b02SRyosuke Niwa CheckedPtr { provide() }->method(); 366ef353b02SRyosuke Niwa } 367ef353b02SRyosuke Niwa } 36873b577ccSRyosuke Niwa 36973b577ccSRyosuke Niwa namespace call_with_checked_ptr { 37073b577ccSRyosuke Niwa 37173b577ccSRyosuke Niwa class Foo : public CheckedObj { 37273b577ccSRyosuke Niwa public: 37373b577ccSRyosuke Niwa CheckedPtr<CheckedObj> obj1() { return m_obj; } 37473b577ccSRyosuke Niwa CheckedRef<CheckedObj> obj2() { return *m_obj; } 37573b577ccSRyosuke Niwa private: 37673b577ccSRyosuke Niwa CheckedObj* m_obj; 37773b577ccSRyosuke Niwa }; 37873b577ccSRyosuke Niwa 37973b577ccSRyosuke Niwa Foo* getFoo(); 38073b577ccSRyosuke Niwa 38173b577ccSRyosuke Niwa void bar() { 38273b577ccSRyosuke Niwa getFoo()->obj1()->method(); 38373b577ccSRyosuke Niwa getFoo()->obj2()->method(); 38473b577ccSRyosuke Niwa } 38573b577ccSRyosuke Niwa 38673b577ccSRyosuke Niwa } 387