[PATCH] libstdc++: Use aligned new for filesystem::path internals [PR122300]
Tomasz Kaminski
tkaminsk@redhat.com
Wed Mar 4 14:46:28 GMT 2026
On Wed, Mar 4, 2026 at 12:56 PM Jonathan Wakely <jwakely@redhat.com> wrote:
> As Bug 122300 shows, we have at least one target where the
> static_assert added by r16-4422-g1b18a9e53960f3 fails. This patch
> resurrects the original proposal for using aligned new that I posted in
> https://gcc.gnu.org/pipermail/libstdc++/2025-October/063904.html
>
> Instead of just asserting that the memory from operator new will be
> sufficiently aligned, check whether it will be and use aligned new if
> needed. We don't just use aligned new unconditionally, because that can
> add overhead on targets where malloc already meets the requirements.
>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/122300
> * src/c++17/fs_path.cc (path::_List::_Impl): Remove
> static_asserts.
> (path::_List::_Impl::required_alignment)
> (path::_List::_Impl::use_aligned_new): New static data members.
> (path::_List::_Impl::create_unchecked): Check use_aligned_new
> and use aligned new if needed.
> (path::_List::_Impl::alloc_size): New static member function.
> (path::_List::_Impl_deleter::operator): Check use_aligned_new
> and use aligned delete if needed.
> ---
>
> Tested x86_64-linux and bootstrapped pru-unknown-elf, confirming that it
> fixes the failed static_assert during bootstrap.
>
Looks good. Remember discussing these changes with the original patch?
we didn't knew if any target was affected.
>
> libstdc++-v3/src/c++17/fs_path.cc | 27 +++++++++++++++++++++------
> 1 file changed, 21 insertions(+), 6 deletions(-)
>
> diff --git a/libstdc++-v3/src/c++17/fs_path.cc
> b/libstdc++-v3/src/c++17/fs_path.cc
> index 9d8d38266789..c217dc278018 100644
> --- a/libstdc++-v3/src/c++17/fs_path.cc
> +++ b/libstdc++-v3/src/c++17/fs_path.cc
> @@ -260,9 +260,12 @@ struct path::_List::_Impl
>
> // We use the two least significant bits to store a _Type value so
> // require memory aligned to at least 4 bytes:
> - static_assert(__STDCPP_DEFAULT_NEW_ALIGNMENT__ >= 4);
> - // Require memory suitably aligned for an _Impl and its value types:
> - static_assert(__STDCPP_DEFAULT_NEW_ALIGNMENT__ >= alignof(value_type));
> + static constexpr size_t required_alignment
> + = std::max(size_t(4), alignof(value_type));
> +
> + // Only use aligned new if needed, because it might be less efficient.
> + static constexpr bool use_aligned_new
> + = __STDCPP_DEFAULT_NEW_ALIGNMENT__ < required_alignment;
>
> // Clear the lowest two bits from the pointer (i.e. remove the _Type
> value)
> static _Impl* notype(_Impl* p)
> @@ -297,9 +300,18 @@ struct path::_List::_Impl
> static unique_ptr<_Impl, _Impl_deleter>
> create_unchecked(int n)
> {
> - void* p = ::operator new(sizeof(_Impl) + n * sizeof(value_type));
> + const auto bytes = alloc_size(n);
> + void* p;
> + if constexpr (use_aligned_new)
> + p = ::operator new(bytes, align_val_t{required_alignment});
> + else
> + p = ::operator new(bytes);
> return std::unique_ptr<_Impl, _Impl_deleter>(::new(p) _Impl{n});
> }
> +
> + // The number of bytes that must be allocated for _Impl with capacity n.
> + static size_t
> + alloc_size(int n) { return sizeof(_Impl) + n * sizeof(value_type); }
> };
>
> // Destroy and deallocate an _Impl.
> @@ -309,9 +321,12 @@ path::_List::_Impl_deleter::operator()(_Impl* p)
> const noexcept
> p = _Impl::notype(p);
> if (p)
> {
> - const auto n = p->_M_capacity;
> + const auto bytes = _Impl::alloc_size(p->_M_capacity);
> p->~_Impl();
> - ::operator delete(p, sizeof(_Impl) + n * sizeof(_Impl::value_type));
> + if constexpr (_Impl::use_aligned_new)
> + ::operator delete(p, bytes,
> align_val_t{_Impl::required_alignment});
> + else
> + ::operator delete(p, bytes);
> }
> }
>
> --
> 2.53.0
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260304/05df4f3d/attachment.htm>
More information about the Libstdc++
mailing list