authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-11 16:15:08-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-11 16:15:08-07:00
log08eb19456b319cc5b0c287773d52850f12f2bcb5
tree99188572c1ba6c53b9cc8fbd92bb007f3f85cfb6
parenta180168871b6e32a8c0825b1eb309587c3e0d179

add compile error for missing enumeration value in switch


2 files changed, 42 insertions(+), 0 deletions(-)

src/analyze.cpp+25
...@@ -4241,6 +4241,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -4241,6 +4241,8 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
4241 return resolve_expr_const_val_as_bool(g, node, g->is_release_build, true);4241 return resolve_expr_const_val_as_bool(g, node, g->is_release_build, true);
4242 } else if (buf_eql_str(&var_name, "is_test")) {4242 } else if (buf_eql_str(&var_name, "is_test")) {
4243 return resolve_expr_const_val_as_bool(g, node, g->is_test_build, true);4243 return resolve_expr_const_val_as_bool(g, node, g->is_test_build, true);
4244 } else if (buf_eql_str(&var_name, "os")) {
4245 zig_panic("TODO");
4244 } else {4246 } else {
4245 add_node_error(g, *str_node,4247 add_node_error(g, *str_node,
4246 buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(&var_name)));4248 buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(&var_name)));
...@@ -4650,6 +4652,11 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,...@@ -4650,6 +4652,11 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
4650 buf_sprintf("switch on unreachable expression not allowed"));4652 buf_sprintf("switch on unreachable expression not allowed"));
4651 return g->builtin_types.entry_invalid;4653 return g->builtin_types.entry_invalid;
4652 } else {4654 } else {
4655 int *field_use_counts = nullptr;
4656 if (expr_type->id == TypeTableEntryIdEnum) {
4657 field_use_counts = allocate<int>(expr_type->data.enumeration.field_count);
4658 }
4659
4653 AstNode *else_prong = nullptr;4660 AstNode *else_prong = nullptr;
4654 for (int prong_i = 0; prong_i < prong_count; prong_i += 1) {4661 for (int prong_i = 0; prong_i < prong_count; prong_i += 1) {
4655 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);4662 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
...@@ -4686,6 +4693,14 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,...@@ -4686,6 +4693,14 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
4686 if (type_enum_field->type_entry != var_type) {4693 if (type_enum_field->type_entry != var_type) {
4687 all_agree_on_var_type = false;4694 all_agree_on_var_type = false;
4688 }4695 }
4696 uint32_t field_index = type_enum_field->value;
4697 assert(field_use_counts);
4698 field_use_counts[field_index] += 1;
4699 if (field_use_counts[field_index] > 1) {
4700 add_node_error(g, item_node,
4701 buf_sprintf("duplicate switch value: '%s'",
4702 buf_ptr(type_enum_field->name)));
4703 }
4689 } else {4704 } else {
4690 add_node_error(g, item_node,4705 add_node_error(g, item_node,
4691 buf_sprintf("enum '%s' has no field '%s'",4706 buf_sprintf("enum '%s' has no field '%s'",
...@@ -4729,6 +4744,16 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,...@@ -4729,6 +4744,16 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
4729 prong_node->data.switch_prong.expr);4744 prong_node->data.switch_prong.expr);
4730 peer_nodes[prong_i] = prong_node->data.switch_prong.expr;4745 peer_nodes[prong_i] = prong_node->data.switch_prong.expr;
4731 }4746 }
4747
4748 if (expr_type->id == TypeTableEntryIdEnum && !else_prong) {
4749 for (uint32_t i = 0; i < expr_type->data.enumeration.field_count; i += 1) {
4750 if (field_use_counts[i] == 0) {
4751 add_node_error(g, node,
4752 buf_sprintf("enumeration value '%s' not handled in switch",
4753 buf_ptr(expr_type->data.enumeration.fields[i].name)));
4754 }
4755 }
4756 }
4732 }4757 }
4733 return resolve_peer_type_compatibility(g, import, context, node, peer_nodes, peer_types, prong_count);4758 return resolve_peer_type_compatibility(g, import, context, node, peer_nodes, peer_types, prong_count);
4734}4759}
test/run_tests.cpp+17
...@@ -1760,6 +1760,23 @@ const float_x = f32(1.0) / f32(0.0);...@@ -1760,6 +1760,23 @@ const float_x = f32(1.0) / f32(0.0);
1760 ".tmp_source.zig:3:25: error: division by zero is undefined",1760 ".tmp_source.zig:3:25: error: division by zero is undefined",
1761 ".tmp_source.zig:4:22: error: division by zero is undefined",1761 ".tmp_source.zig:4:22: error: division by zero is undefined",
1762 ".tmp_source.zig:5:26: error: division by zero is undefined");1762 ".tmp_source.zig:5:26: error: division by zero is undefined");
1763
1764
1765 add_compile_fail_case("missing switch prong", R"SOURCE(
1766enum Number {
1767 One,
1768 Two,
1769 Three,
1770 Four,
1771}
1772fn f(n: Number) -> i32 {
1773 switch (n) {
1774 One => 1,
1775 Two => 2,
1776 Three => 3,
1777 }
1778}
1779 )SOURCE", 1, ".tmp_source.zig:9:5: error: enumeration value 'Four' not handled in switch");
1763}1780}
17641781
1765//////////////////////////////////////////////////////////////////////////////1782//////////////////////////////////////////////////////////////////////////////