On Mon, 2 Feb 2026 at 19:37, Marek Polacek <[email protected]> wrote:
>
> Bootstrapped/regtested on ppc64le-pc-linux-gnu, ok for trunk?
>
> -- >8 --
> [allocator.members] says that allocator::{,de}allocate should be
> constexpr but currently we don't mark them as such.  I had to

We do mark std::allocator::allocate and deallocate, the ones you're
changing below are std::__new_allocator::allocate and
std::__new_allocator::deallocate, which should never be used during
constant eval:

include/bits/allocator.h has:

#if __cplusplus > 201703L
      [[nodiscard,__gnu__::__always_inline__]]
      constexpr _Tp*
      allocate(size_t __n)
      {
        if (std::__is_constant_evaluated())
          {
            if (__builtin_mul_overflow(__n, sizeof(_Tp), &__n))
              std::__throw_bad_array_new_length();
            return static_cast<_Tp*>(::operator new(__n));
          }

        return __allocator_base<_Tp>::allocate(__n, 0);
      }

      [[__gnu__::__always_inline__]]
      constexpr void
      deallocate(_Tp* __p, size_t __n)
      {
        if (std::__is_constant_evaluated())
          {
            ::operator delete(__p);
            return;
          }
        __allocator_base<_Tp>::deallocate(__p, __n);
      }
#endif // C++20


and __allocator_base is __new_allocator (for the default configure
flags anyway).

So I'm surprised that the __new_allocator members need fixing. Why
does the reflection code ever end up looking at the __new_allocator
members?

> work around that in the Reflection code, but it would be better to
> clean this up.  (I see no allocation_result so I'm not changing that.)

Right, that's not implemented yet.

>
> gcc/cp/ChangeLog:
>
>         * constexpr.cc (is_std_allocator): Don't check for __new_allocator.
>         (is_std_allocator_allocate): Make static.
>         * cp-tree.h (is_std_allocator_allocate): Remove declaration.
>         * reflect.cc (check_out_of_consteval_use): Don't call
>         is_std_allocator_allocate.
>         (check_consteval_only_fn): Likewise.
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/new_allocator.h (__new_allocator::allocate,
>         __new_allocator::deallocate): Add missing constexpr.
> ---
>  gcc/cp/constexpr.cc                       | 6 ++----
>  gcc/cp/cp-tree.h                          | 1 -
>  gcc/cp/reflect.cc                         | 9 +++------
>  libstdc++-v3/include/bits/new_allocator.h | 4 ++--
>  4 files changed, 7 insertions(+), 13 deletions(-)
>
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index a31fe6b113a..a5ccd276a88 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -3247,14 +3247,12 @@ is_std_class (tree ctx, const char *name)
>  bool
>  is_std_allocator (tree ctx)
>  {
> -  return (is_std_class (ctx, "allocator")
> -         || (flag_reflection
> -             && is_std_class (ctx, "__new_allocator")));
> +  return is_std_class (ctx, "allocator");
>  }
>
>  /* Return true if FNDECL is std::allocator<T>::{,de}allocate.  */
>
> -bool
> +static bool
>  is_std_allocator_allocate (tree fndecl)
>  {
>    tree name = DECL_NAME (fndecl);
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 59ab4e40430..1045dfd6014 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -9259,7 +9259,6 @@ extern bool is_nondependent_static_init_expression 
> (tree);
>  extern bool is_static_init_expression    (tree);
>  extern bool is_std_class (tree, const char *);
>  extern bool is_std_allocator (tree);
> -extern bool is_std_allocator_allocate (tree);
>  extern bool potential_rvalue_constant_expression (tree);
>  extern bool require_potential_constant_expression (tree);
>  extern bool require_constant_expression (tree);
> diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
> index 24b8d744810..fe417960acf 100644
> --- a/gcc/cp/reflect.cc
> +++ b/gcc/cp/reflect.cc
> @@ -8154,11 +8154,9 @@ check_out_of_consteval_use (tree expr, bool 
> complain/*=true*/)
>        if (!consteval_only_p (t))
>         return NULL_TREE;
>
> +      /* Already escalated?  */
>        if (current_function_decl
> -         /* Already escalated.  */
> -         && (DECL_IMMEDIATE_FUNCTION_P (current_function_decl)
> -             /* These functions are magic.  */
> -             || is_std_allocator_allocate (current_function_decl)))
> +         && DECL_IMMEDIATE_FUNCTION_P (current_function_decl))
>         {
>           *walk_subtrees = false;
>           return NULL_TREE;
> @@ -8305,8 +8303,7 @@ check_consteval_only_fn (tree decl)
>    if (!DECL_IMMEDIATE_FUNCTION_P (decl)
>        && consteval_only_p (decl)
>        /* But if the function can be escalated, merrily we roll along.  */
> -      && !immediate_escalating_function_p (decl)
> -      && !is_std_allocator_allocate (decl))
> +      && !immediate_escalating_function_p (decl))
>      error_at (DECL_SOURCE_LOCATION (decl),
>               "function of consteval-only type must be declared %qs",
>               "consteval");
> diff --git a/libstdc++-v3/include/bits/new_allocator.h 
> b/libstdc++-v3/include/bits/new_allocator.h
> index 5701b8dd254..4fe67f99e5c 100644
> --- a/libstdc++-v3/include/bits/new_allocator.h
> +++ b/libstdc++-v3/include/bits/new_allocator.h
> @@ -122,7 +122,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>        // NB: __n is permitted to be 0.  The C++ standard says nothing
>        // about what the return value is when __n == 0.
> -      _GLIBCXX_NODISCARD _Tp*
> +      _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _Tp*
>        allocate(size_type __n, const void* = static_cast<const void*>(0))
>        {
>  #if __cplusplus >= 201103L
> @@ -152,7 +152,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        }
>
>        // __p is not permitted to be a null pointer.
> -      void
> +      _GLIBCXX20_CONSTEXPR void
>        deallocate(_Tp* __p, size_type __n __attribute__ ((__unused__)))
>        {
>  #if __cpp_sized_deallocation
>
> base-commit: e02eba0dc7d1aa62c5edf7108e641bcb5c5584b8
> --
> 2.52.0
>

Reply via email to