expr_sizeof.c revision 1.6 1 /* $NetBSD: expr_sizeof.c,v 1.6 2023/06/28 21:41:27 rillig Exp $ */
2 # 3 "expr_sizeof.c"
3
4 /*
5 * C99 6.5.3.4 "The sizeof operator"
6 * C11 6.5.3.4 "The sizeof operator"
7 */
8
9 /* lint1-extra-flags: -X 351 */
10
11 /*
12 * A sizeof expression can either take a type name or an expression.
13 */
14 void sink(unsigned long);
15
16 struct {
17 int member;
18 } s, *ps;
19
20 /*
21 * In a sizeof expression taking a type name, the type name must be enclosed
22 * in parentheses.
23 */
24 /* expect+1: error: negative array dimension (-4) [20] */
25 typedef int sizeof_int[-(int)sizeof(int)];
26
27 /*
28 * In a sizeof expression taking an expression, the expression may or may not
29 * be enclosed in parentheses, like any other expression.
30 */
31 /* expect+1: error: negative array dimension (-4) [20] */
32 typedef int sizeof_paren_zero[-(int)sizeof(0)];
33 /* expect+1: error: negative array dimension (-4) [20] */
34 typedef int sizeof_zero[-(int)sizeof 0];
35
36 /*
37 * Even though 's' is not a constant expression, 'sizeof s' is.
38 */
39 /* expect+1: error: negative array dimension (-4) [20] */
40 typedef int sizeof_global_var[-(int)sizeof s];
41 /* expect+1: error: negative array dimension (-4) [20] */
42 typedef int sizeof_paren_global_var[-(int)sizeof(s)];
43
44 /*
45 * Even though 'sizeof(s)' may look like a function call expression, the
46 * parentheses around 's' are ordinary parentheses and do not influence the
47 * precedence.
48 *
49 * Therefore, the '.' following the '(s)' takes precedence over the 'sizeof'.
50 * Same for the '->' following the '(ps)'. Same for the '[0]' following the
51 * '(arr)'.
52 */
53 /* expect+1: error: negative array dimension (-4) [20] */
54 typedef int sizeof_paren_global_struct_member[-(int)sizeof(s).member];
55 /* expect+1: error: negative array dimension (-4) [20] */
56 typedef int sizeof_paren_global_ptr_struct_member[-(int)sizeof(ps)->member];
57 int arr[] = { 1, 2, 3 };
58 /* expect+1: error: negative array dimension (-3) [20] */
59 typedef int arr_count[-(int)sizeof(arr) / (int)sizeof(arr)[0]];
60
61 /* FIXME: 'n' is actually used, for the variable length array. */
62 /* expect+2: warning: argument 'n' unused in function 'variable_length_array' [231] */
63 void
64 variable_length_array(int n)
65 {
66 int local_arr[n + 5];
67
68 /*
69 * Since the array length is not constant, it cannot be used in a
70 * typedef. Code like this is already rejected by the compiler. For
71 * simplicity, lint assumes that the array has length 1.
72 */
73 /* expect+1: error: negative array dimension (-4) [20] */
74 typedef int sizeof_local_arr[-(int)sizeof(local_arr)];
75 }
76
77 /*
78 * Ensure that anonymous structs and unions are handled correctly. They were
79 * added in C11, and lint did not properly support them until 2023.
80 */
81 void
82 anonymous_struct_and_union(void)
83 {
84 struct {
85 union {
86 unsigned char uc16[16];
87 unsigned char uc32[32];
88 };
89 } su_16_32;
90 /* FIXME: Must be 32, not 48. */
91 /* expect+1: error: negative array dimension (-48) [20] */
92 typedef int sizeof_su_16_32[-(int)sizeof(su_16_32)];
93
94 union {
95 struct {
96 unsigned char uc16[16];
97 unsigned char uc32[32];
98 };
99 } us_16_32;
100 /* expect+1: error: negative array dimension (-48) [20] */
101 typedef int sizeof_us_16_32[-(int)sizeof(us_16_32)];
102 }
103