aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-09-09 16:17:45 -0400
committerGitHub <noreply@github.com>2019-09-09 16:17:45 -0400
commita3993465feefae6e64f16ce7e7a70251a739cb22 (patch)
treeb401f8096bc820007771045f0ef00b9c18d457da /src/ir.cpp
parentfec795cd29909f0e43ba9de303b93309db8858b5 (diff)
parent4b1cd45472cab5569438fef018990fbe8043c6c3 (diff)
downloadzig-a3993465feefae6e64f16ce7e7a70251a739cb22.tar.gz
zig-a3993465feefae6e64f16ce7e7a70251a739cb22.zip
Merge pull request #3200 from LemonBoy/eq-tagged-union
Allow comparison between union tag and enum literal
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index ca2c59e342..3e699b50eb 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -13228,6 +13228,46 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
ir_add_error_node(ira, source_node, buf_sprintf("comparison of '%s' with null",
buf_ptr(&non_null_type->name)));
return ira->codegen->invalid_instruction;
+ } else if (is_equality_cmp && (
+ (op1->value.type->id == ZigTypeIdEnumLiteral && op2->value.type->id == ZigTypeIdUnion) ||
+ (op2->value.type->id == ZigTypeIdEnumLiteral && op1->value.type->id == ZigTypeIdUnion)))
+ {
+ // Support equality comparison between a union's tag value and a enum literal
+ IrInstruction *union_val = op1->value.type->id == ZigTypeIdUnion ? op1 : op2;
+ IrInstruction *enum_val = op1->value.type->id == ZigTypeIdUnion ? op2 : op1;
+
+ ZigType *tag_type = union_val->value.type->data.unionation.tag_type;
+ assert(tag_type != nullptr);
+
+ IrInstruction *casted_union = ir_implicit_cast(ira, union_val, tag_type);
+ if (type_is_invalid(casted_union->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *casted_val = ir_implicit_cast(ira, enum_val, tag_type);
+ if (type_is_invalid(casted_val->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (instr_is_comptime(casted_union)) {
+ ConstExprValue *const_union_val = ir_resolve_const(ira, casted_union, UndefBad);
+ if (!const_union_val)
+ return ira->codegen->invalid_instruction;
+
+ ConstExprValue *const_enum_val = ir_resolve_const(ira, casted_val, UndefBad);
+ if (!const_enum_val)
+ return ira->codegen->invalid_instruction;
+
+ Cmp cmp_result = bigint_cmp(&const_union_val->data.x_union.tag, &const_enum_val->data.x_enum_tag);
+ bool bool_result = (op_id == IrBinOpCmpEq) ? cmp_result == CmpEQ : cmp_result != CmpEQ;
+
+ return ir_const_bool(ira, &bin_op_instruction->base, bool_result);
+ }
+
+ IrInstruction *result = ir_build_bin_op(&ira->new_irb,
+ bin_op_instruction->base.scope, bin_op_instruction->base.source_node,
+ op_id, casted_union, casted_val, bin_op_instruction->safety_check_on);
+ result->value.type = ira->codegen->builtin_types.entry_bool;
+
+ return result;
}
if (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) {