Author: Dan Blackwell
Date: 2026-11-02T13:53:42-08:00
New Revision: 8a64345b184e89ac59b5064da1d6093eaa6d0523

URL: 
https://github.com/llvm/llvm-project/commit/8a64345b184e89ac59b5064da1d6093eaa6d0523
DIFF: 
https://github.com/llvm/llvm-project/commit/8a64345b184e89ac59b5064da1d6093eaa6d0523.diff

LOG: [Objective-C][TSan] Do not emit fused ARC calls under TSan at -O0 to 
detect races on __strong refs (#235150)

At -O0, Clang normally emits fused @llvm.objc.storeStrong calls for
__strong assignments instead of expanding them into retain, load, store,
and release (which it does at -O1 and above). Because TSan does not
instrument @llvm.objc.storeStrong, races on __strong references were
missed at -O0.

This patch makes shouldUseFusedARCCalls() return false when TSan is
enabled so that standard TSan load/store instrumentation makes the race
detectable.

Assisted by LLMs

rdar://35283534

Added: 
    clang/test/CodeGenObjC/sanitize-thread-store-strong.m
    compiler-rt/test/tsan/Darwin/objc-store-strong-race.mm

Modified: 
    clang/lib/CodeGen/CodeGenFunction.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CodeGenFunction.h 
b/clang/lib/CodeGen/CodeGenFunction.h
index 4cc0a45067a017..22f72ead623700 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2269,7 +2269,8 @@ class CodeGenFunction : public CodeGenTypeCache {
   void enableDebugInfo() { DisableDebugInfo = false; }
 
   bool shouldUseFusedARCCalls() {
-    return CGM.getCodeGenOpts().OptimizationLevel == 0;
+    return CGM.getCodeGenOpts().OptimizationLevel == 0 &&
+           !SanOpts.has(SanitizerKind::Thread);
   }
 
   const LangOptions &getLangOpts() const { return CGM.getLangOpts(); }

diff  --git a/clang/test/CodeGenObjC/sanitize-thread-store-strong.m 
b/clang/test/CodeGenObjC/sanitize-thread-store-strong.m
new file mode 100644
index 00000000000000..9ee3174645bb61
--- /dev/null
+++ b/clang/test/CodeGenObjC/sanitize-thread-store-strong.m
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple arm64-apple-macosx -O0 -emit-llvm -fobjc-arc 
-fsanitize=thread -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-macosx -O1 -emit-llvm -fobjc-arc 
-fsanitize=thread -o - %s | FileCheck %s
+
+extern id val;
+
+// CHECK-LABEL: define{{.*}} void @test_store_strong(
+// CHECK-NOT: call void @llvm.objc.storeStrong
+// CHECK: call void @__tsan_write8(ptr [[DST:%.*]])
+// CHECK-NEXT: store ptr {{.*}}, ptr [[DST]], align 8
+// CHECK-NOT: call void @llvm.objc.storeStrong
+// CHECK: ret void
+void test_store_strong(__strong id *dst) {
+  *dst = val;
+}

diff  --git a/compiler-rt/test/tsan/Darwin/objc-store-strong-race.mm 
b/compiler-rt/test/tsan/Darwin/objc-store-strong-race.mm
new file mode 100644
index 00000000000000..9efd3104f0008d
--- /dev/null
+++ b/compiler-rt/test/tsan/Darwin/objc-store-strong-race.mm
@@ -0,0 +1,47 @@
+// RUN: %clangxx_tsan %s -o %t-O0 -O0 -fobjc-arc -framework Foundation
+// RUN: %deflake %run %t-O0 2>&1 | FileCheck %s
+// RUN: %clangxx_tsan %s -o %t-O2 -O2 -fobjc-arc -framework Foundation
+// RUN: %deflake %run %t-O2 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+#import "../test.h"
+
+@interface MyObj : NSObject {
+@public
+  __strong id strongField;
+}
+@end
+
+@implementation MyObj
+@end
+
+int main() {
+  barrier_init(&barrier, 2);
+
+  MyObj *container = [MyObj new];
+  id val1 = [NSObject new];
+  id val2 = [NSObject new];
+
+  dispatch_queue_t q =
+      dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+  dispatch_apply(2, q, ^(size_t i) {
+    if (i == 0) {
+      container->strongField = val1;
+      barrier_wait(&barrier);
+    } else {
+      barrier_wait(&barrier);
+      container->strongField = val2;
+    }
+  });
+
+  fprintf(stderr, "Done.\n");
+  return 0;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK:   Write of size 8 at {{.*}} by {{thread T.*|main thread}}:
+// CHECK:     #0 {{.*}} objc-store-strong-race.mm:[[@LINE-10]]
+// CHECK:   Previous write of size 8 at {{.*}} by {{thread T.*|main thread}}:
+// CHECK:     #0 {{.*}} objc-store-strong-race.mm:[[@LINE-16]]
+// CHECK: Done.


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to