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