xref: /netbsd/tests/usr.bin/xlint/lint1/msg_135.c (revision 57ddfc8e)
1*57ddfc8eSrillig /*	$NetBSD: msg_135.c,v 1.15 2023/04/23 11:52:43 rillig Exp $	*/
2f42ea02bSrillig # 3 "msg_135.c"
3f42ea02bSrillig 
4fc514a2eSrillig // Test for message: converting '%s' to '%s' increases alignment from %u to %u [135]
5f42ea02bSrillig 
6ea649623Srillig /* lint1-extra-flags: -h -X 351 */
707fd9536Srillig 
87beb4fefSrillig void sink(const void *);
97beb4fefSrillig 
1007fd9536Srillig unsigned
read_uint(const unsigned short ** pp)11910e3ad9Srillig read_uint(const unsigned short **pp)
1207fd9536Srillig {
1307fd9536Srillig 	unsigned val;
1407fd9536Srillig 
15fc514a2eSrillig 	/* expect+1: warning: converting 'pointer to const unsigned short' to 'pointer to const unsigned int' increases alignment from 2 to 4 [135] */
16910e3ad9Srillig 	val = *(const unsigned *)(*pp);
1707fd9536Srillig 	pp += sizeof(unsigned);
1807fd9536Srillig 	return val;
1907fd9536Srillig }
207beb4fefSrillig 
21985dd88dSrillig /* expect+1: warning: struct 'incomplete' never defined [233] */
22985dd88dSrillig struct incomplete;
237beb4fefSrillig 
247beb4fefSrillig struct complete {
257beb4fefSrillig 	int member;
267beb4fefSrillig };
277beb4fefSrillig 
287beb4fefSrillig /*
297beb4fefSrillig  * These types of conversions are typically seen in OpenSSL, when converting
307beb4fefSrillig  * from the publicly visible, incomplete 'struct lhash_st' to a private
317beb4fefSrillig  * implementation type such as 'struct lhash_st_OPENSSL_STRING'.
327beb4fefSrillig  *
3375d9a820Srillig  * Before tree.c 1.277 from 2021-04-17, lint warned about this, even though
3475d9a820Srillig  * there was not enough evidence that there really was an alignment problem,
3575d9a820Srillig  * resulting in many false positives.
3675d9a820Srillig  *
377beb4fefSrillig  * See openssl/lhash.h.
387beb4fefSrillig  */
397beb4fefSrillig void
pointer_to_structs(struct incomplete * incomplete)407beb4fefSrillig pointer_to_structs(struct incomplete *incomplete)
417beb4fefSrillig {
427beb4fefSrillig 	struct complete *complete;
437beb4fefSrillig 
4475d9a820Srillig 	complete = (struct complete *)incomplete;
457beb4fefSrillig 	sink(complete);
467beb4fefSrillig }
473a855b12Srillig 
48910e3ad9Srillig /*
49910e3ad9Srillig  * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from
50910e3ad9Srillig  * unsigned char or plain char to another type.  These casts often occur in
51910e3ad9Srillig  * traditional code that does not use void pointers, even 30 years after C90
52910e3ad9Srillig  * introduced 'void'.
53910e3ad9Srillig  */
543a855b12Srillig void
unsigned_char_to_unsigned_type(unsigned char * ucp)553a855b12Srillig unsigned_char_to_unsigned_type(unsigned char *ucp)
563a855b12Srillig {
573a855b12Srillig 	unsigned short *usp;
583a855b12Srillig 
593a855b12Srillig 	usp = (unsigned short *)ucp;
603a855b12Srillig 	sink(usp);
613a855b12Srillig }
623a855b12Srillig 
63910e3ad9Srillig /*
64910e3ad9Srillig  * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from
65910e3ad9Srillig  * unsigned char or plain char to another type.  These casts often occur in
66910e3ad9Srillig  * traditional code that does not use void pointers, even 30 years after C90
67910e3ad9Srillig  * introduced 'void'.
68910e3ad9Srillig  */
693a855b12Srillig void
plain_char_to_unsigned_type(char * cp)703a855b12Srillig plain_char_to_unsigned_type(char *cp)
713a855b12Srillig {
723a855b12Srillig 	unsigned short *usp;
733a855b12Srillig 
743a855b12Srillig 	usp = (unsigned short *)cp;
753a855b12Srillig 	sink(usp);
763a855b12Srillig }
77fc84fcc6Srillig 
78fc84fcc6Srillig /*
79fc84fcc6Srillig  * Converting a pointer with a low alignment requirement to a union that
80*57ddfc8eSrillig  * includes other types with higher alignment requirements is considered safe.
81*57ddfc8eSrillig  * While accessing any other member of the union might trigger an alignment
82*57ddfc8eSrillig  * violation, such an access is not likely from an application point of view,
83*57ddfc8eSrillig  * as it would access undefined memory and thus invoke undefined behavior.
84fc84fcc6Srillig  *
85fc84fcc6Srillig  * A practical case for this pattern are tagged unions, in which the first
86fc84fcc6Srillig  * member of the struct determines how the remaining members are interpreted.
87fc84fcc6Srillig  * See sbin/newfs_udf, function udf_validate_tag_and_crc_sums for an example.
88*57ddfc8eSrillig  *
89*57ddfc8eSrillig  * C99 6.2.5p26 defines the representation and alignment of types, stating
90*57ddfc8eSrillig  * that pointers to union types need not have the same representation and
91*57ddfc8eSrillig  * alignment as pointers to other types.
92*57ddfc8eSrillig  *
93*57ddfc8eSrillig  * C99 6.7.2.1p14 and C23 6.7.2.1p18 both state that a "pointer to a union
94*57ddfc8eSrillig  * object [...] points to each of its members [...], and vice versa".
95fc84fcc6Srillig  */
96fc84fcc6Srillig double
cast_to_union(void)97fc84fcc6Srillig cast_to_union(void)
98fc84fcc6Srillig {
99fc84fcc6Srillig 	int align_4 = 0;
100fc84fcc6Srillig 	double align_8 = 0.0;
101fc84fcc6Srillig 	union both {
102fc84fcc6Srillig 		int p_align_4;
103fc84fcc6Srillig 		double p_align_8;
104fc84fcc6Srillig 	} *both;
105fc84fcc6Srillig 
106fc84fcc6Srillig 	both = (union both *)&align_4;
107fc84fcc6Srillig 	both = (union both *)&align_8;
108fc84fcc6Srillig 	return both->p_align_8;
109fc84fcc6Srillig }
110