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