Re: [PATCH] cmpxchg: allow const-qualified old value in cmpxchg()

David Laight
2026-04-02T08:58:10Z

On Thu, 02 Apr 2026 14:56:01 +0800
Hangbin Liu <liuhangbin@gmail.com> wrote:

> The old value passed to cmpxchg() is semantically read-only: it is
> only loaded into a register as a comparand and is never written back.
> However, the macro currently assigns it implicitly to a local variable
> of type __typeof__(*(ptr)), which triggers -Werror=discarded-qualifiers
> when old is a const-qualified pointer and ptr points to a non-const type.
>
> To avoid this, let's add an explicit cast to __typeof__(*(ptr)) for the
> old local variable in the cmpxchg macros. This explicit cast suppresses
> the -Wdiscarded-qualifiers diagnostic.
>
> The new value is intentionally left without a cast: new will be stored
> into *ptr, so silently accepting a const-qualified new would allow
> callers to store a pointer-to-const into a non-const location without
> any compiler warning.
>
> Suggested-by: Jakub Kicinski <kuba@kernel.org>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
...
>
> diff --git a/arch/alpha/include/asm/cmpxchg.h b/arch/alpha/include/asm/cmpxchg.h
> index ae1b96479d0c..b4b8dac759c4 100644
> --- a/arch/alpha/include/asm/cmpxchg.h
> +++ b/arch/alpha/include/asm/cmpxchg.h
> @@ -234,7 +234,7 @@ ____cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
>
> #define arch_cmpxchg_local(ptr, o, n) \
> ({ \
> - __typeof__(*(ptr)) _o_ = (o); \
> + __typeof__(*(ptr)) _o_ = (__typeof__(*(ptr)))(o); \
> __typeof__(*(ptr)) _n_ = (n); \
> (__typeof__(*(ptr))) ____cmpxchg((ptr), (unsigned long)_o_, \
> (unsigned long)_n_, \

That looks like it loses the check that 'o' has the same type as '*ptr'.
Maybe this works?
auto _o_ = 1 ? (o) : *(ptr);

David