From: Anna Zaks Date: Fri, 13 Jan 2017 00:50:50 +0000 (+0000) Subject: [tsan] Do not report errors in __destroy_helper_block_ X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5387b9a4ad0d239ed8e1915ac58b0ee63a21358a;p=clang [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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@291868 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 137c69420d..39c1425842 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -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(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(D)) { + IdentifierInfo *II = FD->getIdentifier(); + if (II && II->isStr("__destroy_helper_block_")) + markAsIgnoreThreadCheckingAtRuntime(Fn); } } diff --git a/test/CodeGen/sanitize-thread-no-checking-at-run-time.m b/test/CodeGen/sanitize-thread-no-checking-at-run-time.m index 098b7cf72f..3d862c0bf7 100644 --- a/test/CodeGen/sanitize-thread-no-checking-at-run-time.m +++ b/test/CodeGen/sanitize-thread-no-checking-at-run-time.m @@ -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" {{.*}} }