Summary
With --toolchain gcc@15.1.0 (and gcc@13.3.0) on x86_64-linux-gnu, any C++ translation unit that reaches libstdc++'s threading primitives fails to compile — including a two-line program that only includes <memory>. The default gcc@16.1.0 is not affected.
include/c++/15.1.0/ext/concurrence.h:257:32: error: cannot convert '<brace-enclosed initializer list>' to 'unsigned int' in initialization
257 | __gthread_cond_t _M_cond = __GTHREAD_COND_INIT;
include/c++/15.1.0/bits/std_mutex.h:208:32: error: cannot convert '<brace-enclosed initializer list>' to 'unsigned int' in initialization
Reproduction
mcpp 2026.9.21.3, xlings 2026.9.16.1, glibc payload xim-x-glibc 2.44.
mkdir -p probe/src && cd probe
printf '[package]\nname = "probe"\nversion = "0.1.0"\n' > mcpp.toml
printf '#include <memory>\nint main() { return *std::make_unique<int>(0); }\n' > src/main.cpp
mcpp build --toolchain gcc@15.1.0 # fails as above
mcpp build --toolchain gcc@16.1.0 # builds
Cause
The gcc 15.1.0 and 13.3.0 payloads ship a fixincludes copy of glibc's pthread.h, taken from the machine the toolchain was built on:
lib/gcc/x86_64-linux-gnu/15.1.0/include-fixed/pthread.h
"It has been auto-edited by fixincludes from:
/home/xlings/.xlings_data/subos/linux/usr/include/pthread.h" (glibc, Copyright 2002-2024)
mcpp adds the realised glibc with -idirafter <xim-x-glibc/2.44>/include, so gcc's include-fixed/ is searched first and this stale pthread.h wins over glibc 2.44's. Its initializer is for the older pthread_cond_t layout:
| header |
PTHREAD_COND_INITIALIZER |
gcc 15.1.0 include-fixed/pthread.h |
{ { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } } |
glibc 2.44 include/pthread.h |
{ { {0}, {0}, {0, 0}, 0, 0, {0, 0}, 0, 0 } } |
glibc 2.44's struct __pthread_cond_s is __wseq, __g1_start, __g1_orig_size, __wrefs, __g_signals[2], ..., so the stale initializer puts a brace list where an unsigned int is — the error above.
Evidence that this file alone is the cause:
include-fixed/ contents per payload: 13.3.0 → pthread.h README, 15.1.0 → pthread.h README, 16.1.0 → README only (and 16.1.0 works).
- With mcpp's own flags plus
-isystem <dir> containing a pthread.h that just #includes glibc 2.44's, gcc 15.1.0 compiles the same sources cleanly (verified on yaml-cpp 0.8.0/0.9.0, cli11, re2).
-fsyntax-only on #include <mutex> with exactly mcpp's -idirafter flags: gcc 13.3.0 exit 1, gcc 15.1.0 exit 1.
- The
x86_64-linux-musl target of gcc 15.1.0 (xim-x-musl-gcc) is unaffected.
Suggested fix
Repackage gcc 13.3.0 / 15.1.0 the way 16.1.0 is packaged — without the fixincludes pthread.h (or with include-fixed/ emptied of headers generated from the build host's glibc). A fixed header describes the build machine's C library, and mcpp always supplies its own glibc, so it can only ever disagree with it.
Found while validating compat.yaml-cpp in mcpplibs/mcpp-index#464 on gcc 15.
Summary
With
--toolchain gcc@15.1.0(andgcc@13.3.0) onx86_64-linux-gnu, any C++ translation unit that reaches libstdc++'s threading primitives fails to compile — including a two-line program that only includes<memory>. The defaultgcc@16.1.0is not affected.Reproduction
mcpp 2026.9.21.3, xlings 2026.9.16.1, glibc payload
xim-x-glibc 2.44.Cause
The gcc 15.1.0 and 13.3.0 payloads ship a fixincludes copy of glibc's
pthread.h, taken from the machine the toolchain was built on:mcpp adds the realised glibc with
-idirafter <xim-x-glibc/2.44>/include, so gcc'sinclude-fixed/is searched first and this stalepthread.hwins over glibc 2.44's. Its initializer is for the olderpthread_cond_tlayout:PTHREAD_COND_INITIALIZERinclude-fixed/pthread.h{ { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } }include/pthread.h{ { {0}, {0}, {0, 0}, 0, 0, {0, 0}, 0, 0 } }glibc 2.44's
struct __pthread_cond_sis__wseq, __g1_start, __g1_orig_size, __wrefs, __g_signals[2], ..., so the stale initializer puts a brace list where anunsigned intis — the error above.Evidence that this file alone is the cause:
include-fixed/contents per payload: 13.3.0 →pthread.h README, 15.1.0 →pthread.h README, 16.1.0 →READMEonly (and 16.1.0 works).-isystem <dir>containing apthread.hthat just#includes glibc 2.44's, gcc 15.1.0 compiles the same sources cleanly (verified on yaml-cpp 0.8.0/0.9.0, cli11, re2).-fsyntax-onlyon#include <mutex>with exactly mcpp's-idirafterflags: gcc 13.3.0 exit 1, gcc 15.1.0 exit 1.x86_64-linux-musltarget of gcc 15.1.0 (xim-x-musl-gcc) is unaffected.Suggested fix
Repackage
gcc13.3.0 / 15.1.0 the way 16.1.0 is packaged — without the fixincludespthread.h(or withinclude-fixed/emptied of headers generated from the build host's glibc). A fixed header describes the build machine's C library, and mcpp always supplies its own glibc, so it can only ever disagree with it.Found while validating
compat.yaml-cppin mcpplibs/mcpp-index#464 on gcc 15.