https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113835

--- Comment #12 from Jonathan Wakely <redi at gcc dot gnu.org> ---
The __uninitialized_default_n_1<true> specialization assumes that we can use
std::fill_n to assign to objects outside their lifetime. I don't think that's
valid during constant evaluation, is it? That's why we use the <false>
specialization which begins the lifetime of every element using
std::_Construct.

GCC accepts this, but Clang rejects it:

#include <algorithm>
#include <memory>

consteval bool f(int n)
{
  int* p = std::allocator<int>().allocate(n);
  std::fill_n(p, n, 99);
  std::allocator<int>().deallocate(p, n);
  return true;
}

static_assert(f(10));


uninit.cc:12:15: error: static assertion expression is not an integral constant
expression
   12 | static_assert(f(10));
      |               ^~~~~
/usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/bits/stl_algobase.h:952:11:
note: assignment to object outside its lifetime is not allowed in a constant
expression
  952 |         *__first = __tmp;
      |         ~~~~~~~~~^~~~~~~



If that is supposed to work, we could remove the
__cpp_lib_is_constant_evaluated group in __uninitialized_default_n and just let
std::fill_n decide whether to do things differently for constant eval ... but I
don't think it's valid.

Reply via email to