Commit 1479c28b49

LemonBoy <thatlemon@gmail.com>
2020-03-16 18:42:01
ir: Correct ABI size calculation for arrays
Zero-length array with a sentinel may not have zero size. Closes #4749
1 parent 013ada1
Changed files (3)
src
test
stage1
behavior
src/analyze.cpp
@@ -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:
src/codegen.cpp
@@ -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 {
test/stage1/behavior/array.zig
@@ -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();
+}