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 if an enum name is used for m...
details: https://anonhg.NetBSD.org/src/rev/a6d0141a96aa
branches: trunk
changeset: 1024677:a6d0141a96aa
user: rillig <rillig%NetBSD.org@localhost>
date: Sat Oct 30 22:04:42 2021 +0000
description:
lint: warn if an enum name is used for mismatched array access
This helps to keep the enum definition and the straight-forward
implementation of a to_string or name function in sync.
The test for message 241 had to be adjusted because of exactly this bug.
That test defined a bit mask enum but accessed it like a value enum
type.
diffstat:
distrib/sets/lists/tests/mi | 4 +-
tests/usr.bin/xlint/lint1/Makefile | 4 +-
tests/usr.bin/xlint/lint1/msg_241.c | 8 +-
tests/usr.bin/xlint/lint1/msg_348.c | 106 ++++++++++++++++++++++++++++++++++
tests/usr.bin/xlint/lint1/msg_348.exp | 4 +
usr.bin/xlint/lint1/err.c | 5 +-
usr.bin/xlint/lint1/tree.c | 43 +++++++++++++-
7 files changed, 165 insertions(+), 9 deletions(-)
diffs (268 lines):
diff -r a2e100e304cb -r a6d0141a96aa distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi Sat Oct 30 21:39:28 2021 +0000
+++ b/distrib/sets/lists/tests/mi Sat Oct 30 22:04:42 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1161 2021/10/23 21:45:14 rillig Exp $
+# $NetBSD: mi,v 1.1162 2021/10/30 22:04:42 rillig Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -7151,6 +7151,8 @@
./usr/tests/usr.bin/xlint/lint1/msg_346.exp tests-usr.bin-tests compattestfile,atf
./usr/tests/usr.bin/xlint/lint1/msg_347.c tests-usr.bin-tests compattestfile,atf
./usr/tests/usr.bin/xlint/lint1/msg_347.exp tests-usr.bin-tests compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/msg_348.c tests-usr.bin-tests compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/msg_348.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 a2e100e304cb -r a6d0141a96aa tests/usr.bin/xlint/lint1/Makefile
--- a/tests/usr.bin/xlint/lint1/Makefile Sat Oct 30 21:39:28 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/Makefile Sat Oct 30 22:04:42 2021 +0000
@@ -1,7 +1,7 @@
-# $NetBSD: Makefile,v 1.113 2021/09/26 03:17:59 rillig Exp $
+# $NetBSD: Makefile,v 1.114 2021/10/30 22:04:42 rillig Exp $
NOMAN= # defined
-MAX_MESSAGE= 347 # see lint1/err.c
+MAX_MESSAGE= 348 # see lint1/err.c
.include <bsd.own.mk>
diff -r a2e100e304cb -r a6d0141a96aa tests/usr.bin/xlint/lint1/msg_241.c
--- a/tests/usr.bin/xlint/lint1/msg_241.c Sat Oct 30 21:39:28 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_241.c Sat Oct 30 22:04:42 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: msg_241.c,v 1.6 2021/08/16 20:11:03 rillig Exp $ */
+/* $NetBSD: msg_241.c,v 1.7 2021/10/30 22:04:42 rillig Exp $ */
# 3 "msg_241.c"
// Test for message: dubious operation on enum, op %s [241]
@@ -86,7 +86,11 @@
const char *
color_name(enum color c)
{
- static const char *name[] = { "red", "green", "blue" };
+ static const char *name[] = {
+ [RED] = "red",
+ [GREEN] = "green",
+ [BLUE] = "blue",
+ };
if (c == RED)
return *(c + name); /* unusual but allowed */
diff -r a2e100e304cb -r a6d0141a96aa tests/usr.bin/xlint/lint1/msg_348.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_348.c Sat Oct 30 22:04:42 2021 +0000
@@ -0,0 +1,106 @@
+/* $NetBSD: msg_348.c,v 1.1 2021/10/30 22:04:42 rillig Exp $ */
+# 3 "msg_348.c"
+
+// Test for message 348: maximum value %d of '%s' does not match maximum array index %d [348]
+
+enum color {
+ red,
+ green,
+ blue
+};
+
+const char *
+color_name(enum color color)
+{
+ static const char *name[] = {
+ "red",
+ "green",
+ "blue"
+ };
+ /* No warning since the maximum enum value matches the array size. */
+ return name[color];
+}
+
+const char *
+color_name_too_few(enum color color)
+{
+ static const char *name[] = {
+ "red",
+ "green"
+ };
+ /* expect+1: warning: maximum value 2 of 'enum color' does not match maximum array index 1 [348] */
+ return name[color];
+}
+
+const char *
+color_name_too_many(enum color color)
+{
+ static const char *name[] = {
+ "red",
+ "green",
+ "blue",
+ "black"
+ };
+ /* expect+1: warning: maximum value 2 of 'enum color' does not match maximum array index 3 [348] */
+ return name[color];
+}
+
+const char *
+color_name_computed_index(enum color color)
+{
+ static const char *name[] = {
+ "unused",
+ "red",
+ "green",
+ "blue"
+ };
+ /* No warning since the array index is not a name. */
+ return name[color + 1];
+}
+
+const char *
+color_name_cast_from_int(int c)
+{
+ static const char *name[] = {
+ "unused",
+ "red",
+ "green",
+ "blue"
+ };
+ /* No warning since the array index before conversion is not a name. */
+ return name[(enum color)(c + 1)];
+}
+
+const char *
+color_name_computed_pointer(enum color color, const char *name)
+{
+ /* No warning since 'name' is not an array. */
+ return (&name)[color];
+}
+
+extern const char *incomplete_color_name[];
+
+const char *
+color_name_incomplete_array(enum color color)
+{
+ /* No warning since 'incomplete_color_name' is incomplete. */
+ return incomplete_color_name[color];
+}
+
+enum large {
+ /* expect+1: warning: integral constant too large [56] */
+ min = -1LL << 40,
+ /* expect+1: warning: integral constant too large [56] */
+ max = 1LL << 40,
+ zero = 0
+};
+
+const char *
+large_name(enum large large)
+{
+ static const char *name[] = {
+ "dummy",
+ };
+ /* No warning since at least 1 enum constant is outside of INT. */
+ return name[large];
+}
diff -r a2e100e304cb -r a6d0141a96aa tests/usr.bin/xlint/lint1/msg_348.exp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_348.exp Sat Oct 30 22:04:42 2021 +0000
@@ -0,0 +1,4 @@
+msg_348.c(32): warning: maximum value 2 of 'enum color' does not match maximum array index 1 [348]
+msg_348.c(45): warning: maximum value 2 of 'enum color' does not match maximum array index 3 [348]
+msg_348.c(92): warning: integral constant too large [56]
+msg_348.c(94): warning: integral constant too large [56]
diff -r a2e100e304cb -r a6d0141a96aa usr.bin/xlint/lint1/err.c
--- a/usr.bin/xlint/lint1/err.c Sat Oct 30 21:39:28 2021 +0000
+++ b/usr.bin/xlint/lint1/err.c Sat Oct 30 22:04:42 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: err.c,v 1.146 2021/10/09 21:56:12 rillig Exp $ */
+/* $NetBSD: err.c,v 1.147 2021/10/30 22:04:42 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.146 2021/10/09 21:56:12 rillig Exp $");
+__RCSID("$NetBSD: err.c,v 1.147 2021/10/30 22:04:42 rillig Exp $");
#endif
#include <sys/types.h>
@@ -402,6 +402,7 @@
"generic selection requires C11 or later", /* 345 */
"call to '%s' effectively discards 'const' from argument", /* 346 */
"redeclaration of '%s' with type '%s', expected '%s'", /* 347 */
+ "maximum value %d of '%s' does not match maximum array index %d", /* 348 */
};
static struct include_level {
diff -r a2e100e304cb -r a6d0141a96aa usr.bin/xlint/lint1/tree.c
--- a/usr.bin/xlint/lint1/tree.c Sat Oct 30 21:39:28 2021 +0000
+++ b/usr.bin/xlint/lint1/tree.c Sat Oct 30 22:04:42 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tree.c,v 1.385 2021/10/09 21:56:12 rillig Exp $ */
+/* $NetBSD: tree.c,v 1.386 2021/10/30 22:04:42 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.385 2021/10/09 21:56:12 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.386 2021/10/30 22:04:42 rillig Exp $");
#endif
#include <float.h>
@@ -1773,6 +1773,44 @@
}
}
+static void
+check_enum_array_index(const tnode_t *ln, const tnode_t *rn)
+{
+ int max_enum_value, max_array_index;
+ const struct sym *ec;
+
+ if (ln->tn_op != ADDR)
+ return;
+ if (ln->tn_left->tn_op != NAME)
+ return;
+ if (ln->tn_left->tn_type->t_tspec != ARRAY)
+ return;
+ if (ln->tn_left->tn_type->t_incomplete_array)
+ return;
+ if (rn->tn_op != CVT)
+ return;
+ if (rn->tn_left->tn_op != LOAD)
+ return;
+ if (rn->tn_left->tn_type->t_tspec != ENUM)
+ return;
+
+ max_enum_value = INT_MIN;
+ ec = rn->tn_type->t_enum->en_first_enumerator;
+ for (; ec != NULL; ec = ec->s_next) {
+ int64_t ev = ec->s_value.v_quad;
+ lint_assert(INT_MIN <= ev && ev <= INT_MAX);
+ if (ev > max_enum_value)
+ max_enum_value = (int)ev;
+ }
+
+ max_array_index = ln->tn_left->tn_type->t_dim - 1;
+ if (max_enum_value == max_array_index)
+ return;
+
+ /* maximum value %d of '%s' does not match maximum array index %d */
+ warning(348, max_enum_value, type_name(rn->tn_type), max_array_index);
+}
+
/*
* Build and initialize a new node.
*/
@@ -2863,6 +2901,7 @@
lint_assert(is_integer(rn->tn_type->t_tspec));
check_ctype_macro_invocation(ln, rn);
+ check_enum_array_index(ln, rn);
ctn = plength(ln->tn_type);
if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec)
Home |
Main Index |
Thread Index |
Old Index