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