xref: /netbsd-src/tests/usr.bin/xlint/lint1/gcc_attribute_aligned.c (revision d69057212d2ebf16ef2f8e0d47e3dda21d3f2a3c)
1*d6905721Srillig /*	$NetBSD: gcc_attribute_aligned.c,v 1.8 2024/05/01 10:30:56 rillig Exp $	*/
2ed02aca1Srillig # 3 "gcc_attribute_aligned.c"
3ed02aca1Srillig 
4ed02aca1Srillig /*
5ed02aca1Srillig  * Test size computations on aligned and packed structs.
6ed02aca1Srillig  */
7ed02aca1Srillig 
8e6298b92Srillig /* lint1-extra-flags: -X 351 */
9e6298b92Srillig 
10ed02aca1Srillig typedef unsigned short uint16_t;
11ed02aca1Srillig typedef unsigned int uint32_t;
12ed02aca1Srillig typedef unsigned long long uint64_t;
13ed02aca1Srillig 
14ed02aca1Srillig /* from sys/arch/x86/include/cpu_extended_state.h */
15ed02aca1Srillig 
16ed02aca1Srillig union fp_addr {
17ed02aca1Srillig 	uint64_t fa_64;
18ed02aca1Srillig 	struct {
19ed02aca1Srillig 		uint32_t fa_off;
20ed02aca1Srillig 		uint16_t fa_seg;
21ed02aca1Srillig 		uint16_t fa_opcode;
22ed02aca1Srillig 	} fa_32;
23ed02aca1Srillig } __attribute__((packed)) __attribute__((aligned(4)));
24ed02aca1Srillig 
25c588212fSrillig /* Each variant of the union has size 8. */
26c588212fSrillig /* expect+1: error: negative array dimension (-8) [20] */
27c588212fSrillig typedef int sizeof_fp_addr[-(int)sizeof(union fp_addr)];
28c588212fSrillig 
29ed02aca1Srillig struct fpacc87 {
30ed02aca1Srillig 	uint64_t f87_mantissa;
31ed02aca1Srillig 	uint16_t f87_exp_sign;
32ed02aca1Srillig } __attribute__((packed)) __attribute__((aligned(2)));
33ed02aca1Srillig 
34c588212fSrillig /*
35c588212fSrillig  * Due to the 'packed', the uint64_t does not need to be aligned on an 8-byte
36c588212fSrillig  * boundary, which allows the struct to have the minimal required size of 10.
37c588212fSrillig  */
38c588212fSrillig /* expect+1: error: negative array dimension (-10) [20] */
39c588212fSrillig typedef int sizeof_fpacc87[-(int)sizeof(struct fpacc87)];
40c588212fSrillig 
41ed02aca1Srillig struct save87 {
42ed02aca1Srillig 	uint16_t s87_cw __attribute__((aligned(4)));
43ed02aca1Srillig 	uint16_t s87_sw __attribute__((aligned(4)));
44ed02aca1Srillig 	uint16_t s87_tw __attribute__((aligned(4)));
45ed02aca1Srillig 	union fp_addr s87_ip;
46ed02aca1Srillig 	union fp_addr s87_dp;
47ed02aca1Srillig 	struct fpacc87 s87_ac[8];
48ed02aca1Srillig };
49ed02aca1Srillig 
50313458bcSrillig /* @4 2 + @4 2 + @4 2 + @4 8 + @4 8 + @2 (8 * 10) == 108 */
51313458bcSrillig /* expect+1: error: negative array dimension (-108) [20] */
52c588212fSrillig typedef int sizeof_save87[-(int)sizeof(struct save87)];
5368d32119Srillig 
5468d32119Srillig 
5568d32119Srillig void
aligned_struct_member(void)5668d32119Srillig aligned_struct_member(void)
5768d32119Srillig {
5868d32119Srillig 	struct aligned {
5968d32119Srillig 		int first;
6068d32119Srillig 		int second __attribute__((__aligned__(16)));
6168d32119Srillig 	};
6268d32119Srillig 
63c588212fSrillig 	/*
64c588212fSrillig 	 * Aligning 'second' to a 16-bytes boundary not only aligns the member
65c588212fSrillig 	 * inside the structure, it also affects the alignment requirement of
66c588212fSrillig 	 * the whole structure.  Due to this struct alignment, the size of the
67c588212fSrillig 	 * structure gets rounded up to 32 instead of using the minimally
68c588212fSrillig 	 * necessary storage of 20.
69c588212fSrillig 	 *
70c588212fSrillig 	 * https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html
71c588212fSrillig 	 */
72313458bcSrillig 	/* expect+1: error: negative array dimension (-32) [20] */
7368d32119Srillig 	typedef int ctassert[-(int)sizeof(struct aligned)];
7468d32119Srillig }
75*d6905721Srillig 
76*d6905721Srillig void
alignment_larger_than_size(void)77*d6905721Srillig alignment_larger_than_size(void)
78*d6905721Srillig {
79*d6905721Srillig 	struct s {
80*d6905721Srillig 		unsigned u32 __attribute__((__aligned__(32)));
81*d6905721Srillig 	} _Alignas(4096);
82*d6905721Srillig 	/* expect+1: error: negative array dimension (-4096) [20] */
83*d6905721Srillig 	typedef int size[-(int)sizeof(struct s)];
84*d6905721Srillig }
85