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]