summaryrefslogtreecommitdiff
path: root/test/tsan/Darwin
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2016-11-12 00:46:07 +0000
committerAnna Zaks <ganna@apple.com>2016-11-12 00:46:07 +0000
commit1c78dba902ae4648e6f83e965a9e58d37efa1abe (patch)
treeaa5f7df7209a581e612edb338b5bb08d054ab1eb /test/tsan/Darwin
parente63fdbb89203e772d83425becd5f3aa06b8f3553 (diff)
downloadcompiler-rt-1c78dba902ae4648e6f83e965a9e58d37efa1abe.tar.gz
[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
Diffstat (limited to 'test/tsan/Darwin')
-rw-r--r--test/tsan/Darwin/norace-objcxx-run-time.mm113
1 files changed, 113 insertions, 0 deletions
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 <Foundation/Foundation.h>
+#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