public inbox for linux-sparse@vger.kernel.org
 help / color / mirror / Atom feed
* 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