1*cbe25320Srillig /* $NetBSD: expr_sizeof.c,v 1.18 2024/05/03 19:16:13 rillig Exp $ */
27997ddceSrillig # 3 "expr_sizeof.c"
37997ddceSrillig
47997ddceSrillig /*
57997ddceSrillig * C99 6.5.3.4 "The sizeof operator"
67997ddceSrillig * C11 6.5.3.4 "The sizeof operator"
77997ddceSrillig */
87997ddceSrillig
9b2baa501Srillig /* lint1-extra-flags: -X 351 */
10b2baa501Srillig
117997ddceSrillig /*
127997ddceSrillig * A sizeof expression can either take a type name or an expression.
137997ddceSrillig */
14fc9c97faSrillig
157997ddceSrillig void sink(unsigned long);
167997ddceSrillig
177997ddceSrillig struct {
187997ddceSrillig int member;
197997ddceSrillig } s, *ps;
207997ddceSrillig
217997ddceSrillig /*
227997ddceSrillig * In a sizeof expression taking a type name, the type name must be enclosed
237997ddceSrillig * in parentheses.
247997ddceSrillig */
257997ddceSrillig /* expect+1: error: negative array dimension (-4) [20] */
267997ddceSrillig typedef int sizeof_int[-(int)sizeof(int)];
277997ddceSrillig
287997ddceSrillig /*
297997ddceSrillig * In a sizeof expression taking an expression, the expression may or may not
307997ddceSrillig * be enclosed in parentheses, like any other expression.
317997ddceSrillig */
327997ddceSrillig /* expect+1: error: negative array dimension (-4) [20] */
337997ddceSrillig typedef int sizeof_paren_zero[-(int)sizeof(0)];
347997ddceSrillig /* expect+1: error: negative array dimension (-4) [20] */
357997ddceSrillig typedef int sizeof_zero[-(int)sizeof 0];
367997ddceSrillig
377997ddceSrillig /*
387997ddceSrillig * Even though 's' is not a constant expression, 'sizeof s' is.
397997ddceSrillig */
407997ddceSrillig /* expect+1: error: negative array dimension (-4) [20] */
417997ddceSrillig typedef int sizeof_global_var[-(int)sizeof s];
427997ddceSrillig /* expect+1: error: negative array dimension (-4) [20] */
437997ddceSrillig typedef int sizeof_paren_global_var[-(int)sizeof(s)];
447997ddceSrillig
457997ddceSrillig /*
467997ddceSrillig * Even though 'sizeof(s)' may look like a function call expression, the
477997ddceSrillig * parentheses around 's' are ordinary parentheses and do not influence the
48f0df5ddfSrillig * precedence.
49f0df5ddfSrillig *
50f0df5ddfSrillig * Therefore, the '.' following the '(s)' takes precedence over the 'sizeof'.
51f0df5ddfSrillig * Same for the '->' following the '(ps)'. Same for the '[0]' following the
52f0df5ddfSrillig * '(arr)'.
537997ddceSrillig */
547997ddceSrillig /* expect+1: error: negative array dimension (-4) [20] */
557997ddceSrillig typedef int sizeof_paren_global_struct_member[-(int)sizeof(s).member];
567997ddceSrillig /* expect+1: error: negative array dimension (-4) [20] */
577997ddceSrillig typedef int sizeof_paren_global_ptr_struct_member[-(int)sizeof(ps)->member];
58f0df5ddfSrillig int arr[] = { 1, 2, 3 };
59f0df5ddfSrillig /* expect+1: error: negative array dimension (-3) [20] */
60f0df5ddfSrillig typedef int arr_count[-(int)sizeof(arr) / (int)sizeof(arr)[0]];
61f0df5ddfSrillig
62f0df5ddfSrillig /* FIXME: 'n' is actually used, for the variable length array. */
63ea332265Srillig /* expect+2: warning: parameter 'n' unused in function 'variable_length_array' [231] */
64f0df5ddfSrillig void
variable_length_array(int n)65f0df5ddfSrillig variable_length_array(int n)
66f0df5ddfSrillig {
67f0df5ddfSrillig int local_arr[n + 5];
68687f4c96Srillig
69687f4c96Srillig /*
70687f4c96Srillig * Since the array length is not constant, it cannot be used in a
71f5235638Srillig * typedef. Code like this is already rejected by the compiler. For
72687f4c96Srillig * simplicity, lint assumes that the array has length 1.
73687f4c96Srillig */
74f0df5ddfSrillig /* expect+1: error: negative array dimension (-4) [20] */
75f0df5ddfSrillig typedef int sizeof_local_arr[-(int)sizeof(local_arr)];
76f0df5ddfSrillig }
77aca02333Srillig
7810704a6fSrillig void
bit_fields(void)7910704a6fSrillig bit_fields(void)
8010704a6fSrillig {
8110704a6fSrillig struct {
8210704a6fSrillig _Bool flag0:1;
8310704a6fSrillig _Bool flag1:1;
8410704a6fSrillig _Bool flag2:1;
8510704a6fSrillig } flags;
8610704a6fSrillig /* expect+1: error: negative array dimension (-1) [20] */
8710704a6fSrillig typedef int sizeof_flags[-(int)sizeof(flags)];
8810704a6fSrillig
8910704a6fSrillig struct {
9010704a6fSrillig struct {
9110704a6fSrillig _Bool flag0:1;
9210704a6fSrillig _Bool flag1:1;
9310704a6fSrillig _Bool flag2:1;
9410704a6fSrillig };
9510704a6fSrillig } anonymous_flags;
96cb8166a1Srillig /* expect+1: error: negative array dimension (-1) [20] */
9710704a6fSrillig typedef int sizeof_anonymous_flags[-(int)sizeof(anonymous_flags)];
9810704a6fSrillig
9910704a6fSrillig struct {
10010704a6fSrillig unsigned int bits0:16;
10110704a6fSrillig unsigned int bits1:16;
10210704a6fSrillig } same_storage_unit;
10310704a6fSrillig /* expect+1: error: negative array dimension (-4) [20] */
10410704a6fSrillig typedef int sizeof_same_storage_unit[-(int)sizeof(same_storage_unit)];
10510704a6fSrillig
10610704a6fSrillig // Detect whether a bit-field can span multiple storage units.
10710704a6fSrillig // If so, the size is 12, if not, the size is 16.
10810704a6fSrillig struct {
10910704a6fSrillig unsigned int bits0:24;
11010704a6fSrillig unsigned int bits1:24;
11110704a6fSrillig unsigned int bits2:24;
11210704a6fSrillig unsigned int bits3:24;
11310704a6fSrillig } cross_storage_unit;
11410704a6fSrillig /* expect+1: error: negative array dimension (-16) [20] */
11510704a6fSrillig typedef int sizeof_cross_storage_unit[-(int)sizeof(cross_storage_unit)];
1167aaf3a05Srillig
1177aaf3a05Srillig /*
1187aaf3a05Srillig * The bit-fields in a struct may be merged into the same storage
1197aaf3a05Srillig * units, even if their types differ. GCC 10, Clang 15 and lint all
120bf86468dSrillig * agree in packing the first group of bit-fields and the char into
121bf86468dSrillig * 4 bytes, even though their underlying types differ. The second
122bf86468dSrillig * group of bit-fields gets its own storage unit.
1237aaf3a05Srillig */
1247aaf3a05Srillig struct mixed {
1257aaf3a05Srillig _Bool flag0:1;
1267aaf3a05Srillig signed int signed0:1;
1277aaf3a05Srillig unsigned int unsigned0:1;
128bf86468dSrillig char ch[3];
1297aaf3a05Srillig _Bool flag1:1;
1307aaf3a05Srillig signed int signed1:1;
1317aaf3a05Srillig unsigned int unsigned1:1;
1327aaf3a05Srillig } mixed;
133bf86468dSrillig /* expect+1: error: negative array dimension (-8) [20] */
1347aaf3a05Srillig typedef int sizeof_mixed[-(int)sizeof(mixed)];
1358d2e8478Srillig /* expect+3: error: negative array dimension (-1) [20] */
1367aaf3a05Srillig typedef int offsetof_mixed_ch[
1377aaf3a05Srillig -(int)__builtin_offsetof(struct mixed, ch)
1387aaf3a05Srillig ];
13910704a6fSrillig }
14010704a6fSrillig
141aca02333Srillig /*
142aca02333Srillig * Ensure that anonymous structs and unions are handled correctly. They were
143aca02333Srillig * added in C11, and lint did not properly support them until 2023.
144aca02333Srillig */
145aca02333Srillig void
anonymous_struct_and_union(void)146aca02333Srillig anonymous_struct_and_union(void)
147aca02333Srillig {
148aca02333Srillig struct {
149aca02333Srillig union {
150aca02333Srillig unsigned char uc16[16];
151aca02333Srillig unsigned char uc32[32];
152aca02333Srillig };
153aca02333Srillig } su_16_32;
154e50dbdf4Srillig /* expect+1: error: negative array dimension (-32) [20] */
155aca02333Srillig typedef int sizeof_su_16_32[-(int)sizeof(su_16_32)];
156aca02333Srillig
157aca02333Srillig union {
158aca02333Srillig struct {
159aca02333Srillig unsigned char uc16[16];
160aca02333Srillig unsigned char uc32[32];
161aca02333Srillig };
162aca02333Srillig } us_16_32;
163aca02333Srillig /* expect+1: error: negative array dimension (-48) [20] */
164aca02333Srillig typedef int sizeof_us_16_32[-(int)sizeof(us_16_32)];
165aca02333Srillig }
166fc9c97faSrillig
167fc9c97faSrillig
168fc9c97faSrillig void
sizeof_errors(void)169fc9c97faSrillig sizeof_errors(void)
170fc9c97faSrillig {
171fc9c97faSrillig /* expect+1: error: cannot take size/alignment of void [146] */
172fc9c97faSrillig typedef int sizeof_void[-(int)sizeof(void)];
173fc9c97faSrillig
174fc9c97faSrillig /*
175fc9c97faSrillig * A 'void array' gets replaced with an 'int array' before
176fc9c97faSrillig * type_size_in_bits gets to see it, thus the 256 * 4 = 1024.
177fc9c97faSrillig */
178fc9c97faSrillig /* expect+2: error: illegal use of 'void' [18] */
179fc9c97faSrillig /* expect+1: error: negative array dimension (-1024) [20] */
180fc9c97faSrillig typedef int sizeof_void_array[-(int)sizeof(void[256])];
181fc9c97faSrillig
182fc9c97faSrillig /* expect+1: warning: enum 'incomplete_enum' never defined [235] */
183fc9c97faSrillig enum incomplete_enum;
184fc9c97faSrillig /* expect+2: warning: cannot take size/alignment of incomplete type [143] */
185fc9c97faSrillig /* expect+1: error: negative array dimension (-4) [20] */
186fc9c97faSrillig typedef int sizeof_incomplete_enum[-(int)sizeof(enum incomplete_enum)];
187fc9c97faSrillig }
188fc9c97faSrillig
189fc9c97faSrillig
190fc9c97faSrillig /*
191fc9c97faSrillig * Due to the 'double' member, the alignment of this struct is 8, so the size
192fc9c97faSrillig * has to be 24 (or at least divisible by 8), otherwise the 'double' member
193fc9c97faSrillig * would not get the correct alignment in an array of this struct.
194fc9c97faSrillig */
195fc9c97faSrillig struct s24 {
196fc9c97faSrillig char c0;
197fc9c97faSrillig double d8;
198fc9c97faSrillig char c16;
199fc9c97faSrillig };
200fc9c97faSrillig /* expect+1: error: negative array dimension (-24) [20] */
201fc9c97faSrillig typedef int sizeof_s24[-(int)sizeof(struct s24)];
2029ca08a69Srillig
2039ca08a69Srillig void
sizeof_array_parameter(short arr[12345])2049ca08a69Srillig sizeof_array_parameter(short arr[12345])
2059ca08a69Srillig {
2069ca08a69Srillig // The size of an array parameter is the size of the decayed pointer.
2079ca08a69Srillig // Subtracting 'sizeof(void *)' makes the test platform-independent.
2089ca08a69Srillig typedef int sizeof_arr[-(int)(sizeof arr - sizeof(void *))];
2099ca08a69Srillig
2109ca08a69Srillig // The 2 comes from 'sizeof(short)', as the type 'array[size] of elem'
2119ca08a69Srillig // decays into the type 'pointer to elem', not 'pointer to array[size]
2129ca08a69Srillig // of elem'.
2139ca08a69Srillig /* expect+1: error: negative array dimension (-2) [20] */
2149ca08a69Srillig typedef int sizeof_arr_elem[-(int)(sizeof *arr)];
2159ca08a69Srillig }
2162e8fec16Srillig
2172e8fec16Srillig
2182e8fec16Srillig void
sequence_of_structs(void)2192e8fec16Srillig sequence_of_structs(void)
2202e8fec16Srillig {
2212e8fec16Srillig typedef unsigned char uint8_t;
222*cbe25320Srillig typedef unsigned short uint16_t;
2232e8fec16Srillig typedef unsigned int uint32_t;
224*cbe25320Srillig typedef unsigned long long uint64_t;
2252e8fec16Srillig
2262e8fec16Srillig union fp_addr {
2272e8fec16Srillig uint64_t fa_64;
2282e8fec16Srillig struct {
2292e8fec16Srillig uint32_t fa_off;
2302e8fec16Srillig uint16_t fa_seg;
2312e8fec16Srillig uint16_t fa_opcode;
2322e8fec16Srillig } fa_32;
2332e8fec16Srillig } __packed _Alignas(4);
2342e8fec16Srillig
2352e8fec16Srillig struct fpacc87 {
2362e8fec16Srillig uint64_t f87_mantissa;
2372e8fec16Srillig uint16_t f87_exp_sign;
2382e8fec16Srillig } __packed _Alignas(2);
2392e8fec16Srillig
2402e8fec16Srillig // FIXME: This otherwise unused struct declaration influences the
2412e8fec16Srillig // offsets checked below. Without this struct, sizeof(struct save87)
2422e8fec16Srillig // is calculated correctly as 108 below.
2432e8fec16Srillig struct fpaccfx {
2442e8fec16Srillig struct fpacc87 r _Alignas(16);
2452e8fec16Srillig };
2462e8fec16Srillig
2472e8fec16Srillig struct save87 {
2482e8fec16Srillig uint16_t s87_cw _Alignas(4);
2492e8fec16Srillig uint16_t s87_sw _Alignas(4);
2502e8fec16Srillig uint16_t s87_tw _Alignas(4);
2512e8fec16Srillig union fp_addr s87_ip;
2522e8fec16Srillig union fp_addr s87_dp;
2532e8fec16Srillig struct fpacc87 s87_ac[8];
2542e8fec16Srillig };
2552e8fec16Srillig
2562e8fec16Srillig /* expect+1: error: negative array dimension (-20) [20] */
2570b487d09Srillig typedef int o1[-(int)((unsigned long)(&(((struct save87 *)0)->s87_dp)))];
2582e8fec16Srillig // FIXME: must be 28.
2592e8fec16Srillig /* expect+1: error: negative array dimension (-32) [20] */
2600b487d09Srillig typedef int o2[-(int)((unsigned long)(&(((struct save87 *)0)->s87_ac)))];
2612e8fec16Srillig // FIXME: must be 108.
2622e8fec16Srillig /* expect+1: error: negative array dimension (-112) [20] */
2632e8fec16Srillig typedef int reveal[-(int)sizeof(struct save87)];
2642e8fec16Srillig }
265