brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.0 KiB · 174e7de Raw
211 lines · plain
1// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -fblocks -verify -Wno-objc-root-class -Wno-implicit-retain-self %s2 3void *_Block_copy(const void *block);4 5@interface Test06- (void) setBlock: (void(^)(void)) block;7- (void) addBlock: (void(^)(void)) block;8- (void) actNow;9@end10void test0(Test0 *x) {11  [x setBlock: // expected-note {{block will be retained by the captured object}}12       ^{ [x actNow]; }]; // expected-warning {{capturing 'x' strongly in this block is likely to lead to a retain cycle}}13  x.block = // expected-note {{block will be retained by the captured object}}14       ^{ [x actNow]; }; // expected-warning {{capturing 'x' strongly in this block is likely to lead to a retain cycle}}15 16  [x addBlock: // expected-note {{block will be retained by the captured object}}17       ^{ [x actNow]; }]; // expected-warning {{capturing 'x' strongly in this block is likely to lead to a retain cycle}}18 19  // These actually don't cause retain cycles.20  __weak Test0 *weakx = x;21  [x addBlock: ^{ [weakx actNow]; }];22  [x setBlock: ^{ [weakx actNow]; }];23  x.block = ^{ [weakx actNow]; };24 25  // These do cause retain cycles, but we're not clever enough to figure that out.26  [weakx addBlock: ^{ [x actNow]; }];27  [weakx setBlock: ^{ [x actNow]; }];28  weakx.block = ^{ [x actNow]; };29 30  x.block = ^{ (void)x.actNow; };  // expected-warning {{capturing 'x' strongly in this block is likely to lead to a retain cycle}} \31                                   // expected-note {{block will be retained by the captured object}}32}33 34@interface BlockOwner35@property (retain) void (^strong)(void); // expected-warning {{retain'ed block property does not copy the block - use copy attribute instead}}36@end37 38@interface Test1 {39@public40  BlockOwner *owner;41};42@property (retain) BlockOwner *owner;43@property (assign) __strong BlockOwner *owner2; // expected-error {{unsafe_unretained property 'owner2' may not also be declared __strong}}44@property (assign) BlockOwner *owner3;45@end46void test1(Test1 *x) {47  x->owner.strong = ^{ (void) x; }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}48  x.owner.strong = ^{ (void) x; }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}49  x.owner2.strong = ^{ (void) x; };50  x.owner3.strong = ^{ (void) x; };51}52 53@implementation Test1 {54  BlockOwner * __unsafe_unretained owner3ivar;55  __weak BlockOwner *weakowner;56}57@dynamic owner;58@dynamic owner2;59@synthesize owner3 = owner3ivar;60 61- (id) init {62  self.owner.strong = ^{ (void) owner; }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}63  self.owner2.strong = ^{ (void) owner; };64 65  // TODO: should we warn here?  What's the story with this kind of mismatch?66  self.owner3.strong = ^{ (void) owner; };67 68  owner.strong = ^{ (void) owner; }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}69 70  owner.strong = ^{ ^{ (void) owner; }(); }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}71 72  owner.strong = ^{ (void) sizeof(self); // expected-note {{block will be retained by an object strongly retained by the captured object}}73                    (void) owner; }; // expected-warning {{capturing 'self' strongly in this block is likely to lead to a retain cycle}}74 75  weakowner.strong = ^{ (void) owner; };76 77  return self;78}79- (void) foo {80  owner.strong = ^{ (void) owner; }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}81}82@end83 84void test2_helper(id);85@interface Test2 {86  void (^block)(void);87  id x;88}89@end90@implementation Test291- (void) test {92  block = ^{ // expected-note {{block will be retained by an object strongly retained by the captured object}}93    test2_helper(x); // expected-warning {{capturing 'self' strongly in this block is likely to lead to a retain cycle}}94  };95}96@end97 98 99@interface NSOperationQueue {}100- (void)addOperationWithBlock:(void (^)(void))block;101- (void)addSomethingElse:(void (^)(void))block;102 103@end104 105@interface Test3 {106  NSOperationQueue *myOperationQueue;107  unsigned count;108}109@end110void doSomething(unsigned v);111@implementation Test3112- (void) test {113  // 'addOperationWithBlock:' is specifically allowlisted.114  [myOperationQueue addOperationWithBlock:^() { // no-warning115    if (count > 20) {116      doSomething(count);117    }118  }];119}120- (void) test_positive {121  // Check that we are really allowlisting 'addOperationWithBlock:' and not doing122  // something funny.123  [myOperationQueue addSomethingElse:^() { // expected-note {{block will be retained by an object strongly retained by the captured object}}124    if (count > 20) {125      doSomething(count); // expected-warning {{capturing 'self' strongly in this block is likely to lead to a retain cycle}}126    }127  }];128}129@end130 131 132void testBlockVariable(void) {133  typedef void (^block_t)(void);134  135  // This case will be caught by -Wuninitialized, and does not create a136  // retain cycle.137  block_t a1 = ^{138    a1(); // no-warning139  };140 141  // This case will also be caught by -Wuninitialized.142  block_t a2;143  a2 = ^{144    a2(); // no-warning145  };146  147  __block block_t b1 = ^{ // expected-note{{block will be retained by the captured object}}148    b1(); // expected-warning{{capturing 'b1' strongly in this block is likely to lead to a retain cycle}}149  };150 151  __block block_t b2;152  b2 = ^{ // expected-note{{block will be retained by the captured object}}153    b2(); // expected-warning{{capturing 'b2' strongly in this block is likely to lead to a retain cycle}}154  };155}156 157 158@interface NSObject159- (id)copy;160 161- (void (^)(void))someRandomMethodReturningABlock;162@end163 164 165void testCopying(Test0 *obj) {166  typedef void (^block_t)(void);167 168  [obj setBlock:[^{ // expected-note{{block will be retained by the captured object}}169    [obj actNow]; // expected-warning{{capturing 'obj' strongly in this block is likely to lead to a retain cycle}}170  } copy]];171 172  [obj addBlock:(__bridge_transfer block_t)_Block_copy((__bridge void *)^{ // expected-note{{block will be retained by the captured object}}173    [obj actNow]; // expected-warning{{capturing 'obj' strongly in this block is likely to lead to a retain cycle}}174  })];175  176  [obj addBlock:[^{177    [obj actNow]; // no-warning178  } someRandomMethodReturningABlock]];179  180  extern block_t someRandomFunctionReturningABlock(block_t);181  [obj setBlock:someRandomFunctionReturningABlock(^{182    [obj actNow]; // no-warning183  })];184}185 186void func(int someCondition) {187 188__block void(^myBlock)(void) = ^{189        if (someCondition) {190            doSomething(1);191            myBlock();192        }193        else {194	    myBlock = ((void*)0);195        }196   };197 198}199 200typedef void (^a_block_t)(void);201 202@interface HonorNoEscape203- (void)addStuffUsingBlock:(__attribute__((noescape)) a_block_t)block;204@end205 206void testNoEscape(HonorNoEscape *obj) {207  [obj addStuffUsingBlock:^{208    (void)obj; // ok.209  }];210}211