Component: glibc / wasm32 port (<stdint.h> + the port's bits/wordsize.h)
Found: 2026-07-10, cross-building clang/LLVM (a self-hosted on-target compiler) against the wasm32-hwjs glibc port.
Symptom. On the wasm32-hwjs glibc port, <stdint.h> types intptr_t/uintptr_t as int/unsigned int, while size_t/ptrdiff_t are unsigned long/long and the compiler's own __INTPTR_TYPE__/__UINTPTR_TYPE__ are long/unsigned long. So the libc's pointer-integer types disagree both with the size/offset types and with the compiler builtins. All are 32-bit on wasm32, but they are distinct types, which breaks any C/C++ that mixes them in a type-strict context (C++ template deduction, _Generic, __builtin_types_compatible_p).
Repro (against the wasm32 glibc sysroot, e.g. via wasmcc-glibc):
#include <stdint.h>
_Static_assert(__builtin_types_compatible_p(uintptr_t, __UINTPTR_TYPE__),
"glibc uintptr_t != compiler __UINTPTR_TYPE__");
error: static assertion failed due to requirement
'__builtin_types_compatible_p(unsigned int, unsigned long)':
glibc uintptr_t != compiler __UINTPTR_TYPE__
Evidence.
- Compiler builtins (this port's clang):
__SIZE_TYPE__ = long unsigned int,__UINTPTR_TYPE__ = long unsigned int,__INTPTR_TYPE__ = long int,__PTRDIFF_TYPE__ = long int— the compiler treats pointer/size integers aslong. - Installed
<stdint.h>,#if __WORDSIZE == 64else-branch:typedef int intptr_t; typedef unsigned int uintptr_t;—int-based, disagreeing with the above. - The port already elects the
longforms for the sibling types via glibc's existing knobs —__WORDSIZE32_SIZE_ULONG(→size_t = unsigned long) and__WORDSIZE32_PTRDIFF_LONG(→ptrdiff_t = long), set in itsbits/wordsize.h. There is no analogous__WORDSIZE32_INTPTR_LONGgate, so[u]intptr_talone stay on theintdefault and fall out of sync withsize_tand with the compiler.
Real-world impact. The clang/LLVM self-hosted-compiler cross-build fails compiling llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp at std::max(SmallBitVector::size() /* size_type = uintptr_t = unsigned int */, LUIdx + 1 /* size_t = unsigned long */) — std::max cannot deduce one _Tp from two distinct 32-bit types. (The musl port avoids this whole class by making its _Addr-derived integer types uniformly consistent — cf. musl#2; glibc's size_t/ptrdiff_t are already correct here, only [u]intptr_t lag.)
Proposed fix
Make [u]intptr_t agree with __INTPTR_TYPE__/__UINTPTR_TYPE__ (long/unsigned long) on the wasm32 port. The idiomatic form mirrors the size/ptrdiff knobs already present: add a __WORDSIZE32_INTPTR_LONG gate to <stdint.h>'s __WORDSIZE == 64 else-branch and set it in the wasm32 bits/wordsize.h, exactly as __WORDSIZE32_SIZE_ULONG / __WORDSIZE32_PTRDIFF_LONG already do for size_t / ptrdiff_t.
Minimal demonstrated change (the two typedefs in the WORDSIZE-32 else-branch of <stdint.h>) — verified to fix the repro above and the LLVM build, and byte-compatible (int == long == 32-bit on wasm32; only the C/C++ type identity changes):
--- a/stdint.h
+++ b/stdint.h
@@ Types for `void *' pointers — __WORDSIZE == 64 else-branch
# ifndef __intptr_t_defined
-typedef int intptr_t;
+typedef long int intptr_t;
# define __intptr_t_defined
# endif
-typedef unsigned int uintptr_t;
+typedef unsigned long int uintptr_t;
No branch: I have no local checkout of brintos/glibc that can push, so the fix is delivered as an inline diff only.
Proposed fix targets brintos/glibc only — no distro submodule pins moved. All distros share one lineage, so pin bumps are coordinated on merge, not per-engineer.