Kristof Umann | e0466f5 | 2018-11-24 12:24:27 +0000 | [diff] [blame] | 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
Kristof Umann | 09ce8ec | 2019-08-23 14:21:13 +0000 | [diff] [blame] | 153 | unscoped_unspecified_t unused; |
| 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 | |
| 161 | void rangeConstrained1(int input) { |
Kristof Umann | e0466f5 | 2018-11-24 12:24:27 +0000 | [diff] [blame] | 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | } |