aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-05-26 12:59:30 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-05-26 12:59:30 -0400
commit21ed9391179a9e472b25c80eaec5eebc9d08aca8 (patch)
treec25253450faa5b0ce2dbf21f096e759f8ff90abd /src/ir.cpp
parent163a8e98bc04ea955ee54d5905436ffac34c93a2 (diff)
downloadzig-21ed9391179a9e472b25c80eaec5eebc9d08aca8.tar.gz
zig-21ed9391179a9e472b25c80eaec5eebc9d08aca8.zip
support enum literals implicit casting to tagged unions
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp46
1 files changed, 34 insertions, 12 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 2d81f0c219..f24b2b6a7b 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -8993,6 +8993,13 @@ static bool slice_is_const(ZigType *type) {
return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
}
+static bool is_tagged_union(ZigType *type) {
+ if (type->id != ZigTypeIdUnion)
+ return false;
+ return (type->data.unionation.decl_node->data.container_decl.auto_enum ||
+ type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr);
+}
+
static void populate_error_set_table(ErrorTableEntry **errors, ZigType *set) {
assert(set->id == ZigTypeIdErrorSet);
for (uint32_t i = 0; i < set->data.error_set.err_count; i += 1) {
@@ -9676,6 +9683,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
continue;
}
}
+ if (is_tagged_union(prev_type) && cur_type->id == ZigTypeIdEnumLiteral) {
+ TypeUnionField *field = find_union_type_field(prev_type, cur_inst->value.data.x_enum_literal);
+ if (field != nullptr) {
+ continue;
+ }
+ }
if (cur_type->id == ZigTypeIdEnum && prev_type->id == ZigTypeIdEnumLiteral) {
TypeEnumField *field = find_enum_type_field(cur_type, prev_inst->value.data.x_enum_literal);
@@ -9685,6 +9698,14 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
}
}
+ if (is_tagged_union(cur_type) && prev_type->id == ZigTypeIdEnumLiteral) {
+ TypeUnionField *field = find_union_type_field(cur_type, prev_inst->value.data.x_enum_literal);
+ if (field != nullptr) {
+ prev_inst = cur_inst;
+ continue;
+ }
+ }
+
if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC &&
(cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt))
{
@@ -10907,11 +10928,17 @@ static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruc
}
static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *target, ZigType *wanted_type)
+ IrInstruction *uncasted_target, ZigType *wanted_type)
{
Error err;
assert(wanted_type->id == ZigTypeIdUnion);
- assert(target->value.type->id == ZigTypeIdEnum);
+
+ if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *target = ir_implicit_cast(ira, uncasted_target, wanted_type->data.unionation.tag_type);
+ if (type_is_invalid(target->value.type))
+ return ira->codegen->invalid_instruction;
if (instr_is_comptime(target)) {
ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
@@ -11788,17 +11815,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
- // enum to union which has the enum as the tag type
- if (wanted_type->id == ZigTypeIdUnion && actual_type->id == ZigTypeIdEnum &&
- (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||
- wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
+ // enum to union which has the enum as the tag type, or
+ // enum literal to union which has a matching enum as the tag type
+ if (is_tagged_union(wanted_type) && (actual_type->id == ZigTypeIdEnum ||
+ actual_type->id == ZigTypeIdEnumLiteral))
{
- if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->invalid_instruction;
-
- if (wanted_type->data.unionation.tag_type == actual_type) {
- return ir_analyze_enum_to_union(ira, source_instr, value, wanted_type);
- }
+ return ir_analyze_enum_to_union(ira, source_instr, value, wanted_type);
}
// cast from *T to *[1]T