https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127695

            Bug ID: 127695
           Summary: [16 Regression] ICE (segfault) in
                    finish_compound_literal instantiating a template from
                    a header unit (scnlib 4.0.1)
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Keywords: ice-on-valid-code, needs-reduction
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: drew.dormann at gmail dot com
  Target Milestone: ---

Created attachment 65738
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65738&action=edit
Reproducer: use.cpp, use_include.cpp (control), repro.sh, ice-16.2.txt (full
GCC 16.2 output)

**Keywords:** ice-on-valid-code, needs-reduction
**Known to work:** 15.2.0
**Known to fail:** 16.1.0, 16.2.0
**Host/Target:** x86_64-linux-gnu
**See also:** meta-bug 103524 ([meta-bug] modules issue)

---

## Description

Importing scnlib 4.0.1's `<scn/scan.h>` as a header unit and instantiating
`scn::scan` makes
cc1plus segfault in `finish_compound_literal`, reached from `tsubst_expr`
during SFINAE substitution
of a `decltype(requires_expr<...>{} , ...)` return type (scnlib's C++17
range-v3 style concept
emulation, `scan.h:2212`).

- Building the header unit itself succeeds.
- The identical code compiled with `#include` instead of `import` succeeds.
- GCC 15.2.0 compiles both variants.
- Independent of `-std` (fails at c++17, c++20, c++26), optimization level, and
scnlib's
  `SCN_DISABLE_*` configuration macros.

## Reproducer

scnlib 4.0.1 is header-only for this purpose (nothing needs to be built):
https://github.com/eliaskosunen/scnlib/releases/tag/v4.0.1

`use.cpp`:

```c++
import <scn/scan.h>;

int f(std::string_view s)
{
  auto r = scn::scan<int>(s, "{}");
  return r ? r->value() : -1;
}
```

```sh
g++ -std=c++20 -fmodules -I scnlib-4.0.1/include -fmodule-header -x c++-header
scnlib-4.0.1/include/scn/scan.h
g++ -std=c++20 -fmodules -I scnlib-4.0.1/include -c use.cpp      # ICE
```

Control (succeeds):

```sh
sed 's|^import <scn/scan.h>;|#include <scn/scan.h>|' use.cpp > use_include.cpp
g++ -std=c++20 -I scnlib-4.0.1/include -c use_include.cpp
```

## Output (16.2.0)

The substitution failing is `partially_ordered_with<const char*, const char*>`:

```
scn/scan.h: In substitution of 'template<class R, class ... Args, class>
std::true_type
  scn::v4::ranges::detail::test_requires_fn(int) [with R =
scn::v4::ranges::detail::partially_ordered_with_concept;
  Args = {const char*, const char*}; ...]':
scn/scan.h:2134:42:   required from 'constexpr const bool
scn::v4::ranges::detail::requires_<..., const char*, const char*>'
scn/scan.h:2219:13:   required from 'constexpr const bool
scn::v4::ranges::detail::partially_ordered_with<const char*, const char*>'
scn/scan.h:2224:39:   required from 'constexpr const bool
scn::v4::ranges::totally_ordered<const char*>'
...
scn/scan.h:2212:71: internal compiler error: Segmentation fault
0x243697f internal_error(char const*, ...)
0x10ff03f crash_signal
0xa55156 finish_compound_literal(tree_node*, tree_node*, int, fcl_t)
0x9ff4e6 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
0x9ff389 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
0x9ff339 tsubst_expr(tree_node*, tree_node*, int, tree_node*)
0xa072a2 tsubst(tree_node*, tree_node*, int, tree_node*)
0xa16cbe tsubst_function_type
0xa18abc tsubst_function_decl
0xa135fd tsubst_decl
0xa2356d instantiate_template(tree_node*, tree_node*, int)
0xa2448c resolve_nondeduced_context(tree_node*, int)
0xa5ead3 finish_decltype_type(tree_node*, bool, int)
0x9f837b type_unification_real
```

`scan.h:2203-2214` (the crashing return type; line 2212 is the `u > t`
operand):

```c++
struct partially_ordered_with_concept {
    template <typename T, typename U>
    auto requires_(const std::remove_reference_t<T>& t,
                   const std::remove_reference_t<U>& u)
        -> decltype(requires_expr<boolean_testable<decltype(t < u)>>{},
                    requires_expr<boolean_testable<decltype(t > u)>>{},
                    requires_expr<boolean_testable<decltype(t <= u)>>{},
                    requires_expr<boolean_testable<decltype(t >= u)>>{},
                    requires_expr<boolean_testable<decltype(u < t)>>{},
                    requires_expr<boolean_testable<decltype(u > t)>>{},
                    requires_expr<boolean_testable<decltype(u <= t)>>{},
                    requires_expr<boolean_testable<decltype(u >= t)>>{});
```

where `requires_expr<B>` is `std::enable_if_t<B, int>`.

## Version

```
gcc version 16.2.0 (GCC)
Configured with: ./../gcc-16.2.0/configure --build=x86_64-linux-gnu
--host=x86_64-linux-gnu
  --prefix=/usr/local/sbin/gcc-16.2.0 --disable-multilib
--enable-languages=c,c++
```

## Notes

A hand reduction of the concept-emulation pattern alone (same `requires_` /
`requires_expr` /
`boolean_testable` machinery, instantiated for `const char*`) does **not**
reproduce, so the trigger
needs more of the header-unit context. Not reduced further; not yet checked
against trunk.

Reply via email to