Module Name: src Committed By: rillig Date: Tue Jul 5 22:50:42 UTC 2022
Modified Files: src/distrib/sets/lists/tests: mi src/tests/usr.bin/xlint/lint1: Makefile src/usr.bin/xlint/lint1: Makefile Makefile.err-msgs-h README.md check-msgs.lua err.c externs1.h lint1.h main1.c makeman tree.c src/usr.bin/xlint/xlint: lint.1 xlint.c Added Files: src/tests/usr.bin/xlint/lint1: queries.c Log Message: lint: add additional queries that are not enabled by default In the last 18 months, several lint warnings have been made adjusted to allow common usage patterns. For example, lint no longer warns about a constant condition in the statement 'do { ... } while (false)' (message 161), as this pattern is well-known in statement-like macros, making it unlikely that the 'false' is a mistake. Another example is casts between unequal pointer types (message 247) for a few well-known patterns that are unlikely to be bugs. Occasionally, it is useful to query the code for patterns or events that would not justify a warning. These patterns are modeled as predefined queries that can be selected individually, in addition to and independently of the existing warnings and errors. New queries can be added as needed, in the same way as new warnings. Queries that are deemed no longer used can be deactivated in the same way as warnings that are no longer used. As long as none of the queries is enabled, they produce a minimal overhead of querying a single global variable. Computations that are more expensive than a few machine instructions should be guarded by any_query_enabled. https://mail-index.netbsd.org/source-changes-d/2022/06/28/msg013716.html ok christos@ To generate a diff of this commit: cvs rdiff -u -r1.1215 -r1.1216 src/distrib/sets/lists/tests/mi cvs rdiff -u -r1.128 -r1.129 src/tests/usr.bin/xlint/lint1/Makefile cvs rdiff -u -r0 -r1.1 src/tests/usr.bin/xlint/lint1/queries.c cvs rdiff -u -r1.91 -r1.92 src/usr.bin/xlint/lint1/Makefile cvs rdiff -u -r1.3 -r1.4 src/usr.bin/xlint/lint1/Makefile.err-msgs-h cvs rdiff -u -r1.7 -r1.8 src/usr.bin/xlint/lint1/README.md cvs rdiff -u -r1.16 -r1.17 src/usr.bin/xlint/lint1/check-msgs.lua cvs rdiff -u -r1.180 -r1.181 src/usr.bin/xlint/lint1/err.c cvs rdiff -u -r1.164 -r1.165 src/usr.bin/xlint/lint1/externs1.h cvs rdiff -u -r1.155 -r1.156 src/usr.bin/xlint/lint1/lint1.h cvs rdiff -u -r1.64 -r1.65 src/usr.bin/xlint/lint1/main1.c cvs rdiff -u -r1.5 -r1.6 src/usr.bin/xlint/lint1/makeman cvs rdiff -u -r1.470 -r1.471 src/usr.bin/xlint/lint1/tree.c cvs rdiff -u -r1.53 -r1.54 src/usr.bin/xlint/xlint/lint.1 cvs rdiff -u -r1.93 -r1.94 src/usr.bin/xlint/xlint/xlint.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/tests/mi diff -u src/distrib/sets/lists/tests/mi:1.1215 src/distrib/sets/lists/tests/mi:1.1216 --- src/distrib/sets/lists/tests/mi:1.1215 Fri Jun 17 20:23:58 2022 +++ src/distrib/sets/lists/tests/mi Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1215 2022/06/17 20:23:58 rillig Exp $ +# $NetBSD: mi,v 1.1216 2022/07/05 22:50:41 rillig Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -7316,6 +7316,7 @@ ./usr/tests/usr.bin/xlint/lint1/platform_schar.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/platform_uchar.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/platform_uchar.exp tests-obsolete obsolete,atf +./usr/tests/usr.bin/xlint/lint1/queries.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/stmt_for.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/stmt_for.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/stmt_goto.c tests-usr.bin-tests compattestfile,atf Index: src/tests/usr.bin/xlint/lint1/Makefile diff -u src/tests/usr.bin/xlint/lint1/Makefile:1.128 src/tests/usr.bin/xlint/lint1/Makefile:1.129 --- src/tests/usr.bin/xlint/lint1/Makefile:1.128 Fri Jun 17 20:31:56 2022 +++ src/tests/usr.bin/xlint/lint1/Makefile Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.128 2022/06/17 20:31:56 rillig Exp $ +# $NetBSD: Makefile,v 1.129 2022/07/05 22:50:41 rillig Exp $ NOMAN= # defined MAX_MESSAGE= 349 # see lint1/err.c @@ -167,6 +167,7 @@ FILES+= platform_long.c FILES+= platform_lp64.c FILES+= platform_schar.c FILES+= platform_uchar.c +FILES+= queries.c FILES+= stmt_for.c FILES+= stmt_goto.c FILES+= stmt_if.c Index: src/usr.bin/xlint/lint1/Makefile diff -u src/usr.bin/xlint/lint1/Makefile:1.91 src/usr.bin/xlint/lint1/Makefile:1.92 --- src/usr.bin/xlint/lint1/Makefile:1.91 Fri Jun 17 20:23:58 2022 +++ src/usr.bin/xlint/lint1/Makefile Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.91 2022/06/17 20:23:58 rillig Exp $ +# $NetBSD: Makefile,v 1.92 2022/07/05 22:50:41 rillig Exp $ .include <bsd.own.mk> @@ -62,9 +62,11 @@ cgram.ln: cgram.c ${CPPFLAGS:C/-([IDUW]) */-\1/Wg:M-[IDUW]*} \ -i -UYYDEBUG ${.IMPSRC} -${MAN}: makeman ${LINT1:./%=%} Makefile ${MAN}.date +${MAN}: makeman err.c Makefile ${MAN}.date ${_MKTARGET_CREATE} - ${HOST_SH} ${.ALLSRC:M*makeman} "$$(cat ${.ALLSRC:M*.date})" ${LINT1} -m >${.TARGET} + ${HOST_SH} ${.ALLSRC:M*makeman} \ + "$$(cat ${.ALLSRC:M*.date})" ${.ALLSRC:M*err.c} \ + >${.TARGET} LDADD+= -lm .ifndef HOSTPROG Index: src/usr.bin/xlint/lint1/Makefile.err-msgs-h diff -u src/usr.bin/xlint/lint1/Makefile.err-msgs-h:1.3 src/usr.bin/xlint/lint1/Makefile.err-msgs-h:1.4 --- src/usr.bin/xlint/lint1/Makefile.err-msgs-h:1.3 Sat Apr 10 23:51:37 2021 +++ src/usr.bin/xlint/lint1/Makefile.err-msgs-h Tue Jul 5 22:50:41 2022 @@ -1,9 +1,9 @@ -# $NetBSD: Makefile.err-msgs-h,v 1.3 2021/04/10 23:51:37 rillig Exp $ +# $NetBSD: Makefile.err-msgs-h,v 1.4 2022/07/05 22:50:41 rillig Exp $ err-msgs.h: err.c Makefile.err-msgs-h ${_MKTARGET_CREATE} sp='[[:space:]]*'; \ - from="^$$sp\(\".*\"\)\,$$sp/\*$$sp\([0-9][0-9]*\)$$sp\*/\$$"; \ + from="^$$sp\(\".*\"\)\,$$sp/\*$$sp\(Q*[0-9][0-9]*\)$$sp\*/\$$"; \ ${TOOL_SED} -n -e "s,$$from,#define MSG_\2 \1,p" < ${.ALLSRC:M*err.c} > ${.TARGET}.tmp mv -f ${.TARGET}.tmp ${.TARGET} Index: src/usr.bin/xlint/lint1/README.md diff -u src/usr.bin/xlint/lint1/README.md:1.7 src/usr.bin/xlint/lint1/README.md:1.8 --- src/usr.bin/xlint/lint1/README.md:1.7 Sun Jul 3 19:47:34 2022 +++ src/usr.bin/xlint/lint1/README.md Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -[//]: # ($NetBSD: README.md,v 1.7 2022/07/03 19:47:34 rillig Exp $) +[//]: # ($NetBSD: README.md,v 1.8 2022/07/05 22:50:41 rillig Exp $) # Introduction @@ -43,8 +43,8 @@ The cleanup after handling a parse error ## Configurable diagnostic messages -Whether lint prints a message and whether each message is an error or a -warning depends on several things: +Whether lint prints a message and whether each message is an error, a warning +or just informational depends on several things: * The language level, with its possible values: * traditional C (`-t`) @@ -61,6 +61,8 @@ warning depends on several things: types, the option `-aa` extends this check to small integer types as well, reusing the same message ID. * The option `-X` suppresses arbitrary messages by their message ID. +* The option `-q` enables additional queries that are not suitable as regular + warnings but may be interesting to look at on a case-by-case basis. # Fundamental types Index: src/usr.bin/xlint/lint1/check-msgs.lua diff -u src/usr.bin/xlint/lint1/check-msgs.lua:1.16 src/usr.bin/xlint/lint1/check-msgs.lua:1.17 --- src/usr.bin/xlint/lint1/check-msgs.lua:1.16 Sun Jul 3 21:17:24 2022 +++ src/usr.bin/xlint/lint1/check-msgs.lua Tue Jul 5 22:50:41 2022 @@ -1,5 +1,5 @@ #! /usr/bin/lua --- $NetBSD: check-msgs.lua,v 1.16 2022/07/03 21:17:24 rillig Exp $ +-- $NetBSD: check-msgs.lua,v 1.17 2022/07/05 22:50:41 rillig Exp $ --[[ @@ -16,7 +16,7 @@ local function load_messages() local f = assert(io.open("err.c")) for line in f:lines() do - local msg, id = line:match("%s*\"(.+)\",%s*/%*%s*(%d+)%s*%*/$") + local msg, id = line:match("%s*\"(.+)\",%s*/%*%s*(Q?%d+)%s*%*/$") if msg ~= nil then msgs[id] = msg end @@ -61,14 +61,15 @@ local function check_message(fname, line fname, lineno, id, msg, comment) end -local is_message_function = { - error = true, - error_at = true, - warning = true, - warning_at = true, - c99ism = true, - c11ism = true, - gnuism = true, +local message_prefix = { + error = "", + error_at = "", + warning = "", + warning_at = "", + query_message = "Q", + c99ism = "", + c11ism = "", + gnuism = "", } local function check_file(fname, msgs) @@ -79,7 +80,9 @@ local function check_file(fname, msgs) lineno = lineno + 1 local func, id = line:match("^%s+([%w_]+)%((%d+)[),]") - if is_message_function[func] then + local prefix = message_prefix[func] + if prefix then + id = prefix .. id local comment = prev:match("^%s+/%* (.+) %*/$") if comment ~= nil then check_message(fname, lineno, id, comment, msgs) Index: src/usr.bin/xlint/lint1/err.c diff -u src/usr.bin/xlint/lint1/err.c:1.180 src/usr.bin/xlint/lint1/err.c:1.181 --- src/usr.bin/xlint/lint1/err.c:1.180 Sat Jul 2 11:17:54 2022 +++ src/usr.bin/xlint/lint1/err.c Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: err.c,v 1.180 2022/07/02 11:17:54 rillig Exp $ */ +/* $NetBSD: err.c,v 1.181 2022/07/05 22:50:41 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: err.c,v 1.180 2022/07/02 11:17:54 rillig Exp $"); +__RCSID("$NetBSD: err.c,v 1.181 2022/07/05 22:50:41 rillig Exp $"); #endif #include <limits.h> @@ -706,3 +706,57 @@ bool va_end(ap); return severity > 0; } + + +static const char *queries[] = { + "", /* unused, to make queries 1-based */ + "implicit conversion from floating point '%s' to integer '%s'", /* Q1 */ + "cast from floating point '%s' to integer '%s'", /* Q2 */ + "implicit conversion changes sign from '%s' to '%s'", /* Q3 */ + "usual arithmetic conversion for '%s' from '%s' to '%s'", /* Q4 */ + "pointer addition has integer on the left-hand side", /* Q5 */ + "no-op cast from '%s' to '%s'", /* Q6 */ + "redundant cast from '%s' to '%s' before assignment", /* Q7 */ +}; + +bool any_query_enabled; /* for optimizing non-query scenarios */ +static bool is_query_enabled[sizeof(queries) / sizeof(queries[0])]; + +void +(query_message)(int query_id, ...) +{ + va_list ap; + + if (!is_query_enabled[query_id]) + return; + + (void)printf("%s(%d): ", lbasename(curr_pos.p_file), curr_pos.p_line); + va_start(ap, query_id); + (void)vprintf(queries[query_id], ap); + va_end(ap); + (void)printf(" [Q%d]\n", query_id); + print_stack_trace(); +} + +void +enable_queries(const char *arg) +{ + + for (const char *s = arg;;) { + const char *e = s + strcspn(s, ","); + + char *end; + unsigned long id = strtoul(s, &end, 10); + if (!(ch_isdigit(s[0]) && end == e && + id < sizeof(queries) / sizeof(queries[0]) && + queries[id][0] != '\0')) + errx(1, "invalid query ID '%s'", s); + + any_query_enabled = true; + is_query_enabled[id] = true; + + if (*e == '\0') + break; + s = e + 1; + } +} Index: src/usr.bin/xlint/lint1/externs1.h diff -u src/usr.bin/xlint/lint1/externs1.h:1.164 src/usr.bin/xlint/lint1/externs1.h:1.165 --- src/usr.bin/xlint/lint1/externs1.h:1.164 Sun Jul 3 14:15:38 2022 +++ src/usr.bin/xlint/lint1/externs1.h Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: externs1.h,v 1.164 2022/07/03 14:15:38 rillig Exp $ */ +/* $NetBSD: externs1.h,v 1.165 2022/07/05 22:50:41 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -155,6 +155,7 @@ void debug_leave(const char *); */ extern int nerr; extern int sytxerr; +extern bool any_query_enabled; extern void msglist(void); extern void error_at(int, const pos_t *, ...); @@ -172,6 +173,9 @@ extern void assert_failed(const char *, extern void update_location(const char *, int, bool, bool); extern void suppress_messages(char *); +extern void query_message(int, ...); +extern void enable_queries(const char *); + /* * decl.c */ Index: src/usr.bin/xlint/lint1/lint1.h diff -u src/usr.bin/xlint/lint1/lint1.h:1.155 src/usr.bin/xlint/lint1/lint1.h:1.156 --- src/usr.bin/xlint/lint1/lint1.h:1.155 Fri Jul 1 21:25:39 2022 +++ src/usr.bin/xlint/lint1/lint1.h Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: lint1.h,v 1.155 2022/07/01 21:25:39 rillig Exp $ */ +/* $NetBSD: lint1.h,v 1.156 2022/07/05 22:50:41 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -488,6 +488,21 @@ check_printf(const char *fmt, ...) # define c11ism(msgid, args...) wrap_check_printf(c11ism, msgid, ##args) #endif +#ifdef DEBUG +# define query_message(query_id, args...) \ + do { \ + debug_step("%s:%d: %s", __FILE__, __LINE__, __func__); \ + check_printf(__CONCAT(MSG_Q, query_id), ##args); \ + (query_message)(query_id, ##args); \ + } while (false) +#else +# define query_message(...) \ + do { \ + if (any_query_enabled) \ + (query_message)(__VA_ARGS__); \ + } while (false) +#endif + static inline bool is_nonzero_val(const val_t *val) { Index: src/usr.bin/xlint/lint1/main1.c diff -u src/usr.bin/xlint/lint1/main1.c:1.64 src/usr.bin/xlint/lint1/main1.c:1.65 --- src/usr.bin/xlint/lint1/main1.c:1.64 Fri Jul 1 21:25:39 2022 +++ src/usr.bin/xlint/lint1/main1.c Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: main1.c,v 1.64 2022/07/01 21:25:39 rillig Exp $ */ +/* $NetBSD: main1.c,v 1.65 2022/07/05 22:50:41 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: main1.c,v 1.64 2022/07/01 21:25:39 rillig Exp $"); +__RCSID("$NetBSD: main1.c,v 1.65 2022/07/05 22:50:41 rillig Exp $"); #endif #include <sys/types.h> @@ -177,7 +177,7 @@ main(int argc, char *argv[]) setprogname(argv[0]); - while ((c = getopt(argc, argv, "abceghmprstuvwyzA:FPR:STX:")) != -1) { + while ((c = getopt(argc, argv, "abceghmpq:rstuvwyzA:FPR:STX:")) != -1) { switch (c) { case 'a': aflag++; break; case 'b': bflag = true; break; @@ -188,6 +188,7 @@ main(int argc, char *argv[]) case 'h': hflag = true; break; case 'p': pflag = true; break; case 'P': Pflag = true; break; + case 'q': enable_queries(optarg); break; case 'r': rflag = true; break; case 's': allow_trad = false; @@ -247,7 +248,7 @@ main(int argc, char *argv[]) /* initialize output */ - outopen(argv[1]); + outopen(any_query_enabled ? "/dev/null" : argv[1]); #ifdef DEBUG setvbuf(stdout, NULL, _IONBF, 0); Index: src/usr.bin/xlint/lint1/makeman diff -u src/usr.bin/xlint/lint1/makeman:1.5 src/usr.bin/xlint/lint1/makeman:1.6 --- src/usr.bin/xlint/lint1/makeman:1.5 Sun Sep 5 13:46:31 2021 +++ src/usr.bin/xlint/lint1/makeman Tue Jul 5 22:50:41 2022 @@ -1,5 +1,5 @@ #!/bin/sh -# $NetBSD: makeman,v 1.5 2021/09/05 13:46:31 rillig Exp $ +# $NetBSD: makeman,v 1.6 2022/07/05 22:50:41 rillig Exp $ # # Copyright (c) 2000 The NetBSD Foundation, Inc. # All rights reserved. @@ -28,11 +28,31 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +tab=' ' -sed "s|@date@|$1|" << \__EOF -.\" $NetBSD: makeman,v 1.5 2021/09/05 13:46:31 rillig Exp $ +list_messages() { + sed -E -n \ + -e 's|^'"$tab"'"(.+)",.*/\* '"$2"'([0-9]+) \*/$|\2'"$tab"'\1|p' \ + -e 's|^'"$tab"'"",.*/\* '"$2"'[0-9]+ \*/$|---'"$tab"'(no longer used)|p' \ + "$1" \ + | sed -E \ + -e 's|\\"|"|g' \ + -e 's|\\\\|\\e|g' \ + -e "s|'|\\'|g" \ + -e 's|^|.It |' +} + +# shellcheck disable=SC2016 +cvsid='$NetBSD: makeman,v 1.6 2022/07/05 22:50:41 rillig Exp $' +date="$1" +year="${date##* }" +messages="$(list_messages "$2" "")" +queries="$(list_messages "$2" "Q")" + +cat << EOF +.\" $cvsid .\" -.\" Copyright (c) 2000 The NetBSD Foundation, Inc. +.\" Copyright (c) 2000,$year The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This code is derived from software contributed to The NetBSD Foundation @@ -48,7 +68,7 @@ sed "s|@date@|$1|" << \__EOF .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" \`\`AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED .\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR .\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS .\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR @@ -58,24 +78,36 @@ sed "s|@date@|$1|" << \__EOF .\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. -.Dd @date@ +.Dd $date .Dt LINT 7 .Os .Sh NAME .Nm lint -.Nd Lint error message list +.Nd Error, warning and query messages from lint .Sh DESCRIPTION The following is a list of message IDs and messages produced by .Xr lint 1 . -It is intended to be used with +It is intended to be used with the .Fl X flag of .Xr lint 1 . .Pp .Bd -ragged -offset indent -compact .Bl -column "XXXX" -__EOF -shift -"$@" | sed -e 's/^/.It /' -e 's/\\/\\e/g' -e "s/'/\\'/" -echo ".El" -echo ".Ed" +$messages +.El +.Ed +.Pp +The following is a list of query IDs and their messages produced by +.Xr lint 1 . +It is intended to be used with the +.Fl q +flag of +.Xr lint 1 . +.Pp +.Bd -ragged -offset indent -compact +.Bl -column "XXXX" +$queries +.El +.Ed +EOF Index: src/usr.bin/xlint/lint1/tree.c diff -u src/usr.bin/xlint/lint1/tree.c:1.470 src/usr.bin/xlint/lint1/tree.c:1.471 --- src/usr.bin/xlint/lint1/tree.c:1.470 Sun Jul 3 14:15:38 2022 +++ src/usr.bin/xlint/lint1/tree.c Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: tree.c,v 1.470 2022/07/03 14:15:38 rillig Exp $ */ +/* $NetBSD: tree.c,v 1.471 2022/07/05 22:50:41 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: tree.c,v 1.470 2022/07/03 14:15:38 rillig Exp $"); +__RCSID("$NetBSD: tree.c,v 1.471 2022/07/05 22:50:41 rillig Exp $"); #endif #include <float.h> @@ -2260,15 +2260,33 @@ balance(op_t op, tnode_t **lnp, tnode_t if (t != lt) { ntp = expr_dup_type((*lnp)->tn_type); ntp->t_tspec = t; + /* usual arithmetic conversion for '%s' from '%s' to '%s' */ + query_message(4, op_name(op), + type_name((*lnp)->tn_type), type_name(ntp)); *lnp = convert(op, 0, ntp, *lnp); } if (t != rt) { ntp = expr_dup_type((*rnp)->tn_type); ntp->t_tspec = t; + /* usual arithmetic conversion for '%s' from '%s' to '%s' */ + query_message(4, op_name(op), + type_name((*rnp)->tn_type), type_name(ntp)); *rnp = convert(op, 0, ntp, *rnp); } } +static void +convert_integer_from_floating(op_t op, const type_t *tp, const tnode_t *tn) +{ + + if (op == CVT) + /* cast from floating point '%s' to integer '%s' */ + query_message(2, type_name(tn->tn_type), type_name(tp)); + else + /* implicit conversion from floating point '%s' to ... */ + query_message(1, type_name(tn->tn_type), type_name(tp)); +} + /* * Insert a conversion operator, which converts the type of the node * to another given type. @@ -2303,7 +2321,7 @@ convert(op_t op, int arg, type_t *tp, tn } else if (is_integer(ot)) { convert_integer_from_integer(op, arg, nt, ot, tp, tn); } else if (is_floating(ot)) { - /* No further checks. */ + convert_integer_from_floating(op, tp, tn); } else if (ot == PTR) { convert_integer_from_pointer(op, nt, tp, tn); } @@ -2482,6 +2500,10 @@ convert_integer_from_integer(op_t op, in type_name(tn->tn_type), type_name(tp)); } } + + if (is_uinteger(nt) != is_uinteger(ot)) + /* implicit conversion changes sign from '%s' to '%s' */ + query_message(3, type_name(tn->tn_type), type_name(tp)); } static void @@ -3178,6 +3200,8 @@ build_plus_minus(op_t op, bool sys, tnod tnode_t *tmp = ln; ln = rn; rn = tmp; + /* pointer addition has integer on the left-hand side */ + query_message(5); } /* pointer +- integer */ @@ -3351,6 +3375,13 @@ build_assignment(op_t op, bool sys, tnod } } + if (any_query_enabled && rn->tn_op == CVT && rn->tn_cast && + eqtype(ln->tn_type, rn->tn_type, false, false, NULL)) { + /* redundant cast from '%s' to '%s' before assignment */ + query_message(7, + type_name(rn->tn_left->tn_type), type_name(rn->tn_type)); + } + ntn = new_tnode(op, sys, ln->tn_type, ln, rn); return ntn; @@ -3912,6 +3943,10 @@ cast(tnode_t *tn, type_t *tp) } else goto invalid_cast; + if (any_query_enabled && eqtype(tp, tn->tn_type, false, false, NULL)) + /* no-op cast from '%s' to '%s' */ + query_message(6, type_name(tn->tn_type), type_name(tp)); + tn = convert(CVT, 0, tp, tn); tn->tn_cast = true; Index: src/usr.bin/xlint/xlint/lint.1 diff -u src/usr.bin/xlint/xlint/lint.1:1.53 src/usr.bin/xlint/xlint/lint.1:1.54 --- src/usr.bin/xlint/xlint/lint.1:1.53 Mon May 30 23:02:02 2022 +++ src/usr.bin/xlint/xlint/lint.1 Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -.\" $NetBSD: lint.1,v 1.53 2022/05/30 23:02:02 rillig Exp $ +.\" $NetBSD: lint.1,v 1.54 2022/07/05 22:50:41 rillig Exp $ .\" .\" Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. .\" Copyright (c) 1994, 1995 Jochen Pohl @@ -30,7 +30,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd May 31, 2022 +.Dd July 5, 2022 .Dt LINT 1 .Os .Sh NAME @@ -49,6 +49,7 @@ .Op Fl MD .Op Fl l Ar library .Op Fl o Ar outputfile +.Op Fl q Ar id Ns Op ,id ... .Op Fl U Ar name .Op Fl W Ar cppwarnarg .Op Fl X Ar id Ns Op ,id ... @@ -343,6 +344,21 @@ when assigning to wider integer types, o to wider types. .It Fl p Attempt to check portability of code to other platforms of C. +.It Fl q Ar id Op ,id ... +In addition to the usual warnings and errors, run the selected queries, +which are listed in +.Xr lint 7 Ns . +These queries are similar to warnings, +they do not highlight possible bugs though, +but instead point to other events in the code +that may be interesting to look at on a case-by-case basis. +The most convenient way to run queries on a source file is to run: +.Pp +.Dl make LINT=\*qlint \-q3,5,7\*q source.ln +.Pp +To allow this command to be run repeatedly, the option +.Fl q +prevents creating the .ln file. .It Fl R Ar old=new Remap .Ar old Index: src/usr.bin/xlint/xlint/xlint.c diff -u src/usr.bin/xlint/xlint/xlint.c:1.93 src/usr.bin/xlint/xlint/xlint.c:1.94 --- src/usr.bin/xlint/xlint/xlint.c:1.93 Mon May 30 23:02:02 2022 +++ src/usr.bin/xlint/xlint/xlint.c Tue Jul 5 22:50:41 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: xlint.c,v 1.93 2022/05/30 23:02:02 rillig Exp $ */ +/* $NetBSD: xlint.c,v 1.94 2022/07/05 22:50:41 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: xlint.c,v 1.93 2022/05/30 23:02:02 rillig Exp $"); +__RCSID("$NetBSD: xlint.c,v 1.94 2022/07/05 22:50:41 rillig Exp $"); #endif #include <sys/param.h> @@ -397,7 +397,7 @@ main(int argc, char *argv[]) (void)signal(SIGQUIT, terminate); (void)signal(SIGTERM, terminate); while ((c = getopt(argc, argv, - "abcd:eghil:no:prstuvwxzA:B:C:D:FHI:L:M:PR:STU:VW:X:Z:")) != -1) { + "abcd:eghil:no:pq:rstuvwxzA:B:C:D:FHI:L:M:PR:STU:VW:X:Z:")) != -1) { switch (c) { case 'a': @@ -414,6 +414,7 @@ main(int argc, char *argv[]) break; case 'A': + case 'q': case 'R': case 'X': pass_flag_to_lint1(c); Added files: Index: src/tests/usr.bin/xlint/lint1/queries.c diff -u /dev/null src/tests/usr.bin/xlint/lint1/queries.c:1.1 --- /dev/null Tue Jul 5 22:50:42 2022 +++ src/tests/usr.bin/xlint/lint1/queries.c Tue Jul 5 22:50:41 2022 @@ -0,0 +1,108 @@ +/* $NetBSD: queries.c,v 1.1 2022/07/05 22:50:41 rillig Exp $ */ +# 3 "queries.c" + +/* + * Demonstrate the case-by-case queries. Unlike warnings, queries do not + * point to questionable code but rather to code that may be interesting to + * inspect manually on a case-by-case basis. + * + * Possible use cases are: + * + * Understanding how C works internally, by making the usual arithmetic + * conversions visible. + * + * Finding code that intentionally suppresses a regular lint warning, + * such as casts between arithmetic types. + */ + +/* lint1-extra-flags: -q 1,2,3,4,5,6,7 */ + +int +Q1(double dbl) +{ + /* expect+1: implicit conversion from floating point 'double' to integer 'int' [Q1] */ + return dbl; +} + +int +Q2(double dbl) +{ + /* expect+2: cast from floating point 'double' to integer 'int' [Q2] */ + /* expect+1: redundant cast from 'double' to 'int' before assignment [Q7] */ + return (int)dbl; +} + +void +Q3(int i, unsigned u) +{ + /* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */ + u = i; + + /* expect+1: implicit conversion changes sign from 'unsigned int' to 'int' [Q3] */ + i = u; +} + +unsigned long long +Q4(char *ptr, int i, unsigned long long ull) +{ + /* + * The conversion from 'char' to 'int' is done by the integer + * promotions (C11 6.3.1.1p2), not by the usual arithmetic + * conversions (C11 6.3.1.8p1). + */ + /* expect+2: usual arithmetic conversion for '+' from 'int' to 'unsigned long long' [Q4] */ + /* expect+1: implicit conversion changes sign from 'int' to 'unsigned long long' [Q3] */ + return ptr[0] + ptr[1] + i + ull; +} + +void +Q5(char *ptr, int i) +{ + if (ptr + i > ptr) + return; + + /* expect+1: pointer addition has integer on the left-hand side [Q5] */ + if (i + ptr > ptr) + return; + + if (ptr[i] != '\0') + return; + + /* expect+1: pointer addition has integer on the left-hand side [Q5] */ + if (i[ptr] != '\0') + return; +} + +void +Q6(int i) +{ + /* expect+1: no-op cast from 'int' to 'int' [Q6] */ + i = (int)4; + + /* expect+1: no-op cast from 'int' to 'int' [Q6] */ + i = (int)i + 1; +} + +extern void *allocate(unsigned long); + +char * +Q7(void) +{ + /* expect+1: redundant cast from 'pointer to void' to 'pointer to char' before assignment [Q7] */ + char *str = (char *)allocate(64); + + if (str == (void *)0) + /* expect+1: redundant cast from 'pointer to void' to 'pointer to char' before assignment [Q7] */ + str = (char *)allocate(64); + + return str; +} + + +/* + * Since queries do not affect the exit status, force a warning to make this + * test conform to the general expectation that a test that produces output + * exits non-successfully. + */ +/* expect+1: warning: static variable 'unused' unused [226] */ +static int unused;