From d0caa4eef702f6eda1ce5ab3d72faabb55b15ca9 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov Date: Mon, 30 Oct 2023 23:06:28 +0400 Subject: [PATCH] [ADT] Backport std::to_underlying from C++23 (#70681) This patch backports a one-liner `std::to_underlying` that came with C++23. This is useful for refactoring unscoped enums into scoped enums, because the latter are not implicitly convertible to integer types. I followed libc++ implementation, but I consider their testing too heavy for us, so I wrote a simpler set of tests. --- llvm/include/llvm/ADT/STLForwardCompat.h | 7 +++++++ llvm/unittests/ADT/STLForwardCompatTest.cpp | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/llvm/include/llvm/ADT/STLForwardCompat.h b/llvm/include/llvm/ADT/STLForwardCompat.h index 97d0bff9aaedbd..6afe3610b257fb 100644 --- a/llvm/include/llvm/ADT/STLForwardCompat.h +++ b/llvm/include/llvm/ADT/STLForwardCompat.h @@ -60,6 +60,13 @@ auto transformOptional(std::optional &&O, const Function &F) return std::nullopt; } +/// Returns underlying integer value of an enum. Backport of C++23 +/// std::to_underlying. +template +[[nodiscard]] constexpr std::underlying_type_t to_underlying(Enum E) { + return static_cast>(E); +} + } // namespace llvm #endif // LLVM_ADT_STLFORWARDCOMPAT_H diff --git a/llvm/unittests/ADT/STLForwardCompatTest.cpp b/llvm/unittests/ADT/STLForwardCompatTest.cpp index e9cd88cd4c27d8..b0c95d09ba2c6e 100644 --- a/llvm/unittests/ADT/STLForwardCompatTest.cpp +++ b/llvm/unittests/ADT/STLForwardCompatTest.cpp @@ -119,4 +119,21 @@ TEST(TransformTest, MoveTransformLlvm) { EXPECT_EQ(0u, MoveOnly::Destructions); } +TEST(TransformTest, ToUnderlying) { + enum E { A1 = 0, B1 = -1 }; + static_assert(llvm::to_underlying(A1) == 0); + static_assert(llvm::to_underlying(B1) == -1); + + enum E2 : unsigned char { A2 = 0, B2 }; + static_assert( + std::is_same_v); + static_assert(llvm::to_underlying(A2) == 0); + static_assert(llvm::to_underlying(B2) == 1); + + enum class E3 { A3 = -1, B3 }; + static_assert(std::is_same_v); + static_assert(llvm::to_underlying(E3::A3) == -1); + static_assert(llvm::to_underlying(E3::B3) == 0); +} + } // namespace