lint: allow pointer casts from 'char *' and 'unsigned char *' For the sake of traditional code that did not yet migrate to using 'void *' for arbitrary pointers. In the standard NetBSD build, this reduces the number of lint warnings by around 7000, of 57000 total.diff -r1.8 -r1.9 src/tests/usr.bin/xlint/lint1/msg_135.c
(rillig)
--- src/tests/usr.bin/xlint/lint1/msg_135.c 2021/07/15 21:12:46 1.8
+++ src/tests/usr.bin/xlint/lint1/msg_135.c 2021/07/15 21:22:19 1.9
@@ -1,28 +1,29 @@ | @@ -1,28 +1,29 @@ | |||
1 | /* $NetBSD: msg_135.c,v 1.8 2021/07/15 21:12:46 rillig Exp $ */ | 1 | /* $NetBSD: msg_135.c,v 1.9 2021/07/15 21:22:19 rillig Exp $ */ | |
2 | # 3 "msg_135.c" | 2 | # 3 "msg_135.c" | |
3 | 3 | |||
4 | // Test for message: converting '%s' to '%s' may cause alignment problem [135] | 4 | // Test for message: converting '%s' to '%s' may cause alignment problem [135] | |
5 | 5 | |||
6 | /* lint1-extra-flags: -h */ | 6 | /* lint1-extra-flags: -h */ | |
7 | 7 | |||
8 | void sink(const void *); | 8 | void sink(const void *); | |
9 | 9 | |||
10 | unsigned | 10 | unsigned | |
11 | read_uint(const unsigned char **pp) | 11 | read_uint(const unsigned short **pp) | |
12 | { | 12 | { | |
13 | unsigned val; | 13 | unsigned val; | |
14 | 14 | |||
15 | val = *(const unsigned *)(*pp); /* expect: 135 */ | 15 | /* expect+1: warning: converting 'pointer to const unsigned short' to 'pointer to const unsigned int' may cause alignment problem [135] */ | |
16 | val = *(const unsigned *)(*pp); | |||
16 | pp += sizeof(unsigned); | 17 | pp += sizeof(unsigned); | |
17 | return val; | 18 | return val; | |
18 | } | 19 | } | |
19 | 20 | |||
20 | struct incomplete; /* expect: never defined */ | 21 | struct incomplete; /* expect: never defined */ | |
21 | 22 | |||
22 | struct complete { | 23 | struct complete { | |
23 | int member; | 24 | int member; | |
24 | }; | 25 | }; | |
25 | 26 | |||
26 | /* | 27 | /* | |
27 | * These types of conversions are typically seen in OpenSSL, when converting | 28 | * These types of conversions are typically seen in OpenSSL, when converting | |
28 | * from the publicly visible, incomplete 'struct lhash_st' to a private | 29 | * from the publicly visible, incomplete 'struct lhash_st' to a private | |
@@ -33,34 +34,42 @@ struct complete { | @@ -33,34 +34,42 @@ struct complete { | |||
33 | * resulting in many false positives. | 34 | * resulting in many false positives. | |
34 | * | 35 | * | |
35 | * See openssl/lhash.h. | 36 | * See openssl/lhash.h. | |
36 | */ | 37 | */ | |
37 | void | 38 | void | |
38 | pointer_to_structs(struct incomplete *incomplete) | 39 | pointer_to_structs(struct incomplete *incomplete) | |
39 | { | 40 | { | |
40 | struct complete *complete; | 41 | struct complete *complete; | |
41 | 42 | |||
42 | complete = (struct complete *)incomplete; | 43 | complete = (struct complete *)incomplete; | |
43 | sink(complete); | 44 | sink(complete); | |
44 | } | 45 | } | |
45 | 46 | |||
47 | /* | |||
48 | * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from | |||
49 | * unsigned char or plain char to another type. These casts often occur in | |||
50 | * traditional code that does not use void pointers, even 30 years after C90 | |||
51 | * introduced 'void'. | |||
52 | */ | |||
46 | void | 53 | void | |
47 | unsigned_char_to_unsigned_type(unsigned char *ucp) | 54 | unsigned_char_to_unsigned_type(unsigned char *ucp) | |
48 | { | 55 | { | |
49 | unsigned short *usp; | 56 | unsigned short *usp; | |
50 | 57 | |||
51 | /* FIXME */ | |||
52 | /* expect+1: warning: converting 'pointer to unsigned char' to 'pointer to unsigned short' may cause alignment problem [135] */ | |||
53 | usp = (unsigned short *)ucp; | 58 | usp = (unsigned short *)ucp; | |
54 | sink(usp); | 59 | sink(usp); | |
55 | } | 60 | } | |
56 | 61 | |||
62 | /* | |||
63 | * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from | |||
64 | * unsigned char or plain char to another type. These casts often occur in | |||
65 | * traditional code that does not use void pointers, even 30 years after C90 | |||
66 | * introduced 'void'. | |||
67 | */ | |||
57 | void | 68 | void | |
58 | plain_char_to_unsigned_type(char *cp) | 69 | plain_char_to_unsigned_type(char *cp) | |
59 | { | 70 | { | |
60 | unsigned short *usp; | 71 | unsigned short *usp; | |
61 | 72 | |||
62 | /* FIXME */ | |||
63 | /* expect+1: warning: converting 'pointer to char' to 'pointer to unsigned short' may cause alignment problem [135] */ | |||
64 | usp = (unsigned short *)cp; | 73 | usp = (unsigned short *)cp; | |
65 | sink(usp); | 74 | sink(usp); | |
66 | } | 75 | } |
--- src/tests/usr.bin/xlint/lint1/Attic/msg_135.exp 2021/07/15 21:12:46 1.6
+++ src/tests/usr.bin/xlint/lint1/Attic/msg_135.exp 2021/07/15 21:22:19 1.7
@@ -1,4 +1,2 @@ | @@ -1,4 +1,2 @@ | |||
1 | msg_135.c(15): warning: converting 'pointer to const unsigned char' to 'pointer to const unsigned int' may cause alignment problem [135] | 1 | msg_135.c(16): warning: converting 'pointer to const unsigned short' to 'pointer to const unsigned int' may cause alignment problem [135] | |
2 | msg_135.c(53): warning: converting 'pointer to unsigned char' to 'pointer to unsigned short' may cause alignment problem [135] | 2 | msg_135.c(21): warning: struct incomplete never defined [233] | |
3 | msg_135.c(64): warning: converting 'pointer to char' to 'pointer to unsigned short' may cause alignment problem [135] | |||
4 | msg_135.c(20): warning: struct incomplete never defined [233] |
--- src/tests/usr.bin/xlint/lint1/msg_247.c 2021/07/15 21:12:46 1.15
+++ src/tests/usr.bin/xlint/lint1/msg_247.c 2021/07/15 21:22:19 1.16
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: msg_247.c,v 1.15 2021/07/15 21:12:46 rillig Exp $ */ | 1 | /* $NetBSD: msg_247.c,v 1.16 2021/07/15 21:22:19 rillig Exp $ */ | |
2 | # 3 "msg_247.c" | 2 | # 3 "msg_247.c" | |
3 | 3 | |||
4 | // Test for message: pointer cast from '%s' to '%s' may be troublesome [247] | 4 | // Test for message: pointer cast from '%s' to '%s' may be troublesome [247] | |
5 | 5 | |||
6 | /* lint1-extra-flags: -c */ | 6 | /* lint1-extra-flags: -c */ | |
7 | 7 | |||
8 | /* example taken from Xlib.h */ | 8 | /* example taken from Xlib.h */ | |
9 | typedef struct { | 9 | typedef struct { | |
10 | int id; | 10 | int id; | |
11 | } *PDisplay; | 11 | } *PDisplay; | |
12 | 12 | |||
13 | struct Other { | 13 | struct Other { | |
14 | int id; | 14 | int id; | |
@@ -147,34 +147,42 @@ struct lhash_st_OPENSSL_STRING { | @@ -147,34 +147,42 @@ struct lhash_st_OPENSSL_STRING { | |||
147 | struct lhash_st_OPENSSL_STRING * | 147 | struct lhash_st_OPENSSL_STRING * | |
148 | lh_OPENSSL_STRING_new(void) | 148 | lh_OPENSSL_STRING_new(void) | |
149 | { | 149 | { | |
150 | /* | 150 | /* | |
151 | * Since tree.c 1.274 from 2021-04-09, lint does not warn about casts | 151 | * Since tree.c 1.274 from 2021-04-09, lint does not warn about casts | |
152 | * to or from incomplete structs anymore. | 152 | * to or from incomplete structs anymore. | |
153 | */ | 153 | */ | |
154 | return (struct lhash_st_OPENSSL_STRING *)OPENSSL_LH_new(); | 154 | return (struct lhash_st_OPENSSL_STRING *)OPENSSL_LH_new(); | |
155 | } | 155 | } | |
156 | # 157 "msg_247.c" 2 | 156 | # 157 "msg_247.c" 2 | |
157 | 157 | |||
158 | void sink(const void *); | 158 | void sink(const void *); | |
159 | 159 | |||
160 | /* | |||
161 | * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from | |||
162 | * unsigned char or plain char to another type. These casts often occur in | |||
163 | * traditional code that does not use void pointers, even 30 years after C90 | |||
164 | * introduced 'void'. | |||
165 | */ | |||
160 | void | 166 | void | |
161 | unsigned_char_to_unsigned_type(unsigned char *ucp) | 167 | unsigned_char_to_unsigned_type(unsigned char *ucp) | |
162 | { | 168 | { | |
163 | unsigned short *usp; | 169 | unsigned short *usp; | |
164 | 170 | |||
165 | /* FIXME */ | |||
166 | /* expect+1: warning: pointer cast from 'pointer to unsigned char' to 'pointer to unsigned short' may be troublesome [247] */ | |||
167 | usp = (unsigned short *)ucp; | 171 | usp = (unsigned short *)ucp; | |
168 | sink(usp); | 172 | sink(usp); | |
169 | } | 173 | } | |
170 | 174 | |||
175 | /* | |||
176 | * Before tree.c 1.316 from 2021-07-15, lint warned about pointer casts from | |||
177 | * unsigned char or plain char to another type. These casts often occur in | |||
178 | * traditional code that does not use void pointers, even 30 years after C90 | |||
179 | * introduced 'void'. | |||
180 | */ | |||
171 | void | 181 | void | |
172 | plain_char_to_unsigned_type(char *cp) | 182 | plain_char_to_unsigned_type(char *cp) | |
173 | { | 183 | { | |
174 | unsigned short *usp; | 184 | unsigned short *usp; | |
175 | 185 | |||
176 | /* FIXME */ | |||
177 | /* expect+1: warning: pointer cast from 'pointer to char' to 'pointer to unsigned short' may be troublesome [247] */ | |||
178 | usp = (unsigned short *)cp; | 186 | usp = (unsigned short *)cp; | |
179 | sink(usp); | 187 | sink(usp); | |
180 | } | 188 | } |
--- src/tests/usr.bin/xlint/lint1/Attic/msg_247.exp 2021/07/15 21:12:46 1.11
+++ src/tests/usr.bin/xlint/lint1/Attic/msg_247.exp 2021/07/15 21:22:19 1.12
@@ -1,5 +1,3 @@ | @@ -1,5 +1,3 @@ | |||
1 | msg_247.c(31): warning: pointer cast from 'pointer to struct Other' to 'pointer to struct <unnamed>' may be troublesome [247] | 1 | msg_247.c(31): warning: pointer cast from 'pointer to struct Other' to 'pointer to struct <unnamed>' may be troublesome [247] | |
2 | msg_247.c(70): warning: pointer cast from 'pointer to struct Other' to 'pointer to signed char' may be troublesome [247] | 2 | msg_247.c(70): warning: pointer cast from 'pointer to struct Other' to 'pointer to signed char' may be troublesome [247] | |
3 | msg_247.c(167): warning: pointer cast from 'pointer to unsigned char' to 'pointer to unsigned short' may be troublesome [247] | |||
4 | msg_247.c(178): warning: pointer cast from 'pointer to char' to 'pointer to unsigned short' may be troublesome [247] | |||
5 | msg_247.c(134): warning: struct lhash_st never defined [233] | 3 | msg_247.c(134): warning: struct lhash_st never defined [233] |
--- src/usr.bin/xlint/lint1/tree.c 2021/07/15 17:03:50 1.315
+++ src/usr.bin/xlint/lint1/tree.c 2021/07/15 21:22:19 1.316
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: tree.c,v 1.315 2021/07/15 17:03:50 rillig Exp $ */ | 1 | /* $NetBSD: tree.c,v 1.316 2021/07/15 21:22:19 rillig Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1994, 1995 Jochen Pohl | 4 | * Copyright (c) 1994, 1995 Jochen Pohl | |
5 | * All Rights Reserved. | 5 | * All Rights Reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -27,27 +27,27 @@ | @@ -27,27 +27,27 @@ | |||
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #if HAVE_NBTOOL_CONFIG_H | 34 | #if HAVE_NBTOOL_CONFIG_H | |
35 | #include "nbtool_config.h" | 35 | #include "nbtool_config.h" | |
36 | #endif | 36 | #endif | |
37 | 37 | |||
38 | #include <sys/cdefs.h> | 38 | #include <sys/cdefs.h> | |
39 | #if defined(__RCSID) && !defined(lint) | 39 | #if defined(__RCSID) && !defined(lint) | |
40 | __RCSID("$NetBSD: tree.c,v 1.315 2021/07/15 17:03:50 rillig Exp $"); | 40 | __RCSID("$NetBSD: tree.c,v 1.316 2021/07/15 21:22:19 rillig Exp $"); | |
41 | #endif | 41 | #endif | |
42 | 42 | |||
43 | #include <float.h> | 43 | #include <float.h> | |
44 | #include <limits.h> | 44 | #include <limits.h> | |
45 | #include <math.h> | 45 | #include <math.h> | |
46 | #include <signal.h> | 46 | #include <signal.h> | |
47 | #include <stdlib.h> | 47 | #include <stdlib.h> | |
48 | #include <string.h> | 48 | #include <string.h> | |
49 | 49 | |||
50 | #include "lint1.h" | 50 | #include "lint1.h" | |
51 | #include "cgram.h" | 51 | #include "cgram.h" | |
52 | 52 | |||
53 | static tnode_t *expr_new_integer_constant(tspec_t, int64_t); | 53 | static tnode_t *expr_new_integer_constant(tspec_t, int64_t); | |
@@ -2070,26 +2070,28 @@ should_warn_about_pointer_cast(const typ | @@ -2070,26 +2070,28 @@ should_warn_about_pointer_cast(const typ | |||
2070 | if (nst == STRUCT && ost == STRUCT && | 2070 | if (nst == STRUCT && ost == STRUCT && | |
2071 | nstp->t_str->sou_first_member != NULL && | 2071 | nstp->t_str->sou_first_member != NULL && | |
2072 | nstp->t_str->sou_first_member->s_type == ostp) | 2072 | nstp->t_str->sou_first_member->s_type == ostp) | |
2073 | return false; | 2073 | return false; | |
2074 | 2074 | |||
2075 | if (is_incomplete(nstp) || is_incomplete(ostp)) | 2075 | if (is_incomplete(nstp) || is_incomplete(ostp)) | |
2076 | return false; | 2076 | return false; | |
2077 | 2077 | |||
2078 | if ((nst == STRUCT || nst == UNION) && nstp->t_str != ostp->t_str) | 2078 | if ((nst == STRUCT || nst == UNION) && nstp->t_str != ostp->t_str) | |
2079 | return true; | 2079 | return true; | |
2080 | 2080 | |||
2081 | if (nst == CHAR || nst == UCHAR) | 2081 | if (nst == CHAR || nst == UCHAR) | |
2082 | return false; /* for the sake of traditional C code */ | 2082 | return false; /* for the sake of traditional C code */ | |
2083 | if (ost == CHAR || ost == UCHAR) | |||
2084 | return false; /* for the sake of traditional C code */ | |||
2083 | 2085 | |||
2084 | return portable_size_in_bits(nst) != portable_size_in_bits(ost); | 2086 | return portable_size_in_bits(nst) != portable_size_in_bits(ost); | |
2085 | } | 2087 | } | |
2086 | 2088 | |||
2087 | /* | 2089 | /* | |
2088 | * Warn about questionable pointer conversions. | 2090 | * Warn about questionable pointer conversions. | |
2089 | */ | 2091 | */ | |
2090 | static void | 2092 | static void | |
2091 | check_pointer_conversion(tnode_t *tn, type_t *ntp) | 2093 | check_pointer_conversion(tnode_t *tn, type_t *ntp) | |
2092 | { | 2094 | { | |
2093 | const type_t *nstp, *otp, *ostp; | 2095 | const type_t *nstp, *otp, *ostp; | |
2094 | tspec_t nst, ost; | 2096 | tspec_t nst, ost; | |
2095 | const char *nts, *ots; | 2097 | const char *nts, *ots; | |
@@ -2108,26 +2110,27 @@ check_pointer_conversion(tnode_t *tn, ty | @@ -2108,26 +2110,27 @@ check_pointer_conversion(tnode_t *tn, ty | |||
2108 | /* ANSI C forbids conversion of %s to %s */ | 2110 | /* ANSI C forbids conversion of %s to %s */ | |
2109 | warning(303, ots, nts); | 2111 | warning(303, ots, nts); | |
2110 | } | 2112 | } | |
2111 | return; | 2113 | return; | |
2112 | } else if (nst == FUNC && ost == FUNC) { | 2114 | } else if (nst == FUNC && ost == FUNC) { | |
2113 | return; | 2115 | return; | |
2114 | } else if (nst == FUNC || ost == FUNC) { | 2116 | } else if (nst == FUNC || ost == FUNC) { | |
2115 | /* converting '%s' to '%s' is questionable */ | 2117 | /* converting '%s' to '%s' is questionable */ | |
2116 | warning(229, type_name(otp), type_name(ntp)); | 2118 | warning(229, type_name(otp), type_name(ntp)); | |
2117 | return; | 2119 | return; | |
2118 | } | 2120 | } | |
2119 | 2121 | |||
2120 | if (hflag && alignment_in_bits(nstp) > alignment_in_bits(ostp) && | 2122 | if (hflag && alignment_in_bits(nstp) > alignment_in_bits(ostp) && | |
2123 | ost != CHAR && ost != UCHAR && | |||
2121 | !is_incomplete(ostp)) { | 2124 | !is_incomplete(ostp)) { | |
2122 | /* converting '%s' to '%s' may cause alignment problem */ | 2125 | /* converting '%s' to '%s' may cause alignment problem */ | |
2123 | warning(135, type_name(otp), type_name(ntp)); | 2126 | warning(135, type_name(otp), type_name(ntp)); | |
2124 | } | 2127 | } | |
2125 | 2128 | |||
2126 | if (cflag && should_warn_about_pointer_cast(nstp, nst, ostp, ost)) { | 2129 | if (cflag && should_warn_about_pointer_cast(nstp, nst, ostp, ost)) { | |
2127 | /* pointer cast from '%s' to '%s' may be troublesome */ | 2130 | /* pointer cast from '%s' to '%s' may be troublesome */ | |
2128 | warning(247, type_name(otp), type_name(ntp)); | 2131 | warning(247, type_name(otp), type_name(ntp)); | |
2129 | } | 2132 | } | |
2130 | } | 2133 | } | |
2131 | 2134 | |||
2132 | static void | 2135 | static void | |
2133 | convert_constant_floating(op_t op, int arg, tspec_t ot, const type_t *tp, | 2136 | convert_constant_floating(op_t op, int arg, tspec_t ot, const type_t *tp, |