https://github.com/melver created 
https://github.com/llvm/llvm-project/pull/172638

Add 2 tests for cast pointer aliases, with the cleanup pattern being a real 
pattern that is considered to be used in the Linux kernel: 
https://lore.kernel.org/all/[email protected]/

This works today, but let's test it to make sure there are no regressions.

>From fa9723148164ca1fd7e4bccaad5339cee5f59577 Mon Sep 17 00:00:00 2001
From: Marco Elver <[email protected]>
Date: Wed, 17 Dec 2025 12:47:57 +0100
Subject: [PATCH] Thread Safety Analysis: Add more cast pointer-alias tests

Add 2 tests for cast pointer aliases, with the cleanup pattern being a
real pattern that is considered to be used in the Linux kernel:
https://lore.kernel.org/all/[email protected]/

This works today, but let's test it to make sure there are no
regressions.
---
 clang/test/Sema/warn-thread-safety-analysis.c      | 8 ++++++++
 clang/test/SemaCXX/warn-thread-safety-analysis.cpp | 9 +++++++++
 2 files changed, 17 insertions(+)

diff --git a/clang/test/Sema/warn-thread-safety-analysis.c 
b/clang/test/Sema/warn-thread-safety-analysis.c
index 549cb1231baa6..7b77057157db3 100644
--- a/clang/test/Sema/warn-thread-safety-analysis.c
+++ b/clang/test/Sema/warn-thread-safety-analysis.c
@@ -94,6 +94,7 @@ int get_value(int *p) SHARED_LOCKS_REQUIRED(foo_.mu_){
 }
 
 void unlock_scope(struct Mutex *const *mu) 
__attribute__((release_capability(**mu)));
+void unlock_scope_type_erased(int **priv) 
__attribute__((release_capability(*(struct Mutex **)priv)));
 
 // Verify late parsing:
 #ifdef LATE_PARSING
@@ -191,6 +192,13 @@ int main(void) {
     struct Mutex* const __attribute__((unused, cleanup(unlock_scope))) scope = 
&mu1;
     mutex_exclusive_lock(&mu1);  // With basic alias analysis lock through mu1 
also works.
   }
+  // Cleanup through cast alias pointer in a for-loop; a variant of this 
pattern
+  // appears in the Linux kernel for generic scoped guard macros.
+  for (int i = (mutex_exclusive_lock(foo_.mu_), 0),
+       *priv __attribute__((cleanup(unlock_scope_type_erased))) = (int 
*)(unsigned long)(foo_.mu_);
+       !i; i++) {
+    a_ = 42;
+  }
 
   foo_.a_value = 0; // expected-warning {{writing variable 'a_value' requires 
holding mutex 'mu_' exclusively}}
   *foo_.a_ptr = 1; // expected-warning {{writing the value pointed to by 
'a_ptr' requires holding mutex 'bar.other_mu' exclusively}}
diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp 
b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
index 7cb416d71569c..66f240b4b7c59 100644
--- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
+++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp
@@ -7325,6 +7325,15 @@ void testBasicPointerAlias(Foo *f) {
   ptr->mu.Unlock();       // unlock through alias
 }
 
+void testCastPointerAlias(Foo *f) {
+  // Cast to void* from unsigned long to test non-pointer cast indirection.
+  void *priv = (void *)(unsigned long)(&f->mu);
+  f->mu.Lock();
+  f->data = 42;
+  auto *mu = (Mutex *)priv;
+  mu->Unlock();
+}
+
 void testBasicPointerAliasNoInit(Foo *f) {
   Foo *ptr;
 

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

Reply via email to