Author: A. Jiang
Date: 2026-02-06T09:20:02Z
New Revision: 88b78bcec6676b24ced83d684467a34133d63659

URL: 
https://github.com/llvm/llvm-project/commit/88b78bcec6676b24ced83d684467a34133d63659
DIFF: 
https://github.com/llvm/llvm-project/commit/88b78bcec6676b24ced83d684467a34133d63659.diff

LOG: [libc++] Short-cut constraints of single-argument `any` constructor 
(#177082)

When a default template argument of a function template uses
`std::is_copy_constructible<T>::value` and `T` is convertible from and
to `any`, the changes in 21dc73f6a46cd786394f10f5aef46ec4a2d26175 would
introduce constraint meta-recursion when compiling with Clang.

This patch short-cuts constraints of the related constructor to avoid
computing `is_copy_constructible<T>` when `decay_t<T>` is `any`, which
gets rid of constraint meta-recursion in the overload resolution of copy
construction of `T`.

Fixes #176877.

(cherry picked from commit aa5428864e86f8e38806fc92d14cadc68b3d0667)

Added: 
    

Modified: 
    libcxx/include/any
    libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/any b/libcxx/include/any
index 382a7c894b86b..d9368df75296e 100644
--- a/libcxx/include/any
+++ b/libcxx/include/any
@@ -89,6 +89,7 @@ namespace std {
 #  include <__type_traits/add_cv_quals.h>
 #  include <__type_traits/add_pointer.h>
 #  include <__type_traits/conditional.h>
+#  include <__type_traits/conjunction.h>
 #  include <__type_traits/decay.h>
 #  include <__type_traits/enable_if.h>
 #  include <__type_traits/is_constructible.h>
@@ -97,6 +98,7 @@ namespace std {
 #  include <__type_traits/is_reference.h>
 #  include <__type_traits/is_same.h>
 #  include <__type_traits/is_void.h>
+#  include <__type_traits/negation.h>
 #  include <__type_traits/remove_cv.h>
 #  include <__type_traits/remove_cvref.h>
 #  include <__type_traits/remove_reference.h>
@@ -201,10 +203,11 @@ public:
       __other.__call(_Action::_Move, this);
   }
 
-  template <class _ValueType,
-            class _Tp        = decay_t<_ValueType>,
-            enable_if_t<!is_same_v<_Tp, any> && 
!__is_inplace_type<_ValueType>::value && is_copy_constructible_v<_Tp>,
-                        int> = 0>
+  template <
+      class _ValueType,
+      class _Tp        = decay_t<_ValueType>,
+      enable_if_t<_And<_Not<is_same<_Tp, any>>, 
_Not<__is_inplace_type<_ValueType>>, is_copy_constructible<_Tp>>::value,
+                  int> = 0>
   _LIBCPP_HIDE_FROM_ABI any(_ValueType&& __value) : __h_(nullptr) {
     __any_imp::_Handler<_Tp>::__create(*this, 
std::forward<_ValueType>(__value));
   }

diff  --git a/libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp 
b/libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp
index 120dfc22f3fbc..b78f72210f7da 100644
--- a/libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp
+++ b/libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp
@@ -21,6 +21,7 @@
 
 #include <any>
 #include <cassert>
+#include <type_traits>
 
 #include "any_helpers.h"
 #include "count_new.h"
@@ -140,6 +141,24 @@ void test_sfinae_constraints() {
     }
 }
 
+// https://llvm.org/PR176877
+// Avoid constraint meta-recursion for a type both convertible from and to 
std::any.
+template <class T, bool = std::is_copy_constructible<T>::value>
+void test_default_template_argument_is_copy_constructible(T) {}
+
+template <class T, bool = std::is_copy_constructible_v<T>>
+void test_default_template_argument_is_copy_constructible_v(T) {}
+
+void test_no_constraint_recursion() {
+  struct ConvertibleFromAndToAny {
+    ConvertibleFromAndToAny(std::any) {}
+  };
+
+  ConvertibleFromAndToAny src = std::any{};
+  test_default_template_argument_is_copy_constructible(src);
+  test_default_template_argument_is_copy_constructible_v(src);
+}
+
 int main(int, char**) {
     test_copy_move_value<small>();
     test_copy_move_value<large>();
@@ -147,6 +166,7 @@ int main(int, char**) {
     test_copy_value_throws<large_throws_on_copy>();
     test_move_value_throws();
     test_sfinae_constraints();
+    test_no_constraint_recursion();
 
-  return 0;
+    return 0;
 }


        
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to