Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -714,6 +714,13 @@ if (SanOpts.has(SanitizerKind::SafeStack)) Fn->addFnAttr(llvm::Attribute::SafeStack); + // Ignore TSan memory acesses from within dealloc and all of its calees at + // run time. + if (SanOpts.has(SanitizerKind::Thread)) + if (const auto *M = dyn_cast_or_null(D)) + if (M->getMethodFamily() == OMF_dealloc) + Fn->addFnAttr("sanitize_thread_no_checking_at_run_time"); + // 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-attr-dealloc.m =================================================================== --- /dev/null +++ test/CodeGen/sanitize-thread-attr-dealloc.m @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefix=TSAN %s + +__attribute__((objc_root_class)) +@interface NSObject +- (void)dealloc; +@end + +@interface MyObject : NSObject +- (void) dealloc; +@end + +@implementation MyObject +- (void)dealloc { + [super dealloc]; +} +@end + +// WITHOUT-NOT: "sanitize_thread_no_checking_at_run_time" + +// TSAN: dealloc{{.*}}) [[ATTR:#[0-9]+]] +// TSAN: attributes [[ATTR]] = { nounwind sanitize_thread {{.*}} "sanitize_thread_no_checking_at_run_time" {{.*}} } +