diff options
| author | LemonBoy <thatlemon@gmail.com> | 2019-11-14 10:20:57 +0100 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-11-14 17:07:20 +0000 |
| commit | a11da377347aea1085d3b43726040993952122c9 (patch) | |
| tree | 3c5e61dd1ff0ff0d51f4d163ade020a3a8dd8328 /src/codegen.cpp | |
| parent | d89f39d71949c85b26f2ccd4071c9445aa8b6d7c (diff) | |
| download | zig-a11da377347aea1085d3b43726040993952122c9.tar.gz zig-a11da377347aea1085d3b43726040993952122c9.zip | |
Update discriminant value also for zero-sized unions
Fixes #3681
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index a97f5cbd55..a288f397fd 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4351,17 +4351,32 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab TypeUnionField *field = instruction->field; if (!type_has_bits(field->type_entry)) { - if (union_type->data.unionation.gen_tag_index == SIZE_MAX) { + ZigType *tag_type = union_type->data.unionation.tag_type; + if (!instruction->initializing || !type_has_bits(tag_type)) return nullptr; + + // The field has no bits but we still have to change the discriminant + // value here + LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr); + + LLVMTypeRef tag_type_ref = get_llvm_type(g, tag_type); + LLVMValueRef tag_field_ptr = nullptr; + if (union_type->data.unionation.gen_field_count == 0) { + assert(union_type->data.unionation.gen_tag_index == SIZE_MAX); + // The whole union is collapsed into the discriminant + tag_field_ptr = LLVMBuildBitCast(g->builder, union_ptr, + LLVMPointerType(tag_type_ref, 0), ""); + } else { + assert(union_type->data.unionation.gen_tag_index != SIZE_MAX); + tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, + union_type->data.unionation.gen_tag_index, ""); } - if (instruction->initializing) { - LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr); - LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, - union_type->data.unionation.gen_tag_index, ""); - LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type), - &field->enum_field->value); - gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); - } + + LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, + &field->enum_field->value); + assert(tag_field_ptr != nullptr); + gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); + return nullptr; } |
