msg_135.c revision 1.13 1 /* $NetBSD: msg_135.c,v 1.13 2023/04/22 19:45:04 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 safe. While
81 * accessing any other member of the union might trigger an alignment
82 * violation, such an access would invoke undefined behavior anyway.
83 *
84 * A practical case for this pattern are tagged unions, in which the first
85 * member of the struct determines how the remaining members are interpreted.
86 * See sbin/newfs_udf, function udf_validate_tag_and_crc_sums for an example.
87 */
88 double
89 cast_to_union(void)
90 {
91 int align_4 = 0;
92 double align_8 = 0.0;
93 union both {
94 int p_align_4;
95 double p_align_8;
96 } *both;
97
98 /* TODO: don't warn here. */
99 /* expect+1: warning: converting 'pointer to int' to 'pointer to union both' increases alignment from 4 to 8 [135] */
100 both = (union both *)&align_4;
101 both = (union both *)&align_8;
102 return both->p_align_8;
103 }
104