1 // RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-linux-gnu -fsyntax-only \
2 // RUN:            -Wtautological-unsigned-enum-zero-compare \
3 // RUN:            -verify=unsigned,unsigned-signed %s
4 // RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only \
5 // RUN:            -Wtautological-unsigned-enum-zero-compare \
6 // RUN:            -verify=unsigned-signed %s
7 // RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only \
8 // RUN:            -verify=silence %s
9 
10 // silence-no-diagnostics
11 
main()12 int main() {
13   // On Windows, all enumerations have a fixed underlying type, which is 'int'
14   // if not otherwise specified, so A is identical to C on Windows. Otherwise,
15   // we follow the C++ rules, which say that the only valid values of A are 0
16   // and 1.
17   enum A { A_foo = 0, A_bar, };
18   enum A a;
19 
20   enum B : unsigned { B_foo = 0, B_bar, };
21   enum B b;
22 
23   enum C : signed { C_foo = 0, C_bar, };
24   enum C c;
25 
26   if (a < 0) // unsigned-warning {{comparison of unsigned enum expression < 0 is always false}}
27     return 0;
28   if (0 >= a)
29     return 0;
30   if (a > 0)
31     return 0;
32   if (0 <= a) // unsigned-warning {{comparison of 0 <= unsigned enum expression is always true}}
33     return 0;
34   if (a <= 0)
35     return 0;
36   if (0 > a) // unsigned-warning {{comparison of 0 > unsigned enum expression is always false}}
37     return 0;
38   if (a >= 0) // unsigned-warning {{comparison of unsigned enum expression >= 0 is always true}}
39     return 0;
40   if (0 < a)
41     return 0;
42 
43   // FIXME: As below, the issue here is that the enumeration is promoted to
44   // unsigned.
45   if (a < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
46     return 0;
47   if (0U >= a)
48     return 0;
49   if (a > 0U)
50     return 0;
51   if (0U <= a) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
52     return 0;
53   if (a <= 0U)
54     return 0;
55   if (0U > a) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
56     return 0;
57   if (a >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
58     return 0;
59   if (0U < a)
60     return 0;
61 
62   if (b < 0) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
63     return 0;
64   if (0 >= b)
65     return 0;
66   if (b > 0)
67     return 0;
68   if (0 <= b) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
69     return 0;
70   if (b <= 0)
71     return 0;
72   if (0 > b) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
73     return 0;
74   if (b >= 0) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
75     return 0;
76   if (0 < b)
77     return 0;
78 
79   if (b < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
80     return 0;
81   if (0U >= b)
82     return 0;
83   if (b > 0U)
84     return 0;
85   if (0U <= b) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
86     return 0;
87   if (b <= 0U)
88     return 0;
89   if (0U > b) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
90     return 0;
91   if (b >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
92     return 0;
93   if (0U < b)
94     return 0;
95 
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   if (c <= 0)
105     return 0;
106   if (0 > c)
107     return 0;
108   if (c >= 0)
109     return 0;
110   if (0 < c)
111     return 0;
112 
113   // FIXME: These diagnostics are terrible. The issue here is that the signed
114   // enumeration value was promoted to an unsigned type.
115   if (c < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
116     return 0;
117   if (0U >= c)
118     return 0;
119   if (c > 0U)
120     return 0;
121   if (0U <= c) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
122     return 0;
123   if (c <= 0U)
124     return 0;
125   if (0U > c) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
126     return 0;
127   if (c >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
128     return 0;
129   if (0U < c)
130     return 0;
131 
132   return 1;
133 }
134 
135 namespace crash_enum_zero_width {
test()136 int test() {
137   enum A : unsigned {
138     A_foo = 0
139   };
140   enum A a;
141 
142   // used to crash in llvm::APSInt::getMaxValue()
143   if (a < 0) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
144     return 0;
145 
146   return 1;
147 }
148 } // namespace crash_enum_zero_width
149