authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-12 16:18:41-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-12 16:18:41-07:00
log69109bc270c3167a3534dd32fc4f4def855e0be9
treeb9839d8b4f0a5475328e6c1988bdb9ccf5c862ad
parentbe4df96e4b80a3307b3661fd5ca3114478499daf

add error for dividing by zero in static function evaluation


6 files changed, 65 insertions(+), 58 deletions(-)

src/analyze.cpp+13-47
......@@ -2653,26 +2653,6 @@ static TypeTableEntry *resolve_expr_const_val_as_float_num_lit(CodeGen *g, AstNo
26532653 return g->builtin_types.entry_num_lit_float;
26542654}
26552655
2656static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *node,
2657 bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), AstNode *op1, AstNode *op2,
2658 TypeTableEntry *resolved_type)
2659{
2660 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2661 ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val;
2662 ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val;
2663
2664 const_val->ok = true;
2665
2666 if (bignum_fn(&const_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum)) {
2667 add_node_error(g, node,
2668 buf_sprintf("value cannot be represented in any integer type"));
2669 } else {
2670 num_lit_fits_in_other_type(g, node, resolved_type);
2671 }
2672
2673 return resolved_type;
2674}
2675
26762656static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
26772657 BlockContext *context, AstNode *node, Buf *err_name)
26782658{
......@@ -3074,37 +3054,23 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
30743054 return resolved_type;
30753055 }
30763056
3077 if (bin_op_type == BinOpTypeAdd) {
3078 return resolve_expr_const_val_as_bignum_op(g, node, bignum_add, *op1, *op2, resolved_type);
3079 } else if (bin_op_type == BinOpTypeSub) {
3080 return resolve_expr_const_val_as_bignum_op(g, node, bignum_sub, *op1, *op2, resolved_type);
3081 } else if (bin_op_type == BinOpTypeMult) {
3082 return resolve_expr_const_val_as_bignum_op(g, node, bignum_mul, *op1, *op2, resolved_type);
3083 } else if (bin_op_type == BinOpTypeDiv) {
3084 ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
3085 if ((is_int && op2_val->data.x_bignum.data.x_uint == 0) ||
3086 (is_float && op2_val->data.x_bignum.data.x_float == 0.0))
3087 {
3057 ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
3058 int err;
3059 if ((err = eval_const_expr_bin_op(op1_val, resolved_type, bin_op_type,
3060 op2_val, resolved_type, out_val)))
3061 {
3062 if (err == ErrorDivByZero) {
30883063 add_node_error(g, node, buf_sprintf("division by zero is undefined"));
30893064 return g->builtin_types.entry_invalid;
3090 } else {
3091 return resolve_expr_const_val_as_bignum_op(g, node, bignum_div, *op1, *op2, resolved_type);
3065 } else if (err == ErrorOverflow) {
3066 add_node_error(g, node, buf_sprintf("value cannot be represented in any integer type"));
3067 return g->builtin_types.entry_invalid;
30923068 }
3093 } else if (bin_op_type == BinOpTypeMod) {
3094 return resolve_expr_const_val_as_bignum_op(g, node, bignum_mod, *op1, *op2, resolved_type);
3095 } else if (bin_op_type == BinOpTypeBinOr) {
3096 return resolve_expr_const_val_as_bignum_op(g, node, bignum_or, *op1, *op2, resolved_type);
3097 } else if (bin_op_type == BinOpTypeBinAnd) {
3098 return resolve_expr_const_val_as_bignum_op(g, node, bignum_and, *op1, *op2, resolved_type);
3099 } else if (bin_op_type == BinOpTypeBinXor) {
3100 return resolve_expr_const_val_as_bignum_op(g, node, bignum_xor, *op1, *op2, resolved_type);
3101 } else if (bin_op_type == BinOpTypeBitShiftLeft) {
3102 return resolve_expr_const_val_as_bignum_op(g, node, bignum_shl, *op1, *op2, resolved_type);
3103 } else if (bin_op_type == BinOpTypeBitShiftRight) {
3104 return resolve_expr_const_val_as_bignum_op(g, node, bignum_shr, *op1, *op2, resolved_type);
3105 } else {
3106 zig_unreachable();
3069 return g->builtin_types.entry_invalid;
31073070 }
3071
3072 num_lit_fits_in_other_type(g, node, resolved_type);
3073 return resolved_type;
31083074 }
31093075 case BinOpTypeUnwrapMaybe:
31103076 {
src/error.cpp+2
......@@ -12,6 +12,8 @@ const char *err_str(int err) {
1212 case ErrorFileNotFound: return "file not found";
1313 case ErrorFileSystem: return "file system error";
1414 case ErrorFileTooBig: return "file too big";
15 case ErrorDivByZero: return "division by zero";
16 case ErrorOverflow: return "overflow";
1517 }
1618 return "(invalid error)";
1719}
src/error.hpp+2
......@@ -19,6 +19,8 @@ enum Error {
1919 ErrorFileNotFound,
2020 ErrorFileSystem,
2121 ErrorFileTooBig,
22 ErrorDivByZero,
23 ErrorOverflow
2224};
2325
2426const char *err_str(int err);
src/eval.cpp+37-10
......@@ -1,5 +1,6 @@
11#include "eval.hpp"
22#include "analyze.hpp"
3#include "error.hpp"
34
45static bool eval_fn_args(EvalFnRoot *efr, FnTableEntry *fn, ConstExprValue *args, ConstExprValue *out_val);
56
......@@ -96,16 +97,20 @@ static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {
9697 }
9798}
9899
99static void eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
100static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
100101 ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *))
101102{
102103 bool overflow = bignum_fn(&out_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum);
103 assert(!overflow);
104 if (overflow) {
105 return ErrorOverflow;
106 }
107
104108 out_val->ok = true;
105109 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
110 return 0;
106111}
107112
108void eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
113int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
109114 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
110115{
111116 assert(op1_val->ok);
......@@ -126,7 +131,7 @@ void eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
126131 case BinOpTypeAssignBoolAnd:
127132 case BinOpTypeAssignBoolOr:
128133 out_val->ok = true;
129 return;
134 return 0;
130135 case BinOpTypeBoolOr:
131136 case BinOpTypeBoolAnd:
132137 assert(op1_type->id == TypeTableEntryIdBool);
......@@ -134,7 +139,7 @@ void eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
134139 out_val->data.x_bool = eval_bool_bin_op_bool(op1_val->data.x_bool, bin_op, op2_val->data.x_bool);
135140 out_val->ok = true;
136141 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
137 return;
142 return 0;
138143 case BinOpTypeCmpEq:
139144 case BinOpTypeCmpNotEq:
140145 case BinOpTypeCmpLessThan:
......@@ -181,7 +186,7 @@ void eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
181186 op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
182187 out_val->data.x_bool = answer;
183188 out_val->ok = true;
184 return;
189 return 0;
185190 }
186191 case BinOpTypeAdd:
187192 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add);
......@@ -215,7 +220,7 @@ void eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
215220 if ((is_int && op2_val->data.x_bignum.data.x_uint == 0) ||
216221 (is_float && op2_val->data.x_bignum.data.x_float == 0.0))
217222 {
218 zig_panic("TODO handle errors in eval");
223 return ErrorDivByZero;
219224 } else {
220225 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_div);
221226 }
......@@ -249,7 +254,26 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)
249254
250255 BinOpType bin_op = node->data.bin_op_expr.bin_op;
251256
252 eval_const_expr_bin_op(&op1_val, op1_type, bin_op, &op2_val, op2_type, out_val);
257 int err;
258 if ((err = eval_const_expr_bin_op(&op1_val, op1_type, bin_op, &op2_val, op2_type, out_val))) {
259 ef->root->abort = true;
260 if (err == ErrorDivByZero) {
261 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
262 buf_sprintf("function evaluation caused division by zero"));
263 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
264 add_error_note(ef->root->codegen, msg, node, buf_sprintf("division by zero here"));
265 } else if (err == ErrorOverflow) {
266 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
267 buf_sprintf("function evaluation caused overflow"));
268 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
269 add_error_note(ef->root->codegen, msg, node, buf_sprintf("overflow occurred here"));
270 } else {
271 zig_unreachable();
272 }
273 return true;
274 }
275
276 assert(out_val->ok);
253277
254278 return false;
255279}
......@@ -1133,8 +1157,11 @@ bool eval_fn(CodeGen *g, AstNode *node, FnTableEntry *fn, ConstExprValue *out_va
11331157 return true;
11341158 }
11351159
1136 assert(out_val->ok);
1160 if (efr.abort) {
1161 return true;
1162 }
11371163
1138 return efr.abort;
1164 assert(out_val->ok);
1165 return false;
11391166}
11401167
src/eval.hpp+1-1
......@@ -14,7 +14,7 @@ bool eval_fn(CodeGen *g, AstNode *node, FnTableEntry *fn, ConstExprValue *out_va
1414 AstNode *struct_node);
1515
1616bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry);
17void eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
17int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
1818 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val);
1919
2020void eval_const_expr_implicit_cast(CastOp cast_op,
test/run_tests.cpp+10
......@@ -1481,6 +1481,16 @@ fn foo() {
14811481 const pointer = &array[0];
14821482}
14831483 )SOURCE", 1, ".tmp_source.zig:4:27: error: out of bounds array access");
1484
1485 add_compile_fail_case("compile time division by zero", R"SOURCE(
1486const x = foo(0);
1487fn foo(x: i32) -> i32 {
1488 1 / x
1489}
1490 )SOURCE", 3,
1491 ".tmp_source.zig:3:1: error: function evaluation caused division by zero",
1492 ".tmp_source.zig:2:14: note: called from here",
1493 ".tmp_source.zig:4:7: note: division by zero here");
14841494}
14851495
14861496//////////////////////////////////////////////////////////////////////////////