xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_135.c (revision 951d06481669f86e0831cdcc3d70aedc6564b7c1)
1 /*	$NetBSD: msg_135.c,v 1.15 2023/04/23 11:52:43 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
read_uint(const unsigned short ** pp)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
pointer_to_structs(struct incomplete * incomplete)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
unsigned_char_to_unsigned_type(unsigned char * ucp)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
plain_char_to_unsigned_type(char * cp)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
cast_to_union(void)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