/*      $NetBSD: msg_348.c,v 1.12 2024/10/31 10:32:08 rillig Exp $      */
# 3 "msg_348.c"

// Test for message: maximum value %d for '%s' of type '%s' does not match maximum array index %d [348]

/* lint1-extra-flags: -r -X 351 */

enum color {
       red,
       green,
       /* expect+5: previous declaration of 'blue' [260] */
       /* expect+4: previous declaration of 'blue' [260] */
       /* expect+3: previous declaration of 'blue' [260] */
       /* expect+2: previous declaration of 'blue' [260] */
       /* expect+1: previous declaration of 'blue' [260] */
       blue
};

const char *
color_name(enum color color)
{
       static const char *name[] = {
           "red",
           "green",
           "blue"
       };
       /* No warning since the maximum enum value equals the maximum array index. */
       return name[color];
}

const char *
color_name_too_few(enum color color)
{
       static const char *name[] = {
           "red",
           "green"
       };
       /* expect+1: warning: maximum value 2 for 'blue' of type '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 for 'blue' of type '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 plain identifier. */
       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 plain
        * identifier.
        */
       return name[(enum color)(c + 1)];
}

const char *
color_name_explicit_cast_to_int(enum color color)
{
       static const char *name[] = {
           "red",
           "green",
       };
       /* No warning due to the explicit cast. */
       return name[(int)color];
}

const char *
color_name_computed_pointer(enum color color, const char *name)
{
       /*
        * No warning since the first operand of the selection expression
        * is '(&name)', whose type is not an array but instead a
        * 'pointer to pointer to const char'.
        */
       return (&name)[color];
}

/*
* If the accessed array has character type, it may contain a trailing null
* character.
*/
void
color_initial_letter(enum color color)
{
       static const char len_2_null[] = "RG";
       static const char len_3_null[] = "RGB";
       static const char len_4_null[] = "RGB_";

       static const char len_2_of_3[3] = "RG";
       static const char len_3_of_3[3] = "RGB";
       static const char len_4_of_4[4] = "RGB_";

       /* TODO: array is too short */
       if (len_2_null[color] != '\0')
               return;

       /* FIXME: lint should not warn since the maximum usable array index is 2 */
       /* expect+1: warning: maximum value 2 for 'blue' of type 'enum color' does not match maximum array index 3 [348] */
       if (len_3_null[color] != '\0')
               return;

       /* FIXME: lint should not warn since the maximum usable array index is 3, not 4 */
       /* expect+1: warning: maximum value 2 for 'blue' of type 'enum color' does not match maximum array index 4 [348] */
       if (len_4_null[color] != '\0')
               return;

       /*
        * The array has 3 elements, as expected.  If lint were to inspect
        * the content of the array, it could see that [2] is a null
        * character.  That null character may be intended though.
        */
       if (len_2_of_3[color] != '\0')
               return;

       if (len_3_of_3[color] != '\0')
               return;

       /* expect+1: warning: maximum value 2 for 'blue' of type 'enum color' does not match maximum array index 3 [348] */
       if (len_4_of_4[color])
               return;
}

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: constant -0x10000000000 too large for 'int' [56] */
       min = -1LL << 40,
       /* expect+1: warning: constant 0x10000000000 too large for 'int' [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];
}

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 word 'num' in the last enum constant
        * MAY indicate a convenience constant for the total number of
        * values, instead of a regular enum value.
        */
       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];
}

enum uppercase_max {
       M_FIRST,
       M_SECOND,
       M_MAX
};

const char *
uppercase_max_name(enum uppercase_max x)
{
       static const char *const name[] = { "first", "second" };
       return name[x];
}

enum lowercase_max {
       M_first,
       M_second,
       M_max
};

const char *
lowercase_max_name(enum lowercase_max x)
{
       static const char *const name[] = { "first", "second" };
       return name[x];
}

enum uppercase_n {
       UPPERCASE_N_FIRST,
       UPPERCASE_N_LAST,
       N_UPPERCASE_N,
};

const char*
uppercase_n_name(enum uppercase_n x)
{
       static const char *const name[] = { "first", "last" };
       return name[x];
}