Re: [PATCH tip/locking/core] compiler-context-analysis: Bump required Clang version to 23

From: Marco Elver

Date: Mon Mar 30 2026 - 10:29:11 EST


On Mon, 30 Mar 2026 at 16:18, Nathan Chancellor <nathan@xxxxxxxxxx> wrote:
>
> On Mon, Mar 30, 2026 at 04:09:50PM +0200, Marco Elver wrote:
> > Clang 23 introduces 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.
> >
> > Clang 23 also provides a few other improvements (such as being able to
> > deal with arrays of locks [2]) that make it worthwhile bumping the
> > compiler version instead of trying to make both Clang 22 and later work
> > while supporting these new features.
> >
> > Link: https://github.com/llvm/llvm-project/pull/186838 [1]
> > Link: https://github.com/llvm/llvm-project/pull/148551 [2]
> > Requested-by: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
> > Signed-off-by: Marco Elver <elver@xxxxxxxxxx>
>
> Fair enough. I will upload a new main snapshot to kernel.org to make it
> more accessible to folks for testing.
>
> Reviewed-by: Nathan Chancellor <nathan@xxxxxxxxxx>

Thanks. I always suspected we'll need to bump the Clang version here,
which is a bit inconvenient for now. But I think it's better to do now
than find odd workarounds in the kernel tree later that we need to
revert.

> > ---
> > v2:
> > * Bump version instead of __guarded_by_any workaround.
> > ---
> > Documentation/dev-tools/context-analysis.rst | 2 +-
> > include/linux/compiler-context-analysis.h | 30 ++++++++++++++------
> > lib/Kconfig.debug | 4 +--
> > lib/test_context-analysis.c | 24 ++++++++++++++++
> > 4 files changed, 49 insertions(+), 11 deletions(-)
> >
> > diff --git a/Documentation/dev-tools/context-analysis.rst b/Documentation/dev-tools/context-analysis.rst
> > index 54d9ee28de98..8e71e1e75b5b 100644
> > --- a/Documentation/dev-tools/context-analysis.rst
> > +++ b/Documentation/dev-tools/context-analysis.rst
> > @@ -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`::
> > diff --git a/include/linux/compiler-context-analysis.h b/include/linux/compiler-context-analysis.h
> > index 00c074a2ccb0..1ab2622621c3 100644
> > --- a/include/linux/compiler-context-analysis.h
> > +++ b/include/linux/compiler-context-analysis.h
> > @@ -39,12 +39,14 @@
> > # 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
> > *
> > @@ -52,17 +54,24 @@
> > * 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
> > *
> > @@ -70,6 +79,11 @@
> > * 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__)))
> >
> > diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> > index 93f356d2b3d9..09e9bd003c70 100644
> > --- a/lib/Kconfig.debug
> > +++ b/lib/Kconfig.debug
> > @@ -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.
> > diff --git a/lib/test_context-analysis.c b/lib/test_context-analysis.c
> > index 06b4a6a028e0..316f4dfcda65 100644
> > --- a/lib/test_context-analysis.c
> > +++ b/lib/test_context-analysis.c
> > @@ -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);
> > --
> > 2.53.0.1018.g2bb0e51243-goog