Skip to content

Commit

Permalink
Merge pull request #9925 from mattbork/uniondecl-fixes
Browse files Browse the repository at this point in the history
stage2: astgen unionDecl fixes
  • Loading branch information
andrewrk authored Oct 10, 2021
2 parents d1fd864 + ea45062 commit f42725c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 4 deletions.
25 changes: 22 additions & 3 deletions src/AstGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4134,7 +4134,7 @@ fn unionDeclInner(
if (member.comptime_token) |comptime_token| {
return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
}
try fields_data.ensureUnusedCapacity(gpa, if (node_tags[member.ast.type_expr] != .@"anytype") 4 else 3);
try fields_data.ensureUnusedCapacity(gpa, 4);

const field_name = try astgen.identAsString(member.ast.name_token);
fields_data.appendAssumeCapacity(field_name);
Expand All @@ -4149,9 +4149,14 @@ fn unionDeclInner(
(@as(u32, @boolToInt(have_value)) << 30) |
(@as(u32, @boolToInt(unused)) << 31);

if (have_type and node_tags[member.ast.type_expr] != .@"anytype") {
const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
if (have_type) {
const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")
.none
else
try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
fields_data.appendAssumeCapacity(@enumToInt(field_type));
} else if (arg_inst == .none and !have_auto_enum) {
return astgen.failNode(member_node, "union field missing type", .{});
}
if (have_align) {
const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr);
Expand All @@ -4172,6 +4177,20 @@ fn unionDeclInner(
},
);
}
if (!have_auto_enum) {
return astgen.failNodeNotes(
node,
"explicitly valued tagged union requires inferred enum tag type",
.{},
&[_]u32{
try astgen.errNoteNode(
member.ast.value_expr,
"tag value specified here",
.{},
),
},
);
}
const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);
fields_data.appendAssumeCapacity(@enumToInt(tag_value));
}
Expand Down
4 changes: 3 additions & 1 deletion src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -12629,8 +12629,10 @@ fn semaUnionFields(
set.putAssumeCapacity(field_name, {});
}

const field_ty: Type = if (field_type_ref == .none)
const field_ty: Type = if (!has_type)
Type.initTag(.void)
else if (field_type_ref == .none)
Type.initTag(.noreturn)
else
// TODO: if we need to report an error here, use a source location
// that points to this type expression rather than the union.
Expand Down
1 change: 1 addition & 0 deletions src/Zir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2686,6 +2686,7 @@ pub const Inst = struct {
/// 9. fields: { // for every fields_len
/// field_name: u32, // null terminated string index
/// field_type: Ref, // if corresponding bit is set
/// - if none, means `anytype`.
/// align: Ref, // if corresponding bit is set
/// tag_value: Ref, // if corresponding bit is set
/// }
Expand Down
34 changes: 34 additions & 0 deletions test/stage2/cbe.zig
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,40 @@ pub fn addCases(ctx: *TestContext) !void {
, "");
}

{
var case = ctx.exeFromCompiledC("unions", .{});

case.addError(
\\const U = union {
\\ a: u32,
\\ b
\\};
, &.{
":3:5: error: union field missing type",
});

case.addError(
\\const E = enum { a, b };
\\const U = union(E) {
\\ a: u32 = 1,
\\ b: f32 = 2,
\\};
, &.{
":2:11: error: explicitly valued tagged union requires inferred enum tag type",
":3:14: note: tag value specified here",
});

case.addError(
\\const U = union(enum) {
\\ a: u32 = 1,
\\ b: f32 = 2,
\\};
, &.{
":1:11: error: explicitly valued tagged union missing integer tag type",
":2:14: note: tag value specified here",
});
}

{
var case = ctx.exeFromCompiledC("enums", .{});

Expand Down

0 comments on commit f42725c

Please sign in to comment.