1/*	$NetBSD: msg_348.c,v 1.10 2024/03/01 17:22:55 rillig Exp $	*/
2# 3 "msg_348.c"
3
4// Test for message: maximum value %d of '%s' does not match maximum array index %d [348]
5
6/* lint1-extra-flags: -r -X 351 */
7
8enum color {
9	red,
10	green,
11	/* expect+5: previous declaration of 'blue' [260] */
12	/* expect+4: previous declaration of 'blue' [260] */
13	/* expect+3: previous declaration of 'blue' [260] */
14	/* expect+2: previous declaration of 'blue' [260] */
15	/* expect+1: previous declaration of 'blue' [260] */
16	blue
17};
18
19const char *
20color_name(enum color color)
21{
22	static const char *name[] = {
23	    "red",
24	    "green",
25	    "blue"
26	};
27	/* No warning since the maximum enum value matches the array size. */
28	return name[color];
29}
30
31const char *
32color_name_too_few(enum color color)
33{
34	static const char *name[] = {
35	    "red",
36	    "green"
37	};
38	/* expect+1: warning: maximum value 2 of 'enum color' does not match maximum array index 1 [348] */
39	return name[color];
40}
41
42const char *
43color_name_too_many(enum color color)
44{
45	static const char *name[] = {
46	    "red",
47	    "green",
48	    "blue",
49	    "black"
50	};
51	/* expect+1: warning: maximum value 2 of 'enum color' does not match maximum array index 3 [348] */
52	return name[color];
53}
54
55const char *
56color_name_computed_index(enum color color)
57{
58	static const char *name[] = {
59	    "unused",
60	    "red",
61	    "green",
62	    "blue"
63	};
64	/* No warning since the array index is not a plain identifier. */
65	return name[color + 1];
66}
67
68const char *
69color_name_cast_from_int(int c)
70{
71	static const char *name[] = {
72	    "unused",
73	    "red",
74	    "green",
75	    "blue"
76	};
77	/*
78	 * No warning since the array index before conversion is not a plain
79	 * identifier.
80	 */
81	return name[(enum color)(c + 1)];
82}
83
84const char *
85color_name_explicit_cast_to_int(enum color color)
86{
87	static const char *name[] = {
88	    "red",
89	    "green",
90	};
91	/* No warning due to the explicit cast. */
92	return name[(int)color];
93}
94
95const char *
96color_name_computed_pointer(enum color color, const char *name)
97{
98	/*
99	 * No warning since the first operand of the selection expression
100	 * is '(&name)', whose type is not an array but instead a
101	 * 'pointer to pointer to const char'.
102	 */
103	return (&name)[color];
104}
105
106/*
107 * If the accessed array has character type, it may contain a trailing null
108 * character.
109 */
110void
111color_initial_letter(enum color color)
112{
113	static const char len_2_null[] = "RG";
114	static const char len_3_null[] = "RGB";
115	static const char len_4_null[] = "RGB_";
116
117	static const char len_2_of_3[3] = "RG";
118	static const char len_3_of_3[3] = "RGB";
119	static const char len_4_of_4[4] = "RGB_";
120
121	/* TODO: array is too short */
122	if (len_2_null[color] != '\0')
123		return;
124
125	/* FIXME: lint should not warn since the maximum usable array index is 2 */
126	/* expect+1: warning: maximum value 2 of 'enum color' does not match maximum array index 3 [348] */
127	if (len_3_null[color] != '\0')
128		return;
129
130	/* FIXME: lint should not warn since the maximum usable array index is 3, not 4 */
131	/* expect+1: warning: maximum value 2 of 'enum color' does not match maximum array index 4 [348] */
132	if (len_4_null[color] != '\0')
133		return;
134
135	/*
136	 * The array has 3 elements, as expected.  If lint were to inspect
137	 * the content of the array, it could see that [2] is a null
138	 * character.  That null character may be intended though.
139	 */
140	if (len_2_of_3[color] != '\0')
141		return;
142
143	if (len_3_of_3[color] != '\0')
144		return;
145
146	/* expect+1: warning: maximum value 2 of 'enum color' does not match maximum array index 3 [348] */
147	if (len_4_of_4[color])
148		return;
149}
150
151extern const char *incomplete_color_name[];
152
153const char *
154color_name_incomplete_array(enum color color)
155{
156	/* No warning since 'incomplete_color_name' is incomplete. */
157	return incomplete_color_name[color];
158}
159
160enum large {
161	/* expect+1: warning: integral constant too large [56] */
162	min = -1LL << 40,
163	/* expect+1: warning: integral constant too large [56] */
164	max = 1LL << 40,
165	zero = 0
166};
167
168const char *
169large_name(enum large large)
170{
171	static const char *name[] = {
172	    "dummy",
173	};
174	/* No warning since at least 1 enum constant is outside of INT. */
175	return name[large];
176}
177
178enum color_with_count {
179	cc_red,
180	cc_green,
181	cc_blue,
182	cc_num_values
183};
184
185const char *
186color_with_count_name(enum color_with_count color)
187{
188	static const char *const name[] = { "red", "green", "blue" };
189	/*
190	 * No warning since the word 'num' in the last enum constant
191	 * MAY indicate a convenience constant for the total number of
192	 * values, instead of a regular enum value.
193	 */
194	return name[color];
195}
196
197/*
198 * If the last enum constant contains "num" in its name, it is not
199 * necessarily the count of the other enum values, it may also be a
200 * legitimate application value, therefore don't warn in this case.
201 */
202const char *
203color_with_num(enum color_with_count color)
204{
205	static const char *const name[] = { "r", "g", "b", "num" };
206	/* No warning since the maximum values already match. */
207	return name[color];
208}
209
210enum color_with_uc_count {
211	CC_RED,
212	CC_GREEN,
213	CC_BLUE,
214	CC_NUM_VALUES
215};
216
217const char *
218color_with_uc_count_name(enum color_with_uc_count color)
219{
220	static const char *const name[] = { "red", "green", "blue" };
221	/* No warning since the maximum enum constant is a count. */
222	return name[color];
223}
224
225enum uppercase_max {
226	M_FIRST,
227	M_SECOND,
228	M_MAX
229};
230
231const char *
232uppercase_max_name(enum uppercase_max x)
233{
234	static const char *const name[] = { "first", "second" };
235	return name[x];
236}
237
238enum lowercase_max {
239	M_first,
240	M_second,
241	M_max
242};
243
244const char *
245lowercase_max_name(enum lowercase_max x)
246{
247	static const char *const name[] = { "first", "second" };
248	return name[x];
249}
250