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