Thu Jul 15 21:22:19 2021 UTC ()
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.


(rillig)
diff -r1.8 -r1.9 src/tests/usr.bin/xlint/lint1/msg_135.c
diff -r1.6 -r1.7 src/tests/usr.bin/xlint/lint1/msg_135.exp
diff -r1.15 -r1.16 src/tests/usr.bin/xlint/lint1/msg_247.c
diff -r1.11 -r1.12 src/tests/usr.bin/xlint/lint1/msg_247.exp
diff -r1.315 -r1.316 src/usr.bin/xlint/lint1/tree.c

cvs diff -r1.8 -r1.9 src/tests/usr.bin/xlint/lint1/msg_135.c (expand / switch to unified diff)

--- 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
8void sink(const void *); 8void sink(const void *);
9 9
10unsigned 10unsigned
11read_uint(const unsigned char **pp) 11read_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
20struct incomplete; /* expect: never defined */ 21struct incomplete; /* expect: never defined */
21 22
22struct complete { 23struct 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 */
37void 38void
38pointer_to_structs(struct incomplete *incomplete) 39pointer_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 */
46void 53void
47unsigned_char_to_unsigned_type(unsigned char *ucp) 54unsigned_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 */
57void 68void
58plain_char_to_unsigned_type(char *cp) 69plain_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}

cvs diff -r1.6 -r1.7 src/tests/usr.bin/xlint/lint1/Attic/msg_135.exp (expand / switch to unified diff)

--- 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 @@
1msg_135.c(15): warning: converting 'pointer to const unsigned char' to 'pointer to const unsigned int' may cause alignment problem [135] 1msg_135.c(16): warning: converting 'pointer to const unsigned short' to 'pointer to const unsigned int' may cause alignment problem [135]
2msg_135.c(53): warning: converting 'pointer to unsigned char' to 'pointer to unsigned short' may cause alignment problem [135] 2msg_135.c(21): warning: struct incomplete never defined [233]
3msg_135.c(64): warning: converting 'pointer to char' to 'pointer to unsigned short' may cause alignment problem [135] 
4msg_135.c(20): warning: struct incomplete never defined [233] 

cvs diff -r1.15 -r1.16 src/tests/usr.bin/xlint/lint1/msg_247.c (expand / switch to unified diff)

--- 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 */
9typedef struct { 9typedef struct {
10 int id; 10 int id;
11} *PDisplay; 11} *PDisplay;
12 12
13struct Other { 13struct 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 {
147struct lhash_st_OPENSSL_STRING * 147struct lhash_st_OPENSSL_STRING *
148lh_OPENSSL_STRING_new(void) 148lh_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
158void sink(const void *); 158void 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 */
160void 166void
161unsigned_char_to_unsigned_type(unsigned char *ucp) 167unsigned_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 */
171void 181void
172plain_char_to_unsigned_type(char *cp) 182plain_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}

cvs diff -r1.11 -r1.12 src/tests/usr.bin/xlint/lint1/Attic/msg_247.exp (expand / switch to unified diff)

--- 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 @@
1msg_247.c(31): warning: pointer cast from 'pointer to struct Other' to 'pointer to struct <unnamed>' may be troublesome [247] 1msg_247.c(31): warning: pointer cast from 'pointer to struct Other' to 'pointer to struct <unnamed>' may be troublesome [247]
2msg_247.c(70): warning: pointer cast from 'pointer to struct Other' to 'pointer to signed char' may be troublesome [247] 2msg_247.c(70): warning: pointer cast from 'pointer to struct Other' to 'pointer to signed char' may be troublesome [247]
3msg_247.c(167): warning: pointer cast from 'pointer to unsigned char' to 'pointer to unsigned short' may be troublesome [247] 
4msg_247.c(178): warning: pointer cast from 'pointer to char' to 'pointer to unsigned short' may be troublesome [247] 
5msg_247.c(134): warning: struct lhash_st never defined [233] 3msg_247.c(134): warning: struct lhash_st never defined [233]

cvs diff -r1.315 -r1.316 src/usr.bin/xlint/lint1/tree.c (expand / switch to unified diff)

--- 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
53static tnode_t *expr_new_integer_constant(tspec_t, int64_t); 53static 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 */
2090static void 2092static void
2091check_pointer_conversion(tnode_t *tn, type_t *ntp) 2093check_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
2132static void 2135static void
2133convert_constant_floating(op_t op, int arg, tspec_t ot, const type_t *tp, 2136convert_constant_floating(op_t op, int arg, tspec_t ot, const type_t *tp,