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 ]
Unified · Split
| @@ -1187,6 +1187,14 @@ CHECKFLAGS += $(if $(CONFIG_CPU_BIG_ENDIAN),-mbig-endian,-mlittle-endian) · 1186 unmodified lines | ||
| 1187 | 1187 | # the checker needs the correct machine size |
| 1188 | 1188 | CHECKFLAGS += $(if $(CONFIG_64BIT),-m64,-m32) |
| 1189 | 1189 | |
| 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 | + | |
| 1190 | 1198 | # Default kernel image to build when no specific target is given. |
| 1191 | 1199 | # KBUILD_IMAGE may be overruled on the command line or |
| 1192 | 1200 | # set in the environment |
| @@ -230,16 +230,6 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, · 229 unmodified lines | ||
| 230 | 230 | __BUILD_BUG_ON_ZERO_MSG(!__is_noncstr(p), \ |
| 231 | 231 | "must be non-C-string (not NUL-terminated)") |
| 232 | 232 | |
| 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 | − | |
| 243 | 233 | /* |
| 244 | 234 | * Define TYPEOF_UNQUAL() to use __typeof_unqual__() as typeof |
| 245 | 235 | * operator when available, to return an unqualified type of the exp. |
| @@ -562,6 +562,14 @@ struct ftrace_likely_data { · 561 unmodified lines | ||
| 562 | 562 | #define asm_inline asm |
| 563 | 563 | #endif |
| 564 | 564 | |
| 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 | + | |
| 565 | 573 | /* Are two types/vars the same type (ignoring qualifiers)? */ |
| 566 | 574 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) |
| 567 | 575 | |
| @@ -569,6 +577,7 @@ struct ftrace_likely_data { · 1 unmodified line | ||
| 569 | 577 | * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving |
| 570 | 578 | * non-scalar types unchanged. |
| 571 | 579 | */ |
| 580 | +#ifndef USE_TYPEOF_UNQUAL | |
| 572 | 581 | /* |
| 573 | 582 | * Prefer C11 _Generic for better compile-times and simpler code. Note: 'char' |
| 574 | 583 | * is not type-compatible with 'signed char', and we define a separate case. |
| @@ -586,6 +595,10 @@ struct ftrace_likely_data { · 11 unmodified lines | ||
| 586 | 595 | __scalar_type_to_expr_cases(long), \ |
| 587 | 596 | __scalar_type_to_expr_cases(long long), \ |
| 588 | 597 | default: (x))) |
| 598 | +#else | |
| 599 | +#define __unqual_scalar_typeof(x) __typeof_unqual__(x) | |
| 600 | +#endif | |
| 601 | +#endif /* !__ASSEMBLY__ */ | |
| 589 | 602 | |
| 590 | 603 | /* Is this type a native word size -- useful for atomic operations */ |
| 591 | 604 | #define __native_word(t) \ |
| @@ -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}' | |