https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127694
Bug ID: 127694
Summary: [modules] segfault in read_cluster with a partition
re-exported by a primary interface
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: me at davud dot io
Target Milestone: ---
Created attachment 65737
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65737&action=edit
Repro code and module dumps
Reproduced on:
- g++ (GCC) 14.3.1 20260214
- g++ (GCC) 15.3.0
- g++ (GCC) 16.2.1 20260810
- g++ (GCC) 17.0.0 20260918 (experimental), commit a87de1ad7, configured with
`--disable-bootstrap --enable-checking=yes --enable-languages=c,c++
--disable-multilib`
Target is x86_64-pc-linux-gnu
Flags are `-std=gnu++23 -fmodules-ts -fmodule-only`
# Description
In `baz.cppm`, a module partition `mod1:part` declares:
- a function template `Conversion` whose return type is an alias template
specialization that depends on the function parameter
- a struct `Bar` with a member function template whose parameter type mentions
`Conversion`.
The primary interface `mod1` in file `bar.cppm` re-exports the partition and
declares `using Foo = Bar;`.
With the checking build, compiling `bar.cppm` results in an assertion inside
`trees_out::type_node`.
With a release build, `bar.cppm` compiles, but `foo.cppm` (the file containing
some `mod2`) segfaults while reading the CMI. `foo.cppm` imports `mod1` and
uses `Namespace::Foo`.
In both cases `baz.cppm` will compile fine.
# Reproduction code
`baz.cppm`
```
module;
template <typename> struct enable_if;
template <typename _Cond> using enable_if_t = enable_if<_Cond>;
template <typename T> auto Conversion(T v) -> enable_if_t<decltype(v)>;
export module mod1:part;
export namespace Namespace {
struct Bar {
template <typename Args>
void Func(decltype(Conversion<Args>));
};
}
```
Note that `baz.cppm` has to be a partition. If it's a separate module that
`bar.cppm` imports and re-exports, no crash happens
`bar.cppm`
```
export module mod1;
export import :part;
export namespace Namespace {
using Foo = Bar;
}
```
`foo.cppm`
```
export module mod2;
import mod1;
Namespace::Foo make() { return {}; }
```
Variant of `baz.cppm` without a GMF. Here, the crash depends on the function's
name. In my case, the name `Conversion` compiled, but renaming the function to
`q` caused the same crash, in both release and checking.
```
export module mod1:part;
export namespace Namespace {
template <typename> struct enable_if;
template <typename _Cond> using enable_if_t = enable_if<_Cond>;
template <typename T> auto q(T v) -> enable_if_t<decltype(v)>;
struct Bar {
template <typename Args>
void Func(decltype(q<Args>));
};
}
```
Compiled using:
```
for f in baz bar foo; do
g++ -std=gnu++23 -fmodules-ts -fmodule-only -x c++ -c $f.cppm
done
```
With the declarations written directly in the GMF there is a `-Wglobal-module`
warning. The result is the same when they come from an `#include`d header.
# Compiler output
GCC 16.2.1 release, compiling `foo.cppm`:
```
foo.cppm:4:12: internal compiler error: Segmentation fault
4 | Namespace::Foo make() { return {}; }
| ^~~
0x19317d8 internal_error(char const*, ...)
0x19deee2 build_function_type(tree_node*, tree_node*, bool)
0x1260254 module_state::read_cluster(unsigned int)
0x1265465 module_state::load_section(unsigned int, binding_slot*)
0x1265552 module_state::lazy_load(unsigned int, binding_slot*)
0x125fd8a module_state::read_cluster(unsigned int)
0x1265465 module_state::load_section(unsigned int, binding_slot*)
0x1265552 module_state::lazy_load(unsigned int, binding_slot*)
0x125fd8a module_state::read_cluster(unsigned int)
0x1265465 module_state::load_section(unsigned int, binding_slot*)
0x12657f4 lazy_load_binding(unsigned int, tree_node*, tree_node*,
binding_slot*)
0x1ba460d lookup_qualified_name(tree_node*, tree_node*, LOOK_want, bool)
0x27a2619 c_parse_file()
0x2778050 c_common_parse_file()
```
On 14.3.1 and 15.3.0 the top frame is `module_state::read_cluster` instead of
`build_function_type`. The rest of the backtrace is the same.
GCC 17 checking build, compiling `bar.cppm`:
```
bar.cppm:1:8: internal compiler error: in type_node, at cp/module.cc:9735
1 | export module mod1;
| ^~~~~~
0x12c138c type_node
../../gcc/gcc/cp/module.cc:9735
0x12c4243 tree_node
../../gcc/gcc/cp/module.cc:10333
0x12cd15b key_mergeable
../../gcc/gcc/cp/module.cc:12087
0x12ba4df decl_value
../../gcc/gcc/cp/module.cc:8527
0x12be80a decl_node
../../gcc/gcc/cp/module.cc:9258
0x12c473c tree_node
../../gcc/gcc/cp/module.cc:10391
0x12c0333 decl_node
../../gcc/gcc/cp/module.cc:9538
0x12c473c tree_node
../../gcc/gcc/cp/module.cc:10391
0x12be99d decl_node
../../gcc/gcc/cp/module.cc:9280
0x12c473c tree_node
../../gcc/gcc/cp/module.cc:10391
0x12c1ba8 type_node
../../gcc/gcc/cp/module.cc:9835
0x12c4243 tree_node
../../gcc/gcc/cp/module.cc:10333
0x12b3766 core_vals
../../gcc/gcc/cp/module.cc:6838
0x12b7d3c tree_node_vals
../../gcc/gcc/cp/module.cc:7893
0x12c2a48 tree_value
../../gcc/gcc/cp/module.cc:9995
0x12c4767 tree_node
../../gcc/gcc/cp/module.cc:10396
0x12cbd4a key_mergeable
../../gcc/gcc/cp/module.cc:11869
0x12ba4df decl_value
../../gcc/gcc/cp/module.cc:8527
```