1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-27 15:29:46 +00:00

Merge pull request #1918 from acqn/PPFix

[cc65] Fixed bitwise-shift in preprocessor
This commit is contained in:
Bob Andrews 2022-11-18 19:09:55 +01:00 committed by GitHub
commit a0a9cfdcd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 138 additions and 10 deletions

View File

@ -519,12 +519,21 @@ static void PPhie7 (PPExpr* Expr)
/* Evaluate */
if (PPEvaluationEnabled && !PPEvaluationFailed) {
/* To shift by a negative value is equivalent to shift to the
** opposite direction.
*/
if ((Rhs.Flags & PPEXPR_UNSIGNED) != 0 && Rhs.IVal > (long)LONG_BITS) {
/* For now we use 32-bit integer types for PP integer constants */
if ((Rhs.Flags & PPEXPR_UNSIGNED) != 0) {
if ((unsigned long)Rhs.IVal > LONG_BITS) {
Rhs.IVal = (long)LONG_BITS;
}
} else if (Rhs.IVal > (long)LONG_BITS) {
Rhs.IVal = (long)LONG_BITS;
} else if (Rhs.IVal < -(long)LONG_BITS) {
Rhs.IVal = -(long)LONG_BITS;
}
/* Positive count for left-shift and negative for right-shift. So
** to shift by a count is equivalent to shift to the opposite
** direction by the negated count.
*/
if (Op == TOK_SHR) {
Rhs.IVal = -Rhs.IVal;
}
@ -532,27 +541,26 @@ static void PPhie7 (PPExpr* Expr)
/* Evaluate the result */
if ((Expr->Flags & PPEXPR_UNSIGNED) != 0) {
if (Rhs.IVal >= (long)LONG_BITS) {
/* For now we use (unsigned) long types for integer constants */
PPWarning ("Integer overflow in preprocessor expression");
Expr->IVal = 0;
} else if (Rhs.IVal > 0) {
Expr->IVal <<= Rhs.IVal;
} else if (Rhs.IVal < -(long)LONG_BITS) {
} else if (Rhs.IVal <= -(long)LONG_BITS) {
Expr->IVal = 0;
} else if (Rhs.IVal < 0) {
Expr->IVal = (unsigned long)Expr->IVal >> -Rhs.IVal;
}
} else {
/* -1 for sign bit */
if (Rhs.IVal >= (long)(LONG_BITS - 1)) {
/* For now we use (unsigned) long types for integer constants */
PPWarning ("Integer overflow in preprocessor expression");
Expr->IVal = 0;
} else if (Rhs.IVal > 0) {
Expr->IVal <<= Rhs.IVal;
} else if (Rhs.IVal < -(long)LONG_BITS) {
Expr->IVal = -1;
} else if (Rhs.IVal <= -(long)LONG_BITS) {
Expr->IVal = Expr->IVal >= 0 ? 0 : -1;
} else if (Rhs.IVal < 0) {
Expr->IVal >>= Expr->IVal >> -Rhs.IVal;
Expr->IVal = (long)Expr->IVal >> -Rhs.IVal;
}
}
}

120
test/val/ppshift.c Normal file
View File

@ -0,0 +1,120 @@
/*
Test of bitwise-shift in preprocessor expressions.
Note: Keep in mind that integer constants are always 32-bit in PP for cc65.
*/
/* Signed lhs */
#if 1 << 16 != 0x00010000
#error 1 << 16 != 0x00010000
#endif
#if 0x00010000 << -16 != 1
#error 0x00010000 << -16 != 1
#endif
#if 0x10000 >> 16 != 1
#error 0x10000 >> 16 != 1
#endif
#if 1 >> -16 != 0x10000
#error 1 >> -16 != 0x10000
#endif
#if 1 << 32 != 0
#error 1 << 32 != 0
#endif
#if 1 << -32 != 0
#error 1 << -32 != 0
#endif
#if 1 >> 32 != 0
#error 1 >> 32 != 0
#endif
#if 1 >> -32 != 0
#error 1 >> -32 != 0
#endif
#if -1 << 32 != 0
#error -1 << 32 != 0
#endif
#if -1 << -32 != -1
#error -1 << -32 != -1
#endif
#if -1 >> 32 != -1
#error -1 >> 32 != -1
#endif
#if -1 >> -32 != 0
#error -1 >> -32 != 0
#endif
/* NOTE: 2147483648 is an UNSIGNED integer! */
#if -1 << 2147483648 != 0
#error -1 << 2147483648 != 0
#endif
/* NOTE: -2147483648 is also an UNSIGNED integer! */
#if -1 << -2147483648 != 0
#error -1 << -2147483648 != 0
#endif
#if -1 << (-2147483647 - 1) != -1
#error -1 << (-2147483647 - 1) != -1
#endif
/* NOTE: 2147483648 is an UNSIGNED integer! */
#if -1 >> 2147483648 != -1
#error -1 >> 2147483648 != -1
#endif
/* NOTE: -2147483648 is also an UNSIGNED integer! */
#if -1 >> -2147483648 != -1
#error -1 >> -2147483648 != 0
#endif
#if -1 >> (-2147483647 - 1) != 0
#error -1 >> (-2147483647 - 1) != 0
#endif
/* Unsigned lhs */
#if 1U << 16 != 0x00010000
#error 1U << 16 != 0x00010000
#endif
#if 0x80000000U << -16 != 0x8000
#error 0x80000000U << -16 != 0x8000
#endif
#if 0x80000000U >> 16 != 0x8000
#error 0x80000000U >> 16 != 0x8000
#endif
#if 1U >> -16 != 0x10000
#error 1U >> -16 != 0x10000
#endif
#if -1U << 32 != 0
#error -1U << 32 != 0
#endif
#if -1U << -32 != 0
#error -1U << -32 != 0
#endif
#if -1U >> 32 != 0
#error -1U >> 32 != 0
#endif
#if -1U >> -32 != 0
#error -1U >> -32 != 0
#endif
int main(void)
{
return 0;
}