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.
```

Reply via email to