* Re: [tip:timers/vdso 12/14] net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers)
[not found] <202601150001.sKSN644a-lkp@intel.com>
@ 2026-01-15 19:28 ` Thomas Gleixner
2026-01-15 21:11 ` Peter Zijlstra
0 siblings, 1 reply; 11+ messages in thread
From: Thomas Gleixner @ 2026-01-15 19:28 UTC (permalink / raw)
To: kernel test robot, Ian Rogers
Cc: oe-kbuild-all, linux-kernel, x86, sparse, linux-sparse,
Peter Zijlstra, Marco Elver
On Thu, Jan 15 2026 at 00:36, kernel test robot wrote:
Cc+ sparse folks.
> sparse warnings: (new ones prefixed by >>)
>>> net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void * @@ got restricted __be64 const * @@
> net/rds/ib_cm.c:96:35: sparse: expected void *
> net/rds/ib_cm.c:96:35: sparse: got restricted __be64 const *
> net/rds/ib_cm.c:103:27: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void * @@ got restricted __be64 const * @@
> net/rds/ib_cm.c:103:27: sparse: expected void *
> net/rds/ib_cm.c:103:27: sparse: got restricted __be64 const *
After staring a while at it, it turns out that get_unaligned_t(), which
uses __unqual_scalar_typeof() to get an unqualified type makes sparse
unhappy when the data type is __be64 (or any other __beNN variant).
__beNN is annotated with __attribute__((bitwise)) when sparse is invoked
(#ifdef CHECKER). That allows sparse to detect incompatible math
operations with __beNN variables.
That annotation also causes the type comparison in the sparse _Generic()
evaluation to fail so that it ends up with the default, i.e. the
original qualified type of a 'const __beNN' pointer. That then ends up as
the first pointer argument to builtin_memcpy(), which obviously causes
the above sparse warnings.
The easiest solution would be to force cast the pointer to void * when
CHECKER is defined, but that reduces coverage.
I've come up with the below, but it's clearly a hack... __CAST_SPARSE()
is required as sparse otherwise complains about storing __u64 in __be64.
Thanks,
tglx
---
include/linux/compiler_types.h | 10 ++++++++++
include/vdso/unaligned.h | 16 +++++++++++-----
2 files changed, 21 insertions(+), 5 deletions(-)
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -577,6 +577,15 @@ struct ftrace_likely_data {
unsigned type: (unsigned type)0, \
signed type: (signed type)0
+#ifdef __CHECKER__
+#define __be_types_expr_cases() \
+ __be16: (__u16)0, \
+ __be32: (__u32)0, \
+ __be64: (__u64)0,
+#else
+#define __be_types_expr_cases()
+#endif
+
#define __unqual_scalar_typeof(x) typeof( \
_Generic((x), \
char: (char)0, \
@@ -585,6 +594,7 @@ struct ftrace_likely_data {
__scalar_type_to_expr_cases(int), \
__scalar_type_to_expr_cases(long), \
__scalar_type_to_expr_cases(long long), \
+ __be_types_expr_cases() \
default: (x)))
/* Is this type a native word size -- useful for atomic operations */
--- a/include/vdso/unaligned.h
+++ b/include/vdso/unaligned.h
@@ -4,6 +4,12 @@
#include <linux/compiler_types.h>
+#ifdef __CHECKER__
+#define __CAST_SPARSE(type) (type __force)
+#else
+#define __CAST_SPARSE(type)
+#endif
+
/**
* __get_unaligned_t - read an unaligned value from memory.
* @type: the type to load from the pointer.
@@ -17,12 +23,12 @@
* expression rather than type, a pointer is used to avoid warnings about mixing
* the use of 0 and NULL. The void* cast silences ubsan warnings.
*/
-#define __get_unaligned_t(type, ptr) ({ \
- type *__get_unaligned_ctrl_type __always_unused = NULL; \
+#define __get_unaligned_t(type, ptr) ({ \
+ type *__get_unaligned_ctrl_type __always_unused = NULL; \
__unqual_scalar_typeof(*__get_unaligned_ctrl_type) __get_unaligned_val; \
- __builtin_memcpy(&__get_unaligned_val, (void *)(ptr), \
- sizeof(__get_unaligned_val)); \
- __get_unaligned_val; \
+ __builtin_memcpy(&__get_unaligned_val, (void *)(ptr), \
+ sizeof(__get_unaligned_val)); \
+ __CAST_SPARSE(type) __get_unaligned_val; \
})
/**
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [tip:timers/vdso 12/14] net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers)
2026-01-15 19:28 ` [tip:timers/vdso 12/14] net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers) Thomas Gleixner
@ 2026-01-15 21:11 ` Peter Zijlstra
2026-01-15 21:19 ` Linus Torvalds
2026-01-15 23:01 ` Thomas Gleixner
0 siblings, 2 replies; 11+ messages in thread
From: Peter Zijlstra @ 2026-01-15 21:11 UTC (permalink / raw)
To: Thomas Gleixner
Cc: kernel test robot, Ian Rogers, oe-kbuild-all, linux-kernel, x86,
sparse, linux-sparse, Marco Elver
On Thu, Jan 15, 2026 at 08:28:51PM +0100, Thomas Gleixner wrote:
> On Thu, Jan 15 2026 at 00:36, kernel test robot wrote:
>
> Cc+ sparse folks.
>
> > sparse warnings: (new ones prefixed by >>)
> >>> net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void * @@ got restricted __be64 const * @@
> > net/rds/ib_cm.c:96:35: sparse: expected void *
> > net/rds/ib_cm.c:96:35: sparse: got restricted __be64 const *
> > net/rds/ib_cm.c:103:27: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void * @@ got restricted __be64 const * @@
> > net/rds/ib_cm.c:103:27: sparse: expected void *
> > net/rds/ib_cm.c:103:27: sparse: got restricted __be64 const *
>
> After staring a while at it, it turns out that get_unaligned_t(), which
> uses __unqual_scalar_typeof() to get an unqualified type makes sparse
> unhappy when the data type is __be64 (or any other __beNN variant).
>
> __beNN is annotated with __attribute__((bitwise)) when sparse is invoked
> (#ifdef CHECKER). That allows sparse to detect incompatible math
> operations with __beNN variables.
>
Per:
https://git.kernel.org/pub/scm/devel/sparse/sparse-dev.git/commit/?id=dc9efe442b8949234a6599fdc94dc7221dd040e1
it seems Sparse now knows about __typeof_unqual__; and it looks like the
implementation does what you want here (although I've not tested it).
Something like so perhaps, which then mandates the very latest Sparse.
---
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 04487c9bd751..7e0583ceb49f 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -232,11 +232,8 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
/*
* Use __typeof_unqual__() when available.
- *
- * XXX: Remove test for __CHECKER__ once
- * sparse learns about __typeof_unqual__().
*/
-#if CC_HAS_TYPEOF_UNQUAL && !defined(__CHECKER__)
+#if CC_HAS_TYPEOF_UNQUAL || defined(__CHECKER__)
# define USE_TYPEOF_UNQUAL 1
#endif
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index d3318a3c2577..a37d832d99a8 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -569,6 +569,7 @@ struct ftrace_likely_data {
* __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
* non-scalar types unchanged.
*/
+#ifndef USE_TYPEOF_UNQUAL
/*
* Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
* is not type-compatible with 'signed char', and we define a separate case.
@@ -586,6 +587,9 @@ struct ftrace_likely_data {
__scalar_type_to_expr_cases(long), \
__scalar_type_to_expr_cases(long long), \
default: (x)))
+#else
+#define __unqual_scalar_typeof(x) __typeof_unqual__(x)
+#endif
/* Is this type a native word size -- useful for atomic operations */
#define __native_word(t) \
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [tip:timers/vdso 12/14] net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers)
2026-01-15 21:11 ` Peter Zijlstra
@ 2026-01-15 21:19 ` Linus Torvalds
2026-01-15 21:30 ` Peter Zijlstra
2026-01-15 23:01 ` Thomas Gleixner
1 sibling, 1 reply; 11+ messages in thread
From: Linus Torvalds @ 2026-01-15 21:19 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Thomas Gleixner, kernel test robot, Ian Rogers, oe-kbuild-all,
linux-kernel, x86, sparse, linux-sparse, Marco Elver
On Thu, 15 Jan 2026 at 13:13, Peter Zijlstra <peterz@infradead.org> wrote:
>
> Something like so perhaps, which then mandates the very latest Sparse.
Ack. We want that compiler_tpes.h change for the real compilers that
support __typeof_unqual__ anyway.
Eventually we can just force that everywhere, but as Al pointed out in
another thread, we're not quite there yet (ie we'd need clang-19.0.1
and gcc-8.4 to be able to just switch entirely over to
__typeof_unqual__).
For sparse users, I think we should have the policy that we just don't
support older versions at all, since it just gets too painful.
Linus
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [tip:timers/vdso 12/14] net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers)
2026-01-15 21:19 ` Linus Torvalds
@ 2026-01-15 21:30 ` Peter Zijlstra
2026-01-15 23:03 ` Linus Torvalds
0 siblings, 1 reply; 11+ messages in thread
From: Peter Zijlstra @ 2026-01-15 21:30 UTC (permalink / raw)
To: Linus Torvalds
Cc: Thomas Gleixner, kernel test robot, Ian Rogers, oe-kbuild-all,
linux-kernel, x86, sparse, linux-sparse, Marco Elver
On Thu, Jan 15, 2026 at 01:19:14PM -0800, Linus Torvalds wrote:
> Eventually we can just force that everywhere, but as Al pointed out in
> another thread, we're not quite there yet (ie we'd need clang-19.0.1
> and gcc-8.4 to be able to just switch entirely over to
> __typeof_unqual__).
GCC-14 :-/ The GCC-8.4 one was the function return value trick.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [tip:timers/vdso 12/14] net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers)
2026-01-15 21:11 ` Peter Zijlstra
2026-01-15 21:19 ` Linus Torvalds
@ 2026-01-15 23:01 ` Thomas Gleixner
2026-01-16 11:25 ` Thomas Gleixner
1 sibling, 1 reply; 11+ messages in thread
From: Thomas Gleixner @ 2026-01-15 23:01 UTC (permalink / raw)
To: Peter Zijlstra
Cc: kernel test robot, Ian Rogers, oe-kbuild-all, linux-kernel, x86,
sparse, linux-sparse, Marco Elver
On Thu, Jan 15 2026 at 22:11, Peter Zijlstra wrote:
> On Thu, Jan 15, 2026 at 08:28:51PM +0100, Thomas Gleixner wrote:
>> On Thu, Jan 15 2026 at 00:36, kernel test robot wrote:
>>
>> Cc+ sparse folks.
>>
>> > sparse warnings: (new ones prefixed by >>)
>> >>> net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void * @@ got restricted __be64 const * @@
>> > net/rds/ib_cm.c:96:35: sparse: expected void *
>> > net/rds/ib_cm.c:96:35: sparse: got restricted __be64 const *
>> > net/rds/ib_cm.c:103:27: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void * @@ got restricted __be64 const * @@
>> > net/rds/ib_cm.c:103:27: sparse: expected void *
>> > net/rds/ib_cm.c:103:27: sparse: got restricted __be64 const *
>>
>> After staring a while at it, it turns out that get_unaligned_t(), which
>> uses __unqual_scalar_typeof() to get an unqualified type makes sparse
>> unhappy when the data type is __be64 (or any other __beNN variant).
>>
>> __beNN is annotated with __attribute__((bitwise)) when sparse is invoked
>> (#ifdef CHECKER). That allows sparse to detect incompatible math
>> operations with __beNN variables.
>>
>
> Per:
>
> https://git.kernel.org/pub/scm/devel/sparse/sparse-dev.git/commit/?id=dc9efe442b8949234a6599fdc94dc7221dd040e1
>
> it seems Sparse now knows about __typeof_unqual__; and it looks like the
> implementation does what you want here (although I've not tested it).
>
> Something like so perhaps, which then mandates the very latest Sparse.
I tried that before and sparse is still upset:
net/rds/ib_cm.c:96:35: warning: incorrect type in argument 1 (different modifiers)
net/rds/ib_cm.c:96:35: expected void *
net/rds/ib_cm.c:96:35: got restricted __be64 const *
net/rds/ib_cm.c:103:27: warning: incorrect type in argument 1 (different modifiers)
net/rds/ib_cm.c:103:27: expected void *
net/rds/ib_cm.c:103:27: got restricted __be64 const *
This time I looked deeper and it seems that USE_TYPEOF_UNQUAL is not
set.
If I force it to be set and use a proper compiler and top of tree
sparse, everything seems to be happy.
Figuring that out is something for tomorrow...
Thanks,
tglx
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [tip:timers/vdso 12/14] net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers)
2026-01-15 21:30 ` Peter Zijlstra
@ 2026-01-15 23:03 ` Linus Torvalds
2026-01-16 8:28 ` Peter Zijlstra
0 siblings, 1 reply; 11+ messages in thread
From: Linus Torvalds @ 2026-01-15 23:03 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Thomas Gleixner, kernel test robot, Ian Rogers, oe-kbuild-all,
linux-kernel, x86, sparse, linux-sparse, Marco Elver
On Thu, 15 Jan 2026 at 13:31, Peter Zijlstra <peterz@infradead.org> wrote:
>
> GCC-14 :-/ The GCC-8.4 one was the function return value trick.
Right you are. And yeah, us moving on to gcc-14 as a minimum version
is not imminent.
Still, while we can't force it, lots of distros are on gcc-15, so
while we'd have the _Generic() macro as a fallback for older versions,
at least most developers would hopefully get the nice clean modern
__typeof_unqual__ thing...
Linus
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [tip:timers/vdso 12/14] net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers)
2026-01-15 23:03 ` Linus Torvalds
@ 2026-01-16 8:28 ` Peter Zijlstra
0 siblings, 0 replies; 11+ messages in thread
From: Peter Zijlstra @ 2026-01-16 8:28 UTC (permalink / raw)
To: Linus Torvalds
Cc: Thomas Gleixner, kernel test robot, Ian Rogers, oe-kbuild-all,
linux-kernel, x86, sparse, linux-sparse, Marco Elver
On Thu, Jan 15, 2026 at 03:03:52PM -0800, Linus Torvalds wrote:
> On Thu, 15 Jan 2026 at 13:31, Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > GCC-14 :-/ The GCC-8.4 one was the function return value trick.
>
> Right you are. And yeah, us moving on to gcc-14 as a minimum version
> is not imminent.
>
> Still, while we can't force it, lots of distros are on gcc-15, so
> while we'd have the _Generic() macro as a fallback for older versions,
> at least most developers would hopefully get the nice clean modern
> __typeof_unqual__ thing...
Absolutely. I'll try and make it happen if tglx doesn't.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [tip:timers/vdso 12/14] net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers)
2026-01-15 23:01 ` Thomas Gleixner
@ 2026-01-16 11:25 ` Thomas Gleixner
2026-01-16 18:18 ` [PATCH] compiler: Use __typeof_unqual__() for __unqual_scalar_typeof() Thomas Gleixner
0 siblings, 1 reply; 11+ messages in thread
From: Thomas Gleixner @ 2026-01-16 11:25 UTC (permalink / raw)
To: Peter Zijlstra
Cc: kernel test robot, Ian Rogers, oe-kbuild-all, linux-kernel, x86,
sparse, linux-sparse, Marco Elver
On Fri, Jan 16 2026 at 00:01, Thomas Gleixner wrote:
> This time I looked deeper and it seems that USE_TYPEOF_UNQUAL is not
> set.
>
> If I force it to be set and use a proper compiler and top of tree
> sparse, everything seems to be happy.
>
> Figuring that out is something for tomorrow...
USE_TYPEOF_UNQUAL is set _after_ the __unqual_scalar muck is
processed...
Updated fix below.
Thanks,
tglx
---
include/linux/compiler.h | 10 ----------
include/linux/compiler_types.h | 11 +++++++++++
2 files changed, 11 insertions(+), 10 deletions(-)
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -231,16 +231,6 @@ void ftrace_likely_update(struct ftrace_
"must be non-C-string (not NUL-terminated)")
/*
- * Use __typeof_unqual__() when available.
- *
- * XXX: Remove test for __CHECKER__ once
- * sparse learns about __typeof_unqual__().
- */
-#if CC_HAS_TYPEOF_UNQUAL && !defined(__CHECKER__)
-# define USE_TYPEOF_UNQUAL 1
-#endif
-
-/*
* Define TYPEOF_UNQUAL() to use __typeof_unqual__() as typeof
* operator when available, to return an unqualified type of the exp.
*/
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -562,6 +562,13 @@ struct ftrace_likely_data {
#define asm_inline asm
#endif
+/*
+ * Use __typeof_unqual__() when available.
+ */
+#if CC_HAS_TYPEOF_UNQUAL || defined(__CHECKER__)
+# define USE_TYPEOF_UNQUAL 1
+#endif
+
/* Are two types/vars the same type (ignoring qualifiers)? */
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
@@ -569,6 +576,7 @@ struct ftrace_likely_data {
* __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
* non-scalar types unchanged.
*/
+#ifndef USE_TYPEOF_UNQUAL
/*
* Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
* is not type-compatible with 'signed char', and we define a separate case.
@@ -586,6 +594,9 @@ struct ftrace_likely_data {
__scalar_type_to_expr_cases(long), \
__scalar_type_to_expr_cases(long long), \
default: (x)))
+#else
+#define __unqual_scalar_typeof(x) __typeof_unqual__(x)
+#endif
/* Is this type a native word size -- useful for atomic operations */
#define __native_word(t) \
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] compiler: Use __typeof_unqual__() for __unqual_scalar_typeof()
2026-01-16 11:25 ` Thomas Gleixner
@ 2026-01-16 18:18 ` Thomas Gleixner
2026-01-17 5:25 ` Ian Rogers
2026-02-25 8:15 ` Dan Carpenter
0 siblings, 2 replies; 11+ messages in thread
From: Thomas Gleixner @ 2026-01-16 18:18 UTC (permalink / raw)
To: Peter Zijlstra
Cc: kernel test robot, Ian Rogers, oe-kbuild-all, linux-kernel, x86,
sparse, linux-sparse, Marco Elver
From: Peter Zijlstra <peterz@infradead.org>
The recent changes to get_unaligned() resulted in a new sparse warning:
net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void * @@ got restricted __be64 const * @@
net/rds/ib_cm.c:96:35: sparse: expected void *
net/rds/ib_cm.c:96:35: sparse: got restricted __be64 const *
The updated get_unaligned_t() uses __unqual_scalar_typeof() to get an
unqualified type. This works correctly for the compilers, but fails for
sparse when the data type is __be64 (or any other __beNN variant).
On sparse runs (C=[12]) __beNN types are annotated with
__attribute__((bitwise)).
That annotation allows sparse to detect incompatible operations on __beNN
variables, but it also prevents sparse from evaluating the _Generic() in
__unqual_scalar_typeof() and map __beNN to a unqualified scalar type, so it
ends up with the default, i.e. the original qualified type of a 'const
__beNN' pointer. That then ends up as the first pointer argument to
builtin_memcpy(), which obviously causes the above sparse warnings.
The sparse git tree supports typeof_unqual() now, which allows to use it
instead of the _Generic() based __unqual_scalar_typeof(). With that sparse
correctly evaluates the unqualified type and keeps the __beNN logic intact.
The downside is that this requires a top of tree sparse build and an old
sparse version will emit a metric ton of incomprehensible error messages
before it dies with a segfault.
Therefore implement a sanity check which validates that the checker is
available and capable of handling typeof_unqual(). Emit a warning if not so
the user can take informed action.
[ tglx: Move the evaluation of USE_TYPEOF_UNQUAL to compiler_types.h so it is
set before use and implement the sanity checker ]
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Closes: https://lore.kernel.org/oe-kbuild-all/202601150001.sKSN644a-lkp@intel.com/
---
Makefile | 8 ++++++++
include/linux/compiler.h | 10 ----------
include/linux/compiler_types.h | 11 +++++++++++
scripts/checker-valid.sh | 19 +++++++++++++++++++
4 files changed, 38 insertions(+), 10 deletions(-)
--- a/Makefile
+++ b/Makefile
@@ -1178,6 +1178,14 @@ ifdef CONFIG_CC_IS_CLANG
KBUILD_USERLDFLAGS += --ld-path=$(LD)
endif
+# Validate the checker is available and functional
+ifneq ($(KBUILD_CHECKSRC), 0)
+ ifneq ($(shell $(srctree)/scripts/checker-valid.sh $(CHECK)), 1)
+ $(warning C=$(KBUILD_CHECKSRC) specified, but $(CHECK) is not available or not up to date)
+ KBUILD_CHECKSRC = 0
+ endif
+endif
+
# make the checker run with the right architecture
CHECKFLAGS += --arch=$(ARCH)
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -231,16 +231,6 @@ void ftrace_likely_update(struct ftrace_
"must be non-C-string (not NUL-terminated)")
/*
- * Use __typeof_unqual__() when available.
- *
- * XXX: Remove test for __CHECKER__ once
- * sparse learns about __typeof_unqual__().
- */
-#if CC_HAS_TYPEOF_UNQUAL && !defined(__CHECKER__)
-# define USE_TYPEOF_UNQUAL 1
-#endif
-
-/*
* Define TYPEOF_UNQUAL() to use __typeof_unqual__() as typeof
* operator when available, to return an unqualified type of the exp.
*/
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -562,6 +562,13 @@ struct ftrace_likely_data {
#define asm_inline asm
#endif
+/*
+ * Use __typeof_unqual__() when available.
+ */
+#if CC_HAS_TYPEOF_UNQUAL || defined(__CHECKER__)
+# define USE_TYPEOF_UNQUAL 1
+#endif
+
/* Are two types/vars the same type (ignoring qualifiers)? */
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
@@ -569,6 +576,7 @@ struct ftrace_likely_data {
* __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
* non-scalar types unchanged.
*/
+#ifndef USE_TYPEOF_UNQUAL
/*
* Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
* is not type-compatible with 'signed char', and we define a separate case.
@@ -586,6 +594,9 @@ struct ftrace_likely_data {
__scalar_type_to_expr_cases(long), \
__scalar_type_to_expr_cases(long long), \
default: (x)))
+#else
+#define __unqual_scalar_typeof(x) __typeof_unqual__(x)
+#endif
/* Is this type a native word size -- useful for atomic operations */
#define __native_word(t) \
--- /dev/null
+++ b/scripts/checker-valid.sh
@@ -0,0 +1,19 @@
+#!/bin/sh -eu
+# SPDX-License-Identifier: GPL-2.0
+
+[ ! -x "$(command -v "$1")" ] && exit 1
+
+tmp_file=$(mktemp)
+trap "rm -f $tmp_file" EXIT
+
+cat << EOF >$tmp_file
+static inline int u(const int *q)
+{
+ __typeof_unqual__(*q) v = *q;
+ return v;
+}
+EOF
+
+# sparse happily exits with 0 on error so validate
+# there is none on stderr. Use awk as grep is a pain with sh -e
+$1 $tmp_file 2>&1 | awk -v c=1 '/error/{c=0}END{print c}'
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] compiler: Use __typeof_unqual__() for __unqual_scalar_typeof()
2026-01-16 18:18 ` [PATCH] compiler: Use __typeof_unqual__() for __unqual_scalar_typeof() Thomas Gleixner
@ 2026-01-17 5:25 ` Ian Rogers
2026-02-25 8:15 ` Dan Carpenter
1 sibling, 0 replies; 11+ messages in thread
From: Ian Rogers @ 2026-01-17 5:25 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Peter Zijlstra, kernel test robot, oe-kbuild-all, linux-kernel,
x86, sparse, linux-sparse, Marco Elver
On Fri, Jan 16, 2026 at 10:18 AM Thomas Gleixner <tglx@kernel.org> wrote:
>
> From: Peter Zijlstra <peterz@infradead.org>
>
> The recent changes to get_unaligned() resulted in a new sparse warning:
>
> net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers) @@ expected void * @@ got restricted __be64 const * @@
> net/rds/ib_cm.c:96:35: sparse: expected void *
> net/rds/ib_cm.c:96:35: sparse: got restricted __be64 const *
>
> The updated get_unaligned_t() uses __unqual_scalar_typeof() to get an
> unqualified type. This works correctly for the compilers, but fails for
> sparse when the data type is __be64 (or any other __beNN variant).
>
> On sparse runs (C=[12]) __beNN types are annotated with
> __attribute__((bitwise)).
>
> That annotation allows sparse to detect incompatible operations on __beNN
> variables, but it also prevents sparse from evaluating the _Generic() in
> __unqual_scalar_typeof() and map __beNN to a unqualified scalar type, so it
> ends up with the default, i.e. the original qualified type of a 'const
> __beNN' pointer. That then ends up as the first pointer argument to
> builtin_memcpy(), which obviously causes the above sparse warnings.
>
> The sparse git tree supports typeof_unqual() now, which allows to use it
> instead of the _Generic() based __unqual_scalar_typeof(). With that sparse
> correctly evaluates the unqualified type and keeps the __beNN logic intact.
Wow, that's painful. Congratulations on finding the root case.
Acked-by: Ian Rogers <irogers@google.com>
Thanks,
Ian
> The downside is that this requires a top of tree sparse build and an old
> sparse version will emit a metric ton of incomprehensible error messages
> before it dies with a segfault.
>
> Therefore implement a sanity check which validates that the checker is
> available and capable of handling typeof_unqual(). Emit a warning if not so
> the user can take informed action.
>
> [ tglx: Move the evaluation of USE_TYPEOF_UNQUAL to compiler_types.h so it is
> set before use and implement the sanity checker ]
>
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Peter Zijlstra <peterz@infradead.org>
> Signed-off-by: Thomas Gleixner <tglx@kernel.org>
> Closes: https://lore.kernel.org/oe-kbuild-all/202601150001.sKSN644a-lkp@intel.com/
> ---
> Makefile | 8 ++++++++
> include/linux/compiler.h | 10 ----------
> include/linux/compiler_types.h | 11 +++++++++++
> scripts/checker-valid.sh | 19 +++++++++++++++++++
> 4 files changed, 38 insertions(+), 10 deletions(-)
>
> --- a/Makefile
> +++ b/Makefile
> @@ -1178,6 +1178,14 @@ ifdef CONFIG_CC_IS_CLANG
> KBUILD_USERLDFLAGS += --ld-path=$(LD)
> endif
>
> +# Validate the checker is available and functional
> +ifneq ($(KBUILD_CHECKSRC), 0)
> + ifneq ($(shell $(srctree)/scripts/checker-valid.sh $(CHECK)), 1)
> + $(warning C=$(KBUILD_CHECKSRC) specified, but $(CHECK) is not available or not up to date)
> + KBUILD_CHECKSRC = 0
> + endif
> +endif
> +
> # make the checker run with the right architecture
> CHECKFLAGS += --arch=$(ARCH)
>
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -231,16 +231,6 @@ void ftrace_likely_update(struct ftrace_
> "must be non-C-string (not NUL-terminated)")
>
> /*
> - * Use __typeof_unqual__() when available.
> - *
> - * XXX: Remove test for __CHECKER__ once
> - * sparse learns about __typeof_unqual__().
> - */
> -#if CC_HAS_TYPEOF_UNQUAL && !defined(__CHECKER__)
> -# define USE_TYPEOF_UNQUAL 1
> -#endif
> -
> -/*
> * Define TYPEOF_UNQUAL() to use __typeof_unqual__() as typeof
> * operator when available, to return an unqualified type of the exp.
> */
> --- a/include/linux/compiler_types.h
> +++ b/include/linux/compiler_types.h
> @@ -562,6 +562,13 @@ struct ftrace_likely_data {
> #define asm_inline asm
> #endif
>
> +/*
> + * Use __typeof_unqual__() when available.
> + */
> +#if CC_HAS_TYPEOF_UNQUAL || defined(__CHECKER__)
> +# define USE_TYPEOF_UNQUAL 1
> +#endif
> +
> /* Are two types/vars the same type (ignoring qualifiers)? */
> #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
>
> @@ -569,6 +576,7 @@ struct ftrace_likely_data {
> * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
> * non-scalar types unchanged.
> */
> +#ifndef USE_TYPEOF_UNQUAL
> /*
> * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
> * is not type-compatible with 'signed char', and we define a separate case.
> @@ -586,6 +594,9 @@ struct ftrace_likely_data {
> __scalar_type_to_expr_cases(long), \
> __scalar_type_to_expr_cases(long long), \
> default: (x)))
> +#else
> +#define __unqual_scalar_typeof(x) __typeof_unqual__(x)
> +#endif
>
> /* Is this type a native word size -- useful for atomic operations */
> #define __native_word(t) \
> --- /dev/null
> +++ b/scripts/checker-valid.sh
> @@ -0,0 +1,19 @@
> +#!/bin/sh -eu
> +# SPDX-License-Identifier: GPL-2.0
> +
> +[ ! -x "$(command -v "$1")" ] && exit 1
> +
> +tmp_file=$(mktemp)
> +trap "rm -f $tmp_file" EXIT
> +
> +cat << EOF >$tmp_file
> +static inline int u(const int *q)
> +{
> + __typeof_unqual__(*q) v = *q;
> + return v;
> +}
> +EOF
> +
> +# sparse happily exits with 0 on error so validate
> +# there is none on stderr. Use awk as grep is a pain with sh -e
> +$1 $tmp_file 2>&1 | awk -v c=1 '/error/{c=0}END{print c}'
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] compiler: Use __typeof_unqual__() for __unqual_scalar_typeof()
2026-01-16 18:18 ` [PATCH] compiler: Use __typeof_unqual__() for __unqual_scalar_typeof() Thomas Gleixner
2026-01-17 5:25 ` Ian Rogers
@ 2026-02-25 8:15 ` Dan Carpenter
1 sibling, 0 replies; 11+ messages in thread
From: Dan Carpenter @ 2026-02-25 8:15 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Peter Zijlstra, kernel test robot, Ian Rogers, oe-kbuild-all,
linux-kernel, x86, sparse, linux-sparse, Marco Elver
On Fri, Jan 16, 2026 at 07:18:16PM +0100, Thomas Gleixner wrote:
> --- a/Makefile
> +++ b/Makefile
> @@ -1178,6 +1178,14 @@ ifdef CONFIG_CC_IS_CLANG
> KBUILD_USERLDFLAGS += --ld-path=$(LD)
> endif
>
> +# Validate the checker is available and functional
> +ifneq ($(KBUILD_CHECKSRC), 0)
> + ifneq ($(shell $(srctree)/scripts/checker-valid.sh $(CHECK)), 1)
> + $(warning C=$(KBUILD_CHECKSRC) specified, but $(CHECK) is not available or not up to date)
> + KBUILD_CHECKSRC = 0
> + endif
> +endif
> +
This means we can't run "CHECK="valgrind smatch -p=kernel" because
valgrind always prints output to stderr. So hopefully we can
eventually remove this check.
regards,
dan carpenter
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-02-25 8:15 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <202601150001.sKSN644a-lkp@intel.com>
2026-01-15 19:28 ` [tip:timers/vdso 12/14] net/rds/ib_cm.c:96:35: sparse: sparse: incorrect type in argument 1 (different modifiers) Thomas Gleixner
2026-01-15 21:11 ` Peter Zijlstra
2026-01-15 21:19 ` Linus Torvalds
2026-01-15 21:30 ` Peter Zijlstra
2026-01-15 23:03 ` Linus Torvalds
2026-01-16 8:28 ` Peter Zijlstra
2026-01-15 23:01 ` Thomas Gleixner
2026-01-16 11:25 ` Thomas Gleixner
2026-01-16 18:18 ` [PATCH] compiler: Use __typeof_unqual__() for __unqual_scalar_typeof() Thomas Gleixner
2026-01-17 5:25 ` Ian Rogers
2026-02-25 8:15 ` Dan Carpenter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox