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();
+    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