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...@@ -8177,18 +8177,25 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
8177 if (is_int && is_signed) {8177 if (is_int && is_signed) {
8178 bool ok = false;8178 bool ok = false;
8179 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {8179 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
8180 BigNum trunc_result;8180 if (op2->value.data.x_bignum.data.x_uint == 0) {
8181 BigNum floor_result;8181 // the division by zero error will be caught later, but we don't have a
8182 if (bignum_div_trunc(&trunc_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {8182 // division function ambiguity problem.
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;
8190 op_id = IrBinOpDivTrunc;8183 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 }
8192 }8199 }
8193 if (!ok) {8200 if (!ok) {
8194 ir_add_error(ira, &bin_op_instruction->base,8201 ir_add_error(ira, &bin_op_instruction->base,
...@@ -8204,15 +8211,23 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -8204,15 +8211,23 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
8204 if (is_signed) {8211 if (is_signed) {
8205 bool ok = false;8212 bool ok = false;
8206 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {8213 if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
8207 BigNum rem_result;8214 if ((is_int && op2->value.data.x_bignum.data.x_uint == 0) ||
8208 BigNum mod_result;8215 (!is_int && op2->value.data.x_bignum.data.x_float == 0.0))
8209 if (bignum_rem(&rem_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {8216 {
8210 zig_unreachable();8217 // the division by zero error will be caught later, but we don't
8211 }8218 // have a remainder function ambiguity problem
8212 if (bignum_mod(&mod_result, &op1->value.data.x_bignum, &op2->value.data.x_bignum)) {8219 ok = true;
8213 zig_unreachable();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);
8214 }8230 }
8215 ok = bignum_cmp_eq(&rem_result, &mod_result);
8216 }8231 }
8217 if (!ok) {8232 if (!ok) {
8218 ir_add_error(ira, &bin_op_instruction->base,8233 ir_add_error(ira, &bin_op_instruction->base,
test/compile_errors.zig+18
...@@ -1809,4 +1809,22 @@ pub fn addCases(cases: &tests.CompileErrorContext) {...@@ -1809,4 +1809,22 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
1809 \\}1809 \\}
1810 ,1810 ,
1811 ".tmp_source.zig:3:25: error: attempt to cast negative value to unsigned integer");1811 ".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");
1812}1830}