22
33/* ========== 1. Fixtures ========== */
44
5- // Unscoped, no fixed type
5+ // Unscoped, no fixed type - narrowest possible: char
66enum Unfixed { U0, U1, U2 };
77enum Unfixed2 { V0 = 10 , V1, V2 };
88
9+ // Unscoped, no fixed type - narrowest possible: std::int16_t (needs > 127
10+ // signed)
11+ enum UnfixedMedium { UM0 = -1 , UM1 = 1000 };
12+
13+ // Unscoped, no fixed type - narrowest possible: std::uint32_t
14+ enum UnfixedLargeU { ULU0 = 0x7FFFFFFF , ULU1 };
15+
16+ // Unscoped, no fixed type - narrowest possible: std::int64_t
17+ enum UnfixedLargeS { ULS0 = -1 , ULS1 = 0x80000000 };
18+
919// Unscoped, with fixed type
1020enum Fixed : std::int32_t { F0 = 20 , F1, F2 };
1121enum Fixed2 : std::int32_t { G0 = 30 , G1, G2 };
@@ -16,9 +26,6 @@ enum class Scoped { S0, S1, S2 };
1626// Scoped, with fixed type
1727enum class ScopedFixed : std::int32_t { SF0, SF1, SF2 };
1828
19- // Unscoped, no fixed type, large values
20- enum UnfixedLarge { UL0 = 0x7FFFFFFF , UL1 };
21-
2229/* ========== 2. Arithmetic operators ========== */
2330
2431void arithmetic () {
@@ -121,19 +128,47 @@ void relational() {
121128/* ========== 8. Assignment ========== */
122129
123130void assignment () {
124- Unfixed u = U0;
131+ Unfixed u = U0; // Narrowest: char
132+ UnfixedMedium um = UM0; // Narrowest: std::int16_t
133+ UnfixedLargeU ulu = ULU0; // Narrowest: std::uint32_t
134+ UnfixedLargeS uls = ULS0; // Narrowest: std::int64_t
125135 Fixed f = F0;
126136
127- std::int32_t i32 ;
128137 std::int8_t i8 ;
138+ std::int16_t i16 ;
139+ std::int32_t i32 ;
140+ std::uint32_t u32 ;
129141 std::int64_t i64 ;
130142
131- i32 = u; // COMPLIANT: std::int32_t large enough
132- i64 = u; // COMPLIANT: std::int64_t large enough
133- i8 = u; // NON_COMPLIANT: std::int8_t might not hold all values
134-
135- i32 = f; // COMPLIANT: fixed underlying type
143+ // Unfixed { U0, U1, U2 } - narrowest: char
144+ i8 = u; // COMPLIANT: std::int8_t >= char
145+ i16 = u; // COMPLIANT: std::int16_t >= char
146+ i32 = u; // COMPLIANT: std::int32_t >= char
147+ i64 = u; // COMPLIANT: std::int64_t >= char
148+
149+ // UnfixedMedium { UM0 = -1, UM1 = 1000 } - narrowest: std::int16_t
150+ i8 = um; // NON_COMPLIANT: std::int8_t < std::int16_t
151+ i16 = um; // COMPLIANT: std::int16_t >= std::int16_t
152+ i32 = um; // COMPLIANT: std::int32_t >= std::int16_t
153+ i64 = um; // COMPLIANT: std::int64_t >= std::int16_t
154+
155+ // UnfixedLargeU { ULU0 = 0x7FFFFFFF, ULU1 } - narrowest: std::uint32_t
156+ i8 = ulu; // NON_COMPLIANT: std::int8_t < std::uint32_t
157+ i16 = ulu; // NON_COMPLIANT: std::int16_t < std::uint32_t
158+ i32 = ulu; // NON_COMPLIANT: std::int32_t < std::uint32_t (signed vs unsigned)
159+ u32 = ulu; // COMPLIANT: std::uint32_t >= std::uint32_t
160+ i64 = ulu; // COMPLIANT: std::int64_t >= std::uint32_t
161+
162+ // UnfixedLargeS { ULS0 = -1, ULS1 = 0x80000000 } - narrowest: std::int64_t
163+ i8 = uls; // NON_COMPLIANT: std::int8_t < std::int64_t
164+ i16 = uls; // NON_COMPLIANT: std::int16_t < std::int64_t
165+ i32 = uls; // NON_COMPLIANT: std::int32_t < std::int64_t
166+ u32 = uls; // NON_COMPLIANT: std::uint32_t < std::int64_t
167+ i64 = uls; // COMPLIANT: std::int64_t >= std::int64_t
168+
169+ // Fixed underlying type - rule doesn't apply
136170 i8 = f; // COMPLIANT: fixed underlying type
171+ i32 = f; // COMPLIANT: fixed underlying type
137172
138173 Unfixed u2;
139174 u2 = u; // COMPLIANT: same enum type
@@ -179,25 +214,44 @@ void switch_statements() {
179214/* ========== 10. static_cast FROM unfixed enum ========== */
180215
181216void static_cast_from_unfixed () {
182- Unfixed u = U0;
217+ Unfixed u = U0; // Narrowest: char
218+ UnfixedMedium um = UM0; // Narrowest: std::int16_t
219+ UnfixedLargeU ulu = ULU0; // Narrowest: std::uint32_t
220+ UnfixedLargeS uls = ULS0; // Narrowest: std::int64_t
183221
184222 // Target is same enumeration type
185223 static_cast <Unfixed>(u); // COMPLIANT: same enum type
186224
187- // Target is integer type large enough
188- static_cast <int >(u); // COMPLIANT: int guaranteed large enough
189- static_cast <long >(u); // COMPLIANT: long >= int
190- static_cast <std::int64_t >(u); // COMPLIANT: std::int64_t >= int
191- static_cast <unsigned int >(u); // COMPLIANT: unsigned int large enough
192-
193- // Target is integer type that might not be large enough
194- static_cast <std::int8_t >(
195- u); // NON_COMPLIANT: std::int8_t might not hold all values
196- static_cast <std::uint8_t >(
197- u); // NON_COMPLIANT: std::uint8_t might not hold all values
198- static_cast <std::int16_t >(
199- u); // NON_COMPLIANT: std::int16_t might not hold all values
200- static_cast <char >(u); // NON_COMPLIANT: char might not hold all values
225+ // Unfixed { U0, U1, U2 } - narrowest: char
226+ static_cast <std::int8_t >(u); // COMPLIANT: std::int8_t >= char
227+ static_cast <std::int16_t >(u); // COMPLIANT: std::int16_t >= char
228+ static_cast <std::int32_t >(u); // COMPLIANT: std::int32_t >= char
229+ static_cast <std::int64_t >(u); // COMPLIANT: std::int64_t >= char
230+ static_cast <int >(u); // COMPLIANT: int >= char
231+ static_cast <long >(u); // COMPLIANT: long >= char
232+ static_cast <unsigned int >(u); // COMPLIANT: unsigned int >= char
233+
234+ // UnfixedMedium { UM0 = -1, UM1 = 1000 } - narrowest: std::int16_t
235+ static_cast <std::int8_t >(um); // NON_COMPLIANT: std::int8_t < std::int16_t
236+ static_cast <char >(um); // NON_COMPLIANT: char < std::int16_t
237+ static_cast <std::int16_t >(um); // COMPLIANT: std::int16_t >= std::int16_t
238+ static_cast <std::int32_t >(um); // COMPLIANT: std::int32_t >= std::int16_t
239+ static_cast <std::int64_t >(um); // COMPLIANT: std::int64_t >= std::int16_t
240+
241+ // UnfixedLargeU { ULU0 = 0x7FFFFFFF, ULU1 } - narrowest: std::uint32_t
242+ static_cast <std::int8_t >(ulu); // NON_COMPLIANT: std::int8_t < std::uint32_t
243+ static_cast <std::int16_t >(ulu); // NON_COMPLIANT: std::int16_t < std::uint32_t
244+ static_cast <std::int32_t >(ulu); // NON_COMPLIANT: std::int32_t < std::uint32_t
245+ static_cast <std::uint32_t >(ulu); // COMPLIANT: std::uint32_t >= std::uint32_t
246+ static_cast <std::int64_t >(ulu); // COMPLIANT: std::int64_t >= std::uint32_t
247+
248+ // UnfixedLargeS { ULS0 = -1, ULS1 = 0x80000000 } - narrowest: std::int64_t
249+ static_cast <std::int8_t >(uls); // NON_COMPLIANT: std::int8_t < std::int64_t
250+ static_cast <std::int16_t >(uls); // NON_COMPLIANT: std::int16_t < std::int64_t
251+ static_cast <std::int32_t >(uls); // NON_COMPLIANT: std::int32_t < std::int64_t
252+ static_cast <std::uint32_t >(
253+ uls); // NON_COMPLIANT: std::uint32_t < std::int64_t
254+ static_cast <std::int64_t >(uls); // COMPLIANT: std::int64_t >= std::int64_t
201255
202256 // Target is different enumeration type
203257 static_cast <Unfixed2>(u); // NON_COMPLIANT: different enum type
@@ -287,7 +341,6 @@ void cross_enum_relational() {
287341
288342 // Unfixed vs Scoped - with cast
289343 u == static_cast <int >(s); // NON_COMPLIANT: unfixed enum compared to int
290-
291344 static_cast <int >(u) == static_cast <int >(s); // COMPLIANT: comparing ints
292345
293346 // Fixed vs Scoped - with cast
@@ -411,4 +464,4 @@ class C1 {
411464 }
412465};
413466
414- int main () { return 0 ; }
467+ int main () { return 0 ; }
0 commit comments