[libcxx-commits] [clang] [libcxx] [Clang] Add __builtin_invoke and use it in libc++ (PR #116709)

Alexander Kornienko via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 23 22:24:24 PDT 2025


alexfh wrote:

The reduced test case: https://gcc.godbolt.org/z/KhebWaGsc

```
#include <variant>
#include <vector>
namespace testing {
template <typename T> struct Matcher {
  Matcher(int);
  Matcher(T);
};
template <typename T, typename M>
Matcher<T> SafeMatcherCast(M polymorphic_matcher_or_value) {
  return polymorphic_matcher_or_value;
}
namespace internal {
template <typename MatcherTuple> struct ElementsAreMatcher {
  template <typename Container> operator Matcher<Container>() {
    typedef typename std::remove_const<
        typename std::remove_reference<Container>::type>::type ::value_type
        Element;
    typedef std::vector<Matcher<Element>> MatcherVec;
    MatcherVec matchers;
    matchers.reserve(std::tuple_size<MatcherTuple>::value);
    return 0;
  }
};
} // namespace internal
} // namespace testing
template <typename> struct Nullable {
  template <typename V> Nullable(V);
};
void f(testing::internal::ElementsAreMatcher<std::tuple<>> m) {
  testing::SafeMatcherCast<std::vector<std::variant<Nullable<int>>>>(m);
}
```

```
In file included from <source>:1:
/opt/compiler-explorer/clang-trunk-20250723/bin/../include/c++/v1/variant:1186:37: fatal error: recursive template instantiation exceeded maximum depth of 1024
 1186 |              enable_if_t<!is_same_v<__remove_cvref_t<_Arg>, variant>, int>        = 0,
      |                                     ^
/opt/compiler-explorer/clang-trunk-20250723/bin/../include/c++/v1/variant:1192:35: note: while substituting prior template arguments into non-type template parameter [with _Arg = testing::Matcher<std::variant<Nullable<int>>>]
 1192 |   _LIBCPP_HIDE_FROM_ABI constexpr variant(_Arg&& __arg) noexcept(is_nothrow_constructible_v<_Tp, _Arg>)
      |                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1193 |       : __impl_(in_place_index<_Ip>, std::forward<_Arg>(__arg)) {}
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20250723/bin/../include/c++/v1/__type_traits/invoke.h:71:69: note: while substituting deduced template arguments into function template 'variant' [with _Arg = testing::Matcher<std::variant<Nullable<int>>>, $1 = (no value), $2 = (no value), $3 = (no value), _Tp = (no value), _Ip = (no value), $6 = (no value)]
   71 | using __invoke_result_t _LIBCPP_NODEBUG = decltype(__builtin_invoke(std::declval<_Args>()...));
      |                                                                     ^
/opt/compiler-explorer/clang-trunk-20250723/bin/../include/c++/v1/__type_traits/invoke.h:387:1: note: in instantiation of template type alias '__invoke_result_t' requested here
  387 | using invoke_result_t = __invoke_result_t<_Fn, _Args...>;
      | ^
/opt/compiler-explorer/clang-trunk-20250723/bin/../include/c++/v1/variant:1140:1: note: in instantiation of template type alias 'invoke_result_t' requested here
 1140 | using __best_match_t _LIBCPP_NODEBUG = typename invoke_result_t<_MakeOverloads<_Types...>, _Tp, _Tp>::type;
      | ^
/opt/compiler-explorer/clang-trunk-20250723/bin/../include/c++/v1/variant:1189:45: note: in instantiation of template type alias '__best_match_t' requested here
 1189 |              class _Tp  = __variant_detail::__best_match_t<_Arg, _Types...>,
      |                                             ^
/opt/compiler-explorer/clang-trunk-20250723/bin/../include/c++/v1/variant:1192:35: note: (skipping 2539 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
 1192 |   _LIBCPP_HIDE_FROM_ABI constexpr variant(_Arg&& __arg) noexcept(is_nothrow_constructible_v<_Tp, _Arg>)
      |                                   ^
/opt/compiler-explorer/clang-trunk-20250723/bin/../include/c++/v1/__vector/vector.h:845:8: note: in instantiation of function template specialization 'std::__uninitialized_allocator_relocate<std::allocator<testing::Matcher<std::variant<Nullable<int>>>>, testing::Matcher<std::variant<Nullable<int>>> *>' requested here
  845 |   std::__uninitialized_allocator_relocate(
      |        ^
/opt/compiler-explorer/clang-trunk-20250723/bin/../include/c++/v1/__vector/vector.h:1101:5: note: in instantiation of member function 'std::vector<testing::Matcher<std::variant<Nullable<int>>>>::__swap_out_circular_buffer' requested here
 1101 |     __swap_out_circular_buffer(__v);
      |     ^
<source>:20:14: note: in instantiation of member function 'std::vector<testing::Matcher<std::variant<Nullable<int>>>>::reserve' requested here
   20 |     matchers.reserve(std::tuple_size<MatcherTuple>::value);
      |              ^
<source>:10:10: note: in instantiation of function template specialization 'testing::internal::ElementsAreMatcher<std::tuple<>>::operator Matcher<std::vector<std::variant<Nullable<int>>>>' requested here
   10 |   return polymorphic_matcher_or_value;
      |          ^
<source>:30:12: note: in instantiation of function template specialization 'testing::SafeMatcherCast<std::vector<std::variant<Nullable<int>>>, testing::internal::ElementsAreMatcher<std::tuple<>>>' requested here
   30 |   testing::SafeMatcherCast<std::vector<std::variant<Nullable<int>>>>(m);
      |            ^
```

@philnik777 PTAL

https://github.com/llvm/llvm-project/pull/116709


More information about the libcxx-commits mailing list