diff --git a/stl/inc/any b/stl/inc/any index c9d30736a57..e9d7f0731dd 100644 --- a/stl/inc/any +++ b/stl/inc/any @@ -130,10 +130,13 @@ public: _Move_from(_That); } - template , any>>, - negation<_Is_specialization, in_place_type_t>>, - is_copy_constructible>>, - int> = 0> + template , any> && !_Is_specialization_v, in_place_type_t>, + int> = 0, // Separate these conditions into two `enable_if_t`s to avoid meta-recursion. + // See LLVM-176877 and GH-6109. N5032 [temp.deduct.general]/7 guarantees: + // "The substitution proceeds in lexical order and stops when + // a condition that causes deduction to fail is encountered." + enable_if_t>, int> = 0> any(_ValueType&& _Value) { // initialize with _Value _Emplace>(_STD forward<_ValueType>(_Value)); } diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index f43ba600439..971a27c8889 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -1112,9 +1112,6 @@ std/input.output/file.streams/fstreams/filebuf.virtuals/xsputn.pass.cpp:1 FAIL std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:0 FAIL std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp:1 FAIL -# Not analyzed. Clang error: no member named 'value' in 'std::is_copy_constructible' -std/utilities/any/any.class/any.cons/value.pass.cpp:2 FAIL - # Not analyzed. Assertion failed: globalMemCounter.checkOutstandingNewLessThanOrEqual(1) std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp FAIL std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp FAIL diff --git a/tests/std/tests/P0220R1_any/test.cpp b/tests/std/tests/P0220R1_any/test.cpp index 391bb7b0ed1..c8b1f4ec43c 100644 --- a/tests/std/tests/P0220R1_any/test.cpp +++ b/tests/std/tests/P0220R1_any/test.cpp @@ -1040,6 +1040,7 @@ int run_test() #include #include +#include #include "any_helpers.h" #include "count_new.h" @@ -1160,6 +1161,24 @@ void test_sfinae_constraints() { } } +// https://llvm.org/PR176877 +// Avoid constraint meta-recursion for a type both convertible from and to std::any. +template ::value> +void test_default_template_argument_is_copy_constructible(T) {} + +template > +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 run_test() { test_copy_move_value(); test_copy_move_value(); @@ -1167,8 +1186,9 @@ int run_test() { test_copy_value_throws(); test_move_value_throws(); test_sfinae_constraints(); + test_no_constraint_recursion(); - return 0; + return 0; } } // namespace ctor::value // -- END: test/std/utilities/any/any.class/any.cons/value.pass.cpp