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