summaryrefslogtreecommitdiff
path: root/test/tsan/libdispatch/sync-block-copy.cc
diff options
context:
space:
mode:
Diffstat (limited to 'test/tsan/libdispatch/sync-block-copy.cc')
-rw-r--r--test/tsan/libdispatch/sync-block-copy.cc45
1 files changed, 45 insertions, 0 deletions
diff --git a/test/tsan/libdispatch/sync-block-copy.cc b/test/tsan/libdispatch/sync-block-copy.cc
new file mode 100644
index 000000000..1f10d958b
--- /dev/null
+++ b/test/tsan/libdispatch/sync-block-copy.cc
@@ -0,0 +1,45 @@
+// This test verifies that dispatch_sync() doesn't actually copy the block under TSan (without TSan, it doesn't).
+
+// RUN: %clangxx_tsan %s -o %t_no_tsan -fno-sanitize=thread
+// RUN: %clangxx_tsan %s -o %t_with_tsan
+
+// RUN: %run %t_no_tsan 2>&1 | FileCheck %s
+// RUN: %run %t_with_tsan 2>&1 | FileCheck %s --implicit-check-not='ThreadSanitizer'
+
+#include <dispatch/dispatch.h>
+
+#include <stdio.h>
+
+struct MyClass {
+ static int copyCount;
+ static void printCopyCount() {
+ fprintf(stderr, "copyCount = %d\n", copyCount);
+ }
+ MyClass(){};
+ MyClass(const MyClass &obj) { copyCount++; };
+ void foo() const {
+ fprintf(stderr, "MyClass::foo\n");
+ }
+};
+int MyClass::copyCount = 0;
+
+int main(int argc, const char* argv[]) {
+ dispatch_queue_t q = dispatch_queue_create("my.queue", NULL);
+ MyClass obj;
+ MyClass::printCopyCount();
+ void (^block)(void) = ^{
+ obj.foo();
+ };
+ MyClass::printCopyCount();
+ dispatch_sync(q, block);
+ MyClass::printCopyCount();
+
+ fprintf(stderr, "Done.\n");
+ return 0;
+}
+
+// CHECK: copyCount = 0
+// CHECK: copyCount = 1
+// CHECK: MyClass::foo
+// CHECK: copyCount = 1
+// CHECK: Done.