aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-08-29 00:40:02 +0300
committerAndrew Kelley <andrew@ziglang.org>2022-08-29 13:45:37 -0700
commita4b52ccd9fb538bdcd77cf2d45b9310e189cc243 (patch)
treef87cb9fef812ba510ab6938eff266010cd7343e2 /src/Sema.zig
parent15cc4514e0566430ed1d95e85aaa462642b70364 (diff)
downloadzig-a4b52ccd9fb538bdcd77cf2d45b9310e189cc243.tar.gz
zig-a4b52ccd9fb538bdcd77cf2d45b9310e189cc243.zip
Sema: fix access of inactive union field when enum and union fields are in different order
Closes #12667
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig20
1 files changed, 10 insertions, 10 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index ff32dc4b33..f884684d73 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -21892,17 +21892,18 @@ fn unionFieldPtr(
if (union_val.isUndef()) {
return sema.failWithUseOfUndef(block, src);
}
+ const enum_field_index = union_obj.tag_ty.enumFieldIndex(field_name).?;
const tag_and_val = union_val.castTag(.@"union").?.data;
var field_tag_buf: Value.Payload.U32 = .{
.base = .{ .tag = .enum_field_index },
- .data = field_index,
+ .data = @intCast(u32, enum_field_index),
};
const field_tag = Value.initPayload(&field_tag_buf.base);
const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod);
if (!tag_matches) {
const msg = msg: {
const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data;
- const active_field_name = union_obj.fields.keys()[active_index];
+ const active_field_name = union_obj.tag_ty.enumFieldName(active_index);
const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name });
errdefer msg.destroy(sema.gpa);
try sema.addDeclaredHereNote(msg, union_ty);
@@ -21927,12 +21928,11 @@ fn unionFieldPtr(
if (!initializing and union_obj.layout == .Auto and block.wantSafety() and
union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1)
{
- const enum_ty = union_ty.unionTagTypeHypothetical();
const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index);
- const wanted_tag = try sema.addConstant(enum_ty, wanted_tag_val);
+ const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val);
// TODO would it be better if get_union_tag supported pointers to unions?
const union_val = try block.addTyOp(.load, union_ty, union_ptr);
- const active_tag = try block.addTyOp(.get_union_tag, enum_ty, union_val);
+ const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_val);
const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag);
try sema.addSafetyCheck(block, ok, .inactive_union_field);
}
@@ -21963,9 +21963,10 @@ fn unionFieldVal(
if (union_val.isUndef()) return sema.addConstUndef(field.ty);
const tag_and_val = union_val.castTag(.@"union").?.data;
+ const enum_field_index = union_obj.tag_ty.enumFieldIndex(field_name).?;
var field_tag_buf: Value.Payload.U32 = .{
.base = .{ .tag = .enum_field_index },
- .data = field_index,
+ .data = @intCast(u32, enum_field_index),
};
const field_tag = Value.initPayload(&field_tag_buf.base);
const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod);
@@ -21976,7 +21977,7 @@ fn unionFieldVal(
} else {
const msg = msg: {
const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data;
- const active_field_name = union_obj.fields.keys()[active_index];
+ const active_field_name = union_obj.tag_ty.enumFieldName(active_index);
const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name });
errdefer msg.destroy(sema.gpa);
try sema.addDeclaredHereNote(msg, union_ty);
@@ -22001,10 +22002,9 @@ fn unionFieldVal(
if (union_obj.layout == .Auto and block.wantSafety() and
union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1)
{
- const enum_ty = union_ty.unionTagTypeHypothetical();
const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index);
- const wanted_tag = try sema.addConstant(enum_ty, wanted_tag_val);
- const active_tag = try block.addTyOp(.get_union_tag, enum_ty, union_byval);
+ const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val);
+ const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval);
const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag);
try sema.addSafetyCheck(block, ok, .inactive_union_field);
}