1 // RUN: %clang_analyze_cc1 \
2 // RUN: -analyzer-checker=core,alpha.cplusplus.EnumCastOutOfRange \
3 // RUN: -std=c++11 -verify %s
4
5 enum unscoped_unspecified_t {
6 unscoped_unspecified_0 = -4,
7 unscoped_unspecified_1,
8 unscoped_unspecified_2 = 1,
9 unscoped_unspecified_3,
10 unscoped_unspecified_4 = 4
11 };
12
13 enum unscoped_specified_t : int {
14 unscoped_specified_0 = -4,
15 unscoped_specified_1,
16 unscoped_specified_2 = 1,
17 unscoped_specified_3,
18 unscoped_specified_4 = 4
19 };
20
21 enum class scoped_unspecified_t {
22 scoped_unspecified_0 = -4,
23 scoped_unspecified_1,
24 scoped_unspecified_2 = 1,
25 scoped_unspecified_3,
26 scoped_unspecified_4 = 4
27 };
28
29 enum class scoped_specified_t : int {
30 scoped_specified_0 = -4,
31 scoped_specified_1,
32 scoped_specified_2 = 1,
33 scoped_specified_3,
34 scoped_specified_4 = 4
35 };
36
37 struct S {
38 unscoped_unspecified_t E : 5;
39 };
40
unscopedUnspecified()41 void unscopedUnspecified() {
42 unscoped_unspecified_t InvalidBeforeRangeBegin = static_cast<unscoped_unspecified_t>(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
43 unscoped_unspecified_t ValidNegativeValue1 = static_cast<unscoped_unspecified_t>(-4); // OK.
44 unscoped_unspecified_t ValidNegativeValue2 = static_cast<unscoped_unspecified_t>(-3); // OK.
45 unscoped_unspecified_t InvalidInsideRange1 = static_cast<unscoped_unspecified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
46 unscoped_unspecified_t InvalidInsideRange2 = static_cast<unscoped_unspecified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
47 unscoped_unspecified_t InvalidInsideRange3 = static_cast<unscoped_unspecified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
48 unscoped_unspecified_t ValidPositiveValue1 = static_cast<unscoped_unspecified_t>(1); // OK.
49 unscoped_unspecified_t ValidPositiveValue2 = static_cast<unscoped_unspecified_t>(2); // OK.
50 unscoped_unspecified_t InvalidInsideRange4 = static_cast<unscoped_unspecified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
51 unscoped_unspecified_t ValidPositiveValue3 = static_cast<unscoped_unspecified_t>(4); // OK.
52 unscoped_unspecified_t InvalidAfterRangeEnd = static_cast<unscoped_unspecified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
53 }
54
unscopedSpecified()55 void unscopedSpecified() {
56 unscoped_specified_t InvalidBeforeRangeBegin = static_cast<unscoped_specified_t>(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
57 unscoped_specified_t ValidNegativeValue1 = static_cast<unscoped_specified_t>(-4); // OK.
58 unscoped_specified_t ValidNegativeValue2 = static_cast<unscoped_specified_t>(-3); // OK.
59 unscoped_specified_t InvalidInsideRange1 = static_cast<unscoped_specified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
60 unscoped_specified_t InvalidInsideRange2 = static_cast<unscoped_specified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
61 unscoped_specified_t InvalidInsideRange3 = static_cast<unscoped_specified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
62 unscoped_specified_t ValidPositiveValue1 = static_cast<unscoped_specified_t>(1); // OK.
63 unscoped_specified_t ValidPositiveValue2 = static_cast<unscoped_specified_t>(2); // OK.
64 unscoped_specified_t InvalidInsideRange4 = static_cast<unscoped_specified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
65 unscoped_specified_t ValidPositiveValue3 = static_cast<unscoped_specified_t>(4); // OK.
66 unscoped_specified_t InvalidAfterRangeEnd = static_cast<unscoped_specified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
67 }
68
scopedUnspecified()69 void scopedUnspecified() {
70 scoped_unspecified_t InvalidBeforeRangeBegin = static_cast<scoped_unspecified_t>(-5); // expected-warning{{The value provided to the cast expression is not in the valid range of values for the enum}}
71 scoped_unspecified_t ValidNegativeValue1 = static_cast<scoped_unspecified_t>(-4); // OK.
72 scoped_unspecified_t ValidNegativeValue2 = static_cast<scoped_unspecified_t>(-3); // OK.
73 scoped_unspecified_t InvalidInsideRange1 = static_cast<scoped_unspecified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
74 scoped_unspecified_t InvalidInsideRange2 = static_cast<scoped_unspecified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
75 scoped_unspecified_t InvalidInsideRange3 = static_cast<scoped_unspecified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
76 scoped_unspecified_t ValidPositiveValue1 = static_cast<scoped_unspecified_t>(1); // OK.
77 scoped_unspecified_t ValidPositiveValue2 = static_cast<scoped_unspecified_t>(2); // OK.
78 scoped_unspecified_t InvalidInsideRange4 = static_cast<scoped_unspecified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
79 scoped_unspecified_t ValidPositiveValue3 = static_cast<scoped_unspecified_t>(4); // OK.
80 scoped_unspecified_t InvalidAfterRangeEnd = static_cast<scoped_unspecified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
81 }
82
scopedSpecified()83 void scopedSpecified() {
84 scoped_specified_t InvalidBeforeRangeBegin = static_cast<scoped_specified_t>(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
85 scoped_specified_t ValidNegativeValue1 = static_cast<scoped_specified_t>(-4); // OK.
86 scoped_specified_t ValidNegativeValue2 = static_cast<scoped_specified_t>(-3); // OK.
87 scoped_specified_t InvalidInsideRange1 = static_cast<scoped_specified_t>(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
88 scoped_specified_t InvalidInsideRange2 = static_cast<scoped_specified_t>(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
89 scoped_specified_t InvalidInsideRange3 = static_cast<scoped_specified_t>(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
90 scoped_specified_t ValidPositiveValue1 = static_cast<scoped_specified_t>(1); // OK.
91 scoped_specified_t ValidPositiveValue2 = static_cast<scoped_specified_t>(2); // OK.
92 scoped_specified_t InvalidInsideRange4 = static_cast<scoped_specified_t>(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
93 scoped_specified_t ValidPositiveValue3 = static_cast<scoped_specified_t>(4); // OK.
94 scoped_specified_t InvalidAfterRangeEnd = static_cast<scoped_specified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
95 }
96
unscopedUnspecifiedCStyle()97 void unscopedUnspecifiedCStyle() {
98 unscoped_unspecified_t InvalidBeforeRangeBegin = (unscoped_unspecified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
99 unscoped_unspecified_t ValidNegativeValue1 = (unscoped_unspecified_t)(-4); // OK.
100 unscoped_unspecified_t ValidNegativeValue2 = (unscoped_unspecified_t)(-3); // OK.
101 unscoped_unspecified_t InvalidInsideRange1 = (unscoped_unspecified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
102 unscoped_unspecified_t InvalidInsideRange2 = (unscoped_unspecified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
103 unscoped_unspecified_t InvalidInsideRange3 = (unscoped_unspecified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
104 unscoped_unspecified_t ValidPositiveValue1 = (unscoped_unspecified_t)(1); // OK.
105 unscoped_unspecified_t ValidPositiveValue2 = (unscoped_unspecified_t)(2); // OK.
106 unscoped_unspecified_t InvalidInsideRange4 = (unscoped_unspecified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
107 unscoped_unspecified_t ValidPositiveValue3 = (unscoped_unspecified_t)(4); // OK.
108 unscoped_unspecified_t InvalidAfterRangeEnd = (unscoped_unspecified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
109 }
110
unscopedSpecifiedCStyle()111 void unscopedSpecifiedCStyle() {
112 unscoped_specified_t InvalidBeforeRangeBegin = (unscoped_specified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
113 unscoped_specified_t ValidNegativeValue1 = (unscoped_specified_t)(-4); // OK.
114 unscoped_specified_t ValidNegativeValue2 = (unscoped_specified_t)(-3); // OK.
115 unscoped_specified_t InvalidInsideRange1 = (unscoped_specified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
116 unscoped_specified_t InvalidInsideRange2 = (unscoped_specified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
117 unscoped_specified_t InvalidInsideRange3 = (unscoped_specified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
118 unscoped_specified_t ValidPositiveValue1 = (unscoped_specified_t)(1); // OK.
119 unscoped_specified_t ValidPositiveValue2 = (unscoped_specified_t)(2); // OK.
120 unscoped_specified_t InvalidInsideRange4 = (unscoped_specified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
121 unscoped_specified_t ValidPositiveValue3 = (unscoped_specified_t)(4); // OK.
122 unscoped_specified_t InvalidAfterRangeEnd = (unscoped_specified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
123 }
124
scopedUnspecifiedCStyle()125 void scopedUnspecifiedCStyle() {
126 scoped_unspecified_t InvalidBeforeRangeBegin = (scoped_unspecified_t)(-5); // expected-warning{{The value provided to the cast expression is not in the valid range of values for the enum}}
127 scoped_unspecified_t ValidNegativeValue1 = (scoped_unspecified_t)(-4); // OK.
128 scoped_unspecified_t ValidNegativeValue2 = (scoped_unspecified_t)(-3); // OK.
129 scoped_unspecified_t InvalidInsideRange1 = (scoped_unspecified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
130 scoped_unspecified_t InvalidInsideRange2 = (scoped_unspecified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
131 scoped_unspecified_t InvalidInsideRange3 = (scoped_unspecified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
132 scoped_unspecified_t ValidPositiveValue1 = (scoped_unspecified_t)(1); // OK.
133 scoped_unspecified_t ValidPositiveValue2 = (scoped_unspecified_t)(2); // OK.
134 scoped_unspecified_t InvalidInsideRange4 = (scoped_unspecified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
135 scoped_unspecified_t ValidPositiveValue3 = (scoped_unspecified_t)(4); // OK.
136 scoped_unspecified_t InvalidAfterRangeEnd = (scoped_unspecified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
137 }
138
scopedSpecifiedCStyle()139 void scopedSpecifiedCStyle() {
140 scoped_specified_t InvalidBeforeRangeBegin = (scoped_specified_t)(-5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
141 scoped_specified_t ValidNegativeValue1 = (scoped_specified_t)(-4); // OK.
142 scoped_specified_t ValidNegativeValue2 = (scoped_specified_t)(-3); // OK.
143 scoped_specified_t InvalidInsideRange1 = (scoped_specified_t)(-2); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
144 scoped_specified_t InvalidInsideRange2 = (scoped_specified_t)(-1); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
145 scoped_specified_t InvalidInsideRange3 = (scoped_specified_t)(0); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
146 scoped_specified_t ValidPositiveValue1 = (scoped_specified_t)(1); // OK.
147 scoped_specified_t ValidPositiveValue2 = (scoped_specified_t)(2); // OK.
148 scoped_specified_t InvalidInsideRange4 = (scoped_specified_t)(3); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
149 scoped_specified_t ValidPositiveValue3 = (scoped_specified_t)(4); // OK.
150 scoped_specified_t InvalidAfterRangeEnd = (scoped_specified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
151 }
152
153 unscoped_unspecified_t unused;
unusedExpr()154 void unusedExpr() {
155 // following line is not something that EnumCastOutOfRangeChecker should evaluate. checker should either ignore this line
156 // or process it without producing any warnings. However, compilation will (and should) still generate a warning having
157 // nothing to do with this checker.
158 unused; // expected-warning {{expression result unused}}
159 }
160
rangeConstrained1(int input)161 void rangeConstrained1(int input) {
162 if (input > -5 && input < 5)
163 auto value = static_cast<scoped_specified_t>(input); // OK. Being conservative, this is a possibly good value.
164 }
165
rangeConstrained2(int input)166 void rangeConstrained2(int input) {
167 if (input < -5)
168 auto value = static_cast<scoped_specified_t>(input); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
169 }
170
rangeConstrained3(int input)171 void rangeConstrained3(int input) {
172 if (input >= -2 && input <= -1)
173 auto value = static_cast<scoped_specified_t>(input); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
174 }
175
rangeConstrained4(int input)176 void rangeConstrained4(int input) {
177 if (input >= -2 && input <= 1)
178 auto value = static_cast<scoped_specified_t>(input); // OK. Possibly 1.
179 }
180
rangeConstrained5(int input)181 void rangeConstrained5(int input) {
182 if (input >= 1 && input <= 2)
183 auto value = static_cast<scoped_specified_t>(input); // OK. Strict inner matching.
184 }
185
rangeConstrained6(int input)186 void rangeConstrained6(int input) {
187 if (input >= 2 && input <= 4)
188 auto value = static_cast<scoped_specified_t>(input); // OK. The value is possibly 2 or 4, dont warn.
189 }
190
rangeConstrained7(int input)191 void rangeConstrained7(int input) {
192 if (input >= 3 && input <= 3)
193 auto value = static_cast<scoped_specified_t>(input); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
194 }
195
enumBitFieldAssignment()196 void enumBitFieldAssignment() {
197 S s;
198 s.E = static_cast<unscoped_unspecified_t>(4); // OK.
199 s.E = static_cast<unscoped_unspecified_t>(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}}
200 }
201