[llvm] [ADT] Backport std::to_underlying from C++23 (PR #70681)
Vlad Serebrennikov via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 30 11:57:20 PDT 2023
https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/70681
>From a83117aaf066cb89237d51dec4d9fb23e356fd9c Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 30 Oct 2023 19:11:52 +0300
Subject: [PATCH 1/6] [STLExtras] Backport std::to_underlying from C++23
---
llvm/include/llvm/ADT/STLExtras.h | 6 ++++++
llvm/unittests/ADT/STLExtrasTest.cpp | 22 ++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index 18bc4d108b156bf..98342bfc36e9f83 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -1535,6 +1535,12 @@ constexpr decltype(auto) makeVisitor(CallableTs &&...Callables) {
return detail::Visitor<CallableTs...>(std::forward<CallableTs>(Callables)...);
}
+/// Backport of C++23 std::to_underlying.
+template <typename Enum>
+[[nodiscard]] constexpr typename std::underlying_type_t<Enum> to_underlying(Enum E) {
+ return static_cast<typename std::underlying_type_t<Enum>>(E);
+}
+
//===----------------------------------------------------------------------===//
// Extra additions to <algorithm>
//===----------------------------------------------------------------------===//
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp
index 7db339e4ef31cdc..213b3e4b3d06fb6 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -1332,4 +1332,26 @@ struct Bar {};
static_assert(is_incomplete_v<Foo>, "Foo is incomplete");
static_assert(!is_incomplete_v<Bar>, "Bar is defined");
+TEST(STLExtrasTest, ToUnderlying) {
+ enum E {
+ A1 = 0, B1 = -1
+ };
+ static_assert(to_underlying(A1) == 0);
+ static_assert(to_underlying(B1) == -1);
+
+ enum E2 : unsigned char {
+ A2 = 0, B2
+ };
+ static_assert(std::is_same_v<unsigned char, decltype(to_underlying(A2))>);
+ static_assert(to_underlying(A2) == 0);
+ static_assert(to_underlying(B2) == 1);
+
+ enum class E3 {
+ A3 = -1, B3
+ };
+ static_assert(std::is_same_v<int, decltype(to_underlying(E3::A3))>);
+ static_assert(to_underlying(E3::A3) == -1);
+ static_assert(to_underlying(E3::B3) == 0);
+}
+
} // namespace
>From 1fdc7025a213d7418cdeff984a4162de415be49e Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 30 Oct 2023 19:17:21 +0300
Subject: [PATCH 2/6] Run clang-format
---
llvm/include/llvm/ADT/STLExtras.h | 3 ++-
llvm/unittests/ADT/STLExtrasTest.cpp | 12 +++---------
2 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index 98342bfc36e9f83..513837582072fa0 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -1537,7 +1537,8 @@ constexpr decltype(auto) makeVisitor(CallableTs &&...Callables) {
/// Backport of C++23 std::to_underlying.
template <typename Enum>
-[[nodiscard]] constexpr typename std::underlying_type_t<Enum> to_underlying(Enum E) {
+[[nodiscard]] constexpr typename std::underlying_type_t<Enum>
+to_underlying(Enum E) {
return static_cast<typename std::underlying_type_t<Enum>>(E);
}
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp
index 213b3e4b3d06fb6..7bf7a7d22670127 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -1333,22 +1333,16 @@ static_assert(is_incomplete_v<Foo>, "Foo is incomplete");
static_assert(!is_incomplete_v<Bar>, "Bar is defined");
TEST(STLExtrasTest, ToUnderlying) {
- enum E {
- A1 = 0, B1 = -1
- };
+ enum E { A1 = 0, B1 = -1 };
static_assert(to_underlying(A1) == 0);
static_assert(to_underlying(B1) == -1);
- enum E2 : unsigned char {
- A2 = 0, B2
- };
+ enum E2 : unsigned char { A2 = 0, B2 };
static_assert(std::is_same_v<unsigned char, decltype(to_underlying(A2))>);
static_assert(to_underlying(A2) == 0);
static_assert(to_underlying(B2) == 1);
- enum class E3 {
- A3 = -1, B3
- };
+ enum class E3 { A3 = -1, B3 };
static_assert(std::is_same_v<int, decltype(to_underlying(E3::A3))>);
static_assert(to_underlying(E3::A3) == -1);
static_assert(to_underlying(E3::B3) == 0);
>From a6c496318de9ebfb340de9ad9a00a29c0dbf1b67 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 30 Oct 2023 21:13:59 +0300
Subject: [PATCH 3/6] Move changes from STLExtras to STLForwardCompat
---
llvm/include/llvm/ADT/STLExtras.h | 7 -------
llvm/include/llvm/ADT/STLForwardCompat.h | 7 +++++++
llvm/unittests/ADT/STLExtrasTest.cpp | 16 ----------------
llvm/unittests/ADT/STLForwardCompatTest.cpp | 16 ++++++++++++++++
4 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index 513837582072fa0..18bc4d108b156bf 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -1535,13 +1535,6 @@ constexpr decltype(auto) makeVisitor(CallableTs &&...Callables) {
return detail::Visitor<CallableTs...>(std::forward<CallableTs>(Callables)...);
}
-/// Backport of C++23 std::to_underlying.
-template <typename Enum>
-[[nodiscard]] constexpr typename std::underlying_type_t<Enum>
-to_underlying(Enum E) {
- return static_cast<typename std::underlying_type_t<Enum>>(E);
-}
-
//===----------------------------------------------------------------------===//
// Extra additions to <algorithm>
//===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/ADT/STLForwardCompat.h b/llvm/include/llvm/ADT/STLForwardCompat.h
index 97d0bff9aaedbd5..39fc922a78f5507 100644
--- a/llvm/include/llvm/ADT/STLForwardCompat.h
+++ b/llvm/include/llvm/ADT/STLForwardCompat.h
@@ -60,6 +60,13 @@ auto transformOptional(std::optional<T> &&O, const Function &F)
return std::nullopt;
}
+/// Backport of C++23 std::to_underlying.
+template <typename Enum>
+[[nodiscard]] constexpr typename std::underlying_type_t<Enum>
+to_underlying(Enum E) {
+ return static_cast<typename std::underlying_type_t<Enum>>(E);
+}
+
} // namespace llvm
#endif // LLVM_ADT_STLFORWARDCOMPAT_H
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp
index 7bf7a7d22670127..7db339e4ef31cdc 100644
--- a/llvm/unittests/ADT/STLExtrasTest.cpp
+++ b/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -1332,20 +1332,4 @@ struct Bar {};
static_assert(is_incomplete_v<Foo>, "Foo is incomplete");
static_assert(!is_incomplete_v<Bar>, "Bar is defined");
-TEST(STLExtrasTest, ToUnderlying) {
- enum E { A1 = 0, B1 = -1 };
- static_assert(to_underlying(A1) == 0);
- static_assert(to_underlying(B1) == -1);
-
- enum E2 : unsigned char { A2 = 0, B2 };
- static_assert(std::is_same_v<unsigned char, decltype(to_underlying(A2))>);
- static_assert(to_underlying(A2) == 0);
- static_assert(to_underlying(B2) == 1);
-
- enum class E3 { A3 = -1, B3 };
- static_assert(std::is_same_v<int, decltype(to_underlying(E3::A3))>);
- static_assert(to_underlying(E3::A3) == -1);
- static_assert(to_underlying(E3::B3) == 0);
-}
-
} // namespace
diff --git a/llvm/unittests/ADT/STLForwardCompatTest.cpp b/llvm/unittests/ADT/STLForwardCompatTest.cpp
index e9cd88cd4c27d89..884ad9adb2043b9 100644
--- a/llvm/unittests/ADT/STLForwardCompatTest.cpp
+++ b/llvm/unittests/ADT/STLForwardCompatTest.cpp
@@ -119,4 +119,20 @@ 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<unsigned char, decltype(llvm::to_underlying(A2))>);
+ 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<int, decltype(llvm::to_underlying(E3::A3))>);
+ static_assert(llvm::to_underlying(E3::A3) == -1);
+ static_assert(llvm::to_underlying(E3::B3) == 0);
+}
+
} // namespace
>From c1df3bc5ee684ace312893dba8f040673689ce3f Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 30 Oct 2023 21:15:20 +0300
Subject: [PATCH 4/6] Add description of function
---
llvm/include/llvm/ADT/STLForwardCompat.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/ADT/STLForwardCompat.h b/llvm/include/llvm/ADT/STLForwardCompat.h
index 39fc922a78f5507..1234a17ba13d6b1 100644
--- a/llvm/include/llvm/ADT/STLForwardCompat.h
+++ b/llvm/include/llvm/ADT/STLForwardCompat.h
@@ -60,7 +60,7 @@ auto transformOptional(std::optional<T> &&O, const Function &F)
return std::nullopt;
}
-/// Backport of C++23 std::to_underlying.
+/// Returns underlying integer value of an enum. Backport of C++23 std::to_underlying.
template <typename Enum>
[[nodiscard]] constexpr typename std::underlying_type_t<Enum>
to_underlying(Enum E) {
>From daef3ccf107ced30f163041407d9c38768e6c4e9 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 30 Oct 2023 21:15:56 +0300
Subject: [PATCH 5/6] Remove unnecessary `typename` keyword
---
llvm/include/llvm/ADT/STLForwardCompat.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/ADT/STLForwardCompat.h b/llvm/include/llvm/ADT/STLForwardCompat.h
index 1234a17ba13d6b1..f4abcd7ca67ffc9 100644
--- a/llvm/include/llvm/ADT/STLForwardCompat.h
+++ b/llvm/include/llvm/ADT/STLForwardCompat.h
@@ -60,11 +60,12 @@ auto transformOptional(std::optional<T> &&O, const Function &F)
return std::nullopt;
}
-/// Returns underlying integer value of an enum. Backport of C++23 std::to_underlying.
+/// Returns underlying integer value of an enum. Backport of C++23
+/// std::to_underlying.
template <typename Enum>
-[[nodiscard]] constexpr typename std::underlying_type_t<Enum>
+[[nodiscard]] constexpr std::underlying_type_t<Enum>
to_underlying(Enum E) {
- return static_cast<typename std::underlying_type_t<Enum>>(E);
+ return static_cast<std::underlying_type_t<Enum>>(E);
}
} // namespace llvm
>From 3e416468cad0a2447a56faac561fd412c13b5648 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 30 Oct 2023 21:57:03 +0300
Subject: [PATCH 6/6] Run clang-format
---
llvm/include/llvm/ADT/STLForwardCompat.h | 3 +--
llvm/unittests/ADT/STLForwardCompatTest.cpp | 3 ++-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/ADT/STLForwardCompat.h b/llvm/include/llvm/ADT/STLForwardCompat.h
index f4abcd7ca67ffc9..6afe3610b257fb7 100644
--- a/llvm/include/llvm/ADT/STLForwardCompat.h
+++ b/llvm/include/llvm/ADT/STLForwardCompat.h
@@ -63,8 +63,7 @@ auto transformOptional(std::optional<T> &&O, const Function &F)
/// Returns underlying integer value of an enum. Backport of C++23
/// std::to_underlying.
template <typename Enum>
-[[nodiscard]] constexpr std::underlying_type_t<Enum>
-to_underlying(Enum E) {
+[[nodiscard]] constexpr std::underlying_type_t<Enum> to_underlying(Enum E) {
return static_cast<std::underlying_type_t<Enum>>(E);
}
diff --git a/llvm/unittests/ADT/STLForwardCompatTest.cpp b/llvm/unittests/ADT/STLForwardCompatTest.cpp
index 884ad9adb2043b9..b0c95d09ba2c6e3 100644
--- a/llvm/unittests/ADT/STLForwardCompatTest.cpp
+++ b/llvm/unittests/ADT/STLForwardCompatTest.cpp
@@ -125,7 +125,8 @@ TEST(TransformTest, ToUnderlying) {
static_assert(llvm::to_underlying(B1) == -1);
enum E2 : unsigned char { A2 = 0, B2 };
- static_assert(std::is_same_v<unsigned char, decltype(llvm::to_underlying(A2))>);
+ static_assert(
+ std::is_same_v<unsigned char, decltype(llvm::to_underlying(A2))>);
static_assert(llvm::to_underlying(A2) == 0);
static_assert(llvm::to_underlying(B2) == 1);
More information about the llvm-commits
mailing list