authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-14 13:07:45-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-14 13:07:45-04:00
loga7570186ebdffd97878a983b8e8a09902841e279
tree68ad4b544efe41eda086a8af5682ee383d5efbb7
parent63f6676fee83883736af794eaddb4d0ccb890c06

add compile error for comptime division by zero

closes #372

2 files changed, 52 insertions(+), 19 deletions(-)

src/ir.cpp+34-19
......@@ -8177,18 +8177,25 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
81778177 if (is_int && is_signed) {
81788178 bool ok = false;
81798179 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
8180 BigNum trunc_result;
8181 BigNum floor_result;
8182 if (bignum_div_trunc(&trunc_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8183 zig_unreachable();
8184 }
8185 if (bignum_div_floor(&floor_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8186 zig_unreachable();
8187 }
8188 if (bignum_cmp_eq(&trunc_result, &floor_result)) {
8189 ok = true;
8180 if (op2->value.data.x_bignum.data.x_uint == 0) {
8181 // the division by zero error will be caught later, but we don't have a
8182 // division function ambiguity problem.
81908183 op_id = IrBinOpDivTrunc;
8191 }
8184 ok = true;
8185 } else {
8186 BigNum trunc_result;
8187 BigNum floor_result;
8188 if (bignum_div_trunc(&trunc_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8189 zig_unreachable();
8190 }
8191 if (bignum_div_floor(&floor_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8192 zig_unreachable();
8193 }
8194 if (bignum_cmp_eq(&trunc_result, &floor_result)) {
8195 ok = true;
8196 op_id = IrBinOpDivTrunc;
8197 }
8198 }
81928199 }
81938200 if (!ok) {
81948201 ir_add_error(ira, &bin_op_instruction->base,
......@@ -8204,15 +8211,23 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
82048211 if (is_signed) {
82058212 bool ok = false;
82068213 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
8207 BigNum rem_result;
8208 BigNum mod_result;
8209 if (bignum_rem(&rem_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8210 zig_unreachable();
8211 }
8212 if (bignum_mod(&mod_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8213 zig_unreachable();
8214 if ((is_int && op2->value.data.x_bignum.data.x_uint == 0) ||
8215 (!is_int && op2->value.data.x_bignum.data.x_float == 0.0))
8216 {
8217 // the division by zero error will be caught later, but we don't
8218 // have a remainder function ambiguity problem
8219 ok = true;
8220 } else {
8221 BigNum rem_result;
8222 BigNum mod_result;
8223 if (bignum_rem(&rem_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8224 zig_unreachable();
8225 }
8226 if (bignum_mod(&mod_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {
8227 zig_unreachable();
8228 }
8229 ok = bignum_cmp_eq(&rem_result, &mod_result);
82148230 }
8215 ok = bignum_cmp_eq(&rem_result, &mod_result);
82168231 }
82178232 if (!ok) {
82188233 ir_add_error(ira, &bin_op_instruction->base,
test/compile_errors.zig+18
......@@ -1809,4 +1809,22 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
18091809 \\}
18101810 ,
18111811 ".tmp_source.zig:3:25: error: attempt to cast negative value to unsigned integer");
1812
1813 cases.add("compile-time division by zero",
1814 \\comptime {
1815 \\ const a: i32 = 1;
1816 \\ const b: i32 = 0;
1817 \\ const c = a / b;
1818 \\}
1819 ,
1820 ".tmp_source.zig:4:17: error: division by zero is undefined");
1821
1822 cases.add("compile-time remainder division by zero",
1823 \\comptime {
1824 \\ const a: i32 = 1;
1825 \\ const b: i32 = 0;
1826 \\ const c = a % b;
1827 \\}
1828 ,
1829 ".tmp_source.zig:4:17: error: division by zero is undefined");
18121830}