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: in the check for array[enum], allo...



details:   https://anonhg.NetBSD.org/src/rev/658004e36d26
branches:  trunk
changeset: 990658:658004e36d26
user:      rillig <rillig%NetBSD.org@localhost>
date:      Mon Nov 01 11:46:50 2021 +0000

description:
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.

diffstat:

 tests/usr.bin/xlint/lint1/msg_348.c   |  50 ++++++++++++++++++++++++++++++++++-
 tests/usr.bin/xlint/lint1/msg_348.exp |  13 +++++---
 usr.bin/xlint/lint1/tree.c            |  37 +++++++++++++++++--------
 3 files changed, 82 insertions(+), 18 deletions(-)

diffs (158 lines):

diff -r 98155b55837c -r 658004e36d26 tests/usr.bin/xlint/lint1/msg_348.c
--- a/tests/usr.bin/xlint/lint1/msg_348.c       Mon Nov 01 10:05:18 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_348.c       Mon Nov 01 11:46:50 2021 +0000
@@ -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 @@
        /* 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];
+}
diff -r 98155b55837c -r 658004e36d26 tests/usr.bin/xlint/lint1/msg_348.exp
--- a/tests/usr.bin/xlint/lint1/msg_348.exp     Mon Nov 01 10:05:18 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/msg_348.exp     Mon Nov 01 11:46:50 2021 +0000
@@ -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]
diff -r 98155b55837c -r 658004e36d26 usr.bin/xlint/lint1/tree.c
--- a/usr.bin/xlint/lint1/tree.c        Mon Nov 01 10:05:18 2021 +0000
+++ b/usr.bin/xlint/lint1/tree.c        Mon Nov 01 11:46:50 2021 +0000
@@ -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 @@
 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 @@
        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);
 }
 
 /*



Home | Main Index | Thread Index | Old Index