aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-02-11 15:02:22 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-02-11 15:02:22 -0700
commita180168871b6e32a8c0825b1eb309587c3e0d179 (patch)
tree935616676906c2b56d3d19f8acd6a07e86865e14 /src/analyze.cpp
parent2bf6c28bc3e535deb651d5b37e332226e0d38930 (diff)
downloadzig-a180168871b6e32a8c0825b1eb309587c3e0d179.tar.gz
zig-a180168871b6e32a8c0825b1eb309587c3e0d179.zip
fix division by 0 crashing compiler
closes #99 closes #124 thanks to Michael Patraw for submitting a patch for this.
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 287a8667e1..8d10913926 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -2929,6 +2929,27 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
return resolved_type;
}
+ bool is_int = false;
+ bool is_float = false;
+ if (resolved_type->id == TypeTableEntryIdInt ||
+ resolved_type->id == TypeTableEntryIdNumLitInt)
+ {
+ is_int = true;
+ } else if ((resolved_type->id == TypeTableEntryIdFloat ||
+ resolved_type->id == TypeTableEntryIdNumLitFloat) &&
+ (bin_op_type == BinOpTypeAdd ||
+ bin_op_type == BinOpTypeSub ||
+ bin_op_type == BinOpTypeMult ||
+ bin_op_type == BinOpTypeDiv ||
+ bin_op_type == BinOpTypeMod))
+ {
+ is_float = true;
+ } else {
+ add_node_error(g, node, buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
+ buf_ptr(&lhs_type->name), buf_ptr(&rhs_type->name)));
+ return g->builtin_types.entry_invalid;
+ }
+
ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
if (!op1_val->ok || !op2_val->ok) {
@@ -2942,7 +2963,15 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
} else if (bin_op_type == BinOpTypeMult) {
return resolve_expr_const_val_as_bignum_op(g, node, bignum_mul, *op1, *op2, resolved_type);
} else if (bin_op_type == BinOpTypeDiv) {
- return resolve_expr_const_val_as_bignum_op(g, node, bignum_div, *op1, *op2, resolved_type);
+ ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
+ if ((is_int && op2_val->data.x_bignum.data.x_uint == 0) ||
+ (is_float && op2_val->data.x_bignum.data.x_float == 0.0))
+ {
+ add_node_error(g, node, buf_sprintf("division by zero is undefined"));
+ return g->builtin_types.entry_invalid;
+ } else {
+ return resolve_expr_const_val_as_bignum_op(g, node, bignum_div, *op1, *op2, resolved_type);
+ }
} else if (bin_op_type == BinOpTypeMod) {
return resolve_expr_const_val_as_bignum_op(g, node, bignum_mod, *op1, *op2, resolved_type);
} else if (bin_op_type == BinOpTypeBinOr) {