1/*	$NetBSD: msg_130.c,v 1.16 2023/03/28 14:44:34 rillig Exp $	*/
2# 3 "msg_130.c"
3
4// Test for message: enum type mismatch: '%s' '%s' '%s' [130]
5
6/* See also msg_241.c, which covers unusual operators on enums. */
7
8/* lint1-extra-flags: -X 351 */
9
10enum color {
11	RED	= 1 << 0,
12	GREEN	= 1 << 1,
13	BLUE	= 1 << 2
14};
15
16enum size {
17	SMALL,
18	MEDIUM,
19	LARGE
20};
21
22enum daytime {
23	NIGHT, MORNING, NOON, EVENING
24};
25
26void sink(_Bool);
27
28void
29example(_Bool cond, enum color c, enum size s)
30{
31	/* expect+1: warning: enum type mismatch: 'enum color' ':' 'enum daytime' [130] */
32	sink(cond ? GREEN : MORNING);
33	/* expect+1: warning: enum type mismatch: 'enum color' '!=' 'enum size' [130] */
34	sink(c != s);
35	/* expect+1: warning: enum type mismatch: 'enum color' '==' 'enum size' [130] */
36	sink(c == s);
37	sink((c & MEDIUM) != 0);	/* might be useful to warn about */
38	sink((c | MEDIUM) != 0);	/* might be useful to warn about */
39
40	c |= MEDIUM;			/* might be useful to warn about */
41	c &= MEDIUM;			/* might be useful to warn about */
42
43	/* The cast to unsigned is required by GCC at WARNS=6. */
44	c &= ~(unsigned)MEDIUM;		/* might be useful to warn about */
45}
46
47void
48switch_example(enum color c)
49{
50	switch (c) {
51	case EVENING:			/* maybe someday expect: 130 */
52	case LARGE:			/* maybe someday expect: 130 */
53	case 0:				/* maybe someday expect: 130 */
54		sink(1 == 1);
55		break;
56	default:
57		break;
58	}
59}
60
61/*
62 * Unnamed enum types can be used as a container for constants, especially
63 * since in C90 and C99, even after the declaration 'static const int x = 3',
64 * 'x' is not a constant expression.
65 */
66enum {
67	sizeof_int = sizeof(int),
68	sizeof_short = sizeof(short)
69};
70
71enum {
72	sizeof_uint = sizeof(unsigned int)
73};
74
75int
76enum_constant_from_unnamed_type(int x)
77{
78	/* using an enum constant as constant-expression */
79	switch (x) {
80	case sizeof_int:
81		return 1;
82	case sizeof_short:
83		return 2;
84	default:
85		break;
86	}
87
88	if (x == sizeof_int)
89		return 4;
90	if (x > sizeof_int)
91		return 5;
92
93	/* FIXME */
94	/* expect+1: warning: enum type mismatch: 'enum <unnamed>' '==' 'enum <unnamed>' [130] */
95	if (sizeof_int == sizeof_uint)
96		return 6;
97
98	/* expect+1: warning: statement not reached [193] */
99	return 0;
100}
101
102/*
103 * A typical legitimate use case for an anonymous enum type that should not
104 * be mixed with other types is a state machine.
105 *
106 * This example demonstrates that the type of the 'switch' expression can be
107 * an anonymous enum.
108 */
109void
110state_machine(const char *str)
111{
112	enum {
113		begin,
114		seen_letter,
115		seen_letter_digit,
116		error
117	} state = begin;
118
119	for (const char *p = str; *p != '\0'; p++) {
120		switch (state) {
121		case begin:
122			state = *p == 'A' ? seen_letter : error;
123			break;
124		case seen_letter:
125			state = *p == '1' ? seen_letter_digit : error;
126			break;
127		default:
128			state = error;
129		}
130	}
131
132	if (state == 2)			/* might be worth a warning */
133		return;
134	/* expect+1: warning: enum type mismatch: 'enum <unnamed>' '==' 'enum <unnamed>' [130] */
135	if (state == sizeof_int)
136		return;
137}
138
139/*
140 * For check_case_label_enum, a warning only makes sense if the type of the
141 * enum can actually be specified somehow, either explicitly by using a tag
142 * name or a typedef name, or implicitly by using a variable in a switch
143 * expression.
144 */
145
146typedef enum {
147	has_typedef = 1001
148} typedef_name;
149
150enum tag_name {
151	has_tag = 1002
152};
153
154enum {
155	has_variable = 1003
156} variable;
157
158enum {
159	inaccessible = 1004
160};
161
162/*
163 * This check is already done by Clang, so it may not be necessary to add it
164 * to lint as well.  Except if there are some cases that Clang didn't
165 * implement.
166 */
167void
168test_check_case_label_enum(enum color color)
169{
170	switch (color)
171	{
172	case has_typedef:
173	case has_tag:
174	case has_variable:
175	case inaccessible:
176		return;
177	}
178}
179