Home | History | Annotate | Line # | Download | only in lint1
gcc_attribute_aligned.c revision 1.8
      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 
     10 typedef unsigned short uint16_t;
     11 typedef unsigned int uint32_t;
     12 typedef unsigned long long uint64_t;
     13 
     14 /* from sys/arch/x86/include/cpu_extended_state.h */
     15 
     16 union 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] */
     27 typedef int sizeof_fp_addr[-(int)sizeof(union fp_addr)];
     28 
     29 struct 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] */
     39 typedef int sizeof_fpacc87[-(int)sizeof(struct fpacc87)];
     40 
     41 struct 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] */
     52 typedef int sizeof_save87[-(int)sizeof(struct save87)];
     53 
     54 
     55 void
     56 aligned_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 
     76 void
     77 alignment_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