Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -731,6 +731,20 @@ if (SanOpts.has(SanitizerKind::SafeStack)) 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. + 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); + } + } + } + // Apply xray attributes to the function (as a string, for now) if (D && ShouldXRayInstrumentFunction()) { if (const auto *XRayAttr = D->getAttr()) { Index: test/CodeGen/sanitize-thread-no-checking-at-run-time.m =================================================================== --- /dev/null +++ test/CodeGen/sanitize-thread-no-checking-at-run-time.m @@ -0,0 +1,35 @@ +// 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 + +__attribute__((objc_root_class)) +@interface NSObject +- (void)dealloc; +@end + +class NeedCleanup { +public: + ~NeedCleanup() __attribute__((no_sanitize("thread"))) {} +}; + +@interface MyObject : NSObject { + NeedCleanup v; +}; ++ (void) initialize; +- (void) dealloc; +@end + +@implementation MyObject ++ (void)initialize { +} +- (void)dealloc { + [super dealloc]; +} +@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]+]] +// TSAN: attributes [[ATTR]] = { nounwind {{.*}} "sanitize_thread_no_checking_at_run_time" {{.*}} } +// TSAN-NOT: sanitize_thread