On Mon, Sep 22, 2025 at 2:49 PM Tomasz Kamiński <[email protected]> wrote:
> This allows inplace_vector to use these functions without including the
> entire
> <memory> header.
>
> Preprocessor checks are changed to use __glibcxx macros, so new functions
> are
> available outside memory header, that exports __cpp_lib macros.
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/stl_construct.h (std::start_lifetime_as_array)
> (std::start_lifetime_as): Moved from std/memory, with update
> to guard marcors.
> * include/std/memory (std::start_lifetime_as_array)
> (std::start_lifetime_as): Moved to bits/stl_construct.h.
> ---
> Tested on x86_64-linux locally.
> OK for trunk?
>
> libstdc++-v3/include/bits/stl_construct.h | 128 ++++++++++++++++++++++
> libstdc++-v3/include/std/memory | 128 ----------------------
> 2 files changed, 128 insertions(+), 128 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/stl_construct.h
> b/libstdc++-v3/include/bits/stl_construct.h
> index 217a0416d42..7f6120f6280 100644
> --- a/libstdc++-v3/include/bits/stl_construct.h
> +++ b/libstdc++-v3/include/bits/stl_construct.h
> @@ -281,6 +281,134 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> }
> #endif // C++17
>
> +#if __glibcxx_start_lifetime_as >= 202207L // C++ >= 23
> +namespace std _GLIBCXX_VISIBILITY(default)
> +{
>
We are already in the std namespace, so this is wrong, I have removed
that locally, but forgot to amend the commit before posting.
> +_GLIBCXX_BEGIN_NAMESPACE_VERSION
> + template<typename _Tp>
> + [[__gnu__::__always_inline__]]
> + inline _Tp*
> + start_lifetime_as(void* __p) noexcept
> + {
> +#if __glibcxx_is_implicit_lifetime >= 202302L
> + static_assert(is_implicit_lifetime_v<_Tp>);
> +#endif
> + auto __q = reinterpret_cast<_Tp*>(__p);
> + __asm__ __volatile__("" : "=g" (__q), "=m" (*__q)
> + : "0" (__q), "m" (*__q));
> + return __q;
> + }
> +
> + template<typename _Tp>
> + [[__gnu__::__always_inline__]]
> + inline const _Tp*
> + start_lifetime_as(const void* __p) noexcept
> + {
> +#if __glibcxx_is_implicit_lifetime >= 202302L
> + static_assert(is_implicit_lifetime_v<_Tp>);
> +#endif
> + auto __q = reinterpret_cast<const _Tp*>(__p);
> + auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p));
> + __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
> + : "0" (__q), "m" (*__q));
> + return __q;
> + }
> +
> + template<typename _Tp>
> + [[__gnu__::__always_inline__]]
> + inline volatile _Tp*
> + start_lifetime_as(volatile void* __p) noexcept
> + {
> +#if __glibcxx_is_implicit_lifetime >= 202302L
> + static_assert(is_implicit_lifetime_v<_Tp>);
> +#endif
> + auto __q = reinterpret_cast<volatile _Tp*>(__p);
> + auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p));
> + __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
> + : "0" (__q), "m" (*__q));
> + return __q;
> + }
> +
> + template<typename _Tp>
> + [[__gnu__::__always_inline__]]
> + inline const volatile _Tp*
> + start_lifetime_as(const volatile void* __p) noexcept
> + {
> +#if __glibcxx_is_implicit_lifetime >= 202302L
> + static_assert(is_implicit_lifetime_v<_Tp>);
> +#endif
> + auto __q = reinterpret_cast<const volatile _Tp*>(__p);
> + auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p));
> + __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
> + : "0" (__q), "m" (*__q));
> + return __q;
> + }
> +
> + template<typename _Tp>
> + [[__gnu__::__always_inline__]]
> + inline _Tp*
> + start_lifetime_as_array(void* __p, size_t __n) noexcept
> + {
> + auto __q = reinterpret_cast<_Tp*>(__p);
> + if (!__n)
> + return __q;
> + auto __r = (__extension__ reinterpret_cast<_Tp(*)[__n]>(__p));
> + __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
> + : "0" (__q), "m" (*__r));
> + return __q;
> + }
> +
> + template<typename _Tp>
> + [[__gnu__::__always_inline__]]
> + inline const _Tp*
> + start_lifetime_as_array(const void* __p, size_t __n) noexcept
> + {
> + auto __q = reinterpret_cast<const _Tp*>(__p);
> + if (!__n)
> + return __q;
> + auto __r = (__extension__ reinterpret_cast<const _Tp(*)[__n]>(__p));
> + auto __s = (__extension__
> + reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p)));
> + __asm__ __volatile__("" : "=g" (__q), "=m" (*__s)
> + : "0" (__q), "m" (*__r));
> + return __q;
> + }
> +
> + template<typename _Tp>
> + [[__gnu__::__always_inline__]]
> + inline volatile _Tp*
> + start_lifetime_as_array(volatile void* __p, size_t __n) noexcept
> + {
> + auto __q = reinterpret_cast<volatile _Tp*>(__p);
> + if (!__n)
> + return __q;
> + auto __r = (__extension__ reinterpret_cast<volatile
> _Tp(*)[__n]>(__p));
> + auto __s = (__extension__
> + reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p)));
> + __asm__ __volatile__("" : "=g" (__q), "=m" (*__s)
> + : "0" (__q), "m" (*__r));
> + return __q;
> + }
> +
> + template<typename _Tp>
> + [[__gnu__::__always_inline__]]
> + inline const volatile _Tp*
> + start_lifetime_as_array(const volatile void* __p, size_t __n) noexcept
> + {
> + auto __q = reinterpret_cast<const volatile _Tp*>(__p);
> + if (!__n)
> + return __q;
> + auto __r = (__extension__ reinterpret_cast<const volatile
> _Tp(*)[__n]>(__p));
> + auto __s = (__extension__
> + reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p)));
> + __asm__ __volatile__("" : "=g" (__q), "=m" (*__s)
> + : "0" (__q), "m" (*__r));
> + return __q;
> + }
> +_GLIBCXX_END_NAMESPACE_VERSION
> +} // namespace
>
Similarly, we should not close namespace here.
> +#endif // c++23
> +
> _GLIBCXX_END_NAMESPACE_VERSION
> } // namespace std
>
> diff --git a/libstdc++-v3/include/std/memory
> b/libstdc++-v3/include/std/memory
> index e46db885fe2..9763760b8d6 100644
> --- a/libstdc++-v3/include/std/memory
> +++ b/libstdc++-v3/include/std/memory
> @@ -173,134 +173,6 @@ _GLIBCXX_END_NAMESPACE_VERSION
> } // namespace
> #endif // C++11 to C++20
>
> -#if __cpp_lib_start_lifetime_as >= 202207L // C++ >= 23
> -namespace std _GLIBCXX_VISIBILITY(default)
> -{
> -_GLIBCXX_BEGIN_NAMESPACE_VERSION
> - template<typename _Tp>
> - [[__gnu__::__always_inline__]]
> - inline _Tp*
> - start_lifetime_as(void* __p) noexcept
> - {
> -#if __cpp_lib_is_implicit_lifetime >= 202302L
> - static_assert(is_implicit_lifetime_v<_Tp>);
> -#endif
> - auto __q = reinterpret_cast<_Tp*>(__p);
> - __asm__ __volatile__("" : "=g" (__q), "=m" (*__q)
> - : "0" (__q), "m" (*__q));
> - return __q;
> - }
> -
> - template<typename _Tp>
> - [[__gnu__::__always_inline__]]
> - inline const _Tp*
> - start_lifetime_as(const void* __p) noexcept
> - {
> -#if __cpp_lib_is_implicit_lifetime >= 202302L
> - static_assert(is_implicit_lifetime_v<_Tp>);
> -#endif
> - auto __q = reinterpret_cast<const _Tp*>(__p);
> - auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p));
> - __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
> - : "0" (__q), "m" (*__q));
> - return __q;
> - }
> -
> - template<typename _Tp>
> - [[__gnu__::__always_inline__]]
> - inline volatile _Tp*
> - start_lifetime_as(volatile void* __p) noexcept
> - {
> -#if __cpp_lib_is_implicit_lifetime >= 202302L
> - static_assert(is_implicit_lifetime_v<_Tp>);
> -#endif
> - auto __q = reinterpret_cast<volatile _Tp*>(__p);
> - auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p));
> - __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
> - : "0" (__q), "m" (*__q));
> - return __q;
> - }
> -
> - template<typename _Tp>
> - [[__gnu__::__always_inline__]]
> - inline const volatile _Tp*
> - start_lifetime_as(const volatile void* __p) noexcept
> - {
> -#if __cpp_lib_is_implicit_lifetime >= 202302L
> - static_assert(is_implicit_lifetime_v<_Tp>);
> -#endif
> - auto __q = reinterpret_cast<const volatile _Tp*>(__p);
> - auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p));
> - __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
> - : "0" (__q), "m" (*__q));
> - return __q;
> - }
> -
> - template<typename _Tp>
> - [[__gnu__::__always_inline__]]
> - inline _Tp*
> - start_lifetime_as_array(void* __p, size_t __n) noexcept
> - {
> - auto __q = reinterpret_cast<_Tp*>(__p);
> - if (!__n)
> - return __q;
> - auto __r = (__extension__ reinterpret_cast<_Tp(*)[__n]>(__p));
> - __asm__ __volatile__("" : "=g" (__q), "=m" (*__r)
> - : "0" (__q), "m" (*__r));
> - return __q;
> - }
> -
> - template<typename _Tp>
> - [[__gnu__::__always_inline__]]
> - inline const _Tp*
> - start_lifetime_as_array(const void* __p, size_t __n) noexcept
> - {
> - auto __q = reinterpret_cast<const _Tp*>(__p);
> - if (!__n)
> - return __q;
> - auto __r = (__extension__ reinterpret_cast<const _Tp(*)[__n]>(__p));
> - auto __s = (__extension__
> - reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p)));
> - __asm__ __volatile__("" : "=g" (__q), "=m" (*__s)
> - : "0" (__q), "m" (*__r));
> - return __q;
> - }
> -
> - template<typename _Tp>
> - [[__gnu__::__always_inline__]]
> - inline volatile _Tp*
> - start_lifetime_as_array(volatile void* __p, size_t __n) noexcept
> - {
> - auto __q = reinterpret_cast<volatile _Tp*>(__p);
> - if (!__n)
> - return __q;
> - auto __r = (__extension__ reinterpret_cast<volatile
> _Tp(*)[__n]>(__p));
> - auto __s = (__extension__
> - reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p)));
> - __asm__ __volatile__("" : "=g" (__q), "=m" (*__s)
> - : "0" (__q), "m" (*__r));
> - return __q;
> - }
> -
> - template<typename _Tp>
> - [[__gnu__::__always_inline__]]
> - inline const volatile _Tp*
> - start_lifetime_as_array(const volatile void* __p, size_t __n) noexcept
> - {
> - auto __q = reinterpret_cast<const volatile _Tp*>(__p);
> - if (!__n)
> - return __q;
> - auto __r = (__extension__ reinterpret_cast<const volatile
> _Tp(*)[__n]>(__p));
> - auto __s = (__extension__
> - reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p)));
> - __asm__ __volatile__("" : "=g" (__q), "=m" (*__s)
> - : "0" (__q), "m" (*__r));
> - return __q;
> - }
> -_GLIBCXX_END_NAMESPACE_VERSION
> -} // namespace
> -#endif
> -
> #ifdef __cpp_lib_parallel_algorithm // C++ >= 17 && HOSTED
> // Parallel STL algorithms
> # if _PSTL_EXECUTION_POLICIES_DEFINED
> --
> 2.51.0
>
>