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