Module Name: src Committed By: rillig Date: Mon Nov 1 11:46:50 UTC 2021
Modified Files: src/tests/usr.bin/xlint/lint1: msg_348.c msg_348.exp src/usr.bin/xlint/lint1: tree.c Log Message: lint: in the check for array[enum], allow enum constant NUM When an enum type defines a constant NUM_VALUES, this constant is usually not part of the enum values available to the application but rather a handy place for defining the number of other enum values. Don't warn about this case. Seen in openpam_impl.h and several other places. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/tests/usr.bin/xlint/lint1/msg_348.c \ src/tests/usr.bin/xlint/lint1/msg_348.exp cvs rdiff -u -r1.388 -r1.389 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/tests/usr.bin/xlint/lint1/msg_348.c diff -u src/tests/usr.bin/xlint/lint1/msg_348.c:1.2 src/tests/usr.bin/xlint/lint1/msg_348.c:1.3 --- src/tests/usr.bin/xlint/lint1/msg_348.c:1.2 Sun Oct 31 23:15:44 2021 +++ src/tests/usr.bin/xlint/lint1/msg_348.c Mon Nov 1 11:46:50 2021 @@ -1,11 +1,16 @@ -/* $NetBSD: msg_348.c,v 1.2 2021/10/31 23:15:44 rillig Exp $ */ +/* $NetBSD: msg_348.c,v 1.3 2021/11/01 11:46:50 rillig Exp $ */ # 3 "msg_348.c" // Test for message 348: maximum value %d of '%s' does not match maximum array index %d [348] +/* lint1-extra-flags: -r */ + enum color { red, green, + /* expect+3: previous declaration of blue [260] */ + /* expect+2: previous declaration of blue [260] */ + /* expect+1: previous declaration of blue [260] */ blue }; @@ -115,3 +120,46 @@ large_name(enum large large) /* No warning since at least 1 enum constant is outside of INT. */ return name[large]; } + +enum color_with_count { + cc_red, + cc_green, + cc_blue, + cc_num_values +}; + +const char * +color_with_count_name(enum color_with_count color) +{ + static const char *const name[] = { "red", "green", "blue" }; + /* No warning since the maximum enum constant is a count. */ + return name[color]; +} + +/* + * If the last enum constant contains "num" in its name, it is not + * necessarily the count of the other enum values, it may also be a + * legitimate application value, therefore don't warn in this case. + */ +const char * +color_with_num(enum color_with_count color) +{ + static const char *const name[] = { "r", "g", "b", "num" }; + /* No warning since the maximum values already match. */ + return name[color]; +} + +enum color_with_uc_count { + CC_RED, + CC_GREEN, + CC_BLUE, + CC_NUM_VALUES +}; + +const char * +color_with_uc_count_name(enum color_with_uc_count color) +{ + static const char *const name[] = { "red", "green", "blue" }; + /* No warning since the maximum enum constant is a count. */ + return name[color]; +} Index: src/tests/usr.bin/xlint/lint1/msg_348.exp diff -u src/tests/usr.bin/xlint/lint1/msg_348.exp:1.2 src/tests/usr.bin/xlint/lint1/msg_348.exp:1.3 --- src/tests/usr.bin/xlint/lint1/msg_348.exp:1.2 Sun Oct 31 23:15:44 2021 +++ src/tests/usr.bin/xlint/lint1/msg_348.exp Mon Nov 1 11:46:50 2021 @@ -1,5 +1,8 @@ -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(82): warning: maximum value 2 of 'enum color' does not match maximum array index 1 [348] -msg_348.c(103): warning: integral constant too large [56] -msg_348.c(105): warning: integral constant too large [56] +msg_348.c(37): warning: maximum value 2 of 'enum color' does not match maximum array index 1 [348] +msg_348.c(14): previous declaration of blue [260] +msg_348.c(50): warning: maximum value 2 of 'enum color' does not match maximum array index 3 [348] +msg_348.c(14): previous declaration of blue [260] +msg_348.c(87): warning: maximum value 2 of 'enum color' does not match maximum array index 1 [348] +msg_348.c(14): previous declaration of blue [260] +msg_348.c(108): warning: integral constant too large [56] +msg_348.c(110): warning: integral constant too large [56] Index: src/usr.bin/xlint/lint1/tree.c diff -u src/usr.bin/xlint/lint1/tree.c:1.388 src/usr.bin/xlint/lint1/tree.c:1.389 --- src/usr.bin/xlint/lint1/tree.c:1.388 Sun Oct 31 23:15:44 2021 +++ src/usr.bin/xlint/lint1/tree.c Mon Nov 1 11:46:50 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: tree.c,v 1.388 2021/10/31 23:15:44 rillig Exp $ */ +/* $NetBSD: tree.c,v 1.389 2021/11/01 11:46:50 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.388 2021/10/31 23:15:44 rillig Exp $"); +__RCSID("$NetBSD: tree.c,v 1.389 2021/11/01 11:46:50 rillig Exp $"); #endif #include <float.h> @@ -1776,8 +1776,9 @@ 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; + int max_array_index; + int64_t max_enum_value; + const struct sym *ec, *max_ec; if (ln->tn_op != ADDR) return; @@ -1794,22 +1795,34 @@ check_enum_array_index(const tnode_t *ln if (rn->tn_left->tn_type->t_tspec != ENUM) return; - max_enum_value = INT_MIN; ec = rn->tn_left->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_ec = ec; + lint_assert(ec != NULL); + for (ec = ec->s_next; ec != NULL; ec = ec->s_next) + if (ec->s_value.v_quad > max_ec->s_value.v_quad) + max_ec = ec; + + max_enum_value = max_ec->s_value.v_quad; + lint_assert(INT_MIN <= max_enum_value && max_enum_value <= INT_MAX); max_array_index = ln->tn_left->tn_type->t_dim - 1; if (max_enum_value == max_array_index) return; + /* + * If the largest enum constant is named '*_NUM_*', it is typically + * not part of the allowed enum values but a marker for the number + * of actual enum values. + */ + if (max_enum_value == max_array_index + 1 && + (strstr(max_ec->s_name, "NUM") != NULL || + strstr(max_ec->s_name, "num") != NULL)) + return; + /* maximum value %d of '%s' does not match maximum array index %d */ - warning(348, max_enum_value, type_name(rn->tn_left->tn_type), + warning(348, (int)max_enum_value, type_name(rn->tn_left->tn_type), max_array_index); + print_previous_declaration(-1, max_ec); } /*