/* * Copyright (c) 2010 Apple Inc. All rights reserved. * * @APPLE_LLVM_LICENSE_HEADER@ */ // TEST_CFLAGS -framework Foundation #import <Foundation/Foundation.h> #import <Block.h> #import <Block_private.h> #import <objc/objc-auto.h> #import "test.h" int recovered = 0; @interface TestObject : NSObject { } @end @implementation TestObject - (void)finalize { ++recovered; [super finalize]; } - (void)dealloc { ++recovered; [super dealloc]; } @end typedef struct { struct Block_layout layout; // assumes copy helper struct Block_byref *byref_ptr; } Block_with_byref; void testRoutine() { __block id to = [[TestObject alloc] init]; void (^b)(void) = [^{ [to self]; } copy]; for (int i = 0; i < 10; ++i) [b retain]; for (int i = 0; i < 10; ++i) [b release]; for (int i = 0; i < 10; ++i) (void)Block_copy(b); // leak for (int i = 0; i < 10; ++i) Block_release(b); for (int i = 0; i < 10; ++i) { (void)Block_copy(b); // make sure up Block_release(b); // and down work under GC } [b release]; [to release]; // block_byref_release needed under non-GC to get rid of testobject } int main() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; for (int i = 0; i < 200; ++i) // do enough to trigger TLC if GC is on testRoutine(); if (objc_collectingEnabled()) { objc_collect(OBJC_EXHAUSTIVE_COLLECTION | OBJC_WAIT_UNTIL_DONE); } [pool drain]; if (recovered == 0) { fail("didn't recover byref block variable"); } succeed(__FILE__); }