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;

Reply via email to