From: Jonathan Wakely Date: Mon, 18 Mar 2024 16:58:23 +0000 (+0000) Subject: libstdc++: Optimize std::to_address X-Git-Tag: basepoints/gcc-16~8457 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=94997567ea5cbeb35571e94cf76d7f99ea3f9c43;p=thirdparty%2Fgcc.git libstdc++: Optimize std::to_address We can use if-constexpr and variable templates to simplify and optimize std::to_address. This should compile faster (and run faster for -O0) than dispatching to the pre-C++20 std::__to_address overloads. libstdc++-v3/ChangeLog: * include/bits/ptr_traits.h (to_address): Optimize. * testsuite/20_util/to_address/1_neg.cc: Adjust dg-error text. --- diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index 6c65001cb741..ca67feecca38 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -200,36 +200,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>; +#ifndef __glibcxx_to_address // C++ < 20 template + [[__gnu__::__always_inline__]] constexpr _Tp* __to_address(_Tp* __ptr) noexcept { - static_assert(!std::is_function<_Tp>::value, "not a function pointer"); + static_assert(!std::is_function<_Tp>::value, "std::to_address argument " + "must not be a function pointer"); return __ptr; } -#ifndef __glibcxx_to_address // C++ < 20 template constexpr typename std::pointer_traits<_Ptr>::element_type* __to_address(const _Ptr& __ptr) { return std::__to_address(__ptr.operator->()); } #else - template - constexpr auto - __to_address(const _Ptr& __ptr) noexcept - -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) - { return std::pointer_traits<_Ptr>::to_address(__ptr); } - - template - constexpr auto - __to_address(const _Ptr& __ptr, _None...) noexcept - { - if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>) - return std::__to_address(__ptr.base().operator->()); - else - return std::__to_address(__ptr.operator->()); - } - /** * @brief Obtain address referenced by a pointer to an object * @param __ptr A pointer to an object @@ -237,9 +223,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @ingroup pointer_abstractions */ template + [[__gnu__::__always_inline__]] constexpr _Tp* to_address(_Tp* __ptr) noexcept - { return std::__to_address(__ptr); } + { + static_assert(!is_function_v<_Tp>, "std::to_address argument " + "must not be a function pointer"); + return __ptr; + } /** * @brief Obtain address referenced by a pointer to an object @@ -251,7 +242,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template constexpr auto to_address(const _Ptr& __ptr) noexcept - { return std::__to_address(__ptr); } + { + if constexpr (requires { pointer_traits<_Ptr>::to_address(__ptr); }) + return pointer_traits<_Ptr>::to_address(__ptr); + else if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>) + return std::to_address(__ptr.base().operator->()); + else + return std::to_address(__ptr.operator->()); + } + + /// @cond undocumented + /// Compatibility for use in code that is also compiled as pre-C++20. + template + [[__gnu__::__always_inline__]] + constexpr auto + __to_address(const _Ptr& __ptr) noexcept + { return std::to_address(__ptr); } + /// @endcond #endif // __glibcxx_to_address _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc b/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc index 7385f0f335c0..10e919757bbb 100644 --- a/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc +++ b/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc @@ -16,7 +16,7 @@ // . // { dg-do compile { target c++20 } } -// { dg-error "not a function pointer" "" { target *-*-* } 0 } +// { dg-error "must not be a function pointer" "" { target *-*-* } 0 } #include