| author | |
| committer | |
| log | f42725c39bbbe5db13c1a1706db3f31aa0549307 |
| tree | 08284761e667668a852e512a4a5ab193ded5288c |
| parent | d1fd864da7859989828feb8be806634606cc761c |
| parent | ea45062d8227f9f9f1356c78eac5a0daa578f97e |
| signature |
stage2: astgen unionDecl fixes4 files changed, 60 insertions(+), 4 deletions(-)
src/AstGen.zig+22-3| ... | ... | @@ -4134,7 +4134,7 @@ fn unionDeclInner( |
| 4134 | 4134 | if (member.comptime_token) |comptime_token| { |
| 4135 | 4135 | return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); |
| 4136 | 4136 | } |
| 4137 | try fields_data.ensureUnusedCapacity(gpa, if (node_tags[member.ast.type_expr] != .@"anytype") 4 else 3); | |
| 4137 | try fields_data.ensureUnusedCapacity(gpa, 4); | |
| 4138 | 4138 | |
| 4139 | 4139 | const field_name = try astgen.identAsString(member.ast.name_token); |
| 4140 | 4140 | fields_data.appendAssumeCapacity(field_name); |
| ... | ... | @@ -4149,9 +4149,14 @@ fn unionDeclInner( |
| 4149 | 4149 | (@as(u32, @boolToInt(have_value)) << 30) | |
| 4150 | 4150 | (@as(u32, @boolToInt(unused)) << 31); |
| 4151 | 4151 | |
| 4152 | if (have_type and node_tags[member.ast.type_expr] != .@"anytype") { | |
| 4153 | const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); | |
| 4152 | if (have_type) { | |
| 4153 | const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype") | |
| 4154 | .none | |
| 4155 | else | |
| 4156 | try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); | |
| 4154 | 4157 | fields_data.appendAssumeCapacity(@enumToInt(field_type)); |
| 4158 | } else if (arg_inst == .none and !have_auto_enum) { | |
| 4159 | return astgen.failNode(member_node, "union field missing type", .{}); | |
| 4155 | 4160 | } |
| 4156 | 4161 | if (have_align) { |
| 4157 | 4162 | const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr); |
| ... | ... | @@ -4172,6 +4177,20 @@ fn unionDeclInner( |
| 4172 | 4177 | }, |
| 4173 | 4178 | ); |
| 4174 | 4179 | } |
| 4180 | if (!have_auto_enum) { | |
| 4181 | return astgen.failNodeNotes( | |
| 4182 | node, | |
| 4183 | "explicitly valued tagged union requires inferred enum tag type", | |
| 4184 | .{}, | |
| 4185 | &[_]u32{ | |
| 4186 | try astgen.errNoteNode( | |
| 4187 | member.ast.value_expr, | |
| 4188 | "tag value specified here", | |
| 4189 | .{}, | |
| 4190 | ), | |
| 4191 | }, | |
| 4192 | ); | |
| 4193 | } | |
| 4175 | 4194 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr); |
| 4176 | 4195 | fields_data.appendAssumeCapacity(@enumToInt(tag_value)); |
| 4177 | 4196 | } |
src/Sema.zig+3-1| ... | ... | @@ -12629,8 +12629,10 @@ fn semaUnionFields( |
| 12629 | 12629 | set.putAssumeCapacity(field_name, {}); |
| 12630 | 12630 | } |
| 12631 | 12631 | |
| 12632 | const field_ty: Type = if (field_type_ref == .none) | |
| 12632 | const field_ty: Type = if (!has_type) | |
| 12633 | 12633 | Type.initTag(.void) |
| 12634 | else if (field_type_ref == .none) | |
| 12635 | Type.initTag(.noreturn) | |
| 12634 | 12636 | else |
| 12635 | 12637 | // TODO: if we need to report an error here, use a source location |
| 12636 | 12638 | // that points to this type expression rather than the union. |
src/Zir.zig+1| ... | ... | @@ -2686,6 +2686,7 @@ pub const Inst = struct { |
| 2686 | 2686 | /// 9. fields: { // for every fields_len |
| 2687 | 2687 | /// field_name: u32, // null terminated string index |
| 2688 | 2688 | /// field_type: Ref, // if corresponding bit is set |
| 2689 | /// - if none, means `anytype`. | |
| 2689 | 2690 | /// align: Ref, // if corresponding bit is set |
| 2690 | 2691 | /// tag_value: Ref, // if corresponding bit is set |
| 2691 | 2692 | /// } |
test/stage2/cbe.zig+34| ... | ... | @@ -570,6 +570,40 @@ pub fn addCases(ctx: *TestContext) !void { |
| 570 | 570 | , ""); |
| 571 | 571 | } |
| 572 | 572 | |
| 573 | { | |
| 574 | var case = ctx.exeFromCompiledC("unions", .{}); | |
| 575 | ||
| 576 | case.addError( | |
| 577 | \\const U = union { | |
| 578 | \\ a: u32, | |
| 579 | \\ b | |
| 580 | \\}; | |
| 581 | , &.{ | |
| 582 | ":3:5: error: union field missing type", | |
| 583 | }); | |
| 584 | ||
| 585 | case.addError( | |
| 586 | \\const E = enum { a, b }; | |
| 587 | \\const U = union(E) { | |
| 588 | \\ a: u32 = 1, | |
| 589 | \\ b: f32 = 2, | |
| 590 | \\}; | |
| 591 | , &.{ | |
| 592 | ":2:11: error: explicitly valued tagged union requires inferred enum tag type", | |
| 593 | ":3:14: note: tag value specified here", | |
| 594 | }); | |
| 595 | ||
| 596 | case.addError( | |
| 597 | \\const U = union(enum) { | |
| 598 | \\ a: u32 = 1, | |
| 599 | \\ b: f32 = 2, | |
| 600 | \\}; | |
| 601 | , &.{ | |
| 602 | ":1:11: error: explicitly valued tagged union missing integer tag type", | |
| 603 | ":2:14: note: tag value specified here", | |
| 604 | }); | |
| 605 | } | |
| 606 | ||
| 573 | 607 | { |
| 574 | 608 | var case = ctx.exeFromCompiledC("enums", .{}); |
| 575 | 609 |