authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-08 17:49:14-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-08 17:49:14-05:00
log756a218e27831a20395cc370fb3d667666dee20d
treef652f1ae7f44769dd2acc361955435aff028581a
parent3577a80bb67923c0c165bd3c6e57ef3248e1b59c

add implicit cast from enum tag type of union to const ptr to the union

closes #654

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

src/ir.cpp+34
......@@ -7492,6 +7492,19 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
74927492 }
74937493 }
74947494
7495 // implicit enum to &const union which has the enum as the tag type
7496 if (actual_type->id == TypeTableEntryIdEnum && expected_type->id == TypeTableEntryIdPointer) {
7497 TypeTableEntry *union_type = expected_type->data.pointer.child_type;
7498 if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
7499 union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)
7500 {
7501 type_ensure_zero_bits_known(ira->codegen, union_type);
7502 if (union_type->data.unionation.tag_type == actual_type) {
7503 return ImplicitCastMatchResultYes;
7504 }
7505 }
7506 }
7507
74957508 // implicit undefined literal to anything
74967509 if (actual_type->id == TypeTableEntryIdUndefLit) {
74977510 return ImplicitCastMatchResultYes;
......@@ -9079,6 +9092,27 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
90799092 }
90809093 }
90819094
9095 // explicit enum to &const union which has the enum as the tag type
9096 if (actual_type->id == TypeTableEntryIdEnum && wanted_type->id == TypeTableEntryIdPointer) {
9097 TypeTableEntry *union_type = wanted_type->data.pointer.child_type;
9098 if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
9099 union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)
9100 {
9101 type_ensure_zero_bits_known(ira->codegen, union_type);
9102 if (union_type->data.unionation.tag_type == actual_type) {
9103 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, union_type, value);
9104 if (type_is_invalid(cast1->value.type))
9105 return ira->codegen->invalid_instruction;
9106
9107 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
9108 if (type_is_invalid(cast2->value.type))
9109 return ira->codegen->invalid_instruction;
9110
9111 return cast2;
9112 }
9113 }
9114 }
9115
90829116 // explicit cast from undefined to anything
90839117 if (actual_type->id == TypeTableEntryIdUndefLit) {
90849118 return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
test/cases/union.zig+14
......@@ -206,3 +206,17 @@ test "implicit cast union to its tag type" {
206206fn giveMeLetterB(x: Letter2) {
207207 assert(x == Value2.B);
208208}
209
210test "implicit cast from @EnumTagType(TheUnion) to &const TheUnion" {
211 assertIsTheUnion2Item1(TheUnion2.Item1);
212}
213
214const TheUnion2 = union(enum) {
215 Item1,
216 Item2: i32,
217};
218
219fn assertIsTheUnion2Item1(value: &const TheUnion2) {
220 assert(*value == TheUnion2.Item1);
221}
222