Module Name:    src
Committed By:   rillig
Date:           Mon Aug  9 20:07:24 UTC 2021

Modified Files:
        src/distrib/sets/lists/tests: mi
        src/tests/usr.bin/xlint/lint1: Makefile
        src/usr.bin/xlint/lint1: err.c tree.c
Added Files:
        src/tests/usr.bin/xlint/lint1: msg_346.c msg_346.exp

Log Message:
lint: warn about 'char * = strchr(const char *, int)'

Found in findcc.c, there are about 25 other instances of this
incongruency in the whole source tree.

For more examples of functions from the C Standard Library that
implicitly remove the 'const' qualifier from an argument, see the C++
include file 'cstring'.


To generate a diff of this commit:
cvs rdiff -u -r1.1108 -r1.1109 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.102 -r1.103 src/tests/usr.bin/xlint/lint1/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/usr.bin/xlint/lint1/msg_346.c \
    src/tests/usr.bin/xlint/lint1/msg_346.exp
cvs rdiff -u -r1.134 -r1.135 src/usr.bin/xlint/lint1/err.c
cvs rdiff -u -r1.330 -r1.331 src/usr.bin/xlint/lint1/tree.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.1108 src/distrib/sets/lists/tests/mi:1.1109
--- src/distrib/sets/lists/tests/mi:1.1108	Sun Aug  8 00:02:02 2021
+++ src/distrib/sets/lists/tests/mi	Mon Aug  9 20:07:23 2021
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1108 2021/08/08 00:02:02 rillig Exp $
+# $NetBSD: mi,v 1.1109 2021/08/09 20:07:23 rillig Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -7004,6 +7004,8 @@
 ./usr/tests/usr.bin/xlint/lint1/msg_344.exp			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/msg_345.c			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/msg_345.exp			tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/msg_346.c			tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/msg_346.exp			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/op_colon.c			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/op_colon.exp			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/op_shl_lp64.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.102 src/tests/usr.bin/xlint/lint1/Makefile:1.103
--- src/tests/usr.bin/xlint/lint1/Makefile:1.102	Thu Aug  5 06:34:43 2021
+++ src/tests/usr.bin/xlint/lint1/Makefile	Mon Aug  9 20:07:24 2021
@@ -1,7 +1,7 @@
-# $NetBSD: Makefile,v 1.102 2021/08/05 06:34:43 rillig Exp $
+# $NetBSD: Makefile,v 1.103 2021/08/09 20:07:24 rillig Exp $
 
 NOMAN=		# defined
-MAX_MESSAGE=	345		# see lint1/err.c
+MAX_MESSAGE=	346		# see lint1/err.c
 
 .include <bsd.own.mk>
 

Index: src/usr.bin/xlint/lint1/err.c
diff -u src/usr.bin/xlint/lint1/err.c:1.134 src/usr.bin/xlint/lint1/err.c:1.135
--- src/usr.bin/xlint/lint1/err.c:1.134	Tue Aug  3 20:57:06 2021
+++ src/usr.bin/xlint/lint1/err.c	Mon Aug  9 20:07:23 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: err.c,v 1.134 2021/08/03 20:57:06 rillig Exp $	*/
+/*	$NetBSD: err.c,v 1.135 2021/08/09 20:07:23 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: err.c,v 1.134 2021/08/03 20:57:06 rillig Exp $");
+__RCSID("$NetBSD: err.c,v 1.135 2021/08/09 20:07:23 rillig Exp $");
 #endif
 
 #include <sys/types.h>
@@ -400,6 +400,7 @@ const char *const msgs[] = {
 	"static array size is a C11 extension",			      /* 343 */
 	"bit-field of type plain 'int' has implementation-defined signedness", /* 344 */
 	"generic selection requires C11 or later",		      /* 345 */
+	"call to '%s' effectively discards 'const' from argument",    /* 346 */
 };
 
 static struct include_level {

Index: src/usr.bin/xlint/lint1/tree.c
diff -u src/usr.bin/xlint/lint1/tree.c:1.330 src/usr.bin/xlint/lint1/tree.c:1.331
--- src/usr.bin/xlint/lint1/tree.c:1.330	Tue Aug  3 21:09:26 2021
+++ src/usr.bin/xlint/lint1/tree.c	Mon Aug  9 20:07:23 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: tree.c,v 1.330 2021/08/03 21:09:26 rillig Exp $	*/
+/*	$NetBSD: tree.c,v 1.331 2021/08/09 20:07:23 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: tree.c,v 1.330 2021/08/03 21:09:26 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.331 2021/08/09 20:07:23 rillig Exp $");
 #endif
 
 #include <float.h>
@@ -1346,6 +1346,63 @@ check_pointer_comparison(op_t op, const 
 	}
 }
 
+static bool
+is_direct_function_call(const tnode_t *tn, const char *name)
+{
+	return tn->tn_op == CALL &&
+	       tn->tn_left->tn_op == ADDR &&
+	       tn->tn_left->tn_left->tn_op == NAME &&
+	       strcmp(tn->tn_left->tn_left->tn_sym->s_name, name) == 0;
+}
+
+static bool
+is_const_char_pointer(const tnode_t *tn)
+{
+	const type_t *tp;
+
+	/*
+	 * For traditional reasons, C99 6.4.5p5 defines that string literals
+	 * have type 'char[]'.  They are often implicitly converted to
+	 * 'char *', for example when they are passed as function arguments.
+	 *
+	 * C99 6.4.5p6 further defines that modifying a string that is
+	 * constructed from a string literal invokes undefined behavior.
+	 *
+	 * Out of these reasons, string literals are treated as 'effectively
+	 * const' here.
+	 */
+	if (tn->tn_op == CVT &&
+	    tn->tn_left->tn_op == ADDR &&
+	    tn->tn_left->tn_left->tn_op == STRING)
+		return true;
+
+	tp = before_conversion(tn)->tn_type;
+	return tp->t_tspec == PTR &&
+	       tp->t_subt->t_tspec == CHAR &&
+	       tp->t_subt->t_const;
+}
+
+static bool
+is_strchr_arg_const(const tnode_t *tn)
+{
+	return tn->tn_right->tn_op == PUSH &&
+	       tn->tn_right->tn_right->tn_op == PUSH &&
+	       tn->tn_right->tn_right->tn_right == NULL &&
+	       is_const_char_pointer(tn->tn_right->tn_right->tn_left);
+}
+
+static void
+check_unconst_strchr(const type_t *lstp,
+		     const tnode_t *rn, const type_t *rstp)
+{
+	if (lstp->t_tspec == CHAR && !lstp->t_const &&
+	    is_direct_function_call(rn, "strchr") &&
+	    is_strchr_arg_const(rn)) {
+		/* call to '%s' effectively discards 'const' from argument */
+		warning(346, "strchr");
+	}
+}
+
 /*
  * Checks type compatibility for ASSIGN, INIT, FARG and RETURN
  * and prints warnings/errors if necessary.
@@ -1429,6 +1486,10 @@ check_assign_types_compatible(op_t op, i
 				break;
 			}
 		}
+
+		if (!tflag)
+			check_unconst_strchr(lstp, rn, rstp);
+
 		return true;
 	}
 

Added files:

Index: src/tests/usr.bin/xlint/lint1/msg_346.c
diff -u /dev/null src/tests/usr.bin/xlint/lint1/msg_346.c:1.1
--- /dev/null	Mon Aug  9 20:07:24 2021
+++ src/tests/usr.bin/xlint/lint1/msg_346.c	Mon Aug  9 20:07:24 2021
@@ -0,0 +1,32 @@
+/*	$NetBSD: msg_346.c,v 1.1 2021/08/09 20:07:24 rillig Exp $	*/
+# 3 "msg_346.c"
+
+// Test for message: call to '%s' effectively discards 'const' from argument [346]
+
+char *strchr(const char *, int);
+
+void take_const_char_ptr(const char *);
+void take_char_ptr(char *);
+
+void
+example(void)
+{
+	const char *ccp = "const char *";
+	char *cp = "char *";
+
+	ccp = strchr(ccp, 'c');
+	ccp = strchr(cp, 'c');
+	/* expect+1: warning: call to 'strchr' effectively discards 'const' from argument [346] */
+	cp = strchr(ccp, 'c');
+	cp = strchr(cp, 'c');
+
+	take_const_char_ptr(strchr(ccp, 'c'));
+	take_const_char_ptr(strchr(cp, 'c'));
+	/* expect+1: warning: call to 'strchr' effectively discards 'const' from argument [346] */
+	take_char_ptr(strchr(ccp, 'c'));
+	take_char_ptr(strchr(cp, 'c'));
+
+	take_const_char_ptr(strchr("literal", 'c'));
+	/* expect+1: warning: call to 'strchr' effectively discards 'const' from argument [346] */
+	take_char_ptr(strchr("literal", 'c'));
+}
Index: src/tests/usr.bin/xlint/lint1/msg_346.exp
diff -u /dev/null src/tests/usr.bin/xlint/lint1/msg_346.exp:1.1
--- /dev/null	Mon Aug  9 20:07:24 2021
+++ src/tests/usr.bin/xlint/lint1/msg_346.exp	Mon Aug  9 20:07:24 2021
@@ -0,0 +1,3 @@
+msg_346.c(20): warning: call to 'strchr' effectively discards 'const' from argument [346]
+msg_346.c(26): warning: call to 'strchr' effectively discards 'const' from argument [346]
+msg_346.c(31): warning: call to 'strchr' effectively discards 'const' from argument [346]

Reply via email to