On Wed, 1 Oct 2025 at 13:36, Jonathan Wakely <[email protected]> wrote:
>
> I noticed that several tests were doing:
>
> static_assert([] { /* ... */; return true; });
>
> i.e. just testing a lambda, not invoking it and testing the result. This
> change fixes that, so that all the lambdas are invoked.
>
> After fixing that, most of the tests failed because they were using
> __gnu_test::tracker_allocator or std::scoped_allocator_adaptor in
> constexpr functions. The tracker_allocator modifies global state, so can
> never be constexpr, and none of std::scoped_allocator_adaptor's members
> are marked constexpr.
>
> This change makes __gnu_test::uneq_allocator and
> __gnu_test::propagating_allocator usable in constant expressions, which
> allows some of the tests which can't be constexpr to be duplicated to
> new functions which use uneq_allocator or propagating_allocator instead
> of tracker_allocator. This new functions can be tested with the
> static_assert calling a lambda.
>
> In some cases none of the tests could be adapted to be constexpr, so the
> static_assert and lambda were just removed.
>
> Two changes were also needed for the actual library code, because the
> move assignment operators for std::indirect and std::polymorphic were
> using copy-assignment on the allocator. Although the semantics of
> move-assignment for allocators should be equivalent to copy-assignment,
> an allocator isn't actually required to support copy-assignment unless
> propagate_on_container_copy_assignment is true. So we have to use
> move-assignment for propagate_on_container_move_assignment cases.
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/indirect.h (indirect::operator=(indirect&&)):
>         Move assign allocator when POCMA is true.
>         (polymorphic::operator=(polymorphic&&)): Likewise.
>         * testsuite/std/memory/indirect/copy.cc: Remove constexpr from
>         functions that use tracker_allocator. Add test_constexpr().
>         * testsuite/std/memory/indirect/copy_alloc.cc: Remove constexpr
>         from all functions and remove static_assert.
>         * testsuite/std/memory/indirect/ctor.cc: Do not use
>         scoped_allocator_adaptor during constant evaluation.
>         * testsuite/std/memory/indirect/move.cc: Remove constexpr from
>         functions that use tracker_allocator. Add test_constexpr().
>         * testsuite/std/memory/indirect/move_alloc.cc: Remove constexpr
>         from all functions and remove static_assert.
>         * testsuite/std/memory/indirect/relops.cc: Invoke lambda in
>         static_assert.
>         * testsuite/std/memory/polymorphic/copy.cc: Remove constexpr
>         from functions that use tracker_allocator. Add test_constexpr().
>         * testsuite/std/memory/polymorphic/copy_alloc.cc: Remove
>         constexpr from all functions and remove static_assert.
>         * testsuite/std/memory/polymorphic/ctor.cc: Do not use
>         scoped_allocator_adaptor during constant evaluation.
>         * testsuite/std/memory/polymorphic/ctor_poly.cc: Likewise.
>         * testsuite/std/memory/polymorphic/move.cc: Remove constexpr
>         from functions that use tracker_allocator. Add test_constexpr().
>         * testsuite/std/memory/polymorphic/move_alloc.cc: Remove
>         constexpr from all functions and remove static_assert.
>         * testsuite/util/testsuite_allocator.h (tracker_allocator):
>         Remove redundant 'inline' from friend.
>         (uneq_allocator): Make all functions constexpr.
>         (uneq_allocator::base, uneq_allocator::swap_base): Remove.
>         (uneq_allocator::~uneq_allocator): Remove.
>         (uneq_allocator::allocate, uneq_allocator::deallocate): Do not
>         use map of allocations during constant evaluation.
>         (propagating_allocator): Make all functions constexpr.
>         (propagating_allocator::base): Remove.
>         (propagating_allocator::swap_base): Simplify.
>         (ExplicitConsAlloc, CustomPointerAlloc, NullablePointer): Add
>         constexpr to all functions.
> ---
>
> Tested powerpc64le-linux.
>
>  libstdc++-v3/include/bits/indirect.h          |  4 +-
>  .../testsuite/std/memory/indirect/copy.cc     | 55 +++++++++--
>  .../std/memory/indirect/copy_alloc.cc         | 12 +--
>  .../testsuite/std/memory/indirect/ctor.cc     | 11 ++-
>  .../testsuite/std/memory/indirect/move.cc     | 85 ++++++++++++++---
>  .../std/memory/indirect/move_alloc.cc         | 18 ++--
>  .../testsuite/std/memory/indirect/relops.cc   |  2 +-
>  .../testsuite/std/memory/polymorphic/copy.cc  | 55 +++++++++--
>  .../std/memory/polymorphic/copy_alloc.cc      | 24 ++---
>  .../testsuite/std/memory/polymorphic/ctor.cc  | 11 ++-
>  .../std/memory/polymorphic/ctor_poly.cc       |  8 +-
>  .../testsuite/std/memory/polymorphic/move.cc  | 82 +++++++++++++---
>  .../std/memory/polymorphic/move_alloc.cc      | 18 ++--
>  .../testsuite/util/testsuite_allocator.h      | 94 ++++++++++++-------
>  14 files changed, 343 insertions(+), 136 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/indirect.h 
> b/libstdc++-v3/include/bits/indirect.h
> index 89fa8c874fbd..2df46cc39a21 100644
> --- a/libstdc++-v3/include/bits/indirect.h
> +++ b/libstdc++-v3/include/bits/indirect.h
> @@ -263,7 +263,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>         _M_reset(__ptr);
>
>         if constexpr (__pocma)
> -         _M_alloc = __other._M_alloc;
> +         _M_alloc = std::move(__other._M_alloc);
>
>         return *this;
>        }
> @@ -736,7 +736,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>         _M_reset(__ptr);
>
>         if constexpr (__pocma)
> -         _M_alloc = __other._M_alloc;
> +         _M_alloc = std::move(__other._M_alloc);
>
>         return *this;
>        }
> diff --git a/libstdc++-v3/testsuite/std/memory/indirect/copy.cc 
> b/libstdc++-v3/testsuite/std/memory/indirect/copy.cc
> index 0ac6e92a9213..5ecfbbd898f4 100644
> --- a/libstdc++-v3/testsuite/std/memory/indirect/copy.cc
> +++ b/libstdc++-v3/testsuite/std/memory/indirect/copy.cc
> @@ -14,7 +14,7 @@ using Vector = std::vector<int>;
>  using Indirect = std::indirect<Vector, tracker_allocator<Vector>>;
>  const Indirect src(std::in_place, {1, 2, 3});
>
> -constexpr void
> +void
>  test_ctor()
>  {
>    Counter::reset();
> @@ -36,7 +36,7 @@ test_ctor()
>    VERIFY( Counter::get_destruct_count() == 0 );
>  }
>
> -constexpr void
> +void
>  test_assign()
>  {
>    Indirect i1;
> @@ -62,7 +62,7 @@ test_assign()
>    VERIFY( Counter::get_destruct_count() == 0 );
>  }
>
> -constexpr void
> +void
>  test_valueless()
>  {
>    Indirect e;
> @@ -103,19 +103,54 @@ test_valueless()
>  }
>
>  constexpr void
> -test_all()
> +test_constexpr()
>  {
> -  test_ctor();
> -  test_assign();
> -  test_valueless();
> +  using Alloc = __gnu_test::uneq_allocator<Vector>;
> +  using Indirect = std::indirect<Vector, Alloc>;
> +  const Indirect src(std::in_place, {1, 2, 3});
> +
> +  Indirect i1(src);
> +  VERIFY( *i1 == *src );
> +  VERIFY( &*i1 != &*src );
> +  VERIFY( i1.get_allocator() == Alloc{} );
> +
> +  Indirect i2(std::allocator_arg, Alloc{2}, src);
> +  VERIFY( *i2 == *src );
> +  VERIFY( &*i2 != &*src );
> +  VERIFY( i2.get_allocator() == Alloc{2} );
> +
> +  Indirect i3(std::allocator_arg, Alloc{3});
> +  i3 = src;
> +  VERIFY( *i3 == *src );
> +  VERIFY( &*i3 != &*src );
> +  VERIFY( i3.get_allocator() == Alloc{3} );
> +
> +  Indirect e;
> +  auto(std::move(e));
> +  VERIFY( e.valueless_after_move() );
> +
> +  Indirect e1(e);
> +  VERIFY( e1.valueless_after_move() );
> +
> +  Indirect e2(std::allocator_arg, {}, e);
> +  VERIFY( e2.valueless_after_move() );
> +
> +  i3 = e;
> +  VERIFY( i3.valueless_after_move() );
> +
> +  i3 = e;
> +  VERIFY( i3.valueless_after_move() );
>  }
>
>  int main()
>  {
> -  test_all();
> +  test_ctor();
> +  test_assign();
> +  test_valueless();
> +  test_constexpr();
>
>    static_assert([] {
> -    test_all();
> +    test_constexpr();
>      return true;
> -  });
> +  }());
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/indirect/copy_alloc.cc 
> b/libstdc++-v3/testsuite/std/memory/indirect/copy_alloc.cc
> index d5865b9a580d..e48855a0eac5 100644
> --- a/libstdc++-v3/testsuite/std/memory/indirect/copy_alloc.cc
> +++ b/libstdc++-v3/testsuite/std/memory/indirect/copy_alloc.cc
> @@ -13,7 +13,7 @@ using __gnu_test::tracker_allocator;
>  using Counter = __gnu_test::tracker_allocator_counter;
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_ctor()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -59,7 +59,7 @@ test_ctor()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_assign()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -144,7 +144,7 @@ test_assign()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_valueless()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -219,10 +219,4 @@ int main()
>  {
>    test_all<true>();
>    test_all<false>();
> -
> -  static_assert([] {
> -    test_all<true>();
> -    test_all<false>();
> -    return true;
> -  });
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/indirect/ctor.cc 
> b/libstdc++-v3/testsuite/std/memory/indirect/ctor.cc
> index 124874d02fe6..dfd9341582f5 100644
> --- a/libstdc++-v3/testsuite/std/memory/indirect/ctor.cc
> +++ b/libstdc++-v3/testsuite/std/memory/indirect/ctor.cc
> @@ -58,6 +58,9 @@ test_default_ctor()
>    std::indirect<Obj, default_init_allocator<Obj>> i2(std::allocator_arg, a);
>    VERIFY( i2.get_allocator() == a );
>
> +  if (std::is_constant_evaluated())
> +    return;
> +
>    // Object is constructed using allocator-aware constructor.
>    std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc>
>      i3(std::allocator_arg, ScopedAlloc(11, 22));
> @@ -93,6 +96,9 @@ test_forwarding_ctor()
>    std::indirect<Obj> i6(7);
>    VERIFY( i6->i == 7 );
>
> +  if (std::is_constant_evaluated())
> +    return;
> +
>    std::vector<int, UneqAlloc> v{1, 2, 3, 4, 5};
>    // Object is constructed using allocator-aware constructor.
>    std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc>
> @@ -165,6 +171,9 @@ test_inplace_ctor()
>    VERIFY( i10->at(2) == 3 );
>    VERIFY( i10->get_allocator().get_personality() == 42 );
>
> +  if (std::is_constant_evaluated())
> +    return;
> +
>    std::indirect<std::vector<int, UneqAlloc>, ScopedAlloc>
>      i14(std::allocator_arg, ScopedAlloc(11, 22),
>         std::in_place);
> @@ -200,5 +209,5 @@ int main()
>      test_forwarding_ctor();
>      test_inplace_ctor();
>      return true;
> -  });
> +  }());
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/indirect/move.cc 
> b/libstdc++-v3/testsuite/std/memory/indirect/move.cc
> index 6e87c60adb0d..9800f7fd1a79 100644
> --- a/libstdc++-v3/testsuite/std/memory/indirect/move.cc
> +++ b/libstdc++-v3/testsuite/std/memory/indirect/move.cc
> @@ -15,7 +15,7 @@ using Vector = std::vector<int>;
>  using Indirect = std::indirect<Vector, tracker_allocator<Vector>>;
>  const Indirect val(std::in_place, {1, 2, 3});
>
> -constexpr void
> +void
>  verifyNoAllocations()
>  {
>    VERIFY( Counter::get_allocation_count() == 0 );
> @@ -24,7 +24,7 @@ verifyNoAllocations()
>    VERIFY( Counter::get_destruct_count() == 0 );
>  }
>
> -constexpr void
> +void
>  test_ctor()
>  {
>    std::optional<Indirect> src;
> @@ -45,7 +45,7 @@ test_ctor()
>    verifyNoAllocations();
>  }
>
> -constexpr void
> +void
>  test_assign()
>  {
>    std::optional<Indirect> src;
> @@ -72,7 +72,7 @@ test_assign()
>    verifyNoAllocations();
>  }
>
> -constexpr void
> +void
>  test_swap()
>  {
>    const Indirect val1(std::in_place, {1, 2, 3});
> @@ -87,7 +87,7 @@ test_swap()
>    verifyNoAllocations();
>
>    auto(std::move(i1));
> -
> +
>    Counter::reset();
>    i1.swap(i2);
>    VERIFY( *i1 == *val1 );
> @@ -95,7 +95,7 @@ test_swap()
>    verifyNoAllocations();
>  }
>
> -constexpr void
> +void
>  test_valueless()
>  {
>    auto e = [] {
> @@ -125,20 +125,77 @@ test_valueless()
>  }
>
>  constexpr void
> -test_all()
> +test_constexpr()
> +{
> +  using Alloc = __gnu_test::uneq_allocator<Vector>;
> +  using Indirect = std::indirect<Vector, Alloc>;
> +  const Indirect val(std::in_place, {1, 2, 3});
> +
> +  std::optional<Indirect> src;
> +  auto make = [&src, &val] -> Indirect&& {
> +    src.emplace(val);
> +    return std::move(*src);
> +  };
> +
> +  Indirect i1(make());
> +  VERIFY( src->valueless_after_move() );
> +  VERIFY( *i1 == *val );
> +
> +  Indirect i2(std::allocator_arg, {}, make());
> +  VERIFY( src->valueless_after_move() );
> +  VERIFY( *i2 == *val );
> +
> +  i2 = make();
> +  VERIFY( src->valueless_after_move() );
> +  VERIFY( *i2 == *val );
> +
> +  auto(std::move(i2));
> +  i2 = make();
> +  VERIFY( *i2 == *val );
> +  VERIFY( src->valueless_after_move() );
> +
> +  const Indirect val1(std::in_place, {1, 2, 3});
> +  const Indirect val2(std::in_place, {2, 4, 6});
> +
> +  Indirect s1(val1);
> +  Indirect s2(val2);
> +  s1.swap(s2);
> +  VERIFY( *s2 == *val1 );
> +  VERIFY( *s1 == *val2 );
> +
> +  auto(std::move(s1));
> +
> +  s1.swap(s2);
> +  VERIFY( *s1 == *val1 );
> +  VERIFY( s2.valueless_after_move() );
> +
> +  auto e = [] {
> +    Indirect res;
> +    auto(std::move(res));
> +    return res;
> +  };
> +
> +  Indirect e1(e());
> +  VERIFY( e1.valueless_after_move() );
> +
> +  Indirect e2(std::allocator_arg, {}, e());
> +  VERIFY( e2.valueless_after_move() );
> +
> +  Indirect e3(val);
> +  e3 = e();
> +  e3 = e();
> +}
> +
> +int main()
>  {
>    test_ctor();
>    test_assign();
>    test_swap();
>    test_valueless();
> -}
> -
> -int main()
> -{
> -  test_all();
> +  test_constexpr();
>
>    static_assert([] {
> -    test_all();
> +    test_constexpr();
>      return true;
> -  });
> +  }());
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/indirect/move_alloc.cc 
> b/libstdc++-v3/testsuite/std/memory/indirect/move_alloc.cc
> index cd6f90dcdc56..cf35e83310f7 100644
> --- a/libstdc++-v3/testsuite/std/memory/indirect/move_alloc.cc
> +++ b/libstdc++-v3/testsuite/std/memory/indirect/move_alloc.cc
> @@ -13,7 +13,7 @@ using __gnu_test::propagating_allocator;
>  using __gnu_test::tracker_allocator;
>  using Counter = __gnu_test::tracker_allocator_counter;
>
> -constexpr void
> +void
>  verifyNoAllocations()
>  {
>    VERIFY( Counter::get_allocation_count() == 0 );
> @@ -23,7 +23,7 @@ verifyNoAllocations()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_ctor()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -68,7 +68,7 @@ test_ctor()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_assign()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -159,7 +159,7 @@ test_assign()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_swap()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -212,7 +212,7 @@ test_swap()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_valueless()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -274,7 +274,7 @@ test_valueless()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_all()
>  {
>    test_ctor<Propagate>();
> @@ -287,10 +287,4 @@ int main()
>  {
>    test_all<true>();
>    test_all<false>();
> -
> -  static_assert([] {
> -    test_all<true>();
> -    test_all<false>();
> -    return true;
> -  });
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/indirect/relops.cc 
> b/libstdc++-v3/testsuite/std/memory/indirect/relops.cc
> index d77fef2a4306..77d599c80861 100644
> --- a/libstdc++-v3/testsuite/std/memory/indirect/relops.cc
> +++ b/libstdc++-v3/testsuite/std/memory/indirect/relops.cc
> @@ -78,5 +78,5 @@ int main()
>      test_relops();
>      test_comp_with_t();
>      return true;
> -  });
> +  }());
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/copy.cc 
> b/libstdc++-v3/testsuite/std/memory/polymorphic/copy.cc
> index d66cc0657b39..34c78220e320 100644
> --- a/libstdc++-v3/testsuite/std/memory/polymorphic/copy.cc
> +++ b/libstdc++-v3/testsuite/std/memory/polymorphic/copy.cc
> @@ -47,7 +47,7 @@ using Counter = __gnu_test::tracker_allocator_counter;
>  using Polymorphic = std::polymorphic<Base, tracker_allocator<Base>>;
>  const Polymorphic src(std::in_place_type<Derived>, 1, 2, 3);
>
> -constexpr void
> +void
>  test_ctor()
>  {
>    Counter::reset();
> @@ -69,7 +69,7 @@ test_ctor()
>    VERIFY( Counter::get_destruct_count() == 0 );
>  }
>
> -constexpr void
> +void
>  test_assign()
>  {
>    Counter::reset();
> @@ -98,7 +98,7 @@ test_assign()
>    VERIFY( Counter::get_destruct_count() == 0 );
>  }
>
> -constexpr void
> +void
>  test_valueless()
>  {
>    Polymorphic e(std::in_place_type<Derived>);
> @@ -139,19 +139,54 @@ test_valueless()
>  }
>
>  constexpr void
> -test_all()
> +test_constexpr()
>  {
> -  test_ctor();
> -  test_assign();
> -  test_valueless();
> +  using Polymorphic = std::polymorphic<Base, 
> __gnu_test::uneq_allocator<Base>>;
> +  const Polymorphic src(std::in_place_type<Derived>, 1, 2, 3);
> +
> +  Polymorphic i1(src);
> +  VERIFY( *i1 == *src );
> +  VERIFY( &*i1 != &*src );
> +
> +  Polymorphic i2(std::allocator_arg, {}, src);
> +  VERIFY( *i2 == *src );
> +  VERIFY( &*i2 != &*src );
> +
> +  i1 = Polymorphic(std::in_place_type<Derived>);
> +  VERIFY( *i1 != *src );
> +  i1 = src;
> +  VERIFY( *i1 == *src );
> +  VERIFY( &*i1 != &*src );
> +
> +  auto(std::move(i1));
> +  i1 = src;
> +  VERIFY( *i1 == *src );
> +  VERIFY( &*i1 != &*src );
> +
> +  Polymorphic e(std::in_place_type<Derived>);
> +  auto(std::move(e));
> +  VERIFY( e.valueless_after_move() );
> +
> +  Polymorphic e1(e);
> +  VERIFY( e1.valueless_after_move() );
> +
> +  Polymorphic e2(std::allocator_arg, {}, e);
> +  VERIFY( e2.valueless_after_move() );
> +
> +  Polymorphic e3(src);
> +  e3 = e;
> +  VERIFY( e3.valueless_after_move() );
>  }
>
>  int main()
>  {
> -  test_all();
> +  test_ctor();
> +  test_assign();
> +  test_valueless();
> +  test_constexpr();
>
>    static_assert([] {
> -    test_all();
> +    test_constexpr();
>      return true;
> -  });
> +  }());
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/copy_alloc.cc 
> b/libstdc++-v3/testsuite/std/memory/polymorphic/copy_alloc.cc
> index f41c32e1e1de..f149fc860e02 100644
> --- a/libstdc++-v3/testsuite/std/memory/polymorphic/copy_alloc.cc
> +++ b/libstdc++-v3/testsuite/std/memory/polymorphic/copy_alloc.cc
> @@ -9,16 +9,16 @@
>  #include <testsuite_allocator.h>
>
>  struct Base {
> -  friend constexpr
> +  friend
>    bool operator==(const Base& lhs, const Base& rhs)
>    { return lhs.eq(rhs); }
>
> -  virtual constexpr int
> +  virtual int
>    get_alloc_personality() const
>    { return -1; }
>
>  private:
> -  constexpr virtual bool
> +  virtual bool
>    eq(const Base& other) const = 0;
>  };
>
> @@ -29,13 +29,13 @@ struct VecDerived : Base, std::vector<T, Allocator>
>
>    using VecBase::VecBase;
>
> -  constexpr int
> +  int
>    get_alloc_personality() const override
>    { return this->get_allocator().get_personality(); }
>
>  private:
>
> -  constexpr bool
> +  bool
>    eq(const Base& other) const override
>    {
>      if (auto op = dynamic_cast<const VecDerived*>(&other))
> @@ -50,7 +50,7 @@ using __gnu_test::tracker_allocator;
>  using Counter = __gnu_test::tracker_allocator_counter;
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_ctor()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -96,7 +96,7 @@ test_ctor()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_assign()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -185,7 +185,7 @@ test_assign()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_valueless()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -249,7 +249,7 @@ test_valueless()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_all()
>  {
>    test_ctor<Propagate>();
> @@ -261,10 +261,4 @@ int main()
>  {
>    test_all<true>();
>    test_all<false>();
> -
> -  static_assert([] {
> -    test_all<true>();
> -    test_all<false>();
> -    return true;
> -  });
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc 
> b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc
> index bb4c947285e7..4d043db0ea4a 100644
> --- a/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc
> +++ b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor.cc
> @@ -45,6 +45,9 @@ test_default_ctor()
>    std::polymorphic<Obj, default_init_allocator<Obj>> i2(std::allocator_arg, 
> a);
>    VERIFY( i2.get_allocator() == a );
>
> +  if (std::is_constant_evaluated())
> +    return;
> +
>    // Object is constructed using allocator-aware constructor.
>    std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
>      i3(std::allocator_arg, ScopedAlloc(11, 22));
> @@ -76,6 +79,9 @@ test_forwarding_ctor()
>    std::polymorphic<Obj> i5({1, {'2', '3'}});
>    verify(i5);
>
> +  if (std::is_constant_evaluated())
> +    return;
> +
>    std::vector<int, UneqAlloc> v{1, 2, 3, 4, 5};
>    // Object is constructed using allocator-aware constructor.
>    std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
> @@ -151,6 +157,9 @@ test_inplace_ctor()
>    VERIFY( i10->at(2) == 3 );
>    VERIFY( i10->get_allocator().get_personality() == 42 );
>
> +  if (std::is_constant_evaluated())
> +    return;
> +
>    std::polymorphic<std::vector<int, UneqAlloc>, ScopedAlloc>
>      i14(std::allocator_arg, ScopedAlloc(11, 22),
>         std::in_place_type<std::vector<int, UneqAlloc>>);
> @@ -186,5 +195,5 @@ int main()
>      test_forwarding_ctor();
>      test_inplace_ctor();
>      return true;
> -  });
> +  }());
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc 
> b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc
> index 03519a1db004..cb18031a9037 100644
> --- a/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc
> +++ b/libstdc++-v3/testsuite/std/memory/polymorphic/ctor_poly.cc
> @@ -126,6 +126,9 @@ test_forwarding_ctor()
>    VERIFY( *i4 == src );
>    VERIFY( i4->get_personality() == -2 );
>
> +  if (std::is_constant_evaluated())
> +    return;
> +
>    const VecDerived<int, UneqAlloc> v{1, 2, 3, 4, 5};
>    // Object is constructed using allocator-aware constructor.
>    std::polymorphic<Base, ScopedAlloc>
> @@ -183,6 +186,9 @@ test_inplace_ctor()
>    VERIFY( *i7 == il  );
>    VERIFY( i7->get_personality() == 42 );
>
> +  if (std::is_constant_evaluated())
> +    return;
> +
>    std::polymorphic<Base, ScopedAlloc>
>      i8(std::allocator_arg, ScopedAlloc(11, 22),
>         std::in_place_type<VecDerived<int, UneqAlloc>>);
> @@ -216,5 +222,5 @@ int main()
>      test_forwarding_ctor();
>      test_inplace_ctor();
>      return true;
> -  });
> +  }());
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/move.cc 
> b/libstdc++-v3/testsuite/std/memory/polymorphic/move.cc
> index c80215983b6c..d267994b36a4 100644
> --- a/libstdc++-v3/testsuite/std/memory/polymorphic/move.cc
> +++ b/libstdc++-v3/testsuite/std/memory/polymorphic/move.cc
> @@ -48,7 +48,7 @@ using Counter = __gnu_test::tracker_allocator_counter;
>  using Polymorphic = std::polymorphic<Base, tracker_allocator<Base>>;
>  const Polymorphic val(std::in_place_type<Derived>, 1, 2, 3);
>
> -constexpr void
> +void
>  verifyNoAllocations()
>  {
>    VERIFY( Counter::get_allocation_count() == 0 );
> @@ -57,7 +57,7 @@ verifyNoAllocations()
>    VERIFY( Counter::get_destruct_count() == 0 );
>  }
>
> -constexpr void
> +void
>  test_ctor()
>  {
>    std::optional<Polymorphic> src;
> @@ -78,7 +78,7 @@ test_ctor()
>    verifyNoAllocations();
>  }
>
> -constexpr void
> +void
>  test_assign()
>  {
>    std::optional<Polymorphic> src;
> @@ -105,7 +105,7 @@ test_assign()
>    verifyNoAllocations();
>  }
>
> -constexpr void
> +void
>  test_swap()
>  {
>    const Polymorphic val1(std::in_place_type<Derived>, 1, 2, 3);
> @@ -128,7 +128,7 @@ test_swap()
>    verifyNoAllocations();
>  }
>
> -constexpr void
> +void
>  test_valueless()
>  {
>    auto e = [] {
> @@ -158,20 +158,76 @@ test_valueless()
>  }
>
>  constexpr void
> -test_all()
> +test_constexpr()
> +{
> +  using Polymorphic = std::polymorphic<Base, 
> __gnu_test::uneq_allocator<Base>>;
> +  const Polymorphic val(std::in_place_type<Derived>, 1, 2, 3);
> +
> +  std::optional<Polymorphic> src;
> +  auto make = [&src, &val] -> Polymorphic&& {
> +    src.emplace(val);
> +    return std::move(*src);
> +  };
> +
> +  Polymorphic i1(make());
> +  VERIFY( src->valueless_after_move() );
> +  VERIFY( *i1 == *val );
> +
> +  Polymorphic i2(std::allocator_arg, {}, make());
> +  VERIFY( src->valueless_after_move() );
> +  VERIFY( *i2 == *val );
> +
> +  i1 = make();
> +  VERIFY( src->valueless_after_move() );
> +  VERIFY( *i1 == *val );
> +
> +  auto(std::move(i1));
> +  i1 = make();
> +  VERIFY( *i1 == *val );
> +  VERIFY( src->valueless_after_move() );
> +
> +  const Polymorphic val1(std::in_place_type<Derived>, 1, 2, 3);
> +  const Polymorphic val2(std::in_place_type<Derived>, 2, 4, 6);
> +
> +  Polymorphic s1(val1);
> +  Polymorphic s2(val2);
> +  s1.swap(s2);
> +  VERIFY( *s2 == *val1 );
> +  VERIFY( *s1 == *val2 );
> +
> +  auto(std::move(s1));
> +  s1.swap(s2);
> +  VERIFY( *s1 == *val1 );
> +  VERIFY( s2.valueless_after_move() );
> +
> +  auto e = [] {
> +    Polymorphic res(std::in_place_type<Derived>);
> +    auto(std::move(res));
> +    Counter::reset();

The line above needs to be removed, I missed that this one still failed.

> +    return res;
> +  };
> +
> +  Polymorphic e1(e());
> +  VERIFY( e1.valueless_after_move() );
> +
> +  Polymorphic e2(std::allocator_arg, {}, e());
> +  VERIFY( e2.valueless_after_move() );
> +
> +  Polymorphic e3(val);
> +  e3 = e();
> +  e3 = e();
> +}
> +
> +int main()
>  {
>    test_ctor();
>    test_assign();
>    test_swap();
>    test_valueless();
> -}
> -
> -int main()
> -{
> -  test_all();
> +  test_constexpr();
>
>    static_assert([] {
> -    test_all();
> +    test_constexpr();
>      return true;
> -  });
> +  }());
>  }
> diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/move_alloc.cc 
> b/libstdc++-v3/testsuite/std/memory/polymorphic/move_alloc.cc
> index 09afedb78848..490bffb8c392 100644
> --- a/libstdc++-v3/testsuite/std/memory/polymorphic/move_alloc.cc
> +++ b/libstdc++-v3/testsuite/std/memory/polymorphic/move_alloc.cc
> @@ -50,7 +50,7 @@ using __gnu_test::propagating_allocator;
>  using __gnu_test::tracker_allocator;
>  using Counter = __gnu_test::tracker_allocator_counter;
>
> -constexpr void
> +void
>  verifyNoAllocations()
>  {
>    VERIFY( Counter::get_allocation_count() == 0 );
> @@ -60,7 +60,7 @@ verifyNoAllocations()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_ctor()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -105,7 +105,7 @@ test_ctor()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_assign()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -201,7 +201,7 @@ test_assign()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_swap()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -254,7 +254,7 @@ test_swap()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_valueless()
>  {
>    using PropAlloc = propagating_allocator<int, Propagate>;
> @@ -317,7 +317,7 @@ test_valueless()
>  }
>
>  template<bool Propagate>
> -constexpr void
> +void
>  test_all()
>  {
>    test_ctor<Propagate>();
> @@ -330,10 +330,4 @@ int main()
>  {
>    test_all<true>();
>    test_all<false>();
> -
> -  static_assert([] {
> -    test_all<true>();
> -    test_all<false>();
> -    return true;
> -  });
>  }
> diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h 
> b/libstdc++-v3/testsuite/util/testsuite_allocator.h
> index ee9575266a00..fabbef03f875 100644
> --- a/libstdc++-v3/testsuite/util/testsuite_allocator.h
> +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h
> @@ -43,6 +43,11 @@ namespace unord = std;
>  namespace unord = std::tr1;
>  #endif
>
> +#ifndef __cpp_constexpr
> +// Ignore the constexpr keywords below when compiled as C++98
> +# define constexpr
> +#endif
> +
>  namespace __gnu_test
>  {
>    // A common API for calling max_size() on an allocator in any -std mode.
> @@ -216,7 +221,7 @@ namespace __gnu_test
>        }
>
>        // Implement swap for underlying allocators that might need it.
> -      friend inline void
> +      friend void
>        swap(tracker_allocator& a, tracker_allocator& b)
>        {
>         using std::swap;
> @@ -310,10 +315,6 @@ namespace __gnu_test
>      {
>        typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
>
> -      Alloc& base() { return *this; }
> -      const Alloc& base() const  { return *this; }
> -      void swap_base(Alloc& b) { using std::swap; swap(b, this->base()); }
> -
>      public:
>        typedef typename check_consistent_alloc_value_type<Tp, 
> Alloc>::value_type
>         value_type;
> @@ -332,9 +333,11 @@ namespace __gnu_test
>                 typename AllocTraits::template rebind<Tp1>::other> other;
>         };
>
> +      constexpr
>        uneq_allocator() _GLIBCXX_USE_NOEXCEPT
>        : personality(0) { }
>
> +      constexpr
>        uneq_allocator(int person) _GLIBCXX_USE_NOEXCEPT
>        : personality(person) { }
>
> @@ -344,21 +347,23 @@ namespace __gnu_test
>  #endif
>
>        template<typename Tp1>
> +       constexpr
>         uneq_allocator(const uneq_allocator<Tp1,
>                        typename AllocTraits::template rebind<Tp1>::other>& b)
>         _GLIBCXX_USE_NOEXCEPT
>         : personality(b.get_personality()) { }
>
> -      ~uneq_allocator() _GLIBCXX_USE_NOEXCEPT
> -      { }
> -
> -      int get_personality() const { return personality; }
> +      constexpr int get_personality() const { return personality; }
>
> +      _GLIBCXX20_CONSTEXPR
>        pointer
>        allocate(size_type n, const void* = 0)
>        {
>         pointer p = AllocTraits::allocate(*this, n);
>
> +       if (std::__is_constant_evaluated())
> +         return p;
> +
>         try
>           {
>             get_map().insert(map_type::value_type(reinterpret_cast<void*>(p),
> @@ -373,19 +378,24 @@ namespace __gnu_test
>         return p;
>        }
>
> +      _GLIBCXX14_CONSTEXPR
>        void
>        deallocate(pointer p, size_type n)
>        {
>         VERIFY( p );
>
> -       map_type::iterator it = get_map().find(reinterpret_cast<void*>(p));
> -       VERIFY( it != get_map().end() );
> +       if (!std::__is_constant_evaluated())
> +         {
> +           map_type::iterator it = 
> get_map().find(reinterpret_cast<void*>(p));
> +           VERIFY( it != get_map().end() );
>
> -       // Enforce requirements in Table 32 about deallocation vs
> -       // allocator equality.
> -       VERIFY( it->second == personality );
> +           // Enforce requirements in Table 32 about deallocation vs
> +           // allocator equality.
> +           VERIFY( it->second == personality );
> +
> +           get_map().erase(it);
> +         }
>
> -       get_map().erase(it);
>         AllocTraits::deallocate(*this, p, n);
>        }
>
> @@ -406,22 +416,23 @@ namespace __gnu_test
>
>      private:
>        // ... yet swappable!
> -      friend inline void
> +      friend constexpr void
>        swap(uneq_allocator& a, uneq_allocator& b)
>        {
>         std::swap(a.personality, b.personality);
> -       a.swap_base(b);
> +       using std::swap;
> +       swap(static_cast<Alloc&>(a), static_cast<Alloc&>(b));
>        }
>
>        template<typename Tp1>
> -       friend inline bool
> +       friend constexpr bool
>         operator==(const uneq_allocator& a,
>                    const uneq_allocator<Tp1,
>                    typename AllocTraits::template rebind<Tp1>::other>& b)
>         { return a.personality == b.get_personality(); }
>
>        template<typename Tp1>
> -       friend inline bool
> +       friend constexpr bool
>         operator!=(const uneq_allocator& a,
>                    const uneq_allocator<Tp1,
>                    typename AllocTraits::template rebind<Tp1>::other>& b)
> @@ -438,9 +449,12 @@ namespace __gnu_test
>        typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
>
>        typedef uneq_allocator<Tp, Alloc> base_alloc;
> -      base_alloc& base() { return *this; }
> -      const base_alloc& base() const  { return *this; }
> -      void swap_base(base_alloc& b) { swap(b, this->base()); }
> +      _GLIBCXX14_CONSTEXPR void
> +      swap_base(base_alloc& b)
> +      {
> +       using std::swap;
> +       swap(b, static_cast<base_alloc&>(*this));
> +      }
>
>        typedef std::integral_constant<bool, Propagate> trait_type;
>
> @@ -454,11 +468,13 @@ namespace __gnu_test
>                 typename AllocTraits::template rebind<Up>::other> other;
>         };
>
> +      constexpr
>        propagating_allocator(int i) noexcept
>        : base_alloc(i)
>        { }
>
>        template<typename Up>
> +       constexpr
>         propagating_allocator(const propagating_allocator<Up, Propagate,
>                               typename AllocTraits::template 
> rebind<Up>::other>& a)
>         noexcept
> @@ -469,6 +485,7 @@ namespace __gnu_test
>
>        propagating_allocator(const propagating_allocator&) noexcept = default;
>
> +      _GLIBCXX14_CONSTEXPR
>        propagating_allocator&
>        operator=(const propagating_allocator& a) noexcept
>        {
> @@ -478,6 +495,7 @@ namespace __gnu_test
>        }
>
>        template<bool P2>
> +       _GLIBCXX14_CONSTEXPR
>         propagating_allocator&
>         operator=(const propagating_allocator<Tp, P2, Alloc>& a) noexcept
>         {
> @@ -487,11 +505,13 @@ namespace __gnu_test
>         }
>
>        // postcondition: LWG2593 a.get_personality() un-changed.
> +      constexpr
>        propagating_allocator(propagating_allocator&& a) noexcept
> -      : base_alloc(std::move(a.base()))
> +      : base_alloc(static_cast<base_alloc&&>(a))
>        { }
>
>        // postcondition: LWG2593 a.get_personality() un-changed
> +      _GLIBCXX14_CONSTEXPR
>        propagating_allocator&
>        operator=(propagating_allocator&& a) noexcept
>        {
> @@ -503,7 +523,8 @@ namespace __gnu_test
>        typedef trait_type propagate_on_container_move_assignment;
>        typedef trait_type propagate_on_container_swap;
>
> -      propagating_allocator select_on_container_copy_construction() const
> +      constexpr propagating_allocator
> +      select_on_container_copy_construction() const
>        { return Propagate ? *this : propagating_allocator(); }
>      };
>
> @@ -551,11 +572,11 @@ namespace __gnu_test
>           : state(a.state)
>          { }
>
> -      constexpr T*
> +      _GLIBCXX14_CONSTEXPR T*
>        allocate(std::size_t n)
>        { return std::allocator<T>().allocate(n); }
>
> -      constexpr void
> +      _GLIBCXX14_CONSTEXPR void
>        deallocate(T* p, std::size_t n)
>        { std::allocator<T>().deallocate(p, n); }
>
> @@ -581,7 +602,7 @@ namespace __gnu_test
>        ExplicitConsAlloc() { }
>
>        template<typename Up>
> -        explicit
> +        explicit constexpr
>          ExplicitConsAlloc(const ExplicitConsAlloc<Up>&) { }
>
>        template<typename Up>
> @@ -600,6 +621,7 @@ namespace __gnu_test
>        CustomPointerAlloc() = default;
>
>        template<typename Up>
> +       constexpr
>          CustomPointerAlloc(const CustomPointerAlloc<Up>&) { }
>
>        template<typename Up>
> @@ -611,9 +633,11 @@ namespace __gnu_test
>        typedef Ptr<void>                void_pointer;
>        typedef Ptr<const void>  const_void_pointer;
>
> +      _GLIBCXX14_CONSTEXPR
>        pointer allocate(std::size_t n, const_void_pointer = {})
>        { return pointer(std::allocator<Tp>::allocate(n)); }
>
> +      _GLIBCXX14_CONSTEXPR
>        void deallocate(pointer p, std::size_t n)
>        { std::allocator<Tp>::deallocate(std::addressof(*p), n); }
>      };
> @@ -631,16 +655,16 @@ namespace __gnu_test
>
>        explicit operator bool() const noexcept { return value != nullptr; }
>
> -      friend inline bool
> +      friend constexpr bool
>        operator==(NullablePointer lhs, NullablePointer rhs) noexcept
>        { return lhs.value == rhs.value; }
>
> -      friend inline bool
> +      friend constexpr bool
>        operator!=(NullablePointer lhs, NullablePointer rhs) noexcept
>        { return lhs.value != rhs.value; }
>
>      protected:
> -      explicit NullablePointer(Ptr p) noexcept : value(p) { }
> +      constexpr explicit NullablePointer(Ptr p) noexcept : value(p) { }
>        Ptr value;
>      };
>
> @@ -649,16 +673,16 @@ namespace __gnu_test
>      struct NullablePointer<void>
>      {
>        NullablePointer() = default;
> -      NullablePointer(std::nullptr_t) noexcept { }
> -      explicit NullablePointer(const volatile void*) noexcept { }
> +      constexpr NullablePointer(std::nullptr_t) noexcept { }
> +      constexpr explicit NullablePointer(const volatile void*) noexcept { }
>
> -      explicit operator bool() const noexcept { return false; }
> +      constexpr explicit operator bool() const noexcept { return false; }
>
> -      friend inline bool
> +      friend constexpr bool
>        operator==(NullablePointer, NullablePointer) noexcept
>        { return true; }
>
> -      friend inline bool
> +      friend constexpr bool
>        operator!=(NullablePointer, NullablePointer) noexcept
>        { return false; }
>      };
> --
> 2.51.0
>

Reply via email to