1 // RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -verify %s
2 // RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -verify %s
3 // RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only -DSILENCE -Wno-tautological-unsigned-enum-zero-compare -verify %s
4 
5 int main() {
6   // On Windows, all enumerations have a fixed underlying type, which is 'int'
7   // if not otherwise specified, so A is identical to C on Windows. Otherwise,
8   // we follow the C++ rules, which say that the only valid values of A are 0
9   // and 1.
10   enum A { A_foo = 0, A_bar, };
11   enum A a;
12 
13   enum B : unsigned { B_foo = 0, B_bar, };
14   enum B b;
15 
16   enum C : signed { C_foo = 0, C_bar, };
17   enum C c;
18 
19 #ifdef UNSIGNED
20   if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
21     return 0;
22   if (0 >= a)
23     return 0;
24   if (a > 0)
25     return 0;
26   if (0 <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
27     return 0;
28   if (a <= 0)
29     return 0;
30   if (0 > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
31     return 0;
32   if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
33     return 0;
34   if (0 < a)
35     return 0;
36 
37   if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
38     return 0;
39   if (0U >= a)
40     return 0;
41   if (a > 0U)
42     return 0;
43   if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
44     return 0;
45   if (a <= 0U)
46     return 0;
47   if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
48     return 0;
49   if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
50     return 0;
51   if (0U < a)
52     return 0;
53 
54   if (b < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
55     return 0;
56   if (0 >= b)
57     return 0;
58   if (b > 0)
59     return 0;
60   if (0 <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
61     return 0;
62   if (b <= 0)
63     return 0;
64   if (0 > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
65     return 0;
66   if (b >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
67     return 0;
68   if (0 < b)
69     return 0;
70 
71   if (b < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
72     return 0;
73   if (0U >= b)
74     return 0;
75   if (b > 0U)
76     return 0;
77   if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
78     return 0;
79   if (b <= 0U)
80     return 0;
81   if (0U > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
82     return 0;
83   if (b >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
84     return 0;
85   if (0U < b)
86     return 0;
87 
88   if (c < 0)
89     return 0;
90   if (0 >= c)
91     return 0;
92   if (c > 0)
93     return 0;
94   if (0 <= c)
95     return 0;
96   if (c <= 0)
97     return 0;
98   if (0 > c)
99     return 0;
100   if (c >= 0)
101     return 0;
102   if (0 < c)
103     return 0;
104 
105   // FIXME: These diagnostics are terrible. The issue here is that the signed
106   // enumeration value was promoted to an unsigned type.
107   if (c < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
108     return 0;
109   if (0U >= c)
110     return 0;
111   if (c > 0U)
112     return 0;
113   if (0U <= c) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
114     return 0;
115   if (c <= 0U)
116     return 0;
117   if (0U > c) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
118     return 0;
119   if (c >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
120     return 0;
121   if (0U < c)
122     return 0;
123 #elif defined(SIGNED)
124   if (a < 0)
125     return 0;
126   if (0 >= a)
127     return 0;
128   if (a > 0)
129     return 0;
130   if (0 <= a)
131     return 0;
132   if (a <= 0)
133     return 0;
134   if (0 > a)
135     return 0;
136   if (a >= 0)
137     return 0;
138   if (0 < a)
139     return 0;
140 
141   // FIXME: As above, the issue here is that the enumeration is promoted to
142   // unsigned.
143   if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
144     return 0;
145   if (0U >= a)
146     return 0;
147   if (a > 0U)
148     return 0;
149   if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
150     return 0;
151   if (a <= 0U)
152     return 0;
153   if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
154     return 0;
155   if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
156     return 0;
157   if (0U < a)
158     return 0;
159 
160   if (b < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
161     return 0;
162   if (0 >= b)
163     return 0;
164   if (b > 0)
165     return 0;
166   if (0 <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
167     return 0;
168   if (b <= 0)
169     return 0;
170   if (0 > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
171     return 0;
172   if (b >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
173     return 0;
174   if (0 < b)
175     return 0;
176 
177   if (b < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
178     return 0;
179   if (0U >= b)
180     return 0;
181   if (b > 0U)
182     return 0;
183   if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
184     return 0;
185   if (b <= 0U)
186     return 0;
187   if (0U > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
188     return 0;
189   if (b >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
190     return 0;
191   if (0U < b)
192     return 0;
193 
194   if (c < 0)
195     return 0;
196   if (0 >= c)
197     return 0;
198   if (c > 0)
199     return 0;
200   if (0 <= c)
201     return 0;
202   if (c <= 0)
203     return 0;
204   if (0 > c)
205     return 0;
206   if (c >= 0)
207     return 0;
208   if (0 < c)
209     return 0;
210 
211   if (c < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
212     return 0;
213   if (0U >= c)
214     return 0;
215   if (c > 0U)
216     return 0;
217   if (0U <= c) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
218     return 0;
219   if (c <= 0U)
220     return 0;
221   if (0U > c) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
222     return 0;
223   if (c >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
224     return 0;
225   if (0U < c)
226     return 0;
227 #else
228   // expected-no-diagnostics
229   if (a < 0)
230     return 0;
231   if (0 >= a)
232     return 0;
233   if (a > 0)
234     return 0;
235   if (0 <= a)
236     return 0;
237   if (a <= 0)
238     return 0;
239   if (0 > a)
240     return 0;
241   if (a >= 0)
242     return 0;
243   if (0 < a)
244     return 0;
245 
246   if (a < 0U)
247     return 0;
248   if (0U >= a)
249     return 0;
250   if (a > 0U)
251     return 0;
252   if (0U <= a)
253     return 0;
254   if (a <= 0U)
255     return 0;
256   if (0U > a)
257     return 0;
258   if (a >= 0U)
259     return 0;
260   if (0U < a)
261     return 0;
262 
263   if (b < 0)
264     return 0;
265   if (0 >= b)
266     return 0;
267   if (b > 0)
268     return 0;
269   if (0 <= b)
270     return 0;
271   if (b <= 0)
272     return 0;
273   if (0 > b)
274     return 0;
275   if (b >= 0)
276     return 0;
277   if (0 < b)
278     return 0;
279 
280   if (b < 0U)
281     return 0;
282   if (0U >= b)
283     return 0;
284   if (b > 0U)
285     return 0;
286   if (0U <= b)
287     return 0;
288   if (b <= 0U)
289     return 0;
290   if (0U > b)
291     return 0;
292   if (b >= 0U)
293     return 0;
294   if (0U < b)
295     return 0;
296 
297   if (c < 0)
298     return 0;
299   if (0 >= c)
300     return 0;
301   if (c > 0)
302     return 0;
303   if (0 <= c)
304     return 0;
305   if (c <= 0)
306     return 0;
307   if (0 > c)
308     return 0;
309   if (c >= 0)
310     return 0;
311   if (0 < c)
312     return 0;
313 
314   if (c < 0U)
315     return 0;
316   if (0U >= c)
317     return 0;
318   if (c > 0U)
319     return 0;
320   if (0U <= c)
321     return 0;
322   if (c <= 0U)
323     return 0;
324   if (0U > c)
325     return 0;
326   if (c >= 0U)
327     return 0;
328   if (0U < c)
329     return 0;
330 #endif
331 
332   return 1;
333 }
334 
335 namespace crash_enum_zero_width {
336 int test() {
337   enum A : unsigned {
338     A_foo = 0
339   };
340   enum A a;
341 
342   // used to crash in llvm::APSInt::getMaxValue()
343 #ifndef SILENCE
344   if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
345 #else
346   if (a > 0)
347 #endif
348     return 0;
349 
350   return 1;
351 }
352 } // namespace crash_enum_zero_width
353