msg_135.c revision 1.17 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