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