Home | History | Annotate | Line # | Download | only in lint1
d_c99_bool_strict_syshdr.c revision 1.1
      1 /*	$NetBSD: d_c99_bool_strict_syshdr.c,v 1.1 2021/01/17 23:00:41 rillig Exp $	*/
      2 # 3 "d_c99_bool_strict_syshdr.c"
      3 
      4 /*
      5  * Macros from system headers may use int expressions where bool expressions
      6  * are expected.  These headers are not allowed to include <stdbool.h>
      7  * themselves, and even if they could, lint must accept other scalar types
      8  * as well, since system headers are not changed lightheartedly.
      9  */
     10 
     11 /* lint1-extra-flags: -T */
     12 
     13 /*
     14  * On NetBSD 8, <sys/select.h> defines FD_ISSET by enclosing the statements
     15  * in the well-known 'do { ... } while (constcond 0)' loop.  The 0 in the
     16  * controlling expression has type INT but should be allowed nevertheless.
     17  */
     18 void
     19 strict_bool_system_header_statement_macro(void)
     20 {
     21 
     22 	do {
     23 		println("nothing");
     24 	} while (/*CONSTCOND*/0);	/* expect: 333 */
     25 
     26 # 27 "d_c99_bool_strict_syshdr.c" 3 4
     27 	do {
     28 		println("nothing");
     29 	} while (/*CONSTCOND*/0);	/*FIXME*//* expect: 333 */
     30 
     31 # 32 "d_c99_bool_strict_syshdr.c"
     32 	do {
     33 		println("nothing");
     34 	} while (/*CONSTCOND*/0);	/* expect: 333 */
     35 }
     36 
     37 
     38 /*
     39  * The macros from <ctype.h> can be implemented in different ways.  The C
     40  * standard defines them as returning 'int'.  In strict bool mode, the actual
     41  * return type can be INT or BOOL, depending on whether the macros do the
     42  * comparison against 0 themselves.
     43  *
     44  * Since that is more code to write and in exceptional situations more code
     45  * to execute, they will probably leave out the extra comparison, but both
     46  * ways are possible.
     47  *
     48  * In strict mode, there must be a way to call these function-like macros
     49  * portably, without triggering type errors, no matter whether they return
     50  * BOOL or INT.
     51  *
     52  * The expressions from this example cross the boundary between system header
     53  * and application code.  They need to carry the information that they are
     54  * half-BOOL, half-INT across the enclosing expressions.
     55  */
     56 void
     57 strict_bool_system_header_ctype(int c)
     58 {
     59 	static const unsigned short *ctype_table;
     60 
     61 
     62 	/*
     63 	 * The macro returns INT, which may be outside the range of a
     64 	 * uint8_t variable, therefore it must not be assigned directly.
     65 	 * All other combinations of type are safe from truncation.
     66 	 */
     67 	_Bool system_int_assigned_to_bool =
     68 # 69 "d_c99_bool_strict_syshdr.c" 3 4
     69 	    (int)((ctype_table + 1)[c] & 0x0040)	/* INT */
     70 # 71 "d_c99_bool_strict_syshdr.c"
     71 	    ;			/* expect: 107 */
     72 
     73 	int system_bool_assigned_to_int =
     74 # 75 "d_c99_bool_strict_syshdr.c" 3 4
     75 	    (int)((ctype_table + 1)[c] & 0x0040) != 0	/* BOOL */
     76 # 77 "d_c99_bool_strict_syshdr.c"
     77 	    ;			/* expect: 107 */
     78 
     79 	if (
     80 # 81 "d_c99_bool_strict_syshdr.c" 3 4
     81 	    (int)((ctype_table + 1)[c] & 0x0040)	/* INT */
     82 # 83 "d_c99_bool_strict_syshdr.c"
     83 	)			/*FIXME*//* expect: 333 */
     84 	println("system macro returning INT");
     85 
     86 	if (
     87 # 88 "d_c99_bool_strict_syshdr.c" 3 4
     88 	    ((ctype_table + 1)[c] & 0x0040) != 0	/* BOOL */
     89 # 90 "d_c99_bool_strict_syshdr.c"
     90 	)
     91 	println("system macro returning BOOL");
     92 }
     93