Home | History | Annotate | Line # | Download | only in lint1
msg_135.c revision 1.15.2.1
      1  1.15.2.1  perseant /*	$NetBSD: msg_135.c,v 1.15.2.1 2025/08/02 05:58:16 perseant Exp $	*/
      2       1.1    rillig # 3 "msg_135.c"
      3       1.1    rillig 
      4      1.11    rillig // Test for message: converting '%s' to '%s' increases alignment from %u to %u [135]
      5       1.1    rillig 
      6      1.12    rillig /* lint1-extra-flags: -h -X 351 */
      7       1.3    rillig 
      8       1.6    rillig void sink(const void *);
      9       1.6    rillig 
     10       1.3    rillig unsigned
     11       1.9    rillig read_uint(const unsigned short **pp)
     12       1.3    rillig {
     13       1.3    rillig 	unsigned val;
     14       1.3    rillig 
     15      1.11    rillig 	/* expect+1: warning: converting 'pointer to const unsigned short' to 'pointer to const unsigned int' increases alignment from 2 to 4 [135] */
     16       1.9    rillig 	val = *(const unsigned *)(*pp);
     17       1.3    rillig 	pp += sizeof(unsigned);
     18       1.3    rillig 	return val;
     19       1.3    rillig }
     20       1.6    rillig 
     21      1.10    rillig /* expect+1: warning: struct 'incomplete' never defined [233] */
     22      1.10    rillig struct incomplete;
     23       1.6    rillig 
     24       1.6    rillig struct complete {
     25      1.13    rillig 	int member;
     26       1.6    rillig };
     27       1.6    rillig 
     28       1.6    rillig /*
     29       1.6    rillig  * These types of conversions are typically seen in OpenSSL, when converting
     30       1.6    rillig  * from the publicly visible, incomplete 'struct lhash_st' to a private
     31       1.6    rillig  * implementation type such as 'struct lhash_st_OPENSSL_STRING'.
     32       1.6    rillig  *
     33       1.7    rillig  * Before tree.c 1.277 from 2021-04-17, lint warned about this, even though
     34       1.7    rillig  * there was not enough evidence that there really was an alignment problem,
     35       1.7    rillig  * resulting in many false positives.
     36       1.7    rillig  *
     37       1.6    rillig  * See openssl/lhash.h.
     38       1.6    rillig  */
     39       1.6    rillig void
     40       1.6    rillig pointer_to_structs(struct incomplete *incomplete)
     41       1.6    rillig {
     42       1.6    rillig 	struct complete *complete;
     43       1.6    rillig 
     44       1.7    rillig 	complete = (struct complete *)incomplete;
     45       1.6    rillig 	sink(complete);
     46       1.6    rillig }
     47       1.8    rillig 
     48       1.9    rillig /*
     49       1.9    rillig  * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from
     50       1.9    rillig  * unsigned char or plain char to another type.  These casts often occur in
     51       1.9    rillig  * traditional code that does not use void pointers, even 30 years after C90
     52       1.9    rillig  * introduced 'void'.
     53       1.9    rillig  */
     54       1.8    rillig void
     55       1.8    rillig unsigned_char_to_unsigned_type(unsigned char *ucp)
     56       1.8    rillig {
     57       1.8    rillig 	unsigned short *usp;
     58       1.8    rillig 
     59       1.8    rillig 	usp = (unsigned short *)ucp;
     60       1.8    rillig 	sink(usp);
     61       1.8    rillig }
     62       1.8    rillig 
     63       1.9    rillig /*
     64       1.9    rillig  * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from
     65       1.9    rillig  * unsigned char or plain char to another type.  These casts often occur in
     66       1.9    rillig  * traditional code that does not use void pointers, even 30 years after C90
     67       1.9    rillig  * introduced 'void'.
     68       1.9    rillig  */
     69       1.8    rillig void
     70       1.8    rillig plain_char_to_unsigned_type(char *cp)
     71       1.8    rillig {
     72       1.8    rillig 	unsigned short *usp;
     73       1.8    rillig 
     74       1.8    rillig 	usp = (unsigned short *)cp;
     75       1.8    rillig 	sink(usp);
     76       1.8    rillig }
     77      1.13    rillig 
     78      1.13    rillig /*
     79      1.13    rillig  * Converting a pointer with a low alignment requirement to a union that
     80      1.15    rillig  * includes other types with higher alignment requirements is considered safe.
     81      1.15    rillig  * While accessing any other member of the union might trigger an alignment
     82      1.15    rillig  * violation, such an access is not likely from an application point of view,
     83      1.15    rillig  * as it would access undefined memory and thus invoke undefined behavior.
     84      1.13    rillig  *
     85      1.13    rillig  * A practical case for this pattern are tagged unions, in which the first
     86      1.13    rillig  * member of the struct determines how the remaining members are interpreted.
     87      1.13    rillig  * See sbin/newfs_udf, function udf_validate_tag_and_crc_sums for an example.
     88      1.15    rillig  *
     89      1.15    rillig  * C99 6.2.5p26 defines the representation and alignment of types, stating
     90      1.15    rillig  * that pointers to union types need not have the same representation and
     91      1.15    rillig  * alignment as pointers to other types.
     92      1.15    rillig  *
     93      1.15    rillig  * C99 6.7.2.1p14 and C23 6.7.2.1p18 both state that a "pointer to a union
     94      1.15    rillig  * object [...] points to each of its members [...], and vice versa".
     95      1.13    rillig  */
     96      1.13    rillig double
     97      1.13    rillig cast_to_union(void)
     98      1.13    rillig {
     99      1.13    rillig 	int align_4 = 0;
    100      1.13    rillig 	double align_8 = 0.0;
    101      1.13    rillig 	union both {
    102      1.13    rillig 		int p_align_4;
    103      1.13    rillig 		double p_align_8;
    104      1.13    rillig 	} *both;
    105      1.13    rillig 
    106      1.13    rillig 	both = (union both *)&align_4;
    107      1.13    rillig 	both = (union both *)&align_8;
    108      1.13    rillig 	return both->p_align_8;
    109      1.13    rillig }
    110  1.15.2.1  perseant 
    111  1.15.2.1  perseant /*
    112  1.15.2.1  perseant  * Structures with alignment 1 typically contain padding arrays only, so don't
    113  1.15.2.1  perseant  * warn when they are converted to their structured counterparts.  An example
    114  1.15.2.1  perseant  * of such a conversion is from 'struct sockaddr' to 'struct sockaddr_in6'.
    115  1.15.2.1  perseant  */
    116  1.15.2.1  perseant void
    117  1.15.2.1  perseant from_alignment_1_to_8(void)
    118  1.15.2.1  perseant {
    119  1.15.2.1  perseant 	struct alignment_1 {
    120  1.15.2.1  perseant 		char filler[32];
    121  1.15.2.1  perseant 	};
    122  1.15.2.1  perseant 	struct alignment_8 {
    123  1.15.2.1  perseant 		char filler[32];
    124  1.15.2.1  perseant 		double numbers[4];
    125  1.15.2.1  perseant 	};
    126  1.15.2.1  perseant 
    127  1.15.2.1  perseant 	static struct alignment_1 *pointer_1;
    128  1.15.2.1  perseant 	static struct alignment_8 *pointer_8;
    129  1.15.2.1  perseant 
    130  1.15.2.1  perseant 	pointer_8 = (struct alignment_8 *)pointer_1;
    131  1.15.2.1  perseant 	pointer_1 = (struct alignment_1 *)pointer_8;
    132  1.15.2.1  perseant }
    133