diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index 612aa0213..5af7e513c 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -144,7 +144,16 @@ static int DoConversion (ExprDesc* Expr, int k, type* NewType) /* If the new type is signed, sign extend the value */ if (!IsSignUnsigned (NewType)) { if (Expr->ConstVal & (0x01UL << (NewBits-1))) { - Expr->ConstVal |= ((~0L) << NewBits); + /* Beware: NewBits may be 32, in which case a shift + * creates undefined behaviour if a long does also + * have 32 bits. So apply a somewhat complex special + * handling. + */ + unsigned long SignBits = ~0UL; + SignBits <<= (NewBits / 2); + NewBits -= (NewBits / 2); + SignBits <<= NewBits; + Expr->ConstVal |= SignBits; } } }