Skip to content

Commit fd69b2f

Browse files
Peter ZijlstraThomas Gleixner
authored andcommitted
compiler: Use __typeof_unqual__() for __unqual_scalar_typeof()
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> Acked-by: Ian Rogers <irogers@google.com> Link: https://patch.msgid.link/87ecnp2zh3.ffs@tglx Closes: https://lore.kernel.org/oe-kbuild-all/202601150001.sKSN644a-lkp@intel.com/
1 parent 759a1f9 commit fd69b2f

4 files changed

Lines changed: 40 additions & 10 deletions

File tree

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,14 @@ CHECKFLAGS += $(if $(CONFIG_CPU_BIG_ENDIAN),-mbig-endian,-mlittle-endian)
11871187
# the checker needs the correct machine size
11881188
CHECKFLAGS += $(if $(CONFIG_64BIT),-m64,-m32)
11891189

1190+
# Validate the checker is available and functional
1191+
ifneq ($(KBUILD_CHECKSRC), 0)
1192+
ifneq ($(shell $(srctree)/scripts/checker-valid.sh $(CHECK) $(CHECKFLAGS)), 1)
1193+
$(warning C=$(KBUILD_CHECKSRC) specified, but $(CHECK) is not available or not up to date)
1194+
KBUILD_CHECKSRC = 0
1195+
endif
1196+
endif
1197+
11901198
# Default kernel image to build when no specific target is given.
11911199
# KBUILD_IMAGE may be overruled on the command line or
11921200
# set in the environment

include/linux/compiler.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -230,16 +230,6 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
230230
__BUILD_BUG_ON_ZERO_MSG(!__is_noncstr(p), \
231231
"must be non-C-string (not NUL-terminated)")
232232

233-
/*
234-
* Use __typeof_unqual__() when available.
235-
*
236-
* XXX: Remove test for __CHECKER__ once
237-
* sparse learns about __typeof_unqual__().
238-
*/
239-
#if CC_HAS_TYPEOF_UNQUAL && !defined(__CHECKER__)
240-
# define USE_TYPEOF_UNQUAL 1
241-
#endif
242-
243233
/*
244234
* Define TYPEOF_UNQUAL() to use __typeof_unqual__() as typeof
245235
* operator when available, to return an unqualified type of the exp.

include/linux/compiler_types.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,13 +562,22 @@ struct ftrace_likely_data {
562562
#define asm_inline asm
563563
#endif
564564

565+
#ifndef __ASSEMBLY__
566+
/*
567+
* Use __typeof_unqual__() when available.
568+
*/
569+
#if CC_HAS_TYPEOF_UNQUAL || defined(__CHECKER__)
570+
# define USE_TYPEOF_UNQUAL 1
571+
#endif
572+
565573
/* Are two types/vars the same type (ignoring qualifiers)? */
566574
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
567575

568576
/*
569577
* __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving
570578
* non-scalar types unchanged.
571579
*/
580+
#ifndef USE_TYPEOF_UNQUAL
572581
/*
573582
* Prefer C11 _Generic for better compile-times and simpler code. Note: 'char'
574583
* is not type-compatible with 'signed char', and we define a separate case.
@@ -586,6 +595,10 @@ struct ftrace_likely_data {
586595
__scalar_type_to_expr_cases(long), \
587596
__scalar_type_to_expr_cases(long long), \
588597
default: (x)))
598+
#else
599+
#define __unqual_scalar_typeof(x) __typeof_unqual__(x)
600+
#endif
601+
#endif /* !__ASSEMBLY__ */
589602

590603
/* Is this type a native word size -- useful for atomic operations */
591604
#define __native_word(t) \

scripts/checker-valid.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/sh -eu
2+
# SPDX-License-Identifier: GPL-2.0
3+
4+
[ ! -x "$(command -v "$1")" ] && exit 1
5+
6+
tmp_file=$(mktemp)
7+
trap "rm -f $tmp_file" EXIT
8+
9+
cat << EOF >$tmp_file
10+
static inline int u(const int *q)
11+
{
12+
__typeof_unqual__(*q) v = *q;
13+
return v;
14+
}
15+
EOF
16+
17+
# sparse happily exits with 0 on error so validate
18+
# there is none on stderr. Use awk as grep is a pain with sh -e
19+
$@ $tmp_file 2>&1 | awk -v c=1 '/error/{c=0}END{print c}'

0 commit comments

Comments
 (0)