1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LLVM_LICENSE_HEADER@ 5 */ 6 7// 8// importedblockcopy.m 9// testObjects 10// 11// Created by Blaine Garst on 10/16/08. 12// Copyright 2008 Apple. All rights reserved. 13// 14 15// rdar://6297435 16// TEST_CFLAGS -framework Foundation 17 18#import <Foundation/Foundation.h> 19#import "Block.h" 20#import <objc/objc-auto.h> 21#import "test.h" 22 23int Allocated = 0; 24int Reclaimed = 0; 25 26@interface TestObject : NSObject 27@end 28 29@implementation TestObject 30- (void) dealloc { 31 ++Reclaimed; 32 [super dealloc]; 33} 34 35- (void)finalize { 36 ++Reclaimed; 37 [super finalize]; 38} 39 40- (id)init { 41 self = [super init]; 42 ++Allocated; 43 return self; 44} 45 46@end 47 48void theTest() { 49 // establish a block with an object reference 50 TestObject *to = [[TestObject alloc] init]; 51 void (^inner)(void) = ^ { 52 [to self]; // something that will hold onto "to" 53 }; 54 // establish another block that imports the first one... 55 void (^outer)(void) = ^ { 56 inner(); 57 inner(); 58 }; 59 // now when we copy outer the compiler will _Block_copy_assign inner 60 void (^outerCopy)(void) = Block_copy(outer); 61 // but when released, at least under GC, it won't let go of inner (nor its import: "to") 62 Block_release(outerCopy); 63 [to release]; 64} 65 66 67int main() { 68 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 69 70 for (int i = 0; i < 200; ++i) 71 theTest(); 72 [pool drain]; 73 objc_collect(OBJC_EXHAUSTIVE_COLLECTION | OBJC_WAIT_UNTIL_DONE); 74 75 if ((Reclaimed+10) <= Allocated) { 76 fail("whoops, reclaimed only %d of %d allocated", Reclaimed, Allocated); 77 } 78 79 succeed(__FILE__); 80} 81