Code that triggers the bug(s). It uses enum values stored in an std::array, to generate an std::tuple. Using std::tuple_element_t on the generated tuple causes ICE. Compiler options: -Wall -std=c++20 -O3 #include <memory> #include <type_traits> #include <array> #include <complex> namespace Enum { template<class T> using Empty = std::type_identity<T>; template<class T> constexpr auto add(T base, std::underlying_type_t<T> offset = 1) { return static_cast<T>(std::underlying_type_t<T>(base) + offset); } namespace detail { template<auto types, template<auto> class EnumItemTraits, class T = std::make_integer_sequence<size_t, types.size()>> struct make_tuple_from_array; template<auto types, template<auto> class EnumItemTraits, size_t index> struct int_to_type_array: public EnumItemTraits<types[index]> { }; template<auto types, template<auto> class EnumItemTraits, size_t... indices> struct make_tuple_from_array<types, EnumItemTraits, std::integer_sequence<size_t, indices...>> { using type = std::tuple<typename int_to_type_array<types, EnumItemTraits, indices>::type...>; }; } template<auto types, template<auto> class EnumItemTraits> using TupleFromTypeArray = typename detail::make_tuple_from_array<types, EnumItemTraits>::type; } enum class PortType : size_t { RgbaPixels, GrayscaleRealPixels, GrayscaleComplexPixels, }; constexpr PortType begin(Enum::Empty<PortType>) { return PortType::RgbaPixels; } constexpr PortType end(Enum::Empty<PortType>) { return Enum::add(PortType::GrayscaleComplexPixels); } using vec4_t __attribute__((vector_size(16))) = float; using RgbaValue = vec4_t; using RealValue = double; using ComplexValue = std::complex<RealValue>; template<PortType id> struct PortTypeToType; template<> struct PortTypeToType<PortType::RgbaPixels> { using type = std::unique_ptr<RgbaValue[]>; }; template<> struct PortTypeToType<PortType::GrayscaleRealPixels> { using type = std::unique_ptr<RealValue[]>; }; template<> struct PortTypeToType<PortType::GrayscaleComplexPixels> { using type = std::unique_ptr<ComplexValue[]>; }; template<class T> struct InputPortType { using type = std::conditional_t<(sizeof(T) <= 16), T, std::reference_wrapper<T const>>; }; template<class T> struct InputPortType<std::unique_ptr<T[]>> { using type = T const*; }; template<class T> struct InputPortType<std::unique_ptr<T>> { using type = std::reference_wrapper<T const>; }; namespace detail { template<PortType t> struct GenInputPortType { using type = typename InputPortType<typename PortTypeToType<t>::type>::type; }; } namespace detail { template<class Object, class F, size_t... I> constexpr decltype(auto) create_impl(F&& f, std::index_sequence<I...>) { return Object{f(std::integral_constant<size_t, I>{})...}; } } template<class Tuple, class F, size_t... I> constexpr decltype(auto) createTuple(F&& f) { return detail::create_impl<Tuple>(std::forward<F>(f), std::make_index_sequence<std::tuple_size_v<Tuple>>{}); } template<class T> void doStuffWithTArg(T); template<class T> void doStuffWithT(); template<auto types> class InArgTuple { using storage_type = Enum::TupleFromTypeArray<types, detail::GenInputPortType>; public: constexpr explicit InArgTuple() : m_data{createTuple<storage_type>([]<class Tag>(Tag) { using T = typename detail::GenInputPortType<types[Tag::value]>::type; // Trunk gets stuck here // internal compiler error: in cxx_eval_constant_expression, at cp/constexpr.c:6188 using OtherT = std::tuple_element_t<Tag::value, storage_type>; static_assert(std::is_same_v<T, OtherT>); T foo{}; // This triggers ICE: in finish_expr_stmt, at cp/semantics.c:681 // doStuffWithT<OtherT>(); doStuffWithT<T>(); // Not ICE OtherT bar{}; // This also triggers ICE: in tsubst_copy, at cp/pt.c:16485 //doStuffWithTArg(bar); doStuffWithTArg(foo); // Not ICE // // Also in tsubst_copy, at cp/pt.c:16485 // // return bar; // return foo; })} { } static constexpr auto size() { return types.size(); } template<size_t index> constexpr auto get() const { static_assert(index < types.size()); return std::get<index>(m_data); } private: storage_type m_data; }; void test() { constexpr std::array<PortType, 1> types{PortType::RgbaPixels}; InArgTuple<types> test{}; }
Reduced: typedef int a; template <typename> struct al; template <typename b, b am> using an = al<b, __integer_pack(am)...>; struct { void ap(); } ar; template <auto ar, template <auto> class, class = an<a, ar.ap>> struct as; template <auto ar, template <auto> class at> using au = as<ar, at>; enum av {}; template <av> struct aw; template <auto ar> class ax { using ay = au<ar, aw>; }; ax<ar> az; The ICE is in the same spot as in bug 87765.
https://gcc.godbolt.org/z/n13PKr