xref: /netbsd-src/tests/usr.bin/xlint/lint1/gcc_attribute_aligned.c (revision afab4e300d3a9fb07dd8c80daf53d0feb3345706)
1 /*	$NetBSD: gcc_attribute_aligned.c,v 1.5 2022/08/27 23:24:37 rillig Exp $	*/
2 # 3 "gcc_attribute_aligned.c"
3 
4 /*
5  * Test size computations on aligned and packed structs.
6  */
7 
8 typedef unsigned short uint16_t;
9 typedef unsigned int uint32_t;
10 typedef unsigned long long uint64_t;
11 
12 /* from sys/arch/x86/include/cpu_extended_state.h */
13 
14 union fp_addr {
15 	uint64_t fa_64;
16 	struct {
17 		uint32_t fa_off;
18 		uint16_t fa_seg;
19 		uint16_t fa_opcode;
20 	} fa_32;
21 } __attribute__((packed)) __attribute__((aligned(4)));
22 
23 /* Each variant of the union has size 8. */
24 /* expect+1: error: negative array dimension (-8) [20] */
25 typedef int sizeof_fp_addr[-(int)sizeof(union fp_addr)];
26 
27 struct fpacc87 {
28 	uint64_t f87_mantissa;
29 	uint16_t f87_exp_sign;
30 } __attribute__((packed)) __attribute__((aligned(2)));
31 
32 /*
33  * Due to the 'packed', the uint64_t does not need to be aligned on an 8-byte
34  * boundary, which allows the struct to have the minimal required size of 10.
35  */
36 /* expect+1: error: negative array dimension (-10) [20] */
37 typedef int sizeof_fpacc87[-(int)sizeof(struct fpacc87)];
38 
39 struct save87 {
40 	uint16_t s87_cw __attribute__((aligned(4)));
41 	uint16_t s87_sw __attribute__((aligned(4)));
42 	uint16_t s87_tw __attribute__((aligned(4)));
43 	union fp_addr s87_ip;
44 	union fp_addr s87_dp;
45 	struct fpacc87 s87_ac[8];
46 };
47 
48 /* FIXME: @4 2 + @4 2 + @4 2 + @4 8 + @4 8 + @2 (8 * 10) == 108 */
49 /* expect+1: error: negative array dimension (-104) [20] */
50 typedef int sizeof_save87[-(int)sizeof(struct save87)];
51 
52 
53 void
54 aligned_struct_member(void)
55 {
56 	struct aligned {
57 		int first;
58 		int second __attribute__((__aligned__(16)));
59 	};
60 
61 	/*
62 	 * Aligning 'second' to a 16-bytes boundary not only aligns the member
63 	 * inside the structure, it also affects the alignment requirement of
64 	 * the whole structure.  Due to this struct alignment, the size of the
65 	 * structure gets rounded up to 32 instead of using the minimally
66 	 * necessary storage of 20.
67 	 *
68 	 * https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html
69 	 */
70 	/* TODO: should be -32 instead of -8. */
71 	/* expect+1: error: negative array dimension (-8) [20] */
72 	typedef int ctassert[-(int)sizeof(struct aligned)];
73 }
74