Skip to content

New a parameter pack may not be accessed at an out of bounds index failure #167709

@rupprecht

Description

@rupprecht

Regression that bisects to #164703: the following fails to build, with the error message a parameter pack may not be accessed at an out of bounds index.

Live repro: https://compiler-explorer.com/z/9731oM5qn

Source:

#include <cstdint>
#include <tuple>
#include <type_traits>
#include <utility>

using npos = std::integral_constant<std::size_t, static_cast<std::size_t>(-1)>;

template <class Predicate, class T, std::size_t I, std::size_t N>
struct find_impl
    : std::conditional<Predicate::template apply<
                           typename std::tuple_element<I, T>::type>::value,
                       std::integral_constant<std::size_t, I>,
                       find_impl<Predicate, T, I + 1, N - 1>>::type {};

template <class Predicate, class T, std::size_t I>
struct find_impl<Predicate, T, I, 0> : npos {};

template <class Predicate, class T>
struct find_index_if : find_impl<Predicate, T, 0, std::tuple_size<T>::value> {};

template <typename... Args>
struct IsInvocableOn {
    template <typename Fn>
    struct apply : std::is_invocable<Fn, Args...> {};
};

template <typename... Fns>
struct Overload {
    template <int I>
    using FnAt = typename std::tuple_element<I, std::tuple<Fns...>>::type;

    template <typename... Args>
    auto operator()(Args&&... args) const -> FnAt<
        find_index_if<IsInvocableOn<Args...>, std::tuple<Fns...>>::value>;
};

template <typename Fn>
bool foo = std::is_invocable_v<Overload<Fn>>;

bool foo_v = foo<decltype([](int x) {})>;

Repro just needs clang -std=c++20, and fails w/ either libc++ or libstdc++. gcc also accepts this.

Failure:

In file included from <source>:2:
In file included from /cefs/8d/8d2fd574113d33adba235562_clang-assertions-trunk-20251112/bin/../include/c++/v1/tuple:228:
In file included from /cefs/8d/8d2fd574113d33adba235562_clang-assertions-trunk-20251112/bin/../include/c++/v1/__fwd/get.h:15:
In file included from /cefs/8d/8d2fd574113d33adba235562_clang-assertions-trunk-20251112/bin/../include/c++/v1/__fwd/pair.h:14:
/cefs/8d/8d2fd574113d33adba235562_clang-assertions-trunk-20251112/bin/../include/c++/v1/__fwd/tuple.h:40:52: error: a parameter pack may not be accessed at an out of bounds index
   40 |   using type _LIBCPP_NODEBUG = __type_pack_element<_Ip, _Tp...>;
      |                                                    ^
<source>:30:5: note: in instantiation of template class 'std::tuple_element<18446744073709551615, std::tuple<(lambda at <source>:40:27)>>' requested here
   30 |     using FnAt = typename std::tuple_element<I, std::tuple<Fns...>>::type;
      |     ^
<source>:33:46: note: in instantiation of template type alias 'FnAt' requested here
   33 |     auto operator()(Args&&... args) const -> FnAt<
      |                                              ^
/cefs/8d/8d2fd574113d33adba235562_clang-assertions-trunk-20251112/bin/../include/c++/v1/__type_traits/invoke.h:77:47: note: while substituting deduced template arguments into function template 'operator()' [with Args = <>]
   77 | struct __invoke_result_impl<__void_t<decltype(__builtin_invoke(std::declval<_Args>()...))>, _Args...> {
      |                                               ^
/cefs/8d/8d2fd574113d33adba235562_clang-assertions-trunk-20251112/bin/../include/c++/v1/__type_traits/invoke.h:85:1: note: during template argument deduction for class template partial specialization '__invoke_result_impl<__void_t<decltype(__builtin_invoke(std::declval<_Args>()...))>, _Args...>' [with _Args = <Overload<(lambda at <source>:40:27)>>]
   85 | using __invoke_result_t _LIBCPP_NODEBUG = typename __invoke_result<_Args...>::type;
      | ^
/cefs/8d/8d2fd574113d33adba235562_clang-assertions-trunk-20251112/bin/../include/c++/v1/__type_traits/invoke.h:85:1: note: in instantiation of template class 'std::__invoke_result_impl<void, Overload<(lambda at <source>:40:27)>>' requested here
/cefs/8d/8d2fd574113d33adba235562_clang-assertions-trunk-20251112/bin/../include/c++/v1/__type_traits/invoke.h:97:48: note: in instantiation of template type alias '__invoke_result_t' requested here
   97 | inline const bool __is_invocable_impl<__void_t<__invoke_result_t<_Args...> >, _Args...> = true;
      |                                                ^
/cefs/8d/8d2fd574113d33adba235562_clang-assertions-trunk-20251112/bin/../include/c++/v1/__type_traits/invoke.h:100:38: note: during template argument deduction for variable template partial specialization '__is_invocable_impl<__void_t<__invoke_result_t<_Args...>>, _Args...>' [with _Args = <Overload<(lambda at <source>:40:27)>>]
  100 | inline const bool __is_invocable_v = __is_invocable_impl<void, _Args...>;
      |                                      ^
/cefs/8d/8d2fd574113d33adba235562_clang-assertions-trunk-20251112/bin/../include/c++/v1/__type_traits/invoke.h:370:67: note: in instantiation of variable template specialization 'std::__is_invocable_v<Overload<(lambda at <source>:40:27)>>' requested here
  370 | _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_invocable_v = __is_invocable_v<_Fn, _Args...>;
      |                                                                   ^
<source>:38:17: note: in instantiation of variable template specialization 'std::is_invocable_v<Overload<(lambda at <source>:40:27)>>' requested here
   38 | bool foo = std::is_invocable_v<Overload<Fn>>;
      |                 ^
<source>:40:14: note: in instantiation of variable template specialization 'foo<(lambda at <source>:40:27)>' requested here
   40 | bool foo_v = foo<decltype([](int x) {})>;
      |              ^
1 error generated.
Compiler returned: 1

I also have a repro w/o any headers, although it is clang-specific since it was reduced w/ libc++ which uses the __type_pack_element clang builtin. It may be useful for a regression test but does not allow comparing conformance w/ gcc.

Live link: https://compiler-explorer.com/z/YEK8vsbK5

Source:

template <class>
using __void_t = void;

template <bool>
struct tuple_element;
template <decltype(sizeof(int)) _Ip>
struct tuple_element<_Ip> {
    using type = __type_pack_element<_Ip>;
};

template <class...>
struct __invoke_result_impl;
template <class... _Args>
struct __invoke_result_impl<__void_t<decltype(__builtin_invoke(_Args()...))>,
                            _Args...>;
template <class... _Args>
using __invoke_result = __invoke_result_impl<void, _Args...>;
template <class... _Args>
using __invoke_result_t = __invoke_result<_Args...>::type;

template <class...>
bool __is_invocable_impl;
template <class... _Args>
bool __is_invocable_impl<__void_t<__invoke_result_t<_Args...>>, _Args...>;
template <class... _Args>
bool __is_invocable_v = __is_invocable_impl<void, _Args...>;
template <class _Fn>
bool is_invocable_v = __is_invocable_v<_Fn>;

template <class>
struct find_index_if {
    static const int value = -1;
};

template <typename...>
struct IsInvocableOn;

template <int I>
using FnAt = tuple_element<I>::type;

struct Overload {
    template <typename... Args>
    auto operator()()
        -> FnAt<find_index_if<IsInvocableOn<Args...>>::value>;
};

bool value = is_invocable_v<Overload>;

Metadata

Metadata

Assignees

Labels

clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions