tautological-unsigned-enum-zero-compare.cpp
4.5 KB
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
// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-linux-gnu -fsyntax-only \
// RUN: -Wtautological-unsigned-enum-zero-compare \
// RUN: -verify=unsigned,unsigned-signed %s
// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only \
// RUN: -Wtautological-unsigned-enum-zero-compare \
// RUN: -verify=unsigned-signed %s
// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only \
// RUN: -verify=silence %s
// silence-no-diagnostics
int main() {
// On Windows, all enumerations have a fixed underlying type, which is 'int'
// if not otherwise specified, so A is identical to C on Windows. Otherwise,
// we follow the C++ rules, which say that the only valid values of A are 0
// and 1.
enum A { A_foo = 0, A_bar, };
enum A a;
enum B : unsigned { B_foo = 0, B_bar, };
enum B b;
enum C : signed { C_foo = 0, C_bar, };
enum C c;
if (a < 0) // unsigned-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0 >= a)
return 0;
if (a > 0)
return 0;
if (0 <= a) // unsigned-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (a <= 0)
return 0;
if (0 > a) // unsigned-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
if (a >= 0) // unsigned-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0 < a)
return 0;
// FIXME: As below, the issue here is that the enumeration is promoted to
// unsigned.
if (a < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0U >= a)
return 0;
if (a > 0U)
return 0;
if (0U <= a) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (a <= 0U)
return 0;
if (0U > a) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
if (a >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0U < a)
return 0;
if (b < 0) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0 >= b)
return 0;
if (b > 0)
return 0;
if (0 <= b) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (b <= 0)
return 0;
if (0 > b) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
if (b >= 0) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0 < b)
return 0;
if (b < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0U >= b)
return 0;
if (b > 0U)
return 0;
if (0U <= b) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (b <= 0U)
return 0;
if (0U > b) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
if (b >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0U < b)
return 0;
if (c < 0)
return 0;
if (0 >= c)
return 0;
if (c > 0)
return 0;
if (0 <= c)
return 0;
if (c <= 0)
return 0;
if (0 > c)
return 0;
if (c >= 0)
return 0;
if (0 < c)
return 0;
// FIXME: These diagnostics are terrible. The issue here is that the signed
// enumeration value was promoted to an unsigned type.
if (c < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0U >= c)
return 0;
if (c > 0U)
return 0;
if (0U <= c) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (c <= 0U)
return 0;
if (0U > c) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
if (c >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0U < c)
return 0;
return 1;
}
namespace crash_enum_zero_width {
int test() {
enum A : unsigned {
A_foo = 0
};
enum A a;
// used to crash in llvm::APSInt::getMaxValue()
if (a < 0) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
return 1;
}
} // namespace crash_enum_zero_width