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