xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_135.c (revision 951d06481669f86e0831cdcc3d70aedc6564b7c1)
1*951d0648Srillig /*	$NetBSD: msg_135.c,v 1.15 2023/04/23 11:52:43 rillig Exp $	*/
2a0a15c14Srillig # 3 "msg_135.c"
3a0a15c14Srillig 
4d39a5630Srillig // Test for message: converting '%s' to '%s' increases alignment from %u to %u [135]
5a0a15c14Srillig 
6b2baa501Srillig /* lint1-extra-flags: -h -X 351 */
71a77a0d0Srillig 
8814d2d42Srillig void sink(const void *);
9814d2d42Srillig 
101a77a0d0Srillig unsigned
read_uint(const unsigned short ** pp)11915d5cedSrillig read_uint(const unsigned short **pp)
121a77a0d0Srillig {
131a77a0d0Srillig 	unsigned val;
141a77a0d0Srillig 
15d39a5630Srillig 	/* expect+1: warning: converting 'pointer to const unsigned short' to 'pointer to const unsigned int' increases alignment from 2 to 4 [135] */
16915d5cedSrillig 	val = *(const unsigned *)(*pp);
171a77a0d0Srillig 	pp += sizeof(unsigned);
181a77a0d0Srillig 	return val;
191a77a0d0Srillig }
20814d2d42Srillig 
215d41e58aSrillig /* expect+1: warning: struct 'incomplete' never defined [233] */
225d41e58aSrillig struct incomplete;
23814d2d42Srillig 
24814d2d42Srillig struct complete {
25814d2d42Srillig 	int member;
26814d2d42Srillig };
27814d2d42Srillig 
28814d2d42Srillig /*
29814d2d42Srillig  * These types of conversions are typically seen in OpenSSL, when converting
30814d2d42Srillig  * from the publicly visible, incomplete 'struct lhash_st' to a private
31814d2d42Srillig  * implementation type such as 'struct lhash_st_OPENSSL_STRING'.
32814d2d42Srillig  *
33c322b8c5Srillig  * Before tree.c 1.277 from 2021-04-17, lint warned about this, even though
34c322b8c5Srillig  * there was not enough evidence that there really was an alignment problem,
35c322b8c5Srillig  * resulting in many false positives.
36c322b8c5Srillig  *
37814d2d42Srillig  * See openssl/lhash.h.
38814d2d42Srillig  */
39814d2d42Srillig void
pointer_to_structs(struct incomplete * incomplete)40814d2d42Srillig pointer_to_structs(struct incomplete *incomplete)
41814d2d42Srillig {
42814d2d42Srillig 	struct complete *complete;
43814d2d42Srillig 
44c322b8c5Srillig 	complete = (struct complete *)incomplete;
45814d2d42Srillig 	sink(complete);
46814d2d42Srillig }
478efa1be5Srillig 
48915d5cedSrillig /*
49915d5cedSrillig  * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from
50915d5cedSrillig  * unsigned char or plain char to another type.  These casts often occur in
51915d5cedSrillig  * traditional code that does not use void pointers, even 30 years after C90
52915d5cedSrillig  * introduced 'void'.
53915d5cedSrillig  */
548efa1be5Srillig void
unsigned_char_to_unsigned_type(unsigned char * ucp)558efa1be5Srillig unsigned_char_to_unsigned_type(unsigned char *ucp)
568efa1be5Srillig {
578efa1be5Srillig 	unsigned short *usp;
588efa1be5Srillig 
598efa1be5Srillig 	usp = (unsigned short *)ucp;
608efa1be5Srillig 	sink(usp);
618efa1be5Srillig }
628efa1be5Srillig 
63915d5cedSrillig /*
64915d5cedSrillig  * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from
65915d5cedSrillig  * unsigned char or plain char to another type.  These casts often occur in
66915d5cedSrillig  * traditional code that does not use void pointers, even 30 years after C90
67915d5cedSrillig  * introduced 'void'.
68915d5cedSrillig  */
698efa1be5Srillig void
plain_char_to_unsigned_type(char * cp)708efa1be5Srillig plain_char_to_unsigned_type(char *cp)
718efa1be5Srillig {
728efa1be5Srillig 	unsigned short *usp;
738efa1be5Srillig 
748efa1be5Srillig 	usp = (unsigned short *)cp;
758efa1be5Srillig 	sink(usp);
768efa1be5Srillig }
77a143ec61Srillig 
78a143ec61Srillig /*
79a143ec61Srillig  * Converting a pointer with a low alignment requirement to a union that
80*951d0648Srillig  * includes other types with higher alignment requirements is considered safe.
81*951d0648Srillig  * While accessing any other member of the union might trigger an alignment
82*951d0648Srillig  * violation, such an access is not likely from an application point of view,
83*951d0648Srillig  * as it would access undefined memory and thus invoke undefined behavior.
84a143ec61Srillig  *
85a143ec61Srillig  * A practical case for this pattern are tagged unions, in which the first
86a143ec61Srillig  * member of the struct determines how the remaining members are interpreted.
87a143ec61Srillig  * See sbin/newfs_udf, function udf_validate_tag_and_crc_sums for an example.
88*951d0648Srillig  *
89*951d0648Srillig  * C99 6.2.5p26 defines the representation and alignment of types, stating
90*951d0648Srillig  * that pointers to union types need not have the same representation and
91*951d0648Srillig  * alignment as pointers to other types.
92*951d0648Srillig  *
93*951d0648Srillig  * C99 6.7.2.1p14 and C23 6.7.2.1p18 both state that a "pointer to a union
94*951d0648Srillig  * object [...] points to each of its members [...], and vice versa".
95a143ec61Srillig  */
96a143ec61Srillig double
cast_to_union(void)97a143ec61Srillig cast_to_union(void)
98a143ec61Srillig {
99a143ec61Srillig 	int align_4 = 0;
100a143ec61Srillig 	double align_8 = 0.0;
101a143ec61Srillig 	union both {
102a143ec61Srillig 		int p_align_4;
103a143ec61Srillig 		double p_align_8;
104a143ec61Srillig 	} *both;
105a143ec61Srillig 
106a143ec61Srillig 	both = (union both *)&align_4;
107a143ec61Srillig 	both = (union both *)&align_8;
108a143ec61Srillig 	return both->p_align_8;
109a143ec61Srillig }
110