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