From cc0516c5f95746e2fd2bd5834cf73e9e9fcb05db Mon Sep 17 00:00:00 2001 From: tobiichi3227 Date: Sat, 18 Jul 2026 17:11:43 +0800 Subject: [PATCH 1/2] Fix signed constant modulo evaluation The power-of-two modulo shortcut produced positive remainders for negative dividends. As a result, constant expressions in global initializers disagreed with C's signed modulo semantics. Make signed constant modulo match runtime evaluation for positive and negative divisors, and cover every operand-sign combination with a regression test. --- src/parser.c | 17 +++++++++++++---- tests/driver.sh | 11 +++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/parser.c b/src/parser.c index 123be015..04d01c38 100644 --- a/src/parser.c +++ b/src/parser.c @@ -4,6 +4,7 @@ * shecc is freely redistributable under the BSD 2 clause license. See the * file "LICENSE" for information on usage and redistribution of this file. */ +#include #include #include #include @@ -3516,12 +3517,20 @@ int eval_expression_imm(opcode_t op, int op1, int op2) break; case OP_mod: /* Use bitwise AND for modulo optimization when divisor is power of 2 */ + if (tmp == INT_MIN) { + res = op1 % op2; + break; + } + tmp = tmp < 0 ? -tmp : tmp; tmp &= (tmp - 1); - if ((op2 != 0) && (tmp == 0)) { - res = op1; - res &= (op2 - 1); - } else + if (tmp != 0) { res = op1 % op2; + break; + } + op2 = op2 < 0 ? -op2 : op2; + res = op1 & (op2 - 1); + if (op1 < 0 && res != 0) + res -= op2; break; case OP_lshift: res = op1 << op2; diff --git a/tests/driver.sh b/tests/driver.sh index 3f11b055..b7eb84bb 100755 --- a/tests/driver.sh +++ b/tests/driver.sh @@ -409,6 +409,17 @@ declare -a arithmetic_tests=( run_expr_tests arithmetic_tests expr 6 "111 % 7" +try_output 0 "1 1 -1 -1" << EOF +int v1 = 5 % 4; +int v2 = 5 % -4; +int v3 = -5 % 4; +int v4 = -5 % -4; +int main() { + printf("%d %d %d %d", v1, v2, v3, v4); + return 0; +} +EOF + # Category: Overflow Behavior begin_category "Overflow Behavior" "Testing integer overflow handling" From 0f68934b0ce73339ff7771ce0fcb90b426a08112 Mon Sep 17 00:00:00 2001 From: tobiichi3227 Date: Sat, 18 Jul 2026 17:14:18 +0800 Subject: [PATCH 2/2] Reject zero divisors in constant expressions Immediate evaluation performed division and modulo without checking the divisor. A zero divisor therefore terminated the compiler with a host arithmetic exception instead of reporting an input error. Diagnose both cases through the normal parser error path and add regression tests to ensure invalid global initializers are rejected. --- src/parser.c | 5 +++++ tests/driver.sh | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/parser.c b/src/parser.c index 04d01c38..6af0a77b 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3513,9 +3513,14 @@ int eval_expression_imm(opcode_t op, int op1, int op2) res = op1 * op2; break; case OP_div: + if (!op2) + error_at("Division by zero in constant expression", + cur_token_loc()); res = op1 / op2; break; case OP_mod: + if (!op2) + error_at("Modulo by zero in constant expression", cur_token_loc()); /* Use bitwise AND for modulo optimization when divisor is power of 2 */ if (tmp == INT_MIN) { res = op1 % op2; diff --git a/tests/driver.sh b/tests/driver.sh index b7eb84bb..eb8125b9 100755 --- a/tests/driver.sh +++ b/tests/driver.sh @@ -420,6 +420,16 @@ int main() { } EOF +try_compile_error << EOF +int value = 1 / 0; +int main() { return value; } +EOF + +try_compile_error << EOF +int value = 1 % 0; +int main() { return value; } +EOF + # Category: Overflow Behavior begin_category "Overflow Behavior" "Testing integer overflow handling"