Module Name:    src
Committed By:   rillig
Date:           Sat Jan 28 08:30:12 UTC 2023

Modified Files:
        src/tests/usr.bin/xlint/lint1: gcc_bit_field_types.c

Log Message:
tests/lint: investigate how compilers interpret bit-fields


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/tests/usr.bin/xlint/lint1/gcc_bit_field_types.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/gcc_bit_field_types.c
diff -u src/tests/usr.bin/xlint/lint1/gcc_bit_field_types.c:1.6 src/tests/usr.bin/xlint/lint1/gcc_bit_field_types.c:1.7
--- src/tests/usr.bin/xlint/lint1/gcc_bit_field_types.c:1.6	Sat Jan 15 14:22:03 2022
+++ src/tests/usr.bin/xlint/lint1/gcc_bit_field_types.c	Sat Jan 28 08:30:12 2023
@@ -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
 	 */
 	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);
+}

Reply via email to