Clang Project

clang_source_code/test/Analysis/enum-cast-out-of-range.cpp
1// RUN: %clang_analyze_cc1 \
2// RUN:   -analyzer-checker=core,alpha.cplusplus.EnumCastOutOfRange \
3// RUN:   -std=c++11 -verify %s
4
5enum 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
13enum 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
21enum 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
29enum 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
37struct S {
38  unscoped_unspecified_t E : 5;
39};
40
41void 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
55void 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
69void 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
83void 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
97void 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
111void 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
125void 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
139void 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
153void rangeContstrained1(int input) {
154  if (input > -5 && input < 5)
155    auto value = static_cast<scoped_specified_t>(input); // OK. Being conservative, this is a possibly good value.
156}
157
158void rangeConstrained2(int input) {
159  if (input < -5)
160    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}}
161}
162
163void rangeConstrained3(int input) {
164  if (input >= -2 && input <= -1)
165    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}}
166}
167
168void rangeConstrained4(int input) {
169  if (input >= -2 && input <= 1)
170    auto value = static_cast<scoped_specified_t>(input); // OK. Possibly 1.
171}
172
173void rangeConstrained5(int input) {
174  if (input >= 1 && input <= 2)
175    auto value = static_cast<scoped_specified_t>(input); // OK. Strict inner matching.
176}
177
178void rangeConstrained6(int input) {
179  if (input >= 2 && input <= 4)
180    auto value = static_cast<scoped_specified_t>(input); // OK. The value is possibly 2 or 4, dont warn.
181}
182
183void rangeConstrained7(int input) {
184  if (input >= 3 && input <= 3)
185    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}}
186}
187
188void enumBitFieldAssignment() {
189  S s;
190  s.E = static_cast<unscoped_unspecified_t>(4); // OK.
191  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}}
192}
193