]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
compiler-context-analysis: Bump required Clang version to 23
authorMarco Elver <elver@google.com>
Fri, 15 May 2026 12:43:31 +0000 (14:43 +0200)
committerPeter Zijlstra <peterz@infradead.org>
Thu, 28 May 2026 10:20:19 +0000 (12:20 +0200)
Clang 23 introduces several major improvements:

1. Support for multiple arguments in the `guarded_by` and
   `pt_guarded_by` attributes [1]. This allows defining variables
   protected by multiple context locks, where read access requires
   holding at least one lock (shared or exclusive), and write access
   requires holding all of them exclusively.

2. Function pointer support [2]. We can now add attributes to function
   pointers just like we do on normal functions.

3. A fix to use arrays of locks [3]. Each index is now correctly treated
   as a separate lock instance.

4. A fix for implicit member access in attributes [4]. This allows to
   use __guarded_by(&foo->lock) correctly.

Overall that makes it worthwhile bumping the compiler version instead of
trying to make both Clang 22 and later work while supporting these new
features.

Signed-off-by: Marco Elver <elver@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Link: https://github.com/llvm/llvm-project/pull/186838
Link: https://github.com/llvm/llvm-project/pull/191187
Link: https://github.com/llvm/llvm-project/pull/148551
Link: https://github.com/llvm/llvm-project/pull/194457
Link: https://patch.msgid.link/20260515124426.2227783-1-elver@google.com
Documentation/dev-tools/context-analysis.rst
include/linux/compiler-context-analysis.h
lib/Kconfig.debug
lib/test_context-analysis.c

index 54d9ee28de9829e28cb5e74ddc126ec546311dc5..8e71e1e75b5bc35ac1ee2696b7a0de42fff155c6 100644 (file)
@@ -17,7 +17,7 @@ features. To enable for Clang, configure the kernel with::
 
     CONFIG_WARN_CONTEXT_ANALYSIS=y
 
-The feature requires Clang 22 or later.
+The feature requires Clang 23 or later.
 
 The analysis is *opt-in by default*, and requires declaring which modules and
 subsystems should be analyzed in the respective `Makefile`::
index a9317571e6aff3a8d09adeaa9d74e0826d0ca074..8302ebc2ea8c87aeb18146c093186e60a2caae4e 100644 (file)
 # define __assumes_shared_ctx_lock(...)        __attribute__((assert_shared_capability(__VA_ARGS__)))
 
 /**
- * __guarded_by - struct member and globals attribute, declares variable
- *                only accessible within active context
+ * __guarded_by() - struct member and globals attribute, declares variable
+ *                  only accessible within active context
+ * @...: context lock instance pointer(s)
  *
  * Declares that the struct member or global variable is only accessible within
- * the context entered by the given context lock. Read operations on the data
- * require shared access, while write operations require exclusive access.
+ * the context entered by the given context lock(s). Read operations on the data
+ * require shared access to at least one of the context locks, while write
+ * operations require exclusive access to all listed context locks.
  *
  * .. code-block:: c
  *
  *             spinlock_t lock;
  *             long counter __guarded_by(&lock);
  *     };
+ *
+ *     struct some_state {
+ *             spinlock_t lock1, lock2;
+ *             long counter __guarded_by(&lock1, &lock2);
+ *     };
  */
 # define __guarded_by(...)             __attribute__((guarded_by(__VA_ARGS__)))
 
 /**
- * __pt_guarded_by - struct member and globals attribute, declares pointed-to
- *                   data only accessible within active context
+ * __pt_guarded_by() - struct member and globals attribute, declares pointed-to
+ *                     data only accessible within active context
+ * @...: context lock instance pointer(s)
  *
  * Declares that the data pointed to by the struct member pointer or global
  * pointer is only accessible within the context entered by the given context
- * lock. Read operations on the data require shared access, while write
- * operations require exclusive access.
+ * lock(s). Read operations on the data require shared access to at least one
+ * of the context locks, while write operations require exclusive access to all
+ * listed context locks.
  *
  * .. code-block:: c
  *
  *             spinlock_t lock;
  *             long *counter __pt_guarded_by(&lock);
  *     };
+ *
+ *     struct some_state {
+ *             spinlock_t lock1, lock2;
+ *             long *counter __pt_guarded_by(&lock1, &lock2);
+ *     };
  */
 # define __pt_guarded_by(...)          __attribute__((pt_guarded_by(__VA_ARGS__)))
 
index 8ff5adcfe1e0a2f13893c92c3b95498fedb83855..b0f3028a213dfe1211e53d20480575fe220f3d30 100644 (file)
@@ -630,7 +630,7 @@ config DEBUG_FORCE_WEAK_PER_CPU
 
 config WARN_CONTEXT_ANALYSIS
        bool "Compiler context-analysis warnings"
-       depends on CC_IS_CLANG && CLANG_VERSION >= 220100
+       depends on CC_IS_CLANG && CLANG_VERSION >= 230000
        # Branch profiling re-defines "if", which messes with the compiler's
        # ability to analyze __cond_acquires(..), resulting in false positives.
        depends on !TRACE_BRANCH_PROFILING
@@ -641,7 +641,7 @@ config WARN_CONTEXT_ANALYSIS
          and releasing user-definable "context locks".
 
          Clang's name of the feature is "Thread Safety Analysis". Requires
-         Clang 22.1.0 or later.
+         Clang 23 or later.
 
          Produces warnings by default. Select CONFIG_WERROR if you wish to
          turn these warnings into errors.
index 06b4a6a028e0ecec0893e6b25a33578b5d3e5245..316f4dfcda651384833ee369688f9c13946fddf5 100644 (file)
@@ -159,6 +159,10 @@ TEST_SPINLOCK_COMMON(read_lock,
 struct test_mutex_data {
        struct mutex mtx;
        int counter __guarded_by(&mtx);
+
+       struct mutex mtx2;
+       int anyread __guarded_by(&mtx, &mtx2);
+       int *anyptr __pt_guarded_by(&mtx, &mtx2);
 };
 
 static void __used test_mutex_init(struct test_mutex_data *d)
@@ -219,6 +223,26 @@ static void __used test_mutex_cond_guard(struct test_mutex_data *d)
        }
 }
 
+static void __used test_mutex_multiguard(struct test_mutex_data *d)
+{
+       mutex_lock(&d->mtx);
+       (void)d->anyread;
+       (void)*d->anyptr;
+       mutex_unlock(&d->mtx);
+
+       mutex_lock(&d->mtx2);
+       (void)d->anyread;
+       (void)*d->anyptr;
+       mutex_unlock(&d->mtx2);
+
+       mutex_lock(&d->mtx);
+       mutex_lock(&d->mtx2);
+       d->anyread++;
+       (*d->anyptr)++;
+       mutex_unlock(&d->mtx2);
+       mutex_unlock(&d->mtx);
+}
+
 struct test_seqlock_data {
        seqlock_t sl;
        int counter __guarded_by(&sl);