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