[libcxx-commits] [libcxx] 5c0ea74 - [libc++] Enable the optimized _IsSame on GCC as well as Clang.

Arthur O'Dwyer via libcxx-commits libcxx-commits at lists.llvm.org
Wed Dec 15 17:20:36 PST 2021


Author: Arthur O'Dwyer
Date: 2021-12-15T20:19:56-05:00
New Revision: 5c0ea7488bc051453ad07135f32145465f502a84

URL: https://github.com/llvm/llvm-project/commit/5c0ea7488bc051453ad07135f32145465f502a84
DIFF: https://github.com/llvm/llvm-project/commit/5c0ea7488bc051453ad07135f32145465f502a84.diff

LOG: [libc++] Enable the optimized _IsSame on GCC as well as Clang.

However, there's a problem on both GCC and Clang: they can't mangle
`__is_same(T,U)` if it appears anywhere that affects mangling. That's
a hard error. And it turns out that GCC puts dependent return types
into the mangling more aggressively than Clang, so for GCC's benefit
we need to avoid using raw `_IsSame` in the return type of
`swap(tuple&, tuple&)`. Therefore, make `__all` into a named type
instead of an alias.

If we ever need to support a compiler without the __is_same builtin,
we can make this an alias template for `is_same<T,U>::type`.

Differential Revision: https://reviews.llvm.org/D115100

Added: 
    

Modified: 
    libcxx/include/__tuple
    libcxx/include/type_traits

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__tuple b/libcxx/include/__tuple
index 11fbba260238..e8eb0b3aaf0c 100644
--- a/libcxx/include/__tuple
+++ b/libcxx/include/__tuple
@@ -387,7 +387,7 @@ template <bool ..._Preds>
 struct __all_dummy;
 
 template <bool ..._Pred>
-using __all = _IsSame<__all_dummy<_Pred...>, __all_dummy<((void)_Pred, true)...>>;
+struct __all : _IsSame<__all_dummy<_Pred...>, __all_dummy<((void)_Pred, true)...>> {};
 
 struct __tuple_sfinae_base {
   template <template <class, class...> class _Trait,

diff  --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index 2a61da5bcea7..155b775e4929 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -550,8 +550,6 @@ template <bool _Bp, class _If, class _Then> using conditional_t = typename condi
 
 // is_same
 
-#if __has_keyword(__is_same)
-
 template <class _Tp, class _Up>
 struct _LIBCPP_TEMPLATE_VIS is_same : _BoolConstant<__is_same(_Tp, _Up)> { };
 
@@ -560,36 +558,18 @@ template <class _Tp, class _Up>
 inline constexpr bool is_same_v = __is_same(_Tp, _Up);
 #endif
 
-#else
-
-template <class _Tp, class _Up> struct _LIBCPP_TEMPLATE_VIS is_same           : public false_type {};
-template <class _Tp>            struct _LIBCPP_TEMPLATE_VIS is_same<_Tp, _Tp> : public true_type {};
+// _IsSame<T,U> has the same effect as is_same<T,U> but instantiates fewer types:
+// is_same<A,B> and is_same<C,D> are guaranteed to be 
diff erent types, but
+// _IsSame<A,B> and _IsSame<C,D> are the same type (namely, false_type).
+// Neither GCC nor Clang can mangle the __is_same builtin, so _IsSame
+// mustn't be directly used anywhere that contributes to name-mangling
+// (such as in a dependent return type).
 
-#if _LIBCPP_STD_VER > 14
 template <class _Tp, class _Up>
-inline constexpr bool is_same_v = is_same<_Tp, _Up>::value;
-#endif
-
-#endif // __is_same
+using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
 
 template <class _Tp, class _Up>
-using _IsSame = _BoolConstant<
-#ifdef __clang__
-    __is_same(_Tp, _Up)
-#else
-    is_same<_Tp, _Up>::value
-#endif
->;
-
-template <class _Tp, class _Up>
-using _IsNotSame = _BoolConstant<
-#ifdef __clang__
-    !__is_same(_Tp, _Up)
-#else
-    !is_same<_Tp, _Up>::value
-#endif
->;
-
+using _IsNotSame = _BoolConstant<!__is_same(_Tp, _Up)>;
 
 template <class _Tp>
 using __test_for_primary_template = __enable_if_t<


        


More information about the libcxx-commits mailing list