[libc++] Fix std::variant evaluating template arguments too eagerly (#151028)

This has been reported in https://github.com/llvm/llvm-project/pull/116709#issuecomment-3105095648.

Fixes #151328
This commit is contained in:
Nikolas Klauser 2025-08-11 20:15:59 +02:00 committed by GitHub
parent 005895290d
commit f5f582451e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 5 deletions

View File

@ -67,20 +67,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if __has_builtin(__builtin_invoke)
template <class... _Args>
using __invoke_result_t _LIBCPP_NODEBUG = decltype(__builtin_invoke(std::declval<_Args>()...));
template <class, class... _Args>
struct __invoke_result_impl {};
template <class... _Args>
struct __invoke_result_impl<__void_t<__invoke_result_t<_Args...> >, _Args...> {
using type _LIBCPP_NODEBUG = __invoke_result_t<_Args...>;
struct __invoke_result_impl<__void_t<decltype(__builtin_invoke(std::declval<_Args>()...))>, _Args...> {
using type _LIBCPP_NODEBUG = decltype(__builtin_invoke(std::declval<_Args>()...));
};
template <class... _Args>
using __invoke_result _LIBCPP_NODEBUG = __invoke_result_impl<void, _Args...>;
template <class... _Args>
using __invoke_result_t _LIBCPP_NODEBUG = typename __invoke_result<_Args...>::type;
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __invoke_result_t<_Args...> __invoke(_Args&&... __args)
_NOEXCEPT_(noexcept(__builtin_invoke(std::forward<_Args>(__args)...))) {

View File

@ -173,6 +173,11 @@ void test_vector_bool() {
assert(std::get<0>(v) == true);
}
struct ConvertibleFromAny {
template <class V>
ConvertibleFromAny(V) {}
};
int main(int, char**) {
test_T_ctor_basic();
test_T_ctor_noexcept();
@ -180,5 +185,16 @@ int main(int, char**) {
test_no_narrowing_check_for_class_types();
test_construction_with_repeated_types();
test_vector_bool();
{ // Check that the constraints are evaluated lazily (see https://github.com/llvm/llvm-project/issues/151328)
struct Matcher {
Matcher() {}
Matcher(std::variant<ConvertibleFromAny>) {}
};
Matcher vec;
[[maybe_unused]] Matcher m = std::move(vec);
}
return 0;
}