[libcxx-commits] [libcxx] [libc++] restrict the expected conversion constructor not compete against copy constructor (PR #96101)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jun 22 08:00:40 PDT 2024


https://github.com/huixie90 updated https://github.com/llvm/llvm-project/pull/96101

>From 317403b8d6c73492fe4449a7339ea1d7916bd3d2 Mon Sep 17 00:00:00 2001
From: Hui <hui.xie0621 at gmail.com>
Date: Wed, 19 Jun 2024 19:50:23 +0100
Subject: [PATCH 1/3] [libc++] restrict the expected conversion constructor not
 compete against copy constructor

---
 libcxx/include/__expected/expected.h           |  4 +++-
 .../expected.expected/ctor/ctor.copy.pass.cpp  | 18 ++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 0f994e297a877..da0a0fa85714c 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -507,7 +507,9 @@ class expected : private __expected_base<_Tp, _Err> {
       _And< is_constructible<_Tp, _UfQual>,
             is_constructible<_Err, _OtherErrQual>,
             _If<_Not<is_same<remove_cv_t<_Tp>, bool>>::value,
-                _And< _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>,
+                _And< 
+                      _Not<_And<is_same<_Tp, _Up>, is_same<_Err, _OtherErr>>>,
+                      _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>,
                       _Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>,
                       _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>,
                       _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>>>,
diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
index 581df51207da2..6c278be9de98a 100644
--- a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
@@ -62,6 +62,17 @@ static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonT
 static_assert(!std::is_trivially_copy_constructible_v<std::expected<int, CopyableNonTrivial>>);
 static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonTrivial, CopyableNonTrivial>>);
 
+
+struct Any {
+  constexpr Any() = default;
+  constexpr Any(const Any&) = default;
+  constexpr Any& operator=(const Any&)=default;
+
+  template <class T>
+    requires (!std::is_same_v<Any, std::decay_t<T>> && std::is_copy_constructible_v<std::decay_t<T>>)
+  constexpr Any(T&&){}
+};
+
 constexpr bool test() {
   // copy the value non-trivial
   {
@@ -109,6 +120,13 @@ constexpr bool test() {
     assert(!e2.has_value());
   }
 
+  {
+    // https://github.com/llvm/llvm-project/issues/92676
+    std::expected<Any, int> e1;
+    auto e2 = e1;
+    assert(e2.has_value());
+  }
+
   return true;
 }
 

>From 0223db90ffcde4536bc4b7c21745b5e723859bbe Mon Sep 17 00:00:00 2001
From: Hui <hui.xie0621 at gmail.com>
Date: Sat, 22 Jun 2024 14:05:03 +0100
Subject: [PATCH 2/3] filter clang 17

---
 libcxx/include/__expected/expected.h               |  2 +-
 .../expected.expected/ctor/ctor.copy.pass.cpp      | 14 ++++++++------
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index da0a0fa85714c..f618b20603e60 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -508,7 +508,7 @@ class expected : private __expected_base<_Tp, _Err> {
             is_constructible<_Err, _OtherErrQual>,
             _If<_Not<is_same<remove_cv_t<_Tp>, bool>>::value,
                 _And< 
-                      _Not<_And<is_same<_Tp, _Up>, is_same<_Err, _OtherErr>>>,
+                      _Not<_And<is_same<_Tp, _Up>, is_same<_Err, _OtherErr>>>, // use the copy constructor instead, see #92676
                       _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>,
                       _Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>,
                       _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>,
diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
index 6c278be9de98a..eae3b8830532c 100644
--- a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
@@ -62,15 +62,14 @@ static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonT
 static_assert(!std::is_trivially_copy_constructible_v<std::expected<int, CopyableNonTrivial>>);
 static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonTrivial, CopyableNonTrivial>>);
 
-
 struct Any {
-  constexpr Any() = default;
-  constexpr Any(const Any&) = default;
-  constexpr Any& operator=(const Any&)=default;
+  constexpr Any()                      = default;
+  constexpr Any(const Any&)            = default;
+  constexpr Any& operator=(const Any&) = default;
 
   template <class T>
-    requires (!std::is_same_v<Any, std::decay_t<T>> && std::is_copy_constructible_v<std::decay_t<T>>)
-  constexpr Any(T&&){}
+    requires(!std::is_same_v<Any, std::decay_t<T>> && std::is_copy_constructible_v<std::decay_t<T>>)
+  constexpr Any(T&&) {}
 };
 
 constexpr bool test() {
@@ -121,10 +120,13 @@ constexpr bool test() {
   }
 
   {
+    // TODO(LLVM 20): Remove once we drop support for Clang 17
+#if defined(TEST_CLANG_VER) && TEST_CLANG_VER >= 1700
     // https://github.com/llvm/llvm-project/issues/92676
     std::expected<Any, int> e1;
     auto e2 = e1;
     assert(e2.has_value());
+#endif
   }
 
   return true;

>From 19bb14df6a664f41dc4618ac3229bd2e2cafb9c8 Mon Sep 17 00:00:00 2001
From: Hui <hui.xie0621 at gmail.com>
Date: Sat, 22 Jun 2024 16:00:27 +0100
Subject: [PATCH 3/3] clang17

---
 .../expected/expected.expected/ctor/ctor.copy.pass.cpp          | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
index eae3b8830532c..2fff97a87b0f3 100644
--- a/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.copy.pass.cpp
@@ -62,6 +62,7 @@ static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonT
 static_assert(!std::is_trivially_copy_constructible_v<std::expected<int, CopyableNonTrivial>>);
 static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonTrivial, CopyableNonTrivial>>);
 
+#if defined(TEST_CLANG_VER) && TEST_CLANG_VER >= 1700
 struct Any {
   constexpr Any()                      = default;
   constexpr Any(const Any&)            = default;
@@ -71,6 +72,7 @@ struct Any {
     requires(!std::is_same_v<Any, std::decay_t<T>> && std::is_copy_constructible_v<std::decay_t<T>>)
   constexpr Any(T&&) {}
 };
+#endif
 
 constexpr bool test() {
   // copy the value non-trivial



More information about the libcxx-commits mailing list