Skip to content

[libc++] Use __underlying_type directly in underyling_type_t #135423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 13, 2025

Conversation

philnik777
Copy link
Contributor

@philnik777 philnik777 commented Apr 11, 2025

This avoids instantiating multiple classes, reducing compile times. This patch also introduces __underyling_type_t for internal use, similar to other type traits.

@philnik777 philnik777 force-pushed the optimize_underlying_type branch from 56a9835 to 220cfcc Compare April 12, 2025 08:21
@philnik777 philnik777 force-pushed the optimize_underlying_type branch from 220cfcc to 9c6447b Compare April 12, 2025 08:56
@philnik777 philnik777 marked this pull request as ready for review April 13, 2025 09:01
@philnik777 philnik777 requested a review from a team as a code owner April 13, 2025 09:01
@philnik777 philnik777 merged commit 4e0876e into llvm:main Apr 13, 2025
77 of 82 checks passed
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Apr 13, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 13, 2025

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

This avoids instantiating multiple classes, reducing compile times. This patch also introduces __underyling_type_t for internal use, similar to other type traits.


Full diff: https://github.com/llvm/llvm-project/pull/135423.diff

6 Files Affected:

  • (modified) libcxx/include/__atomic/memory_order.h (+2-2)
  • (modified) libcxx/include/__functional/hash.h (+1-1)
  • (modified) libcxx/include/__type_traits/underlying_type.h (+11-2)
  • (modified) libcxx/include/__utility/convert_to_integral.h (+1-1)
  • (modified) libcxx/include/__utility/to_underlying.h (+2-2)
  • (modified) libcxx/include/future (+1-1)
diff --git a/libcxx/include/__atomic/memory_order.h b/libcxx/include/__atomic/memory_order.h
index 44790fe888b36..355804312b2ec 100644
--- a/libcxx/include/__atomic/memory_order.h
+++ b/libcxx/include/__atomic/memory_order.h
@@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 // to pin the underlying type in C++20.
 enum __legacy_memory_order { __mo_relaxed, __mo_consume, __mo_acquire, __mo_release, __mo_acq_rel, __mo_seq_cst };
 
-using __memory_order_underlying_t _LIBCPP_NODEBUG = underlying_type<__legacy_memory_order>::type;
+using __memory_order_underlying_t _LIBCPP_NODEBUG = __underlying_type_t<__legacy_memory_order>;
 
 #if _LIBCPP_STD_VER >= 20
 
@@ -37,7 +37,7 @@ enum class memory_order : __memory_order_underlying_t {
   seq_cst = __mo_seq_cst
 };
 
-static_assert(is_same<underlying_type<memory_order>::type, __memory_order_underlying_t>::value,
+static_assert(is_same<__underlying_type_t<memory_order>, __memory_order_underlying_t>::value,
               "unexpected underlying type for std::memory_order");
 
 inline constexpr auto memory_order_relaxed = memory_order::relaxed;
diff --git a/libcxx/include/__functional/hash.h b/libcxx/include/__functional/hash.h
index 3b50eccdad387..f9f7d2c767caa 100644
--- a/libcxx/include/__functional/hash.h
+++ b/libcxx/include/__functional/hash.h
@@ -504,7 +504,7 @@ struct hash<long double> : public __scalar_hash<long double> {
 template <class _Tp, bool = is_enum<_Tp>::value>
 struct __enum_hash : public __unary_function<_Tp, size_t> {
   _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT {
-    typedef typename underlying_type<_Tp>::type type;
+    using type = __underlying_type_t<_Tp>;
     return hash<type>()(static_cast<type>(__v));
   }
 };
diff --git a/libcxx/include/__type_traits/underlying_type.h b/libcxx/include/__type_traits/underlying_type.h
index 45a9b40e3e4c9..100734ccf15d6 100644
--- a/libcxx/include/__type_traits/underlying_type.h
+++ b/libcxx/include/__type_traits/underlying_type.h
@@ -18,7 +18,7 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _Tp, bool = is_enum<_Tp>::value>
+template <class _Tp, bool>
 struct __underlying_type_impl;
 
 template <class _Tp>
@@ -32,9 +32,18 @@ struct __underlying_type_impl<_Tp, true> {
 template <class _Tp>
 struct _LIBCPP_NO_SPECIALIZATIONS underlying_type : __underlying_type_impl<_Tp, is_enum<_Tp>::value> {};
 
+// GCC doesn't SFINAE away when using __underlying_type directly
+#if !defined(_LIBCPP_COMPILER_GCC)
+template <class _Tp>
+using __underlying_type_t _LIBCPP_NODEBUG = __underlying_type(_Tp);
+#else
+template <class _Tp>
+using __underlying_type_t _LIBCPP_NODEBUG = typename underlying_type<_Tp>::type;
+#endif
+
 #if _LIBCPP_STD_VER >= 14
 template <class _Tp>
-using underlying_type_t = typename underlying_type<_Tp>::type;
+using underlying_type_t = __underlying_type_t<_Tp>;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__utility/convert_to_integral.h b/libcxx/include/__utility/convert_to_integral.h
index 8947c349d8302..c8149b7744984 100644
--- a/libcxx/include/__utility/convert_to_integral.h
+++ b/libcxx/include/__utility/convert_to_integral.h
@@ -50,7 +50,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __uint128_t __convert_to_integral
 
 template <class _Tp, bool = is_enum<_Tp>::value>
 struct __sfinae_underlying_type {
-  typedef typename underlying_type<_Tp>::type type;
+  using type = __underlying_type_t<_Tp>;
   typedef decltype(((type)1) + 0) __promoted_type;
 };
 
diff --git a/libcxx/include/__utility/to_underlying.h b/libcxx/include/__utility/to_underlying.h
index 77587108f20dc..3e9d405a5f666 100644
--- a/libcxx/include/__utility/to_underlying.h
+++ b/libcxx/include/__utility/to_underlying.h
@@ -21,8 +21,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #ifndef _LIBCPP_CXX03_LANG
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI constexpr typename underlying_type<_Tp>::type __to_underlying(_Tp __val) noexcept {
-  return static_cast<typename underlying_type<_Tp>::type>(__val);
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI constexpr __underlying_type_t<_Tp> __to_underlying(_Tp __val) noexcept {
+  return static_cast<__underlying_type_t<_Tp>>(__val);
 }
 #endif // !_LIBCPP_CXX03_LANG
 
diff --git a/libcxx/include/future b/libcxx/include/future
index 28850ad618dfb..3dfcce80a977d 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -440,7 +440,7 @@ _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(launch)
 
 #    ifndef _LIBCPP_CXX03_LANG
 
-typedef underlying_type<launch>::type __launch_underlying_type;
+using __launch_underlying_type _LIBCPP_NODEBUG = __underlying_type_t<launch>;
 
 inline _LIBCPP_HIDE_FROM_ABI constexpr launch operator&(launch __x, launch __y) {
   return static_cast<launch>(static_cast<__launch_underlying_type>(__x) & static_cast<__launch_underlying_type>(__y));

var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…5423)

This avoids instantiating multiple classes, reducing compile times. This
patch also introduces `__underyling_type_t` for internal use, similar to
other type traits.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants