From 1c78dba902ae4648e6f83e965a9e58d37efa1abe Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Sat, 12 Nov 2016 00:46:07 +0000 Subject: [tsan] Test that false races from ObjC's dealloc, .cxx_destruct, and initialize are ignored Differential Revision: https://reviews.llvm.org/D26228 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@286693 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/tsan/Darwin/norace-objcxx-run-time.mm | 113 +++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 test/tsan/Darwin/norace-objcxx-run-time.mm (limited to 'test/tsan/Darwin') diff --git a/test/tsan/Darwin/norace-objcxx-run-time.mm b/test/tsan/Darwin/norace-objcxx-run-time.mm new file mode 100644 index 000000000..0cf729e7f --- /dev/null +++ b/test/tsan/Darwin/norace-objcxx-run-time.mm @@ -0,0 +1,113 @@ +// RUN: %clang_tsan %s -lc++ -fobjc-arc -lobjc -o %t -framework Foundation +// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s + +// Check that we do not report races between: +// - Object retain and initialize +// - Object release and dealloc +// - Object release and .cxx_destruct + +#import +#include "../test.h" +invisible_barrier_t barrier2; + +class NeedCleanup { + public: + int x; + NeedCleanup() { + x = 1; + } + ~NeedCleanup() { + x = 0; + } +}; + +@interface TestDeallocObject : NSObject { + @public + int v; + } + - (id)init; + - (void)accessMember; + - (void)dealloc; +@end + +@implementation TestDeallocObject + - (id)init { + if ([super self]) { + v = 1; + return self; + } + return nil; + } + - (void)accessMember { + int local = v; + local++; + } + - (void)dealloc { + v = 0; + } +@end + +@interface TestCXXDestructObject : NSObject { + @public + NeedCleanup cxxMemberWithCleanup; + } + - (void)accessMember; +@end + +@implementation TestCXXDestructObject + - (void)accessMember { + int local = cxxMemberWithCleanup.x; + local++; + } +@end + +@interface TestInitializeObject : NSObject +@end + +@implementation TestInitializeObject + static long InitializerAccessedGlobal = 0; + + (void)initialize { + InitializerAccessedGlobal = 42; + } +@end + +int main(int argc, const char *argv[]) { + // Ensure that there is no race when calling initialize on TestInitializeObject; + // otherwise, the locking from ObjC runtime becomes observable. Also ensures that + // blocks are dispatched to 2 different threads. + barrier_init(&barrier, 2); + // Ensure that objects are destructed during block object release. + barrier_init(&barrier2, 3); + + TestDeallocObject *tdo = [[TestDeallocObject alloc] init]; + TestCXXDestructObject *tcxxdo = [[TestCXXDestructObject alloc] init]; + [tdo accessMember]; + [tcxxdo accessMember]; + { + dispatch_queue_t q = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT); + dispatch_async(q, ^{ + [TestInitializeObject new]; + barrier_wait(&barrier); + long local = InitializerAccessedGlobal; + local++; + [tdo accessMember]; + [tcxxdo accessMember]; + barrier_wait(&barrier2); + }); + dispatch_async(q, ^{ + barrier_wait(&barrier); + [TestInitializeObject new]; + long local = InitializerAccessedGlobal; + local++; + [tdo accessMember]; + [tcxxdo accessMember]; + barrier_wait(&barrier2); + }); + } + barrier_wait(&barrier2); + NSLog(@"Done."); + return 0; +} + +// CHECK: Done. +// CHECK-NOT: ThreadSanitizer: data race -- cgit v1.2.1