114 lines · plain
1// RUN: %clang_tsan %s -lc++ -fobjc-arc -lobjc -o %t -framework Foundation2// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s3 4// Check that we do not report races between:5// - Object retain and initialize6// - Object release and dealloc7// - Object release and .cxx_destruct8 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 @public26 int v;27 }28 - (id)init;29 - (void)accessMember;30 - (void)dealloc;31@end32 33@implementation TestDeallocObject34 - (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@end49 50@interface TestCXXDestructObject : NSObject {51 @public52 NeedCleanup cxxMemberWithCleanup;53 }54 - (void)accessMember;55@end56 57@implementation TestCXXDestructObject58 - (void)accessMember {59 int local = cxxMemberWithCleanup.x;60 local++;61 }62@end63 64@interface TestInitializeObject : NSObject65@end66 67@implementation TestInitializeObject68 static long InitializerAccessedGlobal = 0;69 + (void)initialize {70 InitializerAccessedGlobal = 42;71 }72@end73 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 that77 // 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);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);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;110}111 112// CHECK: Done.113// CHECK-NOT: ThreadSanitizer: data race114