brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.9 KiB · 8bef24f Raw
669 lines · plain
1// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}}2// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedCallArgsChecker -verify %s3 4#include "objc-mock-types.h"5 6SomeObj *provide();7void consume_obj(SomeObj*);8 9CFMutableArrayRef provide_cf();10void consume_cf(CFMutableArrayRef);11 12dispatch_queue_t provide_dispatch();13void consume_dispatch(dispatch_queue_t);14 15CGImageRef provideImage();16NSString *stringForImage(CGImageRef);17 18void some_function();19 20namespace simple {21  void foo() {22    consume_obj(provide());23    // expected-warning@-1{{Call argument is unretained and unsafe}}24    consume_cf(provide_cf());25    // expected-warning@-1{{Call argument is unretained and unsafe}}26    consume_dispatch(provide_dispatch());27    // expected-warning@-1{{Call argument is unretained and unsafe}}28  }29 30  // Test that the checker works with [[clang::suppress]].31  void foo_suppressed() {32    [[clang::suppress]] consume_obj(provide()); // no-warning33    [[clang::suppress]] consume_cf(provide_cf()); // no-warning34  }35 36}37 38namespace multi_arg {39  void consume_retainable(int, SomeObj* foo, CFMutableArrayRef bar, dispatch_queue_t baz, bool);40  void foo() {41    consume_retainable(42, provide(), provide_cf(), provide_dispatch(), true);42    // expected-warning@-1{{Call argument for parameter 'foo' is unretained and unsafe}}43    // expected-warning@-2{{Call argument for parameter 'bar' is unretained and unsafe}}44    // expected-warning@-3{{Call argument for parameter 'baz' is unretained and unsafe}}45  }46 47  void consume_retainable(SomeObj* foo, ...);48  void bar() {49    consume_retainable(provide(), 1, provide_cf(), RetainPtr<CFMutableArrayRef> { provide_cf() }.get(), provide_dispatch());50    // expected-warning@-1{{Call argument for parameter 'foo' is unretained and unsafe}}51    // expected-warning@-2{{Call argument is unretained and unsafe}}52    // expected-warning@-3{{Call argument is unretained and unsafe}}53     consume_retainable(RetainPtr<SomeObj> { provide() }.get(), 1, RetainPtr<CFMutableArrayRef> { provide_cf() }.get());54  }55}56 57namespace retained {58  RetainPtr<SomeObj> provide_obj();59  RetainPtr<CFMutableArrayRef> provide_cf();60  OSObjectPtr<dispatch_queue_t> provide_dispatch();61  void foo() {62    consume_obj(provide_obj().get()); // no warning63    consume_cf(provide_cf().get()); // no warning64    consume_dispatch(provide_dispatch().get()); // no warning65  }66}67 68namespace methods {69  struct Consumer {70    void consume_obj(SomeObj* ptr);71    void consume_cf(CFMutableArrayRef ref);72    void consume_dispatch(dispatch_queue_t ptr);73  };74 75  void foo() {76    Consumer c;77 78    c.consume_obj(provide());79    // expected-warning@-1{{Call argument for parameter 'ptr' is unretained and unsafe}}80    c.consume_cf(provide_cf());81    // expected-warning@-1{{Call argument for parameter 'ref' is unretained and unsafe}}82    c.consume_dispatch(provide_dispatch());83    // expected-warning@-1{{Call argument for parameter 'ptr' is unretained and unsafe}}84  }85 86  void foo2() {87    struct Consumer {88      void consume(SomeObj*) { some_function(); }89      void whatever() {90        consume(provide());91        // expected-warning@-1{{Call argument is unretained and unsafe}}92      }93 94      void consume_cf(CFMutableArrayRef) { some_function(); }95      void something() {96        consume_cf(provide_cf());97        // expected-warning@-1{{Call argument is unretained and unsafe}}98      }99 100      void consume_dispatch(dispatch_queue_t) { some_function(); }101      void anything() {102        consume_dispatch(provide_dispatch());103        // expected-warning@-1{{Call argument is unretained and unsafe}}104      }105    };106  }107 108  void foo3() {109    struct Consumer {110      void consume(SomeObj*) { some_function(); }111      void whatever() {112        this->consume(provide());113        // expected-warning@-1{{Call argument is unretained and unsafe}}114      }115 116      void consume_cf(CFMutableArrayRef) { some_function(); }117      void something() {118        this->consume_cf(provide_cf());119        // expected-warning@-1{{Call argument is unretained and unsafe}}120      }121 122      void consume_dispatch(dispatch_queue_t) { some_function(); }123      void anything() {124        this->consume_dispatch(provide_dispatch());125        // expected-warning@-1{{Call argument is unretained and unsafe}}126      }127    };128  }129 130}131 132namespace casts {133  void foo() {134    consume_obj(provide());135    // expected-warning@-1{{Call argument is unretained and unsafe}}136 137    consume_obj(static_cast<OtherObj*>(provide()));138    // expected-warning@-1{{Call argument is unretained and unsafe}}139 140    consume_obj(reinterpret_cast<OtherObj*>(provide()));141    // expected-warning@-1{{Call argument is unretained and unsafe}}142 143    consume_obj(downcast<OtherObj>(provide()));144    // expected-warning@-1{{Call argument is unretained and unsafe}}145  }146}147 148namespace null_ptr {149  void foo_ref() {150    consume_obj(nullptr);151    consume_obj(0);152    consume_cf(nullptr);153    consume_cf(0);154    consume_dispatch(nullptr);155    consume_dispatch(0);156  }157}158 159namespace retain_ptr_lookalike {160  struct Decoy {161    SomeObj* get();162  };163 164  void foo() {165    Decoy D;166 167    consume_obj(D.get());168    // expected-warning@-1{{Call argument is unretained and unsafe}}169  }170 171  struct Decoy2 {172    CFMutableArrayRef get();173  };174 175  void bar() {176    Decoy2 D;177 178    consume_cf(D.get());179    // expected-warning@-1{{Call argument is unretained and unsafe}}180  }181}182 183namespace param_formarding_function {184  void consume_more_obj(OtherObj*);185  void consume_more_cf(CFMutableArrayRef);186  void consume_more_dispatch(dispatch_queue_t);187 188  namespace objc {189    void foo(SomeObj* param) {190      consume_more_obj(downcast<OtherObj>(param));191    }192  }193 194  namespace cf {195    void foo(CFMutableArrayRef param) {196      consume_more_cf(param);197    }198  }199}200 201namespace param_formarding_lambda {202  auto consume_more_obj = [](OtherObj*) { some_function(); };203  auto consume_more_cf = [](CFMutableArrayRef) { some_function(); };204  auto consume_more_dispatch = [](dispatch_queue_t) { some_function(); };205 206  namespace objc {207    void foo(SomeObj* param) {208      consume_more_obj(downcast<OtherObj>(param));209    }210  }211 212  namespace cf {213    void foo(CFMutableArrayRef param) {214      consume_more_cf(param);215    }216  }217  218  namespace os_obj {219    void foo(dispatch_queue_t param) {220      consume_more_dispatch(param);221    }222  }223}224 225namespace param_forwarding_method {226  struct Consumer {227    void consume_obj(SomeObj*);228    static void consume_obj_s(SomeObj*);229    void consume_cf(CFMutableArrayRef);230    static void consume_cf_s(CFMutableArrayRef);231    void consume_dispatch(dispatch_queue_t);232    static void consume_dispatch_s(dispatch_queue_t);233  };234 235  void bar(Consumer* consumer, SomeObj* param) {236    consumer->consume_obj(param);237  }238 239  void foo(SomeObj* param) {240    Consumer::consume_obj_s(param);241  }242 243  void baz(Consumer* consumer, CFMutableArrayRef param) {244    consumer->consume_cf(param);245    Consumer::consume_cf_s(param);246  }247 248  void baz(Consumer* consumer, dispatch_queue_t param) {249    consumer->consume_dispatch(param);250    Consumer::consume_dispatch_s(param);251  }252}253 254 255namespace default_arg {256  SomeObj* global;257  CFMutableArrayRef global_cf;258  dispatch_queue_t global_dispatch;259 260  void function_with_default_arg1(SomeObj* param = global);261  // expected-warning@-1{{Call argument for parameter 'param' is unretained and unsafe}}262 263  void function_with_default_arg2(CFMutableArrayRef param = global_cf);264  // expected-warning@-1{{Call argument for parameter 'param' is unretained and unsafe}}265 266  void function_with_default_arg3(dispatch_queue_t param = global_dispatch);267  // expected-warning@-1{{Call argument for parameter 'param' is unretained and unsafe}}268 269  void foo() {270    function_with_default_arg1();271    function_with_default_arg2();272    function_with_default_arg3();273  }274}275 276namespace cxx_member_func {277  RetainPtr<SomeObj> protectedProvide();278  RetainPtr<CFMutableArrayRef> protectedProvideCF();279 280  void foo() {281    [provide() doWork];282    // expected-warning@-1{{Receiver is unretained and unsafe}}283    [protectedProvide().get() doWork];284 285    CFArrayAppendValue(provide_cf(), nullptr);286    // expected-warning@-1{{Call argument for parameter 'theArray' is unretained and unsafe}}287    CFArrayAppendValue(protectedProvideCF(), nullptr);288  };289 290  void bar() {291    [downcast<OtherObj>(protectedProvide().get()) doMoreWork:downcast<OtherObj>(provide())];292    // expected-warning@-1{{Call argument for parameter 'other' is unretained and unsafe}}293    [protectedProvide().get() doWork];294  };295 296}297 298namespace cxx_member_operator_call {299  // The hidden this-pointer argument without a corresponding parameter caused couple bugs in parameter <-> argument attribution.300  struct Foo {301    Foo& operator+(SomeObj* bad);302    friend Foo& operator-(Foo& lhs, SomeObj* bad);303    void operator()(SomeObj* bad);304    Foo& operator<<(dispatch_queue_t bad);305  };306 307  SomeObj* global;308  dispatch_queue_t global_dispatch;309 310  void foo() {311    Foo f;312    f + global;313    // expected-warning@-1{{Call argument for parameter 'bad' is unretained and unsafe}}314    f - global;315    // expected-warning@-1{{Call argument for parameter 'bad' is unretained and unsafe}}316    f(global);317    // expected-warning@-1{{Call argument for parameter 'bad' is unretained and unsafe}}318    f << global_dispatch;319    // expected-warning@-1{{Call argument for parameter 'bad' is unretained and unsafe}}320  }321}322 323namespace cxx_assignment_op {324 325  SomeObj* provide();326  void foo() {327    RetainPtr<SomeObj> ptr;328    ptr = provide();329    OSObjectPtr<dispatch_queue_t> objPtr;330    objPtr = provide_dispatch();331  }332 333}334 335namespace call_with_ptr_on_ref {336  RetainPtr<SomeObj> provideProtected();337  RetainPtr<CFMutableArrayRef> provideProtectedCF();338  OSObjectPtr<dispatch_queue_t> provideProtectedDispatch();339  void bar(SomeObj* bad);340  void bar_cf(CFMutableArrayRef bad);341  void bar_dispatch(dispatch_queue_t);342  bool baz();343  void foo(bool v) {344    bar(v ? nullptr : provideProtected().get());345    bar(baz() ? provideProtected().get() : nullptr);346    bar(v ? provide() : provideProtected().get());347    // expected-warning@-1{{Call argument for parameter 'bad' is unretained and unsafe}}348    bar(v ? provideProtected().get() : provide());349    // expected-warning@-1{{Call argument for parameter 'bad' is unretained and unsafe}}350 351    bar_cf(v ? nullptr : provideProtectedCF().get());352    bar_cf(baz() ? provideProtectedCF().get() : nullptr);353    bar_cf(v ? provide_cf() : provideProtectedCF().get());354    // expected-warning@-1{{Call argument for parameter 'bad' is unretained and unsafe}}355    bar_cf(v ? provideProtectedCF().get() : provide_cf());356    // expected-warning@-1{{Call argument for parameter 'bad' is unretained and unsafe}}357 358    bar_dispatch(v ? nullptr : provideProtectedDispatch().get());359    bar_dispatch(baz() ? provideProtectedDispatch().get() : nullptr);360    bar_dispatch(v ? provide_dispatch() : provideProtectedDispatch().get());361    // expected-warning@-1{{Call argument is unretained and unsafe}}362    bar_dispatch(v ? provideProtectedDispatch().get() : provide_dispatch());363    // expected-warning@-1{{Call argument is unretained and unsafe}}364  }365}366 367namespace call_with_explicit_temporary_obj {368  void foo() {369    [RetainPtr<SomeObj>(provide()).get() doWork];370    CFArrayAppendValue(RetainPtr<CFMutableArrayRef> { provide_cf() }.get(), nullptr);371  }372  template <typename T>373  void bar() {374    [RetainPtr<SomeObj>(provide()).get() doWork];375    CFArrayAppendValue(RetainPtr<CFMutableArrayRef> { provide_cf() }.get(), nullptr);376  }377  void baz() {378    bar<int>();379  }380  void os_ptr() {381    consume_dispatch(OSObjectPtr { provide_dispatch() }.get());382  }383}384 385namespace call_with_adopt_ref {386  void foo() {387    [adoptNS(provide()).get() doWork];388    CFArrayAppendValue(adoptCF(provide_cf()).get(), nullptr);389    consume_dispatch(adoptOSObject(provide_dispatch()).get());390  }391}392 393#define YES __objc_yes394#define NO 0395 396namespace call_with_cf_constant {397  void bar(const NSArray *);398  void baz(const NSDictionary *);399  void boo(NSNumber *);400  void boo(CFTypeRef);401 402  struct Details {403    int value;404  };405 406  void foo(Details* details) {407    CFArrayCreateMutable(kCFAllocatorDefault, 10);408    bar(@[@"hello"]);409    baz(@{@"hello": @3});410    boo(@YES);411    boo(@NO);412    boo(@(details->value));413  }414}415 416namespace call_with_cf_string {417  void bar(CFStringRef);418  void foo() {419    bar(CFSTR("hello"));420  }421}422 423namespace call_with_ns_string {424  void bar(NSString *);425  void foo() {426    bar(@"world");427  }428}429 430namespace bridge_cast_arg {431  void bar(NSString *);432  void baz(NSString *);433  extern const CFStringRef kCFBundleNameKey;434 435  NSObject *foo(CFStringRef arg) {436    bar((NSString *)bridge_cast((CFTypeRef)arg));437    auto dict = @{438      @"hello": @1,439    };440    return dict[(__bridge NSString *)kCFBundleNameKey];441  }442}443 444namespace alloc_init_pair {445  void foo() {446    auto obj = adoptNS([[SomeObj alloc] init]);447    [obj doWork];448  }449}450 451namespace alloc_class {452  bool foo(NSObject *obj) {453    return [obj isKindOfClass:SomeObj.class] && [obj isKindOfClass:NSClassFromString(@"SomeObj")];454  }455 456  bool bar(NSObject *obj) {457    return [obj isKindOfClass:[SomeObj class]];458  }459 460  bool baz(NSObject *obj) {461    return [obj isKindOfClass:[SomeObj superclass]];462  }463}464 465namespace ptr_conversion {466 467SomeObj *provide_obj();468 469void dobjc(SomeObj* obj) {470  [dynamic_objc_cast<OtherObj>(obj) doMoreWork:nil];471}472 473void cobjc(SomeObj* obj) {474  [checked_objc_cast<OtherObj>(obj) doMoreWork:nil];475}476 477unsigned dcf(CFTypeRef obj) {478  return CFArrayGetCount(dynamic_cf_cast<CFArrayRef>(obj));479}480 481unsigned ccf(CFTypeRef obj) {482  return CFArrayGetCount(checked_cf_cast<CFArrayRef>(obj));483}484 485void some_function(id);486void idcf(CFTypeRef obj) {487  some_function(bridge_id_cast(obj));488}489 490} // ptr_conversion491 492namespace const_global {493 494extern NSString * const SomeConstant;495extern CFDictionaryRef const SomeDictionary;496extern dispatch_queue_t const SomeDispatch;497void doWork(NSString *str, CFDictionaryRef dict, dispatch_queue_t dispatch);498void use_const_global() {499  doWork(SomeConstant, SomeDictionary, SomeDispatch);500}501 502NSString *provide_str();503CFDictionaryRef provide_dict();504void use_const_local() {505  doWork(provide_str(), provide_dict(), provide_dispatch());506  // expected-warning@-1{{Call argument for parameter 'str' is unretained and unsafe}}507  // expected-warning@-2{{Call argument for parameter 'dict' is unretained and unsafe}}508  // expected-warning@-3{{Call argument for parameter 'dispatch' is unretained and unsafe}}509}510 511} // namespace const_global512 513namespace var_decl_ref_singleton {514 515static Class initSomeObject() { return nil; }516static Class (*getSomeObjectClassSingleton)() = initSomeObject;517 518bool foo(NSString *obj) {519  return [obj isKindOfClass:getSomeObjectClassSingleton()];520}521 522class Bar {523public:524  Class someObject();525  static Class staticSomeObject();526};527typedef Class (Bar::*SomeObjectSingleton)();528 529bool bar(NSObject *obj, Bar *bar, SomeObjectSingleton someObjSingleton) {530  return [obj isKindOfClass:(bar->*someObjSingleton)()];531  // expected-warning@-1{{Call argument for parameter 'aClass' is unretained and unsafe}}532}533 534bool baz(NSObject *obj) {535  Class (*someObjectSingleton)() = Bar::staticSomeObject;536  return [obj isKindOfClass:someObjectSingleton()];537}538 539} // namespace var_decl_ref_singleton540 541namespace ns_retained_return_value {542 543NSString *provideNS() NS_RETURNS_RETAINED;544CFDictionaryRef provideCF() CF_RETURNS_RETAINED;545dispatch_queue_t provideDispatch() NS_RETURNS_RETAINED;546void consumeNS(NSString *);547void consumeCF(CFDictionaryRef);548void consumeDispatch(dispatch_queue_t);549 550void foo() {551  consumeNS(provideNS());552  consumeCF(provideCF());553  consumeDispatch(provideDispatch());554}555 556struct Base {557  NSString *provideStr() NS_RETURNS_RETAINED;558};559 560struct Derived : Base {561  void consumeStr(NSString *);562 563  void foo() {564    consumeStr(provideStr());565  }566};567 568} // namespace ns_retained_return_value569 570namespace autoreleased {571 572NSString *provideAutoreleased() __attribute__((ns_returns_autoreleased));573void consume(NSString *);574 575void foo() {576  consume(provideAutoreleased());577}578 579} // autoreleased580 581namespace sel_string {582 583void consumeStr(NSString *);584void consumeSel(SEL);585void consumeClass(Class);586void consumeProtocol(Protocol *);587 588void foo() {589  consumeStr(NSStringFromSelector(@selector(mutableCopy)));590  consumeSel(NSSelectorFromString(@"mutableCopy"));591  consumeStr(NSStringFromClass(NSNumber.class));592  consumeClass(NSClassFromString(@"NSNumber"));593  consumeStr(NSStringFromProtocol(@protocol(NSCopying)));594  consumeProtocol(NSProtocolFromString(@"NSCopying"));595}596 597} // namespace sel_string598 599namespace template_function {600 601class Base {602public:603    virtual ~Base() = default;604    void send(dispatch_queue_t) const;605    void ref() const;606    void deref() const;607};608 609template<typename Traits>610class Derived : public Base {611public:612    virtual ~Derived() = default;613 614    void send(typename Traits::MessageType) const;615 616    virtual OSObjectPtr<dispatch_queue_t> msg(typename Traits::MessageType) const = 0;617};618 619template<typename Traits>620void Derived<Traits>::send(typename Traits::MessageType messageType) const621{622    OSObjectPtr dictionary = msg(messageType);623    Base::send(dictionary.get());624}625 626} // namespace template_function627 628@interface TestObject : NSObject629- (void)doWork:(NSString *)msg, ...;630- (void)doWorkOnSelf;631- (SomeObj *)getSomeObj;632@end633 634@implementation TestObject635 636- (void)doWork:(NSString *)msg, ... {637  some_function();638}639 640- (void)doWorkOnSelf {641  [self doWork:nil];642  [self doWork:@"hello", provide(), provide_cf(), provide_dispatch()];643  // expected-warning@-1{{Call argument is unretained and unsafe}}644  // expected-warning@-2{{Call argument is unretained and unsafe}}645  // expected-warning@-3{{Call argument is unretained and unsafe}}646  [self doWork:@"hello", RetainPtr<SomeObj> { provide() }.get(), RetainPtr<CFMutableArrayRef> { provide_cf() }.get(), OSObjectPtr { provide_dispatch() }.get()];647  [self doWork:__null];648  [self doWork:nil];649  [NSApp run];650}651 652- (SomeObj *)getSomeObj {653    return RetainPtr<SomeObj *>(provide()).autorelease();654}655 656- (void)doWorkOnSomeObj {657    [[self getSomeObj] doWork];658}659 660- (CGImageRef)createImage {661  return provideImage();662}663 664- (NSString *)convertImage {665  RetainPtr<CGImageRef> image = [self createImage];666  return stringForImage(image.get());667}668@end669