tests/lint: investigate how compilers interpret bit-fields

This commit is contained in:
rillig 2023-01-28 08:30:12 +00:00
parent c9f9003339
commit 93f3a70d97
1 changed files with 62 additions and 1 deletions

View File

@ -1,6 +1,11 @@
/* $NetBSD: gcc_bit_field_types.c,v 1.6 2022/01/15 14:22:03 rillig Exp $ */
/* $NetBSD: gcc_bit_field_types.c,v 1.7 2023/01/28 08:30:12 rillig Exp $ */
# 3 "gcc_bit_field_types.c"
struct incompatible {
int dummy;
};
void reveal_type(struct incompatible);
/*
* https://gcc.gnu.org/onlinedocs/gcc/Structures-unions-enumerations-and-bit-fields-implementation.html
*
@ -35,3 +40,59 @@ promote_large_bit_field(struct large_bit_field lbf)
*/
return lbf.member & 0xf;
}
/*
* C99 6.7.2.1p4 says: "A bit-field shall have a type that is a qualified or
* unqualified version of _Bool, signed int, unsigned int, or some other
* implementation-defined type."
*
* The wording of that constraint does not disambiguate whether it is talking
* about the declared underlying type of the storage unit or the expression
* type when evaluating a bit-field as an rvalue.
*/
void
type_of_bit_field(void)
{
struct {
unsigned bits:3;
} s;
/*
* Lint interprets the type of the bit-field is 'unsigned:3', which
* matches the non-bit-field type 'unsigned' in the _Generic
* expression. (XXX: May or may not be intended.)
*
* The _Generic expression prevents the integer promotions from
* getting applied as part of the function argument conversions.
*
* GCC 11 says: error: '_Generic' selector of type 'unsigned char:3'
* is not compatible with any association
*
* Clang 15 says: error: controlling expression type 'unsigned int'
* not compatible with any generic association type
*
* TCC says: error: type 'unsigned int' does not match any association
*
* MSVC 19 says: error C7702: no compatible type for 'unsigned int'
* in _Generic association list
*
* ICC 2021.7.1 says: error: no association matches the selector type
* "unsigned int"
*/
/* expect+4: warning: passing 'pointer to unsigned int' to incompatible 'struct incompatible', arg #1 [155] */
reveal_type(_Generic(s.bits,
int: (int *)0,
unsigned int: (unsigned int *)0
));
/*
* When lint promotes the bit-field as part of the function argument
* conversions, the type 'unsigned:3' gets promoted to 'int', as that
* is the smallest candidate type that can represent all possible
* values from 'unsigned:3', see promote_c90. Maybe that's wrong,
* maybe not, the compilers disagree so lint can offer yet another
* alternative interpretation.
*/
/* expect+1: warning: passing 'unsigned int:3' to incompatible 'struct incompatible', arg #1 [155] */
reveal_type(s.bits);
}