Correct evaluation of optional type alignment

The lazy logic was too oversimplified and produced a different result
than the one computed later causing all kinds of problems.

Closes #4013
master
LemonBoy 2020-01-02 23:56:14 +01:00 committed by Andrew Kelley
parent 3f19bc5d01
commit b91eaba38c
4 changed files with 20 additions and 10 deletions

View File

@ -1331,7 +1331,7 @@ start_over:
zig_unreachable();
}
Error type_val_resolve_abi_align(CodeGen *g, ZigValue *type_val, uint32_t *abi_align) {
Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align) {
Error err;
if (type_val->special != ConstValSpecialLazy) {
assert(type_val->special == ConstValSpecialStatic);
@ -1356,19 +1356,21 @@ Error type_val_resolve_abi_align(CodeGen *g, ZigValue *type_val, uint32_t *abi_a
*abi_align = g->builtin_types.entry_usize->abi_align;
return ErrorNone;
case LazyValueIdOptType: {
LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
return type_val_resolve_abi_align(g, lazy_opt_type->payload_type->value, abi_align);
if ((err = ir_resolve_lazy(g, nullptr, type_val)))
return err;
return type_val_resolve_abi_align(g, source_node, type_val, abi_align);
}
case LazyValueIdArrayType: {
LazyValueArrayType *lazy_array_type =
reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
return type_val_resolve_abi_align(g, lazy_array_type->elem_type->value, abi_align);
return type_val_resolve_abi_align(g, source_node, lazy_array_type->elem_type->value, abi_align);
}
case LazyValueIdErrUnionType: {
LazyValueErrUnionType *lazy_err_union_type =
reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
uint32_t payload_abi_align;
if ((err = type_val_resolve_abi_align(g, lazy_err_union_type->payload_type->value,
if ((err = type_val_resolve_abi_align(g, source_node, lazy_err_union_type->payload_type->value,
&payload_abi_align)))
{
return err;
@ -2335,7 +2337,7 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) {
}
field->align = field->type_entry->abi_align;
} else {
if ((err = type_val_resolve_abi_align(g, field->type_val, &field->align))) {
if ((err = type_val_resolve_abi_align(g, field->decl_node, field->type_val, &field->align))) {
if (g->trace_err != nullptr) {
g->trace_err = add_error_note(g, g->trace_err, field->decl_node,
buf_create_from_str("while checking this field"));
@ -2912,7 +2914,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
} else if (packed) {
field->align = 1;
} else {
if ((err = type_val_resolve_abi_align(g, field->type_val, &field->align))) {
if ((err = type_val_resolve_abi_align(g, field->decl_node, field->type_val, &field->align))) {
if (g->trace_err != nullptr) {
g->trace_err = add_error_note(g, g->trace_err, field->decl_node,
buf_create_from_str("while checking this field"));

View File

@ -260,7 +260,7 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *
void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
bool fn_is_async(ZigFn *fn);
Error type_val_resolve_abi_align(CodeGen *g, ZigValue *type_val, uint32_t *abi_align);
Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align);
Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ZigValue *type_val,
size_t *abi_size, size_t *size_in_bits);
Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent_type,

View File

@ -29200,8 +29200,8 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
}
uint32_t align_in_bytes;
if ((err = type_val_resolve_abi_align(ira->codegen, lazy_align_of->target_type->value,
&align_in_bytes)))
if ((err = type_val_resolve_abi_align(ira->codegen, source_node,
lazy_align_of->target_type->value, &align_in_bytes)))
{
return err;
}

View File

@ -145,3 +145,11 @@ test "coerce an anon struct literal to optional struct" {
S.doTheTest();
comptime S.doTheTest();
}
test "optional with void type" {
const Foo = struct {
x: ?void,
};
var x = Foo{ .x = null };
expect(x.x == null);
}