forked from OSchip/llvm-project
[tsan] Do not report errors in __destroy_helper_block_
There is a synchronization point between the reference count of a block dropping to zero and it's destruction, which TSan does not observe. Do not report errors in the compiler-emitted block destroy method and everything called from it. This is similar to https://reviews.llvm.org/D25857 Differential Revision: https://reviews.llvm.org/D28387 llvm-svn: 291868
This commit is contained in:
parent
dcfc191404
commit
e43b4fc0ae
|
@ -708,6 +708,11 @@ static bool endsWithReturn(const Decl* F) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static void markAsIgnoreThreadCheckingAtRuntime(llvm::Function *Fn) {
|
||||
Fn->addFnAttr("sanitize_thread_no_checking_at_run_time");
|
||||
Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
|
||||
}
|
||||
|
||||
void CodeGenFunction::StartFunction(GlobalDecl GD,
|
||||
QualType RetTy,
|
||||
llvm::Function *Fn,
|
||||
|
@ -751,16 +756,19 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
|
|||
Fn->addFnAttr(llvm::Attribute::SafeStack);
|
||||
|
||||
// Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize,
|
||||
// .cxx_destruct and all of their calees at run time.
|
||||
// .cxx_destruct, __destroy_helper_block_ and all of their calees at run time.
|
||||
if (SanOpts.has(SanitizerKind::Thread)) {
|
||||
if (const auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) {
|
||||
IdentifierInfo *II = OMD->getSelector().getIdentifierInfoForSlot(0);
|
||||
if (OMD->getMethodFamily() == OMF_dealloc ||
|
||||
OMD->getMethodFamily() == OMF_initialize ||
|
||||
(OMD->getSelector().isUnarySelector() && II->isStr(".cxx_destruct"))) {
|
||||
Fn->addFnAttr("sanitize_thread_no_checking_at_run_time");
|
||||
Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
|
||||
markAsIgnoreThreadCheckingAtRuntime(Fn);
|
||||
}
|
||||
} else if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
|
||||
IdentifierInfo *II = FD->getIdentifier();
|
||||
if (II && II->isStr("__destroy_helper_block_"))
|
||||
markAsIgnoreThreadCheckingAtRuntime(Fn);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-darwin -x objective-c++ -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin -x objective-c++ -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefix=TSAN %s
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin -x objective-c++ -fblocks -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin -x objective-c++ -fblocks -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefix=TSAN %s
|
||||
|
||||
// WITHOUT-NOT: "sanitize_thread_no_checking_at_run_time"
|
||||
|
||||
__attribute__((objc_root_class))
|
||||
@interface NSObject
|
||||
|
@ -26,9 +28,14 @@ public:
|
|||
}
|
||||
@end
|
||||
|
||||
// WITHOUT-NOT: "sanitize_thread_no_checking_at_run_time"
|
||||
|
||||
// TSAN: initialize{{.*}}) [[ATTR:#[0-9]+]]
|
||||
// TSAN: dealloc{{.*}}) [[ATTR:#[0-9]+]]
|
||||
// TSAN: cxx_destruct{{.*}}) [[ATTR:#[0-9]+]]
|
||||
|
||||
void test2(id x) {
|
||||
extern void test2_helper(id (^)(void));
|
||||
test2_helper(^{ return x; });
|
||||
// TSAN: define internal void @__destroy_helper_block_(i8*) [[ATTR:#[0-9]+]]
|
||||
}
|
||||
|
||||
// TSAN: attributes [[ATTR]] = { noinline nounwind {{.*}} "sanitize_thread_no_checking_at_run_time" {{.*}} }
|
||||
|
|
Loading…
Reference in New Issue