https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126572
Bug ID: 126572
Summary: [contracts] default handle_contract_violation is a
weak symbol and never resolves on PE targets (mingw)
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: 121539739 at qq dot com
Target Milestone: ---
On x86_64-w64-mingw32, any program that can reach a runtime contract
check fails to link against the default violation handler:
```cpp
int f(const int x) pre(x > 0) { return x; }
int main() { return f(1); }
```
Command line:
g++ -std=c++26 repro.cpp -lstdc++exp
Output:
...undefined reference to
`handle_contract_violation(std::contracts::contract_violation const&)'
The default definition in libstdc++-v3/src/experimental/contract26.cc
line ~135 is declared `__attribute__((weak))`. In
libstdc++exp.a(contract26.o) on PE-COFF it is emitted only as a weak
external(`.weak._Z25handle_contract_violation...`); nm shows no strong
definition of the symbol. Archive member selection does not pull a
member for a weak-only definition, and even
-Wl,--whole-archive -lstdc++exp does not resolve the reference.
A user-provided replacement handler links and behaves correctly
(handler invoked, then termination under enforce semantics), only the
default path is affected.
Note there is long-standing precedent for exactly this policy,
libgcc/gthr.h:136 disables weak usage for mingw targets:
/* The pe-coff weak support isn't fully compatible to ELF's weak.
For static libraries it might would work, but as we need to deal
with shared versions too, we disable it for mingw-targets. */
#ifdef __MINGW32__
#undef GTHREAD_USE_WEAK
#define GTHREAD_USE_WEAK 0
#endif
(cf. PR 57212 / PR 52300, fixed back in the 4.8 era). contract26.cc's
unconditional __attribute__((weak)) needs the same target guard.
Tested with g++ (GCC) 17.0.0 20260707 (experimental), x86_64-w64-mingw32.