Module Name: src Committed By: rillig Date: Fri Jun 30 15:19:10 UTC 2023
Modified Files: src/tests/usr.bin/xlint/lint1: expr_sizeof.c msg_065.c src/usr.bin/xlint/lint1: decl.c Log Message: lint: fix computation of bit-field width When bit-fields in packed structs were added on 2009-10-02, lint assumed that they would only use 'signed int' or 'unsigned int' as storage unit, even though C99 also allows _Bool. The cleanup commit for decl.c 1.225 from 2021-08-28 accidentally changed the rounding mode for bit-field storage units from round-up to round-down. To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/tests/usr.bin/xlint/lint1/expr_sizeof.c cvs rdiff -u -r1.4 -r1.5 src/tests/usr.bin/xlint/lint1/msg_065.c cvs rdiff -u -r1.325 -r1.326 src/usr.bin/xlint/lint1/decl.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/usr.bin/xlint/lint1/expr_sizeof.c diff -u src/tests/usr.bin/xlint/lint1/expr_sizeof.c:1.9 src/tests/usr.bin/xlint/lint1/expr_sizeof.c:1.10 --- src/tests/usr.bin/xlint/lint1/expr_sizeof.c:1.9 Fri Jun 30 09:21:52 2023 +++ src/tests/usr.bin/xlint/lint1/expr_sizeof.c Fri Jun 30 15:19:09 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: expr_sizeof.c,v 1.9 2023/06/30 09:21:52 rillig Exp $ */ +/* $NetBSD: expr_sizeof.c,v 1.10 2023/06/30 15:19:09 rillig Exp $ */ # 3 "expr_sizeof.c" /* @@ -92,7 +92,7 @@ bit_fields(void) _Bool flag2:1; }; } anonymous_flags; - /* FIXME: sizeof must be 1, not 0. */ + /* expect+1: error: negative array dimension (-1) [20] */ typedef int sizeof_anonymous_flags[-(int)sizeof(anonymous_flags)]; struct { Index: src/tests/usr.bin/xlint/lint1/msg_065.c diff -u src/tests/usr.bin/xlint/lint1/msg_065.c:1.4 src/tests/usr.bin/xlint/lint1/msg_065.c:1.5 --- src/tests/usr.bin/xlint/lint1/msg_065.c:1.4 Wed Jun 22 19:23:18 2022 +++ src/tests/usr.bin/xlint/lint1/msg_065.c Fri Jun 30 15:19:09 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_065.c,v 1.4 2022/06/22 19:23:18 rillig Exp $ */ +/* $NetBSD: msg_065.c,v 1.5 2023/06/30 15:19:09 rillig Exp $ */ # 3 "msg_065.c" // Test for message: '%s' has no named members [65] @@ -7,7 +7,7 @@ struct ok { int member; }; -/* XXX: should generate a warning as well. */ +/* Don't warn about completely empty structs, which are a GCC extension. */ struct empty { }; Index: src/usr.bin/xlint/lint1/decl.c diff -u src/usr.bin/xlint/lint1/decl.c:1.325 src/usr.bin/xlint/lint1/decl.c:1.326 --- src/usr.bin/xlint/lint1/decl.c:1.325 Fri Jun 30 14:39:23 2023 +++ src/usr.bin/xlint/lint1/decl.c Fri Jun 30 15:19:09 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: decl.c,v 1.325 2023/06/30 14:39:23 rillig Exp $ */ +/* $NetBSD: decl.c,v 1.326 2023/06/30 15:19:09 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: decl.c,v 1.325 2023/06/30 14:39:23 rillig Exp $"); +__RCSID("$NetBSD: decl.c,v 1.326 2023/06/30 15:19:09 rillig Exp $"); #endif #include <sys/param.h> @@ -456,18 +456,20 @@ set_first_typedef(type_t *tp, sym_t *sym } static unsigned int -bit_field_width(sym_t **mem) +bit_field_width(sym_t **mem, bool *named) { - unsigned int width = (*mem)->s_type->t_bit_field_width; + unsigned int width = 0; + unsigned int align = 0; while (*mem != NULL && (*mem)->s_type->t_bitfield) { + if ((*mem)->s_name != unnamed) + *named = true; width += (*mem)->s_type->t_bit_field_width; + unsigned int mem_align = alignment_in_bits((*mem)->s_type); + if (mem_align > align) + align = mem_align; *mem = (*mem)->s_next; } - - // XXX: Why INT_SIZE? C99 6.7.2.1p4 allows bit-fields to have type - // XXX: _Bool or another implementation-defined type. - // XXX: Why round down instead of up? See expr_sizeof.c, anonymous_flags. - return width - width % INT_SIZE; + return (width + align - 1) & -align; } static void @@ -481,11 +483,12 @@ pack_struct_or_union(type_t *tp) } unsigned int bits = 0; + bool named = false; for (sym_t *mem = tp->t_sou->sou_first_member; mem != NULL; mem = mem->s_next) { // TODO: Maybe update mem->u.s_member.sm_offset_in_bits. if (mem->s_type->t_bitfield) { - bits += bit_field_width(&mem); + bits += bit_field_width(&mem, &named); if (mem == NULL) break; } @@ -1795,24 +1798,25 @@ complete_struct_or_union(sym_t *first_me c99ism(47, tspec_name(tp->t_tspec)); } - int n = 0; + bool has_named_member = false; for (sym_t *mem = first_member; mem != NULL; mem = mem->s_next) { + if (mem->s_name != unnamed) + has_named_member = true; /* bind anonymous members to the structure */ if (mem->u.s_member.sm_sou_type == NULL) { mem->u.s_member.sm_sou_type = sp; if (mem->s_type->t_bitfield) { - sp->sou_size_in_bits += bit_field_width(&mem); + sp->sou_size_in_bits += + bit_field_width(&mem, &has_named_member); if (mem == NULL) break; } sp->sou_size_in_bits += type_size_in_bits(mem->s_type); } - if (mem->s_name != unnamed) - n++; } - if (n == 0 && sp->sou_size_in_bits != 0) { + if (!has_named_member && sp->sou_size_in_bits != 0) { /* '%s' has no named members */ warning(65, type_name(tp)); }