1 /* $NetBSD: msg_135.c,v 1.17 2025/03/21 20:37:31 rillig Exp $ */ 2 # 3 "msg_135.c" 3 4 // Test for message: converting '%s' to '%s' increases alignment from %u to %u [135] 5 6 /* lint1-extra-flags: -h -X 351 */ 7 8 void sink(const void *); 9 10 unsigned 11 read_uint(const unsigned short **pp) 12 { 13 unsigned val; 14 15 /* expect+1: warning: converting 'pointer to const unsigned short' to 'pointer to const unsigned int' increases alignment from 2 to 4 [135] */ 16 val = *(const unsigned *)(*pp); 17 pp += sizeof(unsigned); 18 return val; 19 } 20 21 /* expect+1: warning: struct 'incomplete' never defined [233] */ 22 struct incomplete; 23 24 struct complete { 25 int member; 26 }; 27 28 /* 29 * These types of conversions are typically seen in OpenSSL, when converting 30 * from the publicly visible, incomplete 'struct lhash_st' to a private 31 * implementation type such as 'struct lhash_st_OPENSSL_STRING'. 32 * 33 * Before tree.c 1.277 from 2021-04-17, lint warned about this, even though 34 * there was not enough evidence that there really was an alignment problem, 35 * resulting in many false positives. 36 * 37 * See openssl/lhash.h. 38 */ 39 void 40 pointer_to_structs(struct incomplete *incomplete) 41 { 42 struct complete *complete; 43 44 complete = (struct complete *)incomplete; 45 sink(complete); 46 } 47 48 /* 49 * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from 50 * unsigned char or plain char to another type. These casts often occur in 51 * traditional code that does not use void pointers, even 30 years after C90 52 * introduced 'void'. 53 */ 54 void 55 unsigned_char_to_unsigned_type(unsigned char *ucp) 56 { 57 unsigned short *usp; 58 59 usp = (unsigned short *)ucp; 60 sink(usp); 61 } 62 63 /* 64 * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from 65 * unsigned char or plain char to another type. These casts often occur in 66 * traditional code that does not use void pointers, even 30 years after C90 67 * introduced 'void'. 68 */ 69 void 70 plain_char_to_unsigned_type(char *cp) 71 { 72 unsigned short *usp; 73 74 usp = (unsigned short *)cp; 75 sink(usp); 76 } 77 78 /* 79 * Converting a pointer with a low alignment requirement to a union that 80 * includes other types with higher alignment requirements is considered safe. 81 * While accessing any other member of the union might trigger an alignment 82 * violation, such an access is not likely from an application point of view, 83 * as it would access undefined memory and thus invoke undefined behavior. 84 * 85 * A practical case for this pattern are tagged unions, in which the first 86 * member of the struct determines how the remaining members are interpreted. 87 * See sbin/newfs_udf, function udf_validate_tag_and_crc_sums for an example. 88 * 89 * C99 6.2.5p26 defines the representation and alignment of types, stating 90 * that pointers to union types need not have the same representation and 91 * alignment as pointers to other types. 92 * 93 * C99 6.7.2.1p14 and C23 6.7.2.1p18 both state that a "pointer to a union 94 * object [...] points to each of its members [...], and vice versa". 95 */ 96 double 97 cast_to_union(void) 98 { 99 int align_4 = 0; 100 double align_8 = 0.0; 101 union both { 102 int p_align_4; 103 double p_align_8; 104 } *both; 105 106 both = (union both *)&align_4; 107 both = (union both *)&align_8; 108 return both->p_align_8; 109 } 110 111 /* 112 * Structures with alignment 1 typically contain padding arrays only, so don't 113 * warn when they are converted to their structured counterparts. An example 114 * of such a conversion is from 'struct sockaddr' to 'struct sockaddr_in6'. 115 */ 116 void 117 from_alignment_1_to_8(void) 118 { 119 struct alignment_1 { 120 char filler[32]; 121 }; 122 struct alignment_8 { 123 char filler[32]; 124 double numbers[4]; 125 }; 126 127 static struct alignment_1 *pointer_1; 128 static struct alignment_8 *pointer_8; 129 130 pointer_8 = (struct alignment_8 *)pointer_1; 131 pointer_1 = (struct alignment_1 *)pointer_8; 132 } 133