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)5668d32119Srilligaligned_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*d6905721Srilligalignment_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