Skip to content

Commit 7d68370

Browse files
aferrero2707sawenzel
authored andcommitted
Fix EnumFlags compilation for large enums
The EnumFlags fails to compile when the underlying enum has 30 or more elements. With exactly 32 elements the compilation error is the following: note: shift count 32 >= width of type 'int' (32 bits) static constexpr auto MaxRep{((1 << (Max_u_v - Min_u_v + 1)) - 1) << Min_u_v}; // largest representable value With 30 or 31 elements the compilation error is: note: value -2147483649 is outside the range of representable values of type 'int' static constexpr auto MaxRep{((1 << (Max_u_v - Min_u_v + 1)) - 1) << Min_u_v}; // largest representable value The solution consists in using "1ULL" literals in the MaxRep expression, such that the bit shifts are performed on a variable with at least 64-bits.
1 parent f37a28b commit 7d68370

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

Common/Utils/include/CommonUtils/EnumFlags.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,9 @@ struct FlagsHelper final {
160160
static constexpr auto Max_v{Values.back()}; // Enum last entry
161161
static constexpr auto Min_u_v{static_cast<size_t>(Min_v)}; // Enum first entry as size_t
162162
static constexpr auto Max_u_v{static_cast<size_t>(Max_v)}; // Enum last entry as size_t
163-
static constexpr bool isContinuous() noexcept { return (Max_u_v - Min_u_v + 1) == count(); } // Is the enum continuous
164-
static constexpr auto MaxRep{((1 << (Max_u_v - Min_u_v + 1)) - 1) << Min_u_v}; // largest representable value
163+
static_assert(Max_u_v < std::numeric_limits<U>::digits, "Max Bit is beyond allow range defered from underlying type");
164+
static constexpr bool isContinuous() noexcept { return (Max_u_v - Min_u_v + 1) == count(); } // Is the enum continuous
165+
static constexpr auto MaxRep{((1ULL << (static_cast<unsigned long long>(Max_u_v - Min_u_v) + 1ULL)) - 1ULL) << Min_u_v}; // largest representable value
165166

166167
template <E e>
167168
static constexpr std::string_view getName()

Common/Utils/test/testEnumFlags.cxx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,46 @@ enum class TestEnum : uint8_t {
2828
Bit5VeryLongName,
2929
};
3030

31+
// Very long enum
32+
// to test that it works beyond 32 bits
33+
enum class TestEnumLong : uint64_t {
34+
Bit1,
35+
Bit2,
36+
Bit3,
37+
Bit4,
38+
Bit5,
39+
Bit6,
40+
Bit7,
41+
Bit8,
42+
Bit9,
43+
Bit10,
44+
Bit11,
45+
Bit12,
46+
Bit13,
47+
Bit14,
48+
Bit15,
49+
Bit16,
50+
Bit17,
51+
Bit18,
52+
Bit19,
53+
Bit20,
54+
Bit21,
55+
Bit22,
56+
Bit23,
57+
Bit24,
58+
Bit25,
59+
Bit26,
60+
Bit27,
61+
Bit28,
62+
Bit29,
63+
Bit30,
64+
Bit31,
65+
Bit32,
66+
Bit33,
67+
Bit34,
68+
// ...
69+
};
70+
3171
BOOST_AUTO_TEST_CASE(Flags_test)
3272
{
3373
using EFlags = o2::utils::EnumFlags<TestEnum>;
@@ -257,4 +297,11 @@ BOOST_AUTO_TEST_CASE(Flags_test)
257297
EFlags flags3{TestEnum::Bit4};
258298
BOOST_CHECK(!flags1.contains(flags3)); // flags1 does not contain flags3
259299
}
300+
301+
{
302+
// Test compilation using an enum with more than 32 bits
303+
o2::utils::EnumFlags<TestEnumLong> test;
304+
test.set("Bit32");
305+
BOOST_CHECK(test.test(TestEnumLong::Bit32));
306+
}
260307
}

0 commit comments

Comments
 (0)