Linux SPARSE checker discussions
 help / color / mirror / Atom feed
From: Bart Van Assche <bvanassche@acm.org>
To: linux-sparse@vger.kernel.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	Bart Van Assche <bvanassche@acm.org>
Subject: [PATCH 04/73] bitfield: Pack consecutive _Bool bitfields into byte containers
Date: Mon,  9 Nov 2026 12:31:50 -0800	[thread overview]
Message-ID: <20261109203259.362845-5-bvanassche@acm.org> (raw)
In-Reply-To: <20261109203259.362845-1-bvanassche@acm.org>

Round bitfield base storage unit sizes smaller than a byte up to
bits_in_char in bitfield_base_size() and widen sub-byte bitfield access
containers to uchar_ctype in bitfield_base_type() so _Bool bitfields use
an 8-bit storage unit during both struct layout and IR linearization.

Allow consecutive _Bool bitfields to pack into a single byte in
examine_struct_union_type() and emit bitfield extract and insert
instructions at each member's bit_offset, matching the System V ABI,
GCC, and Clang. Remove check-known-to-fail from
validation/bitfield-bool-layout.c.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 evaluate.c                        | 18 ++++++-------
 linearize.c                       |  2 ++
 symbol.c                          |  2 ++
 symbol.h                          |  2 ++
 validation/bitfield-bool-layout.c |  9 +++----
 validation/linear/bitfield-bool.c | 44 +++++++++++++++++++++++++++++++
 6 files changed, 62 insertions(+), 15 deletions(-)
 create mode 100644 validation/linear/bitfield-bool.c

diff --git a/evaluate.c b/evaluate.c
index 988ace95abed..40778f4e8a63 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1406,12 +1406,12 @@ static int check_assignment_types(struct symbol *target, struct expression **rp,
 				return 1;
 		} else if (!(sclass & TYPE_RESTRICT))
 			goto Cast;
-                if (t == &bool_ctype) {
-                        if (is_fouled_type(s))
-                                warning((*rp)->pos, "%s degrades to integer",
-                                        show_typename(s->ctype.base_type));
-                        goto Cast;
-                }
+		if (is_bool_type(t)) {
+			if (is_fouled_type(s))
+				warning((*rp)->pos, "%s degrades to integer",
+					show_typename(s->ctype.base_type));
+			goto Cast;
+		}
 		*typediff = "different base types";
 		return 0;
 	}
@@ -1475,7 +1475,7 @@ static int check_assignment_types(struct symbol *target, struct expression **rp,
 
 	if (tclass & TYPE_NUM) {
 		/* XXX: need to turn into comparison with NULL */
-		if (t == &bool_ctype && (sclass & TYPE_PTR))
+		if (is_bool_type(t) && (sclass & TYPE_PTR))
 			goto Cast;
 		*typediff = "different base types";
 		return 0;
@@ -3064,7 +3064,7 @@ static struct symbol *evaluate_cast(struct expression *expr)
 			warning(expr->pos, "cast to %s",
 				show_typename(ttype));
 		if (sclass & TYPE_RESTRICT) {
-			if (ttype == &bool_ctype) {
+			if (is_bool_type(ttype)) {
 				if (sclass & TYPE_FOULED)
 					warning(expr->pos, "%s degrades to integer",
 						show_typename(stype));
@@ -3111,7 +3111,7 @@ static struct symbol *evaluate_cast(struct expression *expr)
 		}
 	}
 
-	if (ttype == &bool_ctype)
+	if (is_bool_type(ttype))
 		cast_to_bool(expr);
 
 	// checks pointers to restricted
diff --git a/linearize.c b/linearize.c
index 5bdd6119260f..75850df0a90f 100644
--- a/linearize.c
+++ b/linearize.c
@@ -934,6 +934,8 @@ static struct symbol *bitfield_base_type(struct symbol *sym)
 			base = base->ctype.base_type;
 		if (base->type == SYM_BITFIELD) {
 			base = base->ctype.base_type;
+			if (base->bit_size < bits_in_char)
+				base = &uchar_ctype;
 			if (sym->packed) {
 				int size = bits_to_bytes(sym->bit_offset + sym->bit_size);
 				sym = __alloc_symbol(0);
diff --git a/symbol.c b/symbol.c
index 5470880db271..feaaed3b8a2d 100644
--- a/symbol.c
+++ b/symbol.c
@@ -113,6 +113,8 @@ static int bitfield_base_size(struct symbol *sym)
 		sym = sym->ctype.base_type;
 	if (sym->type == SYM_BITFIELD)
 		sym = sym->ctype.base_type;
+	if (sym->bit_size < bits_in_char)
+		return bits_in_char;
 	return sym->bit_size;
 }
 
diff --git a/symbol.h b/symbol.h
index 9ff2733021b8..bd163450628b 100644
--- a/symbol.h
+++ b/symbol.h
@@ -477,6 +477,8 @@ static inline int is_bool_type(struct symbol *type)
 {
 	if (type->type == SYM_NODE)
 		type = type->ctype.base_type;
+	if (type->type == SYM_BITFIELD)
+		type = type->ctype.base_type;
 	return type == &bool_ctype;
 }
 
diff --git a/validation/bitfield-bool-layout.c b/validation/bitfield-bool-layout.c
index 4e0a2b4a2b60..2f559f98491f 100644
--- a/validation/bitfield-bool-layout.c
+++ b/validation/bitfield-bool-layout.c
@@ -12,14 +12,11 @@ struct bfb foo(struct bfb s)
 
 /*
  * check-name: bitfield-bool-layout
- * check-description: given that bool is here 1-bit wide
- *	each field here above completely 'fill' a bool.
- *	Thus 3 bools need to be allocated, but since the
- *	alignment is 1-byte the result has a size of 3
- *	bytes, 24 bits thus instead of 8.
+ * check-description: Verify that consecutive _Bool bitfields pack into a
+ *	single 1-byte (8-bit) storage unit rather than allocating a separate
+ *	byte per bitfield (24 bits).
  * check-command: test-linearize -Wno-decl $file
  *
- * check-known-to-fail
  * check-output-ignore
  * check-output-excludes: ret\\.24
  * check-output-contains: ret\\.8
diff --git a/validation/linear/bitfield-bool.c b/validation/linear/bitfield-bool.c
new file mode 100644
index 000000000000..91c9111eb91d
--- /dev/null
+++ b/validation/linear/bitfield-bool.c
@@ -0,0 +1,44 @@
+struct bfb {
+	_Bool a:1;
+	_Bool f:1;
+	_Bool z:1;
+};
+
+_Bool get_z(struct bfb *p)
+{
+	return p->z;
+}
+
+void set_f_one(struct bfb *p)
+{
+	p->f = 1;
+}
+
+void set_f_two(struct bfb *p)
+{
+	p->f = 2;
+}
+
+void set_f_ptr(struct bfb *p, int *ptr)
+{
+	p->f = ptr;
+}
+
+int init_bfb(void)
+{
+	struct bfb s = { .a = 1, .z = 1 };
+	return s.a + s.f + s.z;
+}
+
+/*
+ * check-name: bitfield-bool-linearize
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: load\\.1
+ * check-output-excludes: store\\.1
+ * check-output-contains: load\\.8
+ * check-output-contains: store\\.8
+ * check-output-pattern(2): or\\.8.*\\$2
+ * check-output-contains: ret\\.32.*\\$2
+ */

  parent reply	other threads:[~2026-11-09 20:33 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 20:31 Bart Van Assche
2026-11-09 20:31 ` [PATCH 01/73] Makefile: Pass '--' to rm in clean target to handle dash-prefixed files Bart Van Assche
2026-11-09 20:31 ` [PATCH 02/73] sparse-llvm: Use LLVMCreateBuilderForModule() with LLVM 24 and later Bart Van Assche
2026-11-09 20:31 ` [PATCH 03/73] typeof_unqual: Strip qualifiers and address space from types and arrays Bart Van Assche
2026-11-09 20:31 ` Bart Van Assche [this message]
2026-11-09 20:31 ` [PATCH 05/73] allocate: Harden slab allocation bounds, zeroing, and mmap checks Bart Van Assche
2026-11-09 20:31 ` [PATCH 06/73] tokenize: Support 4096-byte identifiers and fix escape bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 07/73] pre-process: Fix macro expansion and include directive handling Bart Van Assche
2026-11-09 20:31 ` [PATCH 08/73] options, lib: Harden warning buffers and command-line option parsing Bart Van Assche
2026-11-09 20:31 ` [PATCH 09/73] builtin: Fix atomic builtin type checking and object_size bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 10/73] parse, show-parse: Fix attribute propagation, enum overflow, and bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 11/73] target-openrisc: Set target_openrisc.mach to MACH_OPENRISC Bart Van Assche
2026-11-09 20:31 ` [PATCH 12/73] evaluate: Fix pointer arithmetic, incomplete types, and qualifiers Bart Van Assche
2026-11-09 20:31 ` [PATCH 13/73] expand: Fix static initializer folding and floating-point casts Bart Van Assche
2026-11-09 20:32 ` [PATCH 14/73] inline: Copy union cast types and VLA bounds when inlining Bart Van Assche
2026-11-09 20:32 ` [PATCH 15/73] linearize, flow: Fix asm operands, switch case bounds, and DSE Bart Van Assche
2026-11-09 20:32 ` [PATCH 16/73] memops, ssa: Walk parent insns in reverse and skip mixed-size SSA Bart Van Assche
2026-11-09 20:32 ` [PATCH 17/73] simplify: Prevent overflow on LLONG_MIN negation and fix simplifications Bart Van Assche
2026-11-09 20:32 ` [PATCH 18/73] sparse: Gate context failure warning on Wcontext and catch underflow Bart Van Assche
2026-11-09 20:32 ` [PATCH 19/73] ast-model: Return AST_N_COLUMNS and inspect child nodes lazily Bart Van Assche
2026-11-09 20:32 ` [PATCH 20/73] c2xml: Guard against recursive symbols and free xmlGetProp() string Bart Van Assche
2026-11-09 20:32 ` [PATCH 21/73] compile-i386: Fix buffer bounds, unsigned '<=' codegen, and null checks Bart Van Assche
2026-11-09 20:32 ` [PATCH 22/73] ctags: Fix line comparison order and handle SYM_RESTRICT and SYM_LABEL Bart Van Assche
2026-11-09 20:32 ` [PATCH 23/73] dissect: Unwrap array element type via base_type() Bart Van Assche
2026-11-09 20:32 ` [PATCH 24/73] example: Fix show_op() rotating buffer dimensions Bart Van Assche
2026-11-09 20:32 ` [PATCH 25/73] graph: Check PSEUDO_SYM before dereferencing insn->func->sym Bart Van Assche
2026-11-09 20:32 ` [PATCH 26/73] scheck: Fix slice() upper bit index calculation Bart Van Assche
2026-11-09 20:32 ` [PATCH 27/73] sparse-llvm: Support arbitrary struct member counts and fix operand types Bart Van Assche
2026-11-09 20:32 ` [PATCH 28/73] inline: Duplicate generic expressions instead of evaluating them Bart Van Assche
2026-11-09 20:32 ` [PATCH 29/73] lib: Avoid mutating fmt before va_start() in warning() Bart Van Assche
2026-11-09 20:32 ` [PATCH 30/73] cse, canon: Cast pointers to uintptr_t before relational comparison Bart Van Assche
2026-11-09 20:32 ` [PATCH 31/73] context: Add "conditional context increment" model Bart Van Assche
2026-11-09 20:32 ` [PATCH 32/73] expand: Simplify signed constants early Bart Van Assche
2026-11-09 20:32 ` [PATCH 33/73] bitwise: Allow all-bits-set as a restricted value Bart Van Assche
2026-11-09 20:32 ` [PATCH 34/73] bitwise: Allow restricted ordered compares with unrestricted values Bart Van Assche
2026-11-09 20:32 ` [PATCH 35/73] bitwise: Keep unrestricted values unrestricted after a cast Bart Van Assche
2026-11-09 20:32 ` [PATCH 36/73] bitwise: Don't remove MOD_SPECIFIER from 'bitwise' types Bart Van Assche
2026-11-09 20:32 ` [PATCH 37/73] bitwise: Allow both regular casts and forced casts for restricted values Bart Van Assche
2026-11-09 20:32 ` [PATCH 38/73] clang-format: Add .clang-format configuration file Bart Van Assche
2026-11-09 20:32 ` [PATCH 39/73] options: Add support for -std=c23, -std=c2x and -std=gnu23 Bart Van Assche
2026-11-09 20:32 ` [PATCH 40/73] preprocessor: Add support for #elifdef and #elifndef Bart Van Assche
2026-11-09 20:32 ` [PATCH 41/73] preprocessor: Add support for __has_include and __has_include_next Bart Van Assche
2026-11-09 20:32 ` [PATCH 42/73] c23: Add support for static_assert, alignas, alignof, thread_local Bart Van Assche
2026-11-09 20:32 ` [PATCH 43/73] c23: Add support for bool, true, and false keywords Bart Van Assche
2026-11-09 20:32 ` [PATCH 44/73] c23: Add support for nullptr and nullptr_t Bart Van Assche
2026-11-09 20:32 ` [PATCH 45/73] c23: Add support for digit separators in numeric literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 46/73] c23: Support unnamed parameters in function definitions Bart Van Assche
2026-11-09 20:32 ` [PATCH 47/73] c23: Support variadic functions without named parameters Bart Van Assche
2026-11-09 20:32 ` [PATCH 48/73] c23: Support labels before declarations and at block ends Bart Van Assche
2026-11-09 20:32 ` [PATCH 49/73] c23: Support auto type inference Bart Van Assche
2026-11-09 20:32 ` [PATCH 50/73] c23: Support constexpr object specifier Bart Van Assche
2026-11-09 20:32 ` [PATCH 51/73] c23: Support enumerations with fixed underlying types Bart Van Assche
2026-11-09 20:32 ` [PATCH 52/73] c23: Support standard [[]] attribute syntax Bart Van Assche
2026-11-09 20:32 ` [PATCH 53/73] preprocessor: Add support for __has_c_attribute Bart Van Assche
2026-11-09 20:32 ` [PATCH 54/73] c23: Support empty initializer braces {} Bart Van Assche
2026-11-09 20:32 ` [PATCH 55/73] preprocessor: Add support for __has_embed Bart Van Assche
2026-11-09 20:32 ` [PATCH 56/73] preprocessor: Add support for #embed directive Bart Van Assche
2026-11-09 20:32 ` [PATCH 57/73] c23: Add support for u8 character constants and string literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 58/73] preprocessor: Add support for __VA_OPT__ Bart Van Assche
2026-11-09 20:32 ` [PATCH 59/73] c23: Treat empty parameter list () as (void) and reject K&R functions Bart Van Assche
2026-11-09 20:32 ` [PATCH 60/73] c23: Support storage-class specifiers in compound literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 61/73] c23: Add support for _BitInt(N) Bart Van Assche
2026-11-09 20:32 ` [PATCH 62/73] enum: Support machine mode attributes on enumeration types Bart Van Assche
2026-11-09 20:32 ` [PATCH 63/73] enum: Support __attribute__((packed)) " Bart Van Assche
2026-11-09 20:32 ` [PATCH 64/73] expand: Ignore top-level non-array address space in compare_types() Bart Van Assche
2026-11-09 20:32 ` [PATCH 65/73] builtin: Support __builtin_infer_alloc_token() as a size_t ICE Bart Van Assche
2026-11-09 20:32 ` [PATCH 66/73] builtin: Add support for Linux kernel compiler builtins Bart Van Assche
2026-11-09 20:32 ` [PATCH 67/73] builtin: Add support for __builtin_has_attribute() Bart Van Assche
2026-11-09 20:32 ` [PATCH 68/73] cleanup: Support __attribute__((cleanup(...))) in linearize and -Wcontext Bart Van Assche
2026-11-09 20:32 ` [PATCH 69/73] builtin: Do not evaluate __builtin_clz(0) and __builtin_ctz(0) Bart Van Assche
2026-11-09 20:32 ` [PATCH 70/73] pre-process: Support long token and string expansions dynamically Bart Van Assche
2026-11-09 20:32 ` [PATCH 71/73] x86: Undefine conflicting bitness macros when parsing -m flags Bart Van Assche
2026-11-09 20:32 ` [PATCH 72/73] evaluate: Accept conditional expressions with only one void side Bart Van Assche
2026-11-09 20:32 ` [PATCH 73/73] ci: Add Linux kernel GitHub Actions workflow and build script Bart Van Assche

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261109203259.362845-5-bvanassche@acm.org \
    --to=bvanassche@acm.org \
    --cc=linux-sparse@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox