Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/xlint/lint1 lint: warn about 'char * = strchr(const ...



details:   https://anonhg.NetBSD.org/src/rev/499096cb533f
branches:  trunk
changeset: 1022852:499096cb533f
user:      rillig <rillig%NetBSD.org@localhost>
date:      Mon Aug 09 20:07:23 2021 +0000

description:
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'.

diffstat:

 distrib/sets/lists/tests/mi           |   4 +-
 tests/usr.bin/xlint/lint1/Makefile    |   4 +-
 tests/usr.bin/xlint/lint1/msg_346.c   |  32 +++++++++++++++++
 tests/usr.bin/xlint/lint1/msg_346.exp |   3 +
 usr.bin/xlint/lint1/err.c             |   5 +-
 usr.bin/xlint/lint1/tree.c            |  65 +++++++++++++++++++++++++++++++++-
 6 files changed, 106 insertions(+), 7 deletions(-)

diffs (193 lines):

diff -r 3b7cf6b26a0e -r 499096cb533f distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi       Mon Aug 09 19:57:57 2021 +0000
+++ b/distrib/sets/lists/tests/mi       Mon Aug 09 20:07:23 2021 +0000
@@ -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
diff -r 3b7cf6b26a0e -r 499096cb533f tests/usr.bin/xlint/lint1/Makefile
--- a/tests/usr.bin/xlint/lint1/Makefile        Mon Aug 09 19:57:57 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/Makefile        Mon Aug 09 20:07:23 2021 +0000
@@ -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>
 
diff -r 3b7cf6b26a0e -r 499096cb533f tests/usr.bin/xlint/lint1/msg_346.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_346.c       Mon Aug 09 20:07:23 2021 +0000
@@ -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'));
+}
diff -r 3b7cf6b26a0e -r 499096cb533f tests/usr.bin/xlint/lint1/msg_346.exp
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_346.exp     Mon Aug 09 20:07:23 2021 +0000
@@ -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]
diff -r 3b7cf6b26a0e -r 499096cb533f usr.bin/xlint/lint1/err.c
--- a/usr.bin/xlint/lint1/err.c Mon Aug 09 19:57:57 2021 +0000
+++ b/usr.bin/xlint/lint1/err.c Mon Aug 09 20:07:23 2021 +0000
@@ -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 @@
        "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 {
diff -r 3b7cf6b26a0e -r 499096cb533f usr.bin/xlint/lint1/tree.c
--- a/usr.bin/xlint/lint1/tree.c        Mon Aug 09 19:57:57 2021 +0000
+++ b/usr.bin/xlint/lint1/tree.c        Mon Aug 09 20:07:23 2021 +0000
@@ -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 @@
        }
 }
 
+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 @@
                                break;
                        }
                }
+
+               if (!tflag)
+                       check_unconst_strchr(lstp, rn, rstp);
+
                return true;
        }
 



Home | Main Index | Thread Index | Old Index