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