[OptTable] Fix typo VALUE => VALUES (NFCI) (#121523)
[llvm-project.git] / compiler-rt / test / tsan / Darwin / norace-objcxx-run-time.mm
blob0cf729e7f2d879ddd25fbacdf92fc1297b6c093d
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
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
9 #import <Foundation/Foundation.h>
10 #include "../test.h"
11 invisible_barrier_t barrier2;
13 class NeedCleanup {
14   public:
15     int x;
16     NeedCleanup() {
17       x = 1;
18     }
19     ~NeedCleanup() {
20       x = 0;
21     }
24 @interface TestDeallocObject : NSObject {
25   @public
26     int v;
27   }
28   - (id)init;
29   - (void)accessMember;
30   - (void)dealloc;
31 @end
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
50 @interface TestCXXDestructObject : NSObject {
51   @public
52     NeedCleanup cxxMemberWithCleanup;
53   }
54   - (void)accessMember;
55 @end
57 @implementation TestCXXDestructObject
58   - (void)accessMember {
59     int local = cxxMemberWithCleanup.x;
60     local++;
61   }
62 @end
64 @interface TestInitializeObject : NSObject
65 @end
67 @implementation TestInitializeObject
68   static long InitializerAccessedGlobal = 0;
69   + (void)initialize {
70       InitializerAccessedGlobal = 42;
71   }
72 @end
74 int 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, 2);
79   // Ensure that objects are destructed during block object release.
80   barrier_init(&barrier2, 3);
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);
91         long local = InitializerAccessedGlobal;
92         local++;
93         [tdo accessMember];
94         [tcxxdo accessMember];
95         barrier_wait(&barrier2);
96     });
97     dispatch_async(q, ^{
98         barrier_wait(&barrier);
99         [TestInitializeObject new];
100         long local = InitializerAccessedGlobal;
101         local++;
102         [tdo accessMember];
103         [tcxxdo accessMember];
104         barrier_wait(&barrier2);
105     });
106   }
107   barrier_wait(&barrier2);
108   NSLog(@"Done.");
109   return 0;
112 // CHECK: Done.
113 // CHECK-NOT: ThreadSanitizer: data race