ir: Correct ABI size calculation for arrays

Zero-length array with a sentinel may not have zero size.

Closes #4749
This commit is contained in:
LemonBoy 2020-03-16 18:42:01 +01:00 committed by Andrew Kelley
parent 013ada1b59
commit 1479c28b49
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
3 changed files with 30 additions and 11 deletions

View File

@ -803,13 +803,7 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi
}
buf_appendf(&entry->name, "]%s", buf_ptr(&child_type->name));
size_t full_array_size;
if (array_size == 0) {
full_array_size = 0;
} else {
full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0);
}
size_t full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0);
entry->size_in_bits = child_type->size_in_bits * full_array_size;
entry->abi_align = child_type->abi_align;
entry->abi_size = child_type->abi_size * full_array_size;
@ -1197,7 +1191,8 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
LazyValueArrayType *lazy_array_type =
reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
if (lazy_array_type->length < 1) {
// The sentinel counts as an extra element
if (lazy_array_type->length == 0 && lazy_array_type->sentinel == nullptr) {
*is_zero_bits = true;
return ErrorNone;
}
@ -1452,7 +1447,8 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV
case LazyValueIdArrayType: {
LazyValueArrayType *lazy_array_type =
reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
if (lazy_array_type->length < 1)
// The sentinel counts as an extra element
if (lazy_array_type->length == 0 && lazy_array_type->sentinel == nullptr)
return OnePossibleValueYes;
return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value);
}
@ -5739,7 +5735,8 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdUnreachable:
return OnePossibleValueYes;
case ZigTypeIdArray:
if (type_entry->data.array.len == 0)
// The sentinel counts as an extra element
if (type_entry->data.array.len == 0 && type_entry->data.array.sentinel == nullptr)
return OnePossibleValueYes;
return type_has_one_possible_value(g, type_entry->data.array.child_type);
case ZigTypeIdStruct:

View File

@ -3584,7 +3584,9 @@ static bool value_is_all_undef(CodeGen *g, ZigValue *const_val) {
}
return true;
} else if (const_val->type->id == ZigTypeIdArray) {
return value_is_all_undef_array(g, const_val, const_val->type->data.array.len);
const size_t full_len = const_val->type->data.array.len +
(const_val->type->data.array.sentinel != nullptr);
return value_is_all_undef_array(g, const_val, full_len);
} else if (const_val->type->id == ZigTypeIdVector) {
return value_is_all_undef_array(g, const_val, const_val->type->data.vector.len);
} else {

View File

@ -376,3 +376,23 @@ test "type deduction for array subscript expression" {
S.doTheTest();
comptime S.doTheTest();
}
test "sentinel element count towards the ABI size calculation" {
const S = struct {
fn doTheTest() void {
const T = packed struct {
fill_pre: u8 = 0x55,
data: [0:0]u8 = undefined,
fill_post: u8 = 0xAA,
};
var x = T{};
var as_slice = mem.asBytes(&x);
expectEqual(@as(usize, 3), as_slice.len);
expectEqual(@as(u8, 0x55), as_slice[0]);
expectEqual(@as(u8, 0xAA), as_slice[2]);
}
};
S.doTheTest();
comptime S.doTheTest();
}