[libcxx-commits] [libcxx] [libc++][test] Make `copy_move_types.h` usable in old modes (PR #199183)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Fri May 22 01:24:44 PDT 2026


https://github.com/frederick-vs-ja created https://github.com/llvm/llvm-project/pull/199183

This PR makes types in `copy_move_types.h` usable in C++03/11 modes. Because it is discovered that some types in `copy_move_types.h` are useful for testing uninitialized memory algorithms in pre-C++20 modes.

>From ab3b17cae65873724e883ca31a9df06dde87ed5d Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Fri, 22 May 2026 16:20:46 +0800
Subject: [PATCH] [libc++][test] Make `copy_move_types.h` usable in old modes

This PR makes types in `copy_move_types.h` usable in C++03/11 modes.
Because it is discovered that some types in `copy_move_types.h` are
useful for testing uninitialized memory algorithms in pre-C++20 modes.
---
 libcxx/test/support/copy_move_types.h | 287 +++++++++++++-------------
 1 file changed, 147 insertions(+), 140 deletions(-)

diff --git a/libcxx/test/support/copy_move_types.h b/libcxx/test/support/copy_move_types.h
index dec8d94cac379..1495eb1957633 100644
--- a/libcxx/test/support/copy_move_types.h
+++ b/libcxx/test/support/copy_move_types.h
@@ -10,134 +10,135 @@
 #define LIBCXX_TEST_STD_UTILITIES_TUPLE_CNSTR_TYPES_H
 
 #include "test_allocator.h"
+#include "test_macros.h"
 #include <type_traits>
 #include <tuple>
+#include <utility>
 
 // Types that can be used to test copy/move operations
 
 struct MutableCopy {
   int val;
-  bool alloc_constructed{false};
+  bool alloc_constructed = false;
 
-  constexpr MutableCopy() = default;
-  constexpr MutableCopy(int _val) : val(_val) {}
-  constexpr MutableCopy(MutableCopy&) = default;
-  constexpr MutableCopy(const MutableCopy&) = delete;
+  MutableCopy() = default;
+  TEST_CONSTEXPR MutableCopy(int _val) : val(_val) {}
+  MutableCopy(MutableCopy&)       = default;
+  MutableCopy(const MutableCopy&) = delete;
 
-  constexpr MutableCopy(std::allocator_arg_t, const test_allocator<int>&, MutableCopy& o)
+  TEST_CONSTEXPR MutableCopy(std::allocator_arg_t, const test_allocator<int>&, MutableCopy& o)
       : val(o.val), alloc_constructed(true) {}
 };
 
 template <>
-struct std::uses_allocator<MutableCopy, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<MutableCopy, test_allocator<int> > : std::true_type {};
 
 struct ConstCopy {
   int val;
-  bool alloc_constructed{false};
+  bool alloc_constructed = false;
 
-  constexpr ConstCopy() = default;
-  constexpr ConstCopy(int _val) : val(_val) {}
-  constexpr ConstCopy(const ConstCopy&) = default;
-  constexpr ConstCopy(ConstCopy&) = delete;
+  ConstCopy() = default;
+  TEST_CONSTEXPR ConstCopy(int _val) : val(_val) {}
+  ConstCopy(const ConstCopy&) = default;
+  ConstCopy(ConstCopy&)       = delete;
 
-  constexpr ConstCopy(std::allocator_arg_t, const test_allocator<int>&, const ConstCopy& o)
+  TEST_CONSTEXPR ConstCopy(std::allocator_arg_t, const test_allocator<int>&, const ConstCopy& o)
       : val(o.val), alloc_constructed(true) {}
 };
 
 template <>
-struct std::uses_allocator<ConstCopy, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<ConstCopy, test_allocator<int> > : std::true_type {};
 
 struct MutableMove {
   int val;
-  bool alloc_constructed{false};
+  bool alloc_constructed = false;
 
-  constexpr MutableMove() = default;
-  constexpr MutableMove(int _val) : val(_val) {}
-  constexpr MutableMove(MutableMove&&) = default;
-  constexpr MutableMove(const MutableMove&&) = delete;
+  MutableMove() = default;
+  TEST_CONSTEXPR MutableMove(int _val) : val(_val) {}
+  MutableMove(MutableMove&&)       = default;
+  MutableMove(const MutableMove&&) = delete;
 
-  constexpr MutableMove(std::allocator_arg_t, const test_allocator<int>&, MutableMove&& o)
+  TEST_CONSTEXPR MutableMove(std::allocator_arg_t, const test_allocator<int>&, MutableMove&& o)
       : val(o.val), alloc_constructed(true) {}
 };
 
 template <>
-struct std::uses_allocator<MutableMove, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<MutableMove, test_allocator<int> > : std::true_type {};
 
 struct ConstMove {
   int val;
-  bool alloc_constructed{false};
+  bool alloc_constructed = false;
 
-  constexpr ConstMove() = default;
-  constexpr ConstMove(int _val) : val(_val) {}
-  constexpr ConstMove(const ConstMove&& o) : val(o.val) {}
-  constexpr ConstMove(ConstMove&&) = delete;
+  ConstMove() = default;
+  TEST_CONSTEXPR ConstMove(int _val) : val(_val) {}
+  TEST_CONSTEXPR ConstMove(const ConstMove&& o) : val(o.val) {}
+  ConstMove(ConstMove&&) = delete;
 
-  constexpr ConstMove(std::allocator_arg_t, const test_allocator<int>&, const ConstMove&& o)
+  TEST_CONSTEXPR ConstMove(std::allocator_arg_t, const test_allocator<int>&, const ConstMove&& o)
       : val(o.val), alloc_constructed(true) {}
 };
 
 template <>
-struct std::uses_allocator<ConstMove, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<ConstMove, test_allocator<int> > : std::true_type {};
 
 template <class T>
 struct ConvertibleFrom {
   T v;
-  bool alloc_constructed{false};
-
-  constexpr ConvertibleFrom() = default;
-  constexpr ConvertibleFrom(T& _v)
-    requires(std::is_constructible_v<T, T&>)
-  : v(_v) {}
-  constexpr ConvertibleFrom(const T& _v)
-    requires(std::is_constructible_v<T, const T&> && !std::is_const_v<T>)
-  : v(_v) {}
-  constexpr ConvertibleFrom(T&& _v)
-    requires(std::is_constructible_v<T, T &&>)
-  : v(std::move(_v)) {}
-  constexpr ConvertibleFrom(const T&& _v)
-    requires(std::is_constructible_v<T, const T &&> && !std::is_const_v<T>)
-  : v(std::move(_v)) {}
-
-  template <class U>
-    requires std::is_constructible_v<ConvertibleFrom, U&&>
-  constexpr ConvertibleFrom(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
-      : ConvertibleFrom{std::forward<U>(_u)} {
+  bool alloc_constructed = false;
+
+  ConvertibleFrom() = default;
+  template <class U = T, typename std::enable_if<std::is_constructible<U, U&>::value, int>::type = 0>
+  TEST_CONSTEXPR ConvertibleFrom(T& _v) : v(_v) {}
+  template <
+      class U                                                                                                   = T,
+      typename std::enable_if<std::is_constructible<U, const U&>::value && !std::is_const<U>::value, int>::type = 0>
+  TEST_CONSTEXPR ConvertibleFrom(const T& _v) : v(_v) {}
+  template <class U = T, typename std::enable_if<std::is_constructible<U, U&&>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 ConvertibleFrom(T&& _v) : v(std::move(_v)) {}
+  template <
+      class U                                                                                                    = T,
+      typename std::enable_if<std::is_constructible<U, const U&&>::value && !std::is_const<U>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 ConvertibleFrom(const T&& _v) : v(std::move(_v)) {}
+
+  template <class U, typename std::enable_if<std::is_constructible<ConvertibleFrom, U&&>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 ConvertibleFrom(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
+      : ConvertibleFrom(std::forward<U>(_u)) {
     alloc_constructed = true;
   }
 };
 
 template <class T>
-struct std::uses_allocator<ConvertibleFrom<T>, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<ConvertibleFrom<T>, test_allocator<int> > : std::true_type {};
 
 template <class T>
 struct ExplicitConstructibleFrom {
   T v;
-  bool alloc_constructed{false};
-
-  constexpr explicit ExplicitConstructibleFrom() = default;
-  constexpr explicit ExplicitConstructibleFrom(T& _v)
-    requires(std::is_constructible_v<T, T&>)
-  : v(_v) {}
-  constexpr explicit ExplicitConstructibleFrom(const T& _v)
-    requires(std::is_constructible_v<T, const T&> && !std::is_const_v<T>)
-  : v(_v) {}
-  constexpr explicit ExplicitConstructibleFrom(T&& _v)
-    requires(std::is_constructible_v<T, T &&>)
-  : v(std::move(_v)) {}
-  constexpr explicit ExplicitConstructibleFrom(const T&& _v)
-    requires(std::is_constructible_v<T, const T &&> && !std::is_const_v<T>)
-  : v(std::move(_v)) {}
-
-  template <class U>
-    requires std::is_constructible_v<ExplicitConstructibleFrom, U&&>
-  constexpr ExplicitConstructibleFrom(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
-      : ExplicitConstructibleFrom{std::forward<U>(_u)} {
+  bool alloc_constructed = false;
+
+  explicit ExplicitConstructibleFrom() = default;
+  template <class U = T, typename std::enable_if<std::is_constructible<U, U&>::value, int>::type = 0>
+  TEST_CONSTEXPR explicit ExplicitConstructibleFrom(T& _v) : v(_v) {}
+  template <
+      class U                                                                                                   = T,
+      typename std::enable_if<std::is_constructible<U, const U&>::value && !std::is_const<U>::value, int>::type = 0>
+  TEST_CONSTEXPR explicit ExplicitConstructibleFrom(const T& _v) : v(_v) {}
+  template <class U = T, typename std::enable_if<std::is_constructible<U, U&&>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 explicit ExplicitConstructibleFrom(T&& _v) : v(std::move(_v)) {}
+  template <
+      class U                                                                                                    = T,
+      typename std::enable_if<std::is_constructible<U, const U&&>::value && !std::is_const<U>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 explicit ExplicitConstructibleFrom(const T&& _v) : v(std::move(_v)) {}
+
+  template <class U,
+            typename std::enable_if<std::is_constructible<ExplicitConstructibleFrom, U&&>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 ExplicitConstructibleFrom(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
+      : ExplicitConstructibleFrom(std::forward<U>(_u)) {
     alloc_constructed = true;
   }
 };
 
 template <class T>
-struct std::uses_allocator<ExplicitConstructibleFrom<T>, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<ExplicitConstructibleFrom<T>, test_allocator<int> > : std::true_type {};
 
 struct TracedCopyMove {
   int nonConstCopy = 0;
@@ -146,172 +147,178 @@ struct TracedCopyMove {
   int constMove = 0;
   bool alloc_constructed = false;
 
-  constexpr TracedCopyMove() = default;
-  constexpr TracedCopyMove(const TracedCopyMove& other)
-      : nonConstCopy(other.nonConstCopy), constCopy(other.constCopy + 1), nonConstMove(other.nonConstMove),
+  TracedCopyMove() = default;
+  TEST_CONSTEXPR TracedCopyMove(const TracedCopyMove& other)
+      : nonConstCopy(other.nonConstCopy),
+        constCopy(other.constCopy + 1),
+        nonConstMove(other.nonConstMove),
         constMove(other.constMove) {}
-  constexpr TracedCopyMove(TracedCopyMove& other)
-      : nonConstCopy(other.nonConstCopy + 1), constCopy(other.constCopy), nonConstMove(other.nonConstMove),
+  TEST_CONSTEXPR TracedCopyMove(TracedCopyMove& other)
+      : nonConstCopy(other.nonConstCopy + 1),
+        constCopy(other.constCopy),
+        nonConstMove(other.nonConstMove),
         constMove(other.constMove) {}
 
-  constexpr TracedCopyMove(TracedCopyMove&& other)
-      : nonConstCopy(other.nonConstCopy), constCopy(other.constCopy), nonConstMove(other.nonConstMove + 1),
+  TEST_CONSTEXPR TracedCopyMove(TracedCopyMove&& other)
+      : nonConstCopy(other.nonConstCopy),
+        constCopy(other.constCopy),
+        nonConstMove(other.nonConstMove + 1),
         constMove(other.constMove) {}
 
-  constexpr TracedCopyMove(const TracedCopyMove&& other)
-      : nonConstCopy(other.nonConstCopy), constCopy(other.constCopy), nonConstMove(other.nonConstMove),
+  TEST_CONSTEXPR TracedCopyMove(const TracedCopyMove&& other)
+      : nonConstCopy(other.nonConstCopy),
+        constCopy(other.constCopy),
+        nonConstMove(other.nonConstMove),
         constMove(other.constMove + 1) {}
 
-  template <class U>
-    requires std::is_constructible_v<TracedCopyMove, U&&>
-  constexpr TracedCopyMove(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
-      : TracedCopyMove{std::forward<U>(_u)} {
+  template <class U, typename std::enable_if<std::is_constructible<TracedCopyMove, U&&>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 TracedCopyMove(std::allocator_arg_t, const test_allocator<int>&, U&& _u)
+      : TracedCopyMove(std::forward<U>(_u)) {
     alloc_constructed = true;
   }
 };
 
 template <>
-struct std::uses_allocator<TracedCopyMove, test_allocator<int>> : std::true_type {};
+struct std::uses_allocator<TracedCopyMove, test_allocator<int> > : std::true_type {};
 
 // If the constructor tuple(tuple<UTypes...>&) is not available,
 // the fallback call to `tuple(const tuple&) = default;` or any other
 // constructor that takes const ref would increment the constCopy.
-inline constexpr bool nonConstCopyCtrCalled(const TracedCopyMove& obj) {
+inline TEST_CONSTEXPR bool nonConstCopyCtrCalled(const TracedCopyMove& obj) {
   return obj.nonConstCopy == 1 && obj.constCopy == 0 && obj.constMove == 0 && obj.nonConstMove == 0;
 }
 
 // If the constructor tuple(const tuple<UTypes...>&&) is not available,
 // the fallback call to `tuple(const tuple&) = default;` or any other
 // constructor that takes const ref would increment the constCopy.
-inline constexpr bool constMoveCtrCalled(const TracedCopyMove& obj) {
+inline TEST_CONSTEXPR bool constMoveCtrCalled(const TracedCopyMove& obj) {
   return obj.nonConstMove == 0 && obj.constMove == 1 && obj.constCopy == 0 && obj.nonConstCopy == 0;
 }
 
 struct NoConstructorFromInt {};
 
+#if TEST_STD_VER >= 11
 struct CvtFromTupleRef : TracedCopyMove {
-  constexpr CvtFromTupleRef() = default;
-  constexpr CvtFromTupleRef(std::tuple<CvtFromTupleRef>& other)
+  CvtFromTupleRef() = default;
+  TEST_CONSTEXPR_CXX14 CvtFromTupleRef(std::tuple<CvtFromTupleRef>& other)
       : TracedCopyMove(static_cast<TracedCopyMove&>(std::get<0>(other))) {}
 };
 
 struct ExplicitCtrFromTupleRef : TracedCopyMove {
-  constexpr explicit ExplicitCtrFromTupleRef() = default;
-  constexpr explicit ExplicitCtrFromTupleRef(std::tuple<ExplicitCtrFromTupleRef>& other)
+  explicit ExplicitCtrFromTupleRef() = default;
+  TEST_CONSTEXPR_CXX14 explicit ExplicitCtrFromTupleRef(std::tuple<ExplicitCtrFromTupleRef>& other)
       : TracedCopyMove(static_cast<TracedCopyMove&>(std::get<0>(other))) {}
 };
 
 struct CvtFromConstTupleRefRef : TracedCopyMove {
-  constexpr CvtFromConstTupleRefRef() = default;
-  constexpr CvtFromConstTupleRefRef(const std::tuple<CvtFromConstTupleRefRef>&& other)
+  CvtFromConstTupleRefRef() = default;
+  TEST_CONSTEXPR_CXX14 CvtFromConstTupleRefRef(const std::tuple<CvtFromConstTupleRefRef>&& other)
       : TracedCopyMove(static_cast<const TracedCopyMove&&>(std::get<0>(other))) {}
 };
 
 struct ExplicitCtrFromConstTupleRefRef : TracedCopyMove {
-  constexpr explicit ExplicitCtrFromConstTupleRefRef() = default;
-  constexpr explicit ExplicitCtrFromConstTupleRefRef(std::tuple<const ExplicitCtrFromConstTupleRefRef>&& other)
+  explicit ExplicitCtrFromConstTupleRefRef() = default;
+  TEST_CONSTEXPR_CXX14 explicit ExplicitCtrFromConstTupleRefRef(
+      std::tuple<const ExplicitCtrFromConstTupleRefRef>&& other)
       : TracedCopyMove(static_cast<const TracedCopyMove&&>(std::get<0>(other))) {}
 };
+#endif
 
+#if TEST_STD_VER >= 20
 template <class T>
 void conversion_test(T);
 
 template <class T, class... Args>
 concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
+#endif
 
 struct CopyAssign {
   int val;
 
-  constexpr CopyAssign() = default;
-  constexpr CopyAssign(int v) : val(v) {}
+  CopyAssign() = default;
+  TEST_CONSTEXPR CopyAssign(int v) : val(v) {}
 
-  constexpr CopyAssign& operator=(const CopyAssign&) = default;
+  CopyAssign& operator=(const CopyAssign&) = default;
 
-  constexpr const CopyAssign& operator=(const CopyAssign&) const = delete;
-  constexpr CopyAssign& operator=(CopyAssign&&) = delete;
-  constexpr const CopyAssign& operator=(CopyAssign&&) const = delete;
+  const CopyAssign& operator=(const CopyAssign&) const = delete;
+  CopyAssign& operator=(CopyAssign&&)                  = delete;
+  const CopyAssign& operator=(CopyAssign&&) const      = delete;
 };
 
 struct ConstCopyAssign {
   mutable int val;
 
-  constexpr ConstCopyAssign() = default;
-  constexpr ConstCopyAssign(int v) : val(v) {}
+  ConstCopyAssign() = default;
+  TEST_CONSTEXPR ConstCopyAssign(int v) : val(v) {}
 
-  constexpr const ConstCopyAssign& operator=(const ConstCopyAssign& other) const {
+  TEST_CONSTEXPR_CXX14 const ConstCopyAssign& operator=(const ConstCopyAssign& other) const {
     val = other.val;
     return *this;
   }
 
-  constexpr ConstCopyAssign& operator=(const ConstCopyAssign&) = delete;
-  constexpr ConstCopyAssign& operator=(ConstCopyAssign&&) = delete;
-  constexpr const ConstCopyAssign& operator=(ConstCopyAssign&&) const = delete;
+  ConstCopyAssign& operator=(const ConstCopyAssign&)        = delete;
+  ConstCopyAssign& operator=(ConstCopyAssign&&)             = delete;
+  const ConstCopyAssign& operator=(ConstCopyAssign&&) const = delete;
 };
 
 struct MoveAssign {
   int val;
 
-  constexpr MoveAssign() = default;
-  constexpr MoveAssign(int v) : val(v) {}
+  MoveAssign() = default;
+  TEST_CONSTEXPR MoveAssign(int v) : val(v) {}
 
-  constexpr MoveAssign& operator=(MoveAssign&&) = default;
+  MoveAssign& operator=(MoveAssign&&) = default;
 
-  constexpr MoveAssign& operator=(const MoveAssign&) = delete;
-  constexpr const MoveAssign& operator=(const MoveAssign&) const = delete;
-  constexpr const MoveAssign& operator=(MoveAssign&&) const = delete;
+  MoveAssign& operator=(const MoveAssign&)             = delete;
+  const MoveAssign& operator=(const MoveAssign&) const = delete;
+  const MoveAssign& operator=(MoveAssign&&) const      = delete;
 };
 
 struct ConstMoveAssign {
   mutable int val;
 
-  constexpr ConstMoveAssign() = default;
-  constexpr ConstMoveAssign(int v) : val(v) {}
+  ConstMoveAssign() = default;
+  TEST_CONSTEXPR ConstMoveAssign(int v) : val(v) {}
 
-  constexpr const ConstMoveAssign& operator=(ConstMoveAssign&& other) const {
+  TEST_CONSTEXPR_CXX14 const ConstMoveAssign& operator=(ConstMoveAssign&& other) const {
     val = other.val;
     return *this;
   }
 
-  constexpr ConstMoveAssign& operator=(const ConstMoveAssign&) = delete;
-  constexpr const ConstMoveAssign& operator=(const ConstMoveAssign&) const = delete;
-  constexpr ConstMoveAssign& operator=(ConstMoveAssign&&) = delete;
+  ConstMoveAssign& operator=(const ConstMoveAssign&)             = delete;
+  const ConstMoveAssign& operator=(const ConstMoveAssign&) const = delete;
+  ConstMoveAssign& operator=(ConstMoveAssign&&)                  = delete;
 };
 
 template <class T>
 struct AssignableFrom {
   T v;
 
-  constexpr AssignableFrom() = default;
+  AssignableFrom() = default;
 
-  template <class U>
-  constexpr AssignableFrom(U&& u)
-    requires std::is_constructible_v<T, U&&>
-  : v(std::forward<U>(u)) {}
+  template <class U, typename std::enable_if<std::is_constructible<T, U&&>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 AssignableFrom(U&& u) : v(std::forward<U>(u)) {}
 
-  constexpr AssignableFrom& operator=(const T& t)
-    requires std::is_copy_assignable_v<T>
-  {
+  template <class U = T, typename std::enable_if<std::is_copy_assignable<U>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 AssignableFrom& operator=(const T& t) {
     v = t;
     return *this;
   }
 
-  constexpr AssignableFrom& operator=(T&& t)
-    requires std::is_move_assignable_v<T>
-  {
+  template <class U = T, typename std::enable_if<std::is_move_assignable<U>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 AssignableFrom& operator=(T&& t) {
     v = std::move(t);
     return *this;
   }
 
-  constexpr const AssignableFrom& operator=(const T& t) const
-    requires std::is_assignable_v<const T&, const T&>
-  {
+  template <class U = T, typename std::enable_if<std::is_assignable<const U&, const U&>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 const AssignableFrom& operator=(const T& t) const {
     v = t;
     return *this;
   }
 
-  constexpr const AssignableFrom& operator=(T&& t) const
-    requires std::is_assignable_v<const T&, T&&>
-  {
+  template <class U = T, typename std::enable_if<std::is_assignable<const U&, U&&>::value, int>::type = 0>
+  TEST_CONSTEXPR_CXX14 const AssignableFrom& operator=(T&& t) const {
     v = std::move(t);
     return *this;
   }
@@ -323,21 +330,21 @@ struct TracedAssignment {
   int moveAssign = 0;
   mutable int constMoveAssign = 0;
 
-  constexpr TracedAssignment() = default;
+  TracedAssignment() = default;
 
-  constexpr TracedAssignment& operator=(const TracedAssignment&) {
+  TEST_CONSTEXPR_CXX14 TracedAssignment& operator=(const TracedAssignment&) {
     copyAssign++;
     return *this;
   }
-  constexpr const TracedAssignment& operator=(const TracedAssignment&) const {
+  TEST_CONSTEXPR_CXX14 const TracedAssignment& operator=(const TracedAssignment&) const {
     constCopyAssign++;
     return *this;
   }
-  constexpr TracedAssignment& operator=(TracedAssignment&&) {
+  TEST_CONSTEXPR_CXX14 TracedAssignment& operator=(TracedAssignment&&) {
     moveAssign++;
     return *this;
   }
-  constexpr const TracedAssignment& operator=(TracedAssignment&&) const {
+  TEST_CONSTEXPR_CXX14 const TracedAssignment& operator=(TracedAssignment&&) const {
     constMoveAssign++;
     return *this;
   }



More information about the libcxx-commits mailing list