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.