Home | History | Annotate | Line # | Download | only in lint1
      1  1.17  rillig /*	$NetBSD: msg_135.c,v 1.17 2025/03/21 20:37:31 rillig 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.16  rillig 
    111  1.17  rillig /*
    112  1.17  rillig  * Structures with alignment 1 typically contain padding arrays only, so don't
    113  1.17  rillig  * warn when they are converted to their structured counterparts.  An example
    114  1.17  rillig  * of such a conversion is from 'struct sockaddr' to 'struct sockaddr_in6'.
    115  1.17  rillig  */
    116  1.16  rillig void
    117  1.16  rillig from_alignment_1_to_8(void)
    118  1.16  rillig {
    119  1.16  rillig 	struct alignment_1 {
    120  1.16  rillig 		char filler[32];
    121  1.16  rillig 	};
    122  1.16  rillig 	struct alignment_8 {
    123  1.16  rillig 		char filler[32];
    124  1.16  rillig 		double numbers[4];
    125  1.16  rillig 	};
    126  1.16  rillig 
    127  1.16  rillig 	static struct alignment_1 *pointer_1;
    128  1.16  rillig 	static struct alignment_8 *pointer_8;
    129  1.16  rillig 
    130  1.16  rillig 	pointer_8 = (struct alignment_8 *)pointer_1;
    131  1.16  rillig 	pointer_1 = (struct alignment_1 *)pointer_8;
    132  1.16  rillig }
    133