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]