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

            Bug ID: 125768
           Summary: `[16 Regression] c++/modules: ICE (segfault
                    build_special_member_call) on member-init of a
                    module-attached class with dense members when 'import
                    std'`
           Product: gcc
           Version: 16.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: emmanuel.prunet at hotmail dot fr
  Target Milestone: ---

## Description

`g++ -fmodules -std=gnu++23` segfaults (ICE) while synthesising the member-init
list of a module-attached class's constructor, defined in a module
implementation unit, when the class has a dense set of members AND `std` is
reached through `import std;` The crash is in `build_special_member_call`
(`cp/call.cc`), reached via `emit_mem_initializers` → `perform_member_init` →
`build_aggr_init` → `expand_default_init`.

Regression: gcc-15.2.0 compiles the identical translation units without error.
gcc-16.1.0 (GNU release tarball) ICEs; the ubuntu-toolchain-r/test 16.0.1 trunk
snapshot ICEs identically — so it is a released-version regression, not a
snapshot artifact. clang-21 + libc++ compiles the same construct cleanly.

`import std` is necessary: reaching the same std types via textual `#include`
in the global module fragment (instead of `import std;`) compiles cleanly —
only the module-std path ICEs. No single member triggers it; the crash needs
the combination (`std::atomic` ×3 + `std::function` +
`std::vector<imported-module type>` + `std::mt19937_64` + a cross-module
move-init + a global-module-fragment PIMPL fwd).

## Reproducer (self-contained, raw g++ — no build system)

Five files (below), then:

```sh
g++ -std=gnu++23 -fmodules -fmodule-only -c <libstdc++>/bits/std.cc   # build
the std module (gcm.cache/std.gcm)
g++ -std=gnu++23 -fmodules -c api.cppm        -o api.o                # ok
g++ -std=gnu++23 -fmodules -c outer.cppm      -o outer.o              # ok
g++ -std=gnu++23 -fmodules -c outer_impl.cpp  -o outer_impl.o         # ICE:
segfault in build_special_member_call
```

(`<libstdc++>/bits/std.cc` is the libstdc++ std-module source, e.g.
`.../include/c++/16.1.0/bits/std.cc`. Equivalently reproducible via a CMake
target with
`CXX_MODULE_STD ON` over the same five files.)

### api.cppm
```cpp
module;
export module api;
import std;
namespace n {
export struct Config { std::string name; std::vector<int> weights; int v{0}; };
}
```

### impl_fwd.hpp
```cpp
#pragma once
namespace n { struct Impl; }   // global-module-attached (textual) forward decl
```

### impl_def.hpp
```cpp
#pragma once
namespace n { struct Impl { int x{0}; }; }
```

### outer.cppm
```cpp
module;
#include "impl_fwd.hpp"
export module outer;
import std;
import api;
namespace n {
export struct Outer {
    Config cfg;
    std::unique_ptr<Impl> p;
    std::atomic<double> a{0};
    std::atomic<double> b{0};
    std::atomic<bool> c{false};
    std::function<void()> cb;
    std::vector<Config> sub;
    std::mt19937_64 rng;
    explicit Outer(Config c, std::uint64_t seed);
    ~Outer();
};
}
```

### outer_impl.cpp  (← ICE site)
```cpp
module;
#include "impl_def.hpp"
module outer;
import std;
import api;
namespace n {
Outer::Outer(Config c, std::uint64_t seed) : cfg{std::move(c)}, rng{seed} {}
Outer::~Outer() = default;
}
```

## ICE output / backtrace (gcc-16.1.0)

```
outer_impl.cpp: In constructor 'n::Outer@outer::Outer(n::Config@api,
uint64_t)':
outer_impl.cpp:7:65: internal compiler error: Segmentation fault
    7 | Outer::Outer(Config c, std::uint64_t seed) : cfg{std::move(c)},
rng{seed} {}
      |                                                                
^~~~~~~~~
0x234531b internal_error(char const*, ...)
        gcc/diagnostic-global-context.cc:787
0x10eb213 crash_signal                              gcc/toplev.cc:325
0x8115a8  build_special_member_call(...)            gcc/cp/call.cc:11688
0x8e53e4  expand_default_init                       gcc/cp/init.cc:2249
0x8e53e4  expand_aggr_init_1                        gcc/cp/init.cc:2368
0x8e81d6  build_aggr_init(...)                      gcc/cp/init.cc:2087
0x8ec857  perform_member_init                       gcc/cp/init.cc:1169
0x8ec857  emit_mem_initializers(tree_node*)         gcc/cp/init.cc:1643
0x9cc06a  cp_parser_mem_initializer_list            gcc/cp/parser.cc:19870
...
```

## Environment

- gcc-16.1.0 (GNU release tarball, `--enable-languages=c,c++ --disable-multilib
  --disable-bootstrap`, x86_64-pc-linux-gnu). Also reproduced on the apt
  `g++-16` 16.0.1 trunk snapshot (r16-8100).
- **Clean on:** gcc-15.2.0 (same files, same flags), and clang-21 + libc++.
- Flags: `-std=gnu++23 -fmodules` (CMake emits `-fmodules-ts -fmodule-mapper=…
-fdeps-format=p1689r5`).

## Why it matters (reporter context)

Surfaced converting a real engine library to C++23 modules: the engine's
module-attached `Agent`/`Engine` classes have exactly this member density, so
it is not dodgeable by restructuring. It blocks the libstdc++ `import std` leg
of a cross-stdlib build; the libc++/clang leg is unaffected.

Reply via email to