diff --git a/llvm/include/llvm/ADT/BitmaskEnum.h b/llvm/include/llvm/ADT/BitmaskEnum.h --- a/llvm/include/llvm/ADT/BitmaskEnum.h +++ b/llvm/include/llvm/ADT/BitmaskEnum.h @@ -77,7 +77,7 @@ /// Get a bitmask with 1s in all places up to the high-order bit of E's largest /// value. -template std::underlying_type_t Mask() { +template constexpr std::underlying_type_t Mask() { // On overflow, NextPowerOf2 returns zero with the type uint64_t, so // subtracting 1 gives us the mask with all bits set, like we want. return NextPowerOf2(static_cast>( @@ -87,7 +87,7 @@ /// Check that Val is in range for E, and return Val cast to E's underlying /// type. -template std::underlying_type_t Underlying(E Val) { +template constexpr std::underlying_type_t Underlying(E Val) { auto U = static_cast>(Val); assert(U >= 0 && "Negative enum values are not allowed."); assert(U <= Mask() && "Enum value too large (or largest val too small?)"); @@ -99,22 +99,22 @@ } template ::value>> -E operator~(E Val) { +constexpr E operator~(E Val) { return static_cast(~Underlying(Val) & Mask()); } template ::value>> -E operator|(E LHS, E RHS) { +constexpr E operator|(E LHS, E RHS) { return static_cast(Underlying(LHS) | Underlying(RHS)); } template ::value>> -E operator&(E LHS, E RHS) { +constexpr E operator&(E LHS, E RHS) { return static_cast(Underlying(LHS) & Underlying(RHS)); } template ::value>> -E operator^(E LHS, E RHS) { +constexpr E operator^(E LHS, E RHS) { return static_cast(Underlying(LHS) ^ Underlying(RHS)); } diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h --- a/llvm/include/llvm/Support/MathExtras.h +++ b/llvm/include/llvm/Support/MathExtras.h @@ -707,7 +707,7 @@ /// Returns the next power of two (in 64-bits) that is strictly greater than A. /// Returns zero on overflow. -inline uint64_t NextPowerOf2(uint64_t A) { +constexpr inline uint64_t NextPowerOf2(uint64_t A) { A |= (A >> 1); A |= (A >> 2); A |= (A >> 4); diff --git a/llvm/unittests/ADT/BitmaskEnumTest.cpp b/llvm/unittests/ADT/BitmaskEnumTest.cpp --- a/llvm/unittests/ADT/BitmaskEnumTest.cpp +++ b/llvm/unittests/ADT/BitmaskEnumTest.cpp @@ -76,6 +76,17 @@ EXPECT_EQ(F3, f); } +TEST(BitmaskEnumTest, ConstantExpression) { + constexpr Flags f1 = ~F1; + constexpr Flags f2 = F1 | F2; + constexpr Flags f3 = F1 & F2; + constexpr Flags f4 = F1 ^ F2; + EXPECT_EQ(f1, ~F1); + EXPECT_EQ(f2, F1 | F2); + EXPECT_EQ(f3, F1 & F2); + EXPECT_EQ(f4, F1 ^ F2); +} + TEST(BitmaskEnumTest, BitwiseNot) { Flags f = ~F1; EXPECT_EQ(14, f); // Largest value for f is 15.