diff options
| -rw-r--r-- | src/ir.cpp | 53 | ||||
| -rw-r--r-- | test/compile_errors.zig | 18 |
2 files changed, 52 insertions, 19 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 6a63597ed8..f506fa093b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8177,18 +8177,25 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp if (is_int && is_signed) { bool ok = false; if (instr_is_comptime(op1) && instr_is_comptime(op2)) { - BigNum trunc_result; - BigNum floor_result; - if (bignum_div_trunc(&trunc_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { - zig_unreachable(); - } - if (bignum_div_floor(&floor_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { - zig_unreachable(); - } - if (bignum_cmp_eq(&trunc_result, &floor_result)) { - ok = true; + if (op2->value.data.x_bignum.data.x_uint == 0) { + // the division by zero error will be caught later, but we don't have a + // division function ambiguity problem. op_id = IrBinOpDivTrunc; - } + ok = true; + } else { + BigNum trunc_result; + BigNum floor_result; + if (bignum_div_trunc(&trunc_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { + zig_unreachable(); + } + if (bignum_div_floor(&floor_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { + zig_unreachable(); + } + if (bignum_cmp_eq(&trunc_result, &floor_result)) { + ok = true; + op_id = IrBinOpDivTrunc; + } + } } if (!ok) { ir_add_error(ira, &bin_op_instruction->base, @@ -8204,15 +8211,23 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp if (is_signed) { bool ok = false; if (instr_is_comptime(op1) && instr_is_comptime(op2)) { - BigNum rem_result; - BigNum mod_result; - if (bignum_rem(&rem_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { - zig_unreachable(); - } - if (bignum_mod(&mod_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { - zig_unreachable(); + if ((is_int && op2->value.data.x_bignum.data.x_uint == 0) || + (!is_int && op2->value.data.x_bignum.data.x_float == 0.0)) + { + // the division by zero error will be caught later, but we don't + // have a remainder function ambiguity problem + ok = true; + } else { + BigNum rem_result; + BigNum mod_result; + if (bignum_rem(&rem_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { + zig_unreachable(); + } + if (bignum_mod(&mod_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) { + zig_unreachable(); + } + ok = bignum_cmp_eq(&rem_result, &mod_result); } - ok = bignum_cmp_eq(&rem_result, &mod_result); } if (!ok) { ir_add_error(ira, &bin_op_instruction->base, diff --git a/test/compile_errors.zig b/test/compile_errors.zig index b854ada34b..2ee7954209 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1809,4 +1809,22 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\} , ".tmp_source.zig:3:25: error: attempt to cast negative value to unsigned integer"); + + cases.add("compile-time division by zero", + \\comptime { + \\ const a: i32 = 1; + \\ const b: i32 = 0; + \\ const c = a / b; + \\} + , + ".tmp_source.zig:4:17: error: division by zero is undefined"); + + cases.add("compile-time remainder division by zero", + \\comptime { + \\ const a: i32 = 1; + \\ const b: i32 = 0; + \\ const c = a % b; + \\} + , + ".tmp_source.zig:4:17: error: division by zero is undefined"); } |
