https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124264
Bug ID: 124264
Summary: [contracts] __tu_has_violation internal linkage causes
undefined reference with modules on MinGW/PE-COFF
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: kachalenko.denis at gmail dot com
Target Milestone: ---
When a non-template inline function with a pre() contract is defined in a
module
interface, the compiler generates a COMDAT section for it in the consumer TU.
This COMDAT references __tu_has_violation from the module TU. However,
__tu_has_violation has internal linkage (TREE_PUBLIC=false in
declare_one_violation_handler_wrapper), so the linker fails with an undefined
reference on PE-COFF targets.
Template functions work because they are instantiated per-TU, which triggers
local emission of __tu_has_violation.
Note: handle_contract_violation is provided via handler.cpp to isolate this
bug from Bug 124263.
--- mod.cppm ---
export module M;
import std;
export struct Box {
int D[4] = {};
constexpr int operator[](int I) const noexcept
pre(I >= 0 && I < 4)
{ return D[I]; }
};
--- main.cpp ---
import M;
import std;
int main() { Box b; std::cout << b[0]; }
--- handler.cpp ---
import std;
extern "C++" void handle_contract_violation(
const std::contracts::contract_violation&) { std::abort(); }
--- commands ---
$ g++ -std=c++26 -fmodules -fcontracts -fcontract-evaluation-semantic=enforce \
-c <gcc-install>/include/c++/16.0.1/bits/std.cc
$ g++ -std=c++26 -fmodules -fcontracts -fcontract-evaluation-semantic=enforce \
-c mod.cppm -o mod.o
$ g++ -std=c++26 -fmodules -fcontracts -fcontract-evaluation-semantic=enforce \
-c main.cpp -o main.o
$ g++ -std=c++26 -fmodules -fcontracts -fcontract-evaluation-semantic=enforce \
-c handler.cpp -o handler.o
$ g++ mod.o main.o handler.o -o test.exe
--- expected ---
Links successfully.
--- actual ---
ld: main.o:main.cpp:(.text$_ZNKW1M3BoxixEi[_ZNKW1M3BoxixEi]+0x2b): undefined
reference to `__tu_has_violation(__builtin_contract_violation_type const&,
unsigned short)'
collect2.exe: error: ld returned 1 exit status
--- analysis ---
nm mod.o shows __tu_has_violation as 't' (local text):
000000000000000e t
_Z18__tu_has_violationRK33__builtin_contract_violation_typet
nm main.o shows it as 'U' (undefined):
U
_Z18__tu_has_violationRK33__builtin_contract_violation_typet
The COMDAT section .text$_ZNKW1M3BoxixEi in main.o has a relocation to the
named symbol __tu_has_violation, but the symbol only exists in mod.o with
internal linkage.
A template version of the same struct links successfully because template
instantiation happens in the consumer TU, triggering per-TU emission of
__tu_has_violation.
Additionally, forcing __tu_has_violation emission via contract_assert(true) in
the consumer causes a secondary issue: the COMDAT relocation changes from a
named symbol reference to a section-relative .text reference, which is invalid
for COMDAT sections.
--- gcc -v ---
Using built-in specs.
Target: x86_64-w64-mingw32
Configured with: ../gcc-source/configure --prefix=/home/kacha/gcc-trunk-install
--build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32
--target=x86_64-w64-mingw32 --enable-languages=c,c++ --enable-threads=posix
--enable-shared --enable-static --enable-lto --enable-plugin
--enable-checking=release --disable-multilib --disable-nls --disable-werror
--disable-bootstrap --with-tune=native --with-system-zlib --with-zstd
--with-native-system-header-dir=/ucrt64/include
Thread model: posix
gcc version 16.0.1 20260221 (experimental) (GCC)
Linker: GNU ld (GNU Binutils) 2.46
Related to Bug 119061 (P2900 Contracts tracker).