brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.7 KiB · f49e7bd Raw
598 lines · plain
1// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UnretainedLocalVarsChecker -verify %s2 3#import "objc-mock-types.h"4#import "mock-system-header.h"5 6void someFunction();7extern "C" CFStringRef LocalGlobalCFString;8extern "C" NSString *LocalGlobalNSString;9 10namespace raw_ptr {11void foo() {12  SomeObj *bar;13  // FIXME: later on we might warn on uninitialized vars too14}15 16void bar(SomeObj *) {}17} // namespace raw_ptr18 19namespace pointer {20SomeObj *provide();21void foo_ref() {22  SomeObj *bar = provide();23  // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}24  [bar doWork];25}26 27bool bar_ref(SomeObj *obj) {28    return !!obj;29}30 31void cf_ptr() {32  CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 10);33  // expected-warning@-1{{Local variable 'array' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}34  CFArrayAppendValue(array, nullptr);35}36 37dispatch_queue_t provide_os();38void os_ptr() {39  auto queue = provide_os();40  // expected-warning@-1{{Local variable 'queue' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}41  dispatch_queue_get_label(queue);42}43 44} // namespace pointer45 46namespace guardian_scopes {47SomeObj *provide();48void foo1() {49  RetainPtr<SomeObj> foo = provide();50  {51    SomeObj *bar = foo.get();52  }53}54 55void foo2() {56  RetainPtr<SomeObj> foo = provide();57  // missing embedded scope here58  SomeObj *bar = foo.get();59  // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}60  [bar doWork];61}62 63void foo3() {64  RetainPtr<SomeObj> foo = provide();65  {66    { SomeObj *bar = foo.get(); }67  }68}69 70void foo4() {71  {72    RetainPtr<SomeObj> foo = provide();73    { SomeObj *bar = foo.get(); }74  }75}76 77CFMutableArrayRef provide_cf();78void foo5() {79  RetainPtr<CFMutableArrayRef> foo = provide_cf();80  {81    CFMutableArrayRef bar = foo.get();82    CFArrayAppendValue(bar, nullptr);83  }84  CFMutableArrayRef baz = foo.get();85  // expected-warning@-1{{Local variable 'baz' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}86  CFArrayAppendValue(baz, nullptr);87}88 89dispatch_queue_t provide_os();90void foo6() {91  OSObjectPtr<dispatch_queue_t> queue = provide_os();92  {93    dispatch_queue_t bar = queue.get();94    dispatch_queue_get_label(bar);95  }96  dispatch_queue_t baz = queue.get();97  // expected-warning@-1{{Local variable 'baz' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}98  dispatch_queue_get_label(baz);99}100 101struct SelfReferencingStruct {102  SelfReferencingStruct* ptr;103  SomeObj* obj { nullptr };104};105 106void foo7(SomeObj* obj) {107  SelfReferencingStruct bar = { &bar, obj };108  [bar.obj doWork];109}110 111void foo8(SomeObj* obj) {112  RetainPtr<SomeObj> foo;113 114  {115    SomeObj *bar = foo.get();116    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}117    foo = nullptr;118    [bar doWork];119  }120  RetainPtr<SomeObj> baz;121  {122    SomeObj *bar = baz.get();123    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}124    baz = obj;125    [bar doWork];126  }127 128  foo = nullptr;129  {130    SomeObj *bar = foo.get();131    // No warning. It's okay to mutate RefPtr in an outer scope.132    [bar doWork];133  }134  foo = obj;135  {136    SomeObj *bar = foo.get();137    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}138    foo.clear();139    [bar doWork];140  }141  {142    SomeObj *bar = foo.get();143    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}144    foo = obj ? obj : nullptr;145    [bar doWork];146  }147  {148    SomeObj *bar = [foo.get() other] ? foo.get() : nullptr;149    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}150    foo = nullptr;151    [bar doWork];152  }153}154 155void foo9(SomeObj* o) {156  RetainPtr<SomeObj> guardian(o);157  {158    SomeObj *bar = guardian.get();159    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}160    guardian = o; // We don't detect that we're setting it to the same value.161    [bar doWork];162  }163  {164    SomeObj *bar = guardian.get();165    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}166    RetainPtr<SomeObj> other(bar); // We don't detect other has the same value as guardian.167    guardian.swap(other);168    [bar doWork];169  }170  {171    SomeObj *bar = guardian.get();172    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}173    RetainPtr<SomeObj> other(static_cast<RetainPtr<SomeObj>&&>(guardian));174    [bar doWork];175  }176  {177    SomeObj *bar = guardian.get();178    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}179    guardian.clear();180    [bar doWork];181  }182  {183    SomeObj *bar = guardian.get();184    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}185    guardian = [o other] ? o : bar;186    [bar doWork];187  }188}189 190bool trivialFunction(CFMutableArrayRef array) { return !!array; }191void foo10() {192  RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(kCFAllocatorDefault, 10));193  {194    CFMutableArrayRef arrayRef = array.get();195    CFArrayAppendValue(arrayRef, nullptr);196  }197  {198    CFMutableArrayRef arrayRef = array.get();199    // expected-warning@-1{{Local variable 'arrayRef' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}200    array = nullptr;201    CFArrayAppendValue(arrayRef, nullptr);202  }203  {204    CFMutableArrayRef arrayRef = array.get();205    if (trivialFunction(arrayRef))206      arrayRef = nullptr;207  }208}209 210bool trivialFunction(dispatch_queue_t queue) { return !!queue; }211void foo11() {212  OSObjectPtr<dispatch_queue_t> queue = adoptOSObject(dispatch_queue_create("some queue", nullptr));213  {214    dispatch_queue_t queuePtr = queue.get();215    dispatch_queue_get_label(queuePtr);216  }217  {218    dispatch_queue_t queuePtr = queue.get();219    // expected-warning@-1{{Local variable 'queuePtr' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}220    queue = nullptr;221    dispatch_queue_get_label(queuePtr);222  }223  {224    dispatch_queue_t queuePtr = queue.get();225    if (trivialFunction(queuePtr))226      queuePtr = nullptr;227  }228}229 230} // namespace guardian_scopes231 232namespace auto_keyword {233class Foo {234  SomeObj *provide_obj();235  CFMutableArrayRef provide_cf_array();236  dispatch_queue_t provide_queue();237  void doWork(CFMutableArrayRef);238  void doWork(dispatch_queue_t);239 240  void evil_func() {241    SomeObj *bar = provide_obj();242    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}243    auto *baz = provide_obj();244    // expected-warning@-1{{Local variable 'baz' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}245    auto *baz2 = this->provide_obj();246    // expected-warning@-1{{Local variable 'baz2' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}247    [[clang::suppress]] auto *baz_suppressed = provide_obj(); // no-warning248  }249 250  void func() {251    SomeObj *bar = provide_obj();252    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}253    if (bar)254      [bar doWork];255  }256 257  void bar() {258    auto bar = provide_cf_array();259    // expected-warning@-1{{Local variable 'bar' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}260    doWork(bar);261    [[clang::suppress]] auto baz = provide_cf_array(); // no-warning262    doWork(baz);263  }264 265  void baz() {266    auto value1 = provide_queue();267    // expected-warning@-1{{Local variable 'value1' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}268    doWork(value1);269    [[clang::suppress]] auto value2 = provide_queue(); // no-warning270    doWork(value2);271  }272 273};274} // namespace auto_keyword275 276namespace guardian_casts {277void foo1() {278  RetainPtr<NSObject> foo;279  {280    SomeObj *bar = downcast<SomeObj>(foo.get());281    [bar doWork];282  }283}284 285void foo2() {286  RetainPtr<NSObject> foo;287  {288    SomeObj *bar = static_cast<SomeObj *>(downcast<SomeObj>(foo.get()));289    someFunction();290  }291}292 293void foo3() {294  OSObjectPtr<dispatch_queue_t> foo;295  {296    dispatch_queue_t bar = foo.get();297    someFunction();298  }299}300} // namespace guardian_casts301 302namespace conditional_op {303SomeObj *provide_obj();304bool bar();305 306void foo() {307  SomeObj *a = bar() ? nullptr : provide_obj();308  // expected-warning@-1{{Local variable 'a' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}309  RetainPtr<SomeObj> b = provide_obj();310  {311    SomeObj* c = bar() ? nullptr : b.get();312    [c doWork];313    SomeObj* d = bar() ? b.get() : nullptr;314    [d doWork];315  }316}317 318} // namespace conditional_op319 320namespace local_assignment_basic {321 322SomeObj *provide_obj();323 324void foo(SomeObj* a) {325  SomeObj* b = a;326  // expected-warning@-1{{Local variable 'b' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}327  if ([b other])328    b = provide_obj();329}330 331void bar(SomeObj* a) {332  SomeObj* b;333  // expected-warning@-1{{Local variable 'b' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}334  b = provide_obj();335}336 337void baz() {338  RetainPtr<SomeObj> a = provide_obj();339  {340    SomeObj* b = a.get();341    // expected-warning@-1{{Local variable 'b' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}342    b = provide_obj();343  }344}345 346} // namespace local_assignment_basic347 348namespace local_assignment_to_parameter {349 350SomeObj *provide_obj();351void someFunction();352 353void foo(SomeObj* a) {354  a = provide_obj();355  // expected-warning@-1{{Assignment to an unretained parameter 'a' is unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}356  someFunction();357  [a doWork];358}359 360CFMutableArrayRef provide_cf_array();361void doWork(CFMutableArrayRef);362 363void bar(CFMutableArrayRef a) {364  a = provide_cf_array();365  // expected-warning@-1{{Assignment to an unretained parameter 'a' is unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}366  doWork(a);367}368 369dispatch_queue_t provide_queue();370void doWork(dispatch_queue_t);371 372void baz(dispatch_queue_t a) {373  a = provide_queue();374  // expected-warning@-1{{Assignment to an unretained parameter 'a' is unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}375  doWork(a);376}377 378} // namespace local_assignment_to_parameter379 380namespace local_assignment_to_static_local {381 382SomeObj *provide_obj();383void someFunction();384 385void foo() {386  static SomeObj* a = nullptr;387  // expected-warning@-1{{Static local variable 'a' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}388  a = provide_obj();389  someFunction();390  [a doWork];391}392 393CFMutableArrayRef provide_cf_array();394void doWork(CFMutableArrayRef);395 396void bar() {397  static CFMutableArrayRef a = nullptr;398  // expected-warning@-1{{Static local variable 'a' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}399  a = provide_cf_array();400  doWork(a);401}402 403dispatch_queue_t provide_queue();404void doWork(dispatch_queue_t);405 406void baz() {407  static dispatch_queue_t a = nullptr;408  // expected-warning@-1{{Static local variable 'a' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}409  a = provide_queue();410  doWork(a);411}412 413} // namespace local_assignment_to_static_local414 415namespace local_assignment_to_global {416 417SomeObj *provide_obj();418void someFunction();419 420SomeObj* g_a = nullptr;421// expected-warning@-1{{Global variable 'local_assignment_to_global::g_a' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}422 423void foo() {424  g_a = provide_obj();425  someFunction();426  [g_a doWork];427}428 429CFMutableArrayRef provide_cf_array();430void doWork(CFMutableArrayRef);431 432CFMutableArrayRef g_b = nullptr;433// expected-warning@-1{{Global variable 'local_assignment_to_global::g_b' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}434 435void bar() {436  g_b = provide_cf_array();437  doWork(g_b);438}439 440dispatch_queue_t provide_queue();441void doWork(dispatch_queue_t);442dispatch_queue_t g_c = nullptr;443// expected-warning@-1{{Global variable 'local_assignment_to_global::g_c' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}444 445void baz() {446  g_c = provide_queue();447  doWork(g_c);448}449 450} // namespace local_assignment_to_global451 452namespace local_var_for_singleton {453  SomeObj *singleton();454  SomeObj *otherSingleton();455  void foo() {456    SomeObj* bar = singleton();457    SomeObj* baz = otherSingleton();458  }459 460  CFMutableArrayRef cfSingleton();461  void bar() {462    CFMutableArrayRef cf = cfSingleton();463  }464 465  dispatch_queue_t osSingleton();466  void baz() {467    dispatch_queue_t os = osSingleton();468  }469}470 471namespace ptr_conversion {472 473SomeObj *provide_obj();474 475void dobjc(SomeObj* obj) {476  if (auto *otherObj = dynamic_objc_cast<OtherObj>(obj))477    [otherObj doMoreWork:nil];478}479 480void cobjc(SomeObj* obj) {481  auto *otherObj = checked_objc_cast<OtherObj>(obj);482  [otherObj doMoreWork:nil];483}484 485unsigned dcf(CFTypeRef obj) {486  if (CFArrayRef array = dynamic_cf_cast<CFArrayRef>(obj))487    return CFArrayGetCount(array);488  return 0;489}490 491unsigned ccf(CFTypeRef obj) {492  CFArrayRef array = checked_cf_cast<CFArrayRef>(obj);493  return CFArrayGetCount(array);494}495 496} // ptr_conversion497 498namespace const_global {499 500extern NSString * const SomeConstant;501extern CFDictionaryRef const SomeDictionary;502extern dispatch_queue_t const SomeQueue;503void doWork(NSString *, CFDictionaryRef, dispatch_queue_t);504void use_const_global() {505  doWork(SomeConstant, SomeDictionary, SomeQueue);506}507 508NSString *provide_str();509CFDictionaryRef provide_dict();510dispatch_queue_t provide_queue();511void use_const_local() {512  NSString * const str = provide_str();513  // expected-warning@-1{{Local variable 'str' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}514  CFDictionaryRef dict = provide_dict();515  // expected-warning@-1{{Local variable 'dict' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}516  dispatch_queue_t queue = provide_queue();517  // expected-warning@-1{{Local variable 'queue' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}518  doWork(str, dict, queue);519}520 521} // namespace const_global522 523namespace ns_retained_return_value {524 525NSString *provideNS() NS_RETURNS_RETAINED;526CFDictionaryRef provideCF() CF_RETURNS_RETAINED;527dispatch_queue_t provideOS() CF_RETURNS_RETAINED;528void consumeNS(NSString *);529void consumeCF(CFDictionaryRef);530int consumeOS(dispatch_queue_t);531 532unsigned foo() {533  auto *string = provideNS();534  auto *dictionary = provideCF();535  auto* queue = provideOS();536  return string.length + CFDictionaryGetCount(dictionary) + consumeOS(queue);537}538 539} // namespace ns_retained_return_value540 541namespace autoreleased {542 543NSString *provideAutoreleased() __attribute__((ns_returns_autoreleased));544void consume(NSString *);545 546void foo() {547  auto *string = provideAutoreleased();548  consume(string);549}550 551} // autoreleased552 553namespace ns_global {554 555void consumeCFString(CFStringRef);556void consumeNSString(NSString *);557 558void cf() {559  auto *str = kCFURLTagNamesKey;560  consumeCFString(str);561  auto *localStr = LocalGlobalCFString;562  // expected-warning@-1{{Local variable 'localStr' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}563  consumeCFString(localStr);564}565 566void ns() {567  auto *str = NSApplicationDidBecomeActiveNotification;568  consumeNSString(str);569  auto *localStr = LocalGlobalNSString;570  // expected-warning@-1{{Local variable 'localStr' is unretained and unsafe [alpha.webkit.UnretainedLocalVarsChecker]}}571  consumeNSString(localStr);572}573 574}575 576bool doMoreWorkOpaque(OtherObj*);577SomeObj* provide();578 579@implementation OtherObj580- (instancetype)init {581  self = [super init];582  return self;583}584 585- (void)doMoreWork:(OtherObj *)other {586  doMoreWorkOpaque(other);587}588 589- (SomeObj*)getSomeObj {590  return RetainPtr<SomeObj *>(provide()).autorelease();591}592 593- (void)storeSomeObj {594  auto *obj = [self getSomeObj];595  [obj doWork];596}597@end598