The type-generic __builtin_{add,sub,mul}_overflow accept operand and result types that all differ, including __int128 and unsigned __int128. Since #1863, the transpiler handles mixed types by computing in i128, but unsigned __int128 values above i128::MAX wrap when cast to i128, silently corrupting the overflow flag. Example: __builtin_add_overflow((unsigned __int128)-1, (unsigned __int128)1, &u64_out) must return true (the true sum 2^128 fits no result type), but in i128 it computes -1 + 1 = 0 with no overflow.
#1863 therefore rejects mixed-type uses where any of the three types is 128-bit, rather than translating them wrongly. Same-type 128-bit uses map to Rust's native u128/i128 overflowing_* and are supported. The rejected cases are pinned by the overflow_128.c snapshot test.
A future implementation could pick the computation domain from the widest type and its signedness, or special-case unsigned __int128 operands. Not needed for libgit2 (#1861); no real-world use observed so far.
The type-generic
__builtin_{add,sub,mul}_overflowaccept operand and result types that all differ, including__int128andunsigned __int128. Since #1863, the transpiler handles mixed types by computing ini128, butunsigned __int128values abovei128::MAXwrap when cast toi128, silently corrupting the overflow flag. Example:__builtin_add_overflow((unsigned __int128)-1, (unsigned __int128)1, &u64_out)must return true (the true sum 2^128 fits no result type), but ini128it computes-1 + 1 = 0with no overflow.#1863 therefore rejects mixed-type uses where any of the three types is 128-bit, rather than translating them wrongly. Same-type 128-bit uses map to Rust's native
u128/i128overflowing_*and are supported. The rejected cases are pinned by theoverflow_128.csnapshot test.A future implementation could pick the computation domain from the widest type and its signedness, or special-case
unsigned __int128operands. Not needed for libgit2 (#1861); no real-world use observed so far.