Module Name:    src
Committed By:   rillig
Date:           Sat Oct 30 22:04:42 UTC 2021

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

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.1161 -r1.1162 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.113 -r1.114 src/tests/usr.bin/xlint/lint1/Makefile
cvs rdiff -u -r1.6 -r1.7 src/tests/usr.bin/xlint/lint1/msg_241.c
cvs rdiff -u -r0 -r1.1 src/tests/usr.bin/xlint/lint1/msg_348.c \
    src/tests/usr.bin/xlint/lint1/msg_348.exp
cvs rdiff -u -r1.146 -r1.147 src/usr.bin/xlint/lint1/err.c
cvs rdiff -u -r1.385 -r1.386 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.1161 src/distrib/sets/lists/tests/mi:1.1162
--- src/distrib/sets/lists/tests/mi:1.1161	Sat Oct 23 21:45:14 2021
+++ src/distrib/sets/lists/tests/mi	Sat Oct 30 22:04:42 2021
@@ -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

Index: src/tests/usr.bin/xlint/lint1/Makefile
diff -u src/tests/usr.bin/xlint/lint1/Makefile:1.113 src/tests/usr.bin/xlint/lint1/Makefile:1.114
--- src/tests/usr.bin/xlint/lint1/Makefile:1.113	Sun Sep 26 03:17:59 2021
+++ src/tests/usr.bin/xlint/lint1/Makefile	Sat Oct 30 22:04:42 2021
@@ -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>
 

Index: src/tests/usr.bin/xlint/lint1/msg_241.c
diff -u src/tests/usr.bin/xlint/lint1/msg_241.c:1.6 src/tests/usr.bin/xlint/lint1/msg_241.c:1.7
--- src/tests/usr.bin/xlint/lint1/msg_241.c:1.6	Mon Aug 16 20:11:03 2021
+++ src/tests/usr.bin/xlint/lint1/msg_241.c	Sat Oct 30 22:04:42 2021
@@ -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 @@ cover_typeok_enum(enum color c, int i)
 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 */

Index: src/usr.bin/xlint/lint1/err.c
diff -u src/usr.bin/xlint/lint1/err.c:1.146 src/usr.bin/xlint/lint1/err.c:1.147
--- src/usr.bin/xlint/lint1/err.c:1.146	Sat Oct  9 21:56:12 2021
+++ src/usr.bin/xlint/lint1/err.c	Sat Oct 30 22:04:42 2021
@@ -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 @@ const char *const msgs[] = {
 	"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 {

Index: src/usr.bin/xlint/lint1/tree.c
diff -u src/usr.bin/xlint/lint1/tree.c:1.385 src/usr.bin/xlint/lint1/tree.c:1.386
--- src/usr.bin/xlint/lint1/tree.c:1.385	Sat Oct  9 21:56:12 2021
+++ src/usr.bin/xlint/lint1/tree.c	Sat Oct 30 22:04:42 2021
@@ -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 @@ check_enum_int_mismatch(op_t op, int arg
 	}
 }
 
+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 @@ build_plus_minus(op_t op, tnode_t *ln, t
 		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)

Added files:

Index: src/tests/usr.bin/xlint/lint1/msg_348.c
diff -u /dev/null src/tests/usr.bin/xlint/lint1/msg_348.c:1.1
--- /dev/null	Sat Oct 30 22:04:43 2021
+++ src/tests/usr.bin/xlint/lint1/msg_348.c	Sat Oct 30 22:04:42 2021
@@ -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];
+}
Index: src/tests/usr.bin/xlint/lint1/msg_348.exp
diff -u /dev/null src/tests/usr.bin/xlint/lint1/msg_348.exp:1.1
--- /dev/null	Sat Oct 30 22:04:43 2021
+++ src/tests/usr.bin/xlint/lint1/msg_348.exp	Sat Oct 30 22:04:42 2021
@@ -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]

Reply via email to