| author | |
| committer | |
| log | 790aaeacaea88782987c4145bc7ae47a401563f1 |
| tree | 0aad6bf2e1c29b0dab883a2633b4d380f68dfc51 |
| parent | bb80daf509b7afd84fe3076347e69e8f39f586d6 |
closes #7424 files changed, 25 insertions(+), 0 deletions(-)
src/all_types.hpp+2| ... | ... | @@ -1096,6 +1096,8 @@ struct TypeTableEntryUnion { |
| 1096 | 1096 | size_t gen_union_index; |
| 1097 | 1097 | size_t gen_tag_index; |
| 1098 | 1098 | |
| 1099 | bool have_explicit_tag_type; | |
| 1100 | ||
| 1099 | 1101 | uint32_t union_size_bytes; |
| 1100 | 1102 | TypeTableEntry *most_aligned_union_member; |
| 1101 | 1103 |
src/analyze.cpp+2| ... | ... | @@ -2558,6 +2558,8 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2558 | 2558 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; |
| 2559 | 2559 | |
| 2560 | 2560 | AstNode *enum_type_node = decl_node->data.container_decl.init_arg_expr; |
| 2561 | union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum || | |
| 2562 | enum_type_node != nullptr; | |
| 2561 | 2563 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); |
| 2562 | 2564 | bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr); |
| 2563 | 2565 | TypeTableEntry *tag_type; |
src/ir.cpp+8| ... | ... | @@ -14137,6 +14137,14 @@ static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source |
| 14137 | 14137 | buf_sprintf("expected enum or union type, found '%s'", buf_ptr(&value->value.type->name))); |
| 14138 | 14138 | return ira->codegen->invalid_instruction; |
| 14139 | 14139 | } |
| 14140 | if (!value->value.type->data.unionation.have_explicit_tag_type && !source_instr->is_gen) { | |
| 14141 | ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("union has no associated enum")); | |
| 14142 | if (value->value.type->data.unionation.decl_node != nullptr) { | |
| 14143 | add_error_note(ira->codegen, msg, value->value.type->data.unionation.decl_node, | |
| 14144 | buf_sprintf("declared here")); | |
| 14145 | } | |
| 14146 | return ira->codegen->invalid_instruction; | |
| 14147 | } | |
| 14140 | 14148 | |
| 14141 | 14149 | TypeTableEntry *tag_type = value->value.type->data.unionation.tag_type; |
| 14142 | 14150 | assert(tag_type->id == TypeTableEntryIdEnum); |
test/compile_errors.zig+13| ... | ... | @@ -1,6 +1,19 @@ |
| 1 | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | |
| 3 | 3 | pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 4 | cases.add("@tagName used on union with no associated enum tag", | |
| 5 | \\const FloatInt = extern union { | |
| 6 | \\ Float: f32, | |
| 7 | \\ Int: i32, | |
| 8 | \\}; | |
| 9 | \\export fn entry() void { | |
| 10 | \\ var fi = FloatInt{.Float = 123.45}; | |
| 11 | \\ var tagName = @tagName(fi); | |
| 12 | \\} | |
| 13 | , | |
| 14 | ".tmp_source.zig:7:19: error: union has no associated enum", | |
| 15 | ".tmp_source.zig:1:18: note: declared here"); | |
| 16 | ||
| 4 | 17 | cases.add("returning error from void async function", |
| 5 | 18 | \\const std = @import("std"); |
| 6 | 19 | \\export fn entry() void { |