1// RUN: %clang_tsan %s -lc++ -fobjc-arc -lobjc -o %t -framework Foundation
2// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
3
4// Check that we do not report races between:
5// - Object retain and initialize
6// - Object release and dealloc
7// - Object release and .cxx_destruct
8
9#import <Foundation/Foundation.h>
10#include "../test.h"
11invisible_barrier_t barrier2;
12
13class NeedCleanup {
14 public:
15 int x;
16 NeedCleanup() {
17 x = 1;
18 }
19 ~NeedCleanup() {
20 x = 0;
21 }
22};
23
24@interface TestDeallocObject : NSObject {
25 @public
26 int v;
27 }
28 - (id)init;
29 - (void)accessMember;
30 - (void)dealloc;
31@end
32
33@implementation TestDeallocObject
34 - (id)init {
35 if ([super self]) {
36 v = 1;
37 return self;
38 }
39 return nil;
40 }
41 - (void)accessMember {
42 int local = v;
43 local++;
44 }
45 - (void)dealloc {
46 v = 0;
47 }
48@end
49
50@interface TestCXXDestructObject : NSObject {
51 @public
52 NeedCleanup cxxMemberWithCleanup;
53 }
54 - (void)accessMember;
55@end
56
57@implementation TestCXXDestructObject
58 - (void)accessMember {
59 int local = cxxMemberWithCleanup.x;
60 local++;
61 }
62@end
63
64@interface TestInitializeObject : NSObject
65@end
66
67@implementation TestInitializeObject
68 static long InitializerAccessedGlobal = 0;
69 + (void)initialize {
70 InitializerAccessedGlobal = 42;
71 }
72@end
73
74int main(int argc, const char *argv[]) {
75 // Ensure that there is no race when calling initialize on TestInitializeObject;
76 // otherwise, the locking from ObjC runtime becomes observable. Also ensures that
77 // blocks are dispatched to 2 different threads.
78 barrier_init(barrier: &barrier, count: 2);
79 // Ensure that objects are destructed during block object release.
80 barrier_init(barrier: &barrier2, count: 3);
81
82 TestDeallocObject *tdo = [[TestDeallocObject alloc] init];
83 TestCXXDestructObject *tcxxdo = [[TestCXXDestructObject alloc] init];
84 [tdo accessMember];
85 [tcxxdo accessMember];
86 {
87 dispatch_queue_t q = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
88 dispatch_async(q, ^{
89 [TestInitializeObject new];
90 barrier_wait(barrier: &barrier);
91 long local = InitializerAccessedGlobal;
92 local++;
93 [tdo accessMember];
94 [tcxxdo accessMember];
95 barrier_wait(barrier: &barrier2);
96 });
97 dispatch_async(q, ^{
98 barrier_wait(barrier: &barrier);
99 [TestInitializeObject new];
100 long local = InitializerAccessedGlobal;
101 local++;
102 [tdo accessMember];
103 [tcxxdo accessMember];
104 barrier_wait(barrier: &barrier2);
105 });
106 }
107 barrier_wait(barrier: &barrier2);
108 NSLog(@"Done.");
109 return 0;
110}
111
112// CHECK: Done.
113// CHECK-NOT: ThreadSanitizer: data race
114

source code of compiler-rt/test/tsan/Darwin/norace-objcxx-run-time.mm