Summary:
Apparently, it makes a difference on where a block lives depending on if
it's passed "inline" versus assigned and then passed via a variable.
Both tests in this commit now give a signal, if `Block_copy` is used in
`dispatch_sync`.
Since these tests use different mechanisms (Objective-C retain versus
C++ copy constructor) as proxies to observe if the block was copied, we
should keep both of them.
Commit, that first avoided the unnecessary copy:
faef7d034a
Subscribers: kubamracek, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D60639
llvm-svn: 358469
46 lines
1.1 KiB
C++
46 lines
1.1 KiB
C++
// 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.
|