aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2019-11-14 10:20:57 +0100
committerAndrew Kelley <andrew@ziglang.org>2019-11-14 17:07:20 +0000
commita11da377347aea1085d3b43726040993952122c9 (patch)
tree3c5e61dd1ff0ff0d51f4d163ade020a3a8dd8328 /src/codegen.cpp
parentd89f39d71949c85b26f2ccd4071c9445aa8b6d7c (diff)
downloadzig-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.cpp33
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;
}