Thanks Jakub & Martin for unconfusing me about where the UB was!
I'd forgotten that left shifting a negative value is UB until C++20. Insert some casts to do unsigned shifts. PR c++/98625 gcc/cp/ * module.cc (bytes_in::i, bytes_in::wi): Avoid left shift of signed type. -- Nathan Sidwell
diff --git i/gcc/cp/module.cc w/gcc/cp/module.cc index 1fd0bcfe3eb..8f9c7940ef8 100644 --- i/gcc/cp/module.cc +++ w/gcc/cp/module.cc @@ -881,9 +881,12 @@ bytes_in::i () v &= 0xf; if (v & 0x8) v |= -1 ^ 0x7; + /* unsigned necessary due to left shifts of -ve values. */ + unsigned uv = unsigned (v); if ((ptr = read (++bytes))) while (bytes--) - v = (v << 8) | (*ptr++ & 0xff); + uv = (uv << 8) | (*ptr++ & 0xff); + v = int (uv); } else if (v & 0x40) v |= -1 ^ 0x3f; @@ -972,9 +975,12 @@ bytes_in::wi () v &= 0xf; if (v & 0x8) v |= -1 ^ 0x7; + /* unsigned necessary due to left shifts of -ve values. */ + unsigned HOST_WIDE_INT uv = (unsigned HOST_WIDE_INT) v; if ((ptr = read (++bytes))) while (bytes--) - v = (v << 8) | (*ptr++ & 0xff); + uv = (uv << 8) | (*ptr++ & 0xff); + v = (HOST_WIDE_INT) uv; } else if (v & 0x40) v |= -1 ^ 0x3f;