https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121287
Bug ID: 121287 Summary: ICE: Segfault in tsubst_lambda_expr with decltype of immediately-invoked templated lambda + variadic lambda expansion (GCC 13+) Product: gcc Version: 15.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: llh282000500 at gmail dot com Target Milestone: --- Created attachment 61991 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61991&action=edit Preprocessed source and crash trace are attached (generated with -freport-bug on Arch Linux GCC 15.1.1). This ICE affects all tested GCC versions >= 13 that support C++20, reproducible on https://godbolt.org. - Example 1 (ICE): https://godbolt.org/z/9EfjWEvTP - Example 2 (ICE): https://godbolt.org/z/fM84Ex34j The ICE occurs when two conditions are simultaneously true inside a templated constexpr function: 1. A templated lambda with a parameter pack is immediately invoked and passed to `decltype(...)`. 2. The result of that `decltype(...)` is used in another templated lambda with parameter pack that also performs parameter pack expansion using the result. This combination causes a crash in `tsubst_lambda_expr` during template substitution. ## Minimal example: 1. decltype([]<...>{}()) + []<...>(){}() ```cpp #include <variant> #include <array> template <std::size_t I> struct SetObjIdx {}; // Must be a template template <typename T = void> constexpr auto makeNameToIdxVariantHashMap() { constexpr auto N = 3U; // N arbitrary // 1. using Res = decltype([] <std::size_t... Idx> (std::index_sequence<Idx...>) { return std::variant<SetObjIdx<Idx>...>{}; } (std::make_index_sequence<N>{})); // 2. return [&] <std::size_t... Idx> (std::index_sequence<Idx...>) { return std::array<Res, N>{ SetObjIdx<Idx>{}... }; }(std::make_index_sequence<N>{}); } int main() { constexpr auto res = makeNameToIdxVariantHashMap(); (void)res; return 0; } ``` 2. decltype([]<>{}()) + []<...>(){}() ```cpp #include <array> template <std::size_t I> struct SetObjIdx { std::size_t _idx; }; // Must be a template template <typename T = void> constexpr auto makeNameToIdxVariantHashMap() { constexpr auto N = 3U; // N arbitrary // 1. Decltype combined with []<>(){}() template using Res = decltype([] <std::size_t Idx> (std::index_sequence<Idx>) { return SetObjIdx<Idx>{Idx}; }(std::index_sequence<N>{})); // 2. It must be <...>Template return [&] <std::size_t... Idx> (std::index_sequence<Idx...>) { return std::array<Res, N>{ SetObjIdx<N>{Idx}... }; }(std::make_index_sequence<N>{}); } int main() { constexpr auto res = makeNameToIdxVariantHashMap(); return 0; } ``` Notes: - Replacing the first lambda with a non-parameter-pack lambda avoids ICE. - If the 'template<typename T=void>' function is deleted, it can be compiled normally - MSVC / Clang compilation is feasible ## Compile error message 1. decltype([]<...>{}()) + []<...>(){}() ```cpp <source>: In instantiation of 'makeNameToIdxVariantHashMap<>()::<lambda(std::index_sequence<__var_indices ...>)> [with long unsigned int ...Idx = {0, 1, 2}; std::index_sequence<__var_indices ...> = std::integer_sequence<long unsigned int, 0, 1, 2>]': <source>:22:6: required from 'constexpr auto makeNameToIdxVariantHashMap() [with T = void]' 18 | return [&] <std::size_t... Idx> (std::index_sequence<Idx...>) { | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 | return std::array<Res, N>{ | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 20 | SetObjIdx<Idx>{}... | ~~~~~~~~~~~~~~~~~~~ 21 | }; | ~~ 22 | }(std::make_index_sequence<N>{}); | ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <source>:26:53: required from here 26 | constexpr auto res = makeNameToIdxVariantHashMap(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~ <source>:13:26: internal compiler error: Segmentation fault 13 | using Res = decltype([] <std::size_t... Idx> (std::index_sequence<Idx...>) { | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 | return std::variant<SetObjIdx<Idx>...>{}; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 | } (std::make_index_sequence<N>{})); | ~ 0x2287785 diagnostic_context::diagnostic_impl(rich_location*, diagnostic_metadata const*, diagnostic_option_id, char const*, __va_list_tag (*) [1], diagnostic_t) ???:0 0x2298cd6 internal_error(char const*, ...) ???:0 0x989f38 template_parms_to_args(tree_node*) ???:0 0x9b8692 tsubst_lambda_expr(tree_node*, tree_node*, int, tree_node*) ???:0 0x9ab9bc tsubst(tree_node*, tree_node*, int, tree_node*) ???:0 0x9b2467 tsubst_template_args(tree_node*, tree_node*, int, tree_node*) ???:0 0x9ab435 tsubst(tree_node*, tree_node*, int, tree_node*) ???:0 0x99f62f instantiate_decl(tree_node*, bool, bool) ???:0 0x894821 maybe_instantiate_decl(tree_node*) ???:0 0x895b67 mark_used(tree_node*, int) ???:0 0x806f93 build_op_call(tree_node*, vec<tree_node*, va_gc, vl_embed>**, int) ???:0 0x9d8b67 finish_call_expr(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, bool, int) ???:0 0x99f62f instantiate_decl(tree_node*, bool, bool) ???:0 0x894821 maybe_instantiate_decl(tree_node*) ???:0 0x895b67 mark_used(tree_node*, int) ???:0 0x80330e build_new_function_call(tree_node*, vec<tree_node*, va_gc, vl_embed>**, int) ???:0 0x9d8b3e finish_call_expr(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, bool, int) ???:0 0x981ebd c_parse_file() ???:0 0xa8b739 c_common_parse_file() ???:0 Please submit a full bug report, with preprocessed source (by using -freport-bug). Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. ```