On Tue, 8 Jul 2025, Jonathan Wakely wrote:

> We should not use the std::fill optimization for trivial types during
> constant evaluation, because we need to begin the lifetime of all
> objects, even trivially default constructible ones.
> 
> This fixes a bug that Clang diagnosed:
> 
> include/c++/16.0.0/bits/stl_algobase.h:925:11: note: assignment to object 
> outside its lifetime is not allowed in a constant expression
>   925 |         *__first = __val;
>       |         ~~~~~~~~~^~~~~~~
> 
> I initially just added the #ifdef __cpp_lib_is_constant_evaluated check,
> but that gave warnings with GCC because the function isn't constexpr
> until C++26. So then I tried checking __glibcxx_raw_memory_algorithms
> for the value indicating constexpr uninitialized_value_construct, but
> that macro depends on __cpp_constexpr >= 202406 and Clang 19 doesn't
> support constexpr placement new, so doesn't define it.
> 
> So I decided to just change __uninitialized_default to use
> _GLIBCXX20_CONSTEXPR which is consistent with __uninitialized_default_n
> (which needs to be constexpr because it's used by std::vector). We don't
> currently need to use __uninitialized_default in constexpr contexts for
> C++20 code, but we might find uses for it, so now it would be possible.

LGTM

> 
> libstdc++-v3/ChangeLog:
> 
>       * include/bits/stl_uninitialized.h (__uninitialized_default):
>       Do not use optimized implementation for constexpr case. Use
>       _GLIBCXX20_CONSTEXPR instead of _GLIBCXX26_CONSTEXPR.
> ---
> 
> Tested x86_64-linux.
> 
>  libstdc++-v3/include/bits/stl_uninitialized.h | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h 
> b/libstdc++-v3/include/bits/stl_uninitialized.h
> index 3a37ddc71ba1..351c3a17457f 100644
> --- a/libstdc++-v3/include/bits/stl_uninitialized.h
> +++ b/libstdc++-v3/include/bits/stl_uninitialized.h
> @@ -922,11 +922,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    // __uninitialized_default
>    // Fills [first, last) with value-initialized value_types.
>    template<typename _ForwardIterator>
> -    _GLIBCXX26_CONSTEXPR
> +    _GLIBCXX20_CONSTEXPR
>      inline void
>      __uninitialized_default(_ForwardIterator __first,
>                           _ForwardIterator __last)
>      {
> +#ifdef __cpp_lib_is_constant_evaluated
> +      if (std::is_constant_evaluated())
> +     return __uninitialized_default_1<false>::
> +              __uninit_default(__first, __last);
> +#endif
> +
>        typedef typename iterator_traits<_ForwardIterator>::value_type
>       _ValueType;
>        // trivial types can have deleted assignment
> -- 
> 2.50.0
> 
> 

Reply via email to