aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authoremekoi <emekankurumeh@outlook.com>2019-07-01 00:27:55 -0500
committeremekoi <emekankurumeh@outlook.com>2019-07-01 00:27:55 -0500
commit2d85ff94653457ea12cd9ab0984ab3b13c9b41e5 (patch)
tree2ef361af1cbc6679cad8c7d82114f44dcf6d7f95 /src/ir.cpp
parent0dd2e93e4cb28205823e840d5fdb0fccce9cc2e7 (diff)
downloadzig-2d85ff94653457ea12cd9ab0984ab3b13c9b41e5.tar.gz
zig-2d85ff94653457ea12cd9ab0984ab3b13c9b41e5.zip
added invalid switch prong error
added error for switch prong with different payloads and support for capturing payload on switch prongs with payloads of the same type
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp38
1 files changed, 34 insertions, 4 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index abae52fcb5..d4cb5f90de 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -19128,10 +19128,6 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
assert(enum_type != nullptr);
assert(enum_type->id == ZigTypeIdEnum);
- if (instruction->prongs_len != 1) {
- return target_value_ptr;
- }
-
IrInstruction *prong_value = instruction->prongs_ptr[0]->child;
if (type_is_invalid(prong_value->value.type))
return ira->codegen->invalid_instruction;
@@ -19146,6 +19142,40 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
TypeUnionField *field = find_union_field_by_tag(target_type, &prong_val->data.x_enum_tag);
+ if (instruction->prongs_len != 1) {
+ ErrorMsg *invalid_payload = nullptr;
+ Buf *invalid_payload_list = nullptr;
+
+ for (size_t i = 1; i < instruction->prongs_len; i++) {
+ IrInstruction *casted_prong_value = ir_implicit_cast(ira, instruction->prongs_ptr[i]->child, enum_type);
+ if (type_is_invalid(casted_prong_value->value.type))
+ return ira->codegen->invalid_instruction;
+
+ ConstExprValue *next_prong = ir_resolve_const(ira, casted_prong_value, UndefBad);
+ if (!next_prong)
+ return ira->codegen->invalid_instruction;
+
+ ZigType *payload = find_union_field_by_tag(target_type, &next_prong->data.x_enum_tag)->type_entry;
+
+ if (field->type_entry != payload) {
+ if (!invalid_payload) {
+ invalid_payload = ir_add_error(ira, &instruction->base,
+ buf_sprintf("switch prong contains cases with differing payloads"));
+ invalid_payload_list = buf_sprintf("types %s", buf_ptr(&field->type_entry->name));
+ }
+
+ if (i == instruction->prongs_len - 1)
+ buf_append_buf(invalid_payload_list, buf_sprintf(" and %s", buf_ptr(&payload->name)));
+ else
+ buf_append_buf(invalid_payload_list, buf_sprintf(", %s", buf_ptr(&payload->name)));
+ }
+ }
+
+ if (invalid_payload)
+ add_error_note(ira->codegen, invalid_payload,
+ ((IrInstruction*)instruction)->source_node, invalid_payload_list);
+ }
+
if (instr_is_comptime(target_value_ptr)) {
ConstExprValue *target_val_ptr = ir_resolve_const(ira, target_value_ptr, UndefBad);
if (!target_value_ptr)