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

            Bug ID: 126209
           Summary: [16/17 regression] [modules] anonymous-namespace
                    variable in a module partition → ICE in
                    append_imported_binding_slot (checking) / segfault in
                    read_namespaces after minutes-long spin (release)
           Product: gcc
           Version: 16.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: stefan_heinzmann at gmx dot de
  Target Milestone: ---

**Known to work:** 15.2 / 15.3 (both release and checking builds)

**Host/target:** x86_64 (Fedora 44, Compiler Explorer); also arm-none-eabi
cross

## Short testcase (4 files, 7 lines — ICEs on checking builds)

    // k_event.cppm
    export module kernel:event;
    namespace { int anchor = 0; }
    // k_memories.cppm
    export module kernel:memories;
    import :event;
    // kernel.cppm
    export module kernel;
    export import :event;
    export import :memories;
    // main.cpp
    import kernel;
    int main() { return 0; }

Compile in that order with `-std=c++20 -fmodules-ts`. On checking-enabled
builds of 16.1 and trunk (17.0 20260705), compiling `main.cpp` fails:

    main.cpp:1:15: internal compiler error: in append_imported_binding_slot,
                   at cp/name-lookup.cc:353

Live demo (Compiler Explorer CMake project, gcc 16.1-assertions + trunk):
https://godbolt.org/z/zhe8GfnW5
gcc 15.2/15.3 assertion builds compile the same tree cleanly (regression).
All three ingredients are needed: the anonymous-namespace variable in the
partition, a sibling partition importing it, and a consumer importing the
primary. Remove any one → compiles cleanly.

## Release-build manifestation (large graph): runaway spin + segfault

On release-checking builds (Fedora 16.0.1; also the arm-none-eabi cross
compiler) the same inconsistency instead surfaces when reading a larger
import graph: cc1plus spins at 100 % CPU for 2–4 minutes, then segfaults.
`repro.py` (attached) generates 67 tiny module files mirroring the real code
base this was reduced from (module `kernel`: 36 partitions, three of them
with the minimal contents above; module `vfs`: 21 empty partitions importing
kernel; a 6-module stack on top) and compiles them in dependency order:

    python3 repro.py workdir      # exit 0 = ICE reproduced (~5 min)
    GXX=g++-15 python3 repro.py w2   # exit 1 = clean on 15.2.1

Symbolized backtrace (16.0.1-0.fc44, gdb on cc1plus):

    #0  get_originating_module_decl(tree_node*)
    #1  get_originating_module(tree_node*, bool)
    #2  init_global_partition(binding_cluster*, tree_node*)
    #3  get_fixed_binding_slot(tree_node**, tree_node*, unsigned int, int)
    #4  append_imported_binding_slot(tree_node**, tree_node*, unsigned int)
    #5  add_imported_namespace(tree_node*, tree_node*, unsigned long, unsigned
int, bool, bool)
    #6  module_state::read_namespaces(unsigned int)
    #7  module_state::read_language(bool)
    #8  direct_import(module_state*, cpp_reader*)
    #9  cp_parser_module_declaration(cp_parser*, module_parse, bool)
    #10 c_parse_file()

Frame #4 is the function whose assertion fires in checking builds, so both
manifestations appear to be the same underlying inconsistency (presumably a
binding slot for the anonymous-namespace entity's namespace being appended
out of order / duplicated).

Bisection notes on the large-graph segfault (why the generated repro is 67
files): the release-build crash is extremely sensitive to graph size —
dropping any one of the 21 vfs partitions, or more than 4 of the 33 empty
kernel filler partitions, makes the crash disappear (memory-layout/ordering
sensitivity). It reproduces with `-std=c++20` and `-std=gnu++23`, with and
without `-O0 -fno-exceptions -w`, and both via a plain `gcm.cache` build and
via CMake's module-mapper path. The minutes-long spin before the crash is
itself anomalous — 15.2 compiles the same reader in well under a second.

## Suspect

r16-3613 (PR121702 rework of read/write_namespaces and using-directive
streaming, Sept 2025) touches exactly this code path; not bisected.

## Attachments

- repro.py — self-contained generator + build driver for the 67-file variant

(the 4-file testcase + CMakeLists.txt is found at the godbolt link)

Reply via email to