Commit f66ac9a5e7

Andrew Kelley <superjoe30@gmail.com>
2018-01-28 00:30:36
fix crash when align 1 field before self referential...
...align 8 field as slice return type closes #723
1 parent ad3e2a5
Changed files (2)
src
test
src/analyze.cpp
@@ -362,8 +362,10 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
     } else {
         assert(bit_offset == 0);
         parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
-        if (*parent_pointer)
+        if (*parent_pointer) {
+            assert((*parent_pointer)->data.pointer.alignment == byte_alignment);
             return *parent_pointer;
+        }
     }
 
     type_ensure_zero_bits_known(g, child_type);
@@ -2356,6 +2358,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
     bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);
     bool *covered_enum_fields;
     ZigLLVMDIEnumerator **di_enumerators;
+    uint32_t abi_alignment_so_far;
     if (create_enum_type) {
         occupied_tag_values.init(field_count);
 
@@ -2377,7 +2380,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
         } else {
             tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
         }
-        union_type->data.unionation.abi_alignment = get_abi_alignment(g, tag_int_type);
+        abi_alignment_so_far = get_abi_alignment(g, tag_int_type);
 
         tag_type = new_type_table_entry(TypeTableEntryIdEnum);
         buf_resize(&tag_type->name, 0);
@@ -2408,9 +2411,10 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
         }
         tag_type = enum_type;
         covered_enum_fields = allocate<bool>(enum_type->data.enumeration.src_field_count);
-        union_type->data.unionation.abi_alignment = get_abi_alignment(g, enum_type);
+        abi_alignment_so_far = get_abi_alignment(g, enum_type);
     } else {
         tag_type = nullptr;
+        abi_alignment_so_far = 0;
     }
     union_type->data.unionation.tag_type = tag_type;
 
@@ -2508,12 +2512,14 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
         uint32_t field_align_bytes = get_abi_alignment(g, field_type);
         if (field_align_bytes > biggest_align_bytes) {
             biggest_align_bytes = field_align_bytes;
-            if (biggest_align_bytes > union_type->data.unionation.abi_alignment) {
-                union_type->data.unionation.abi_alignment = biggest_align_bytes;
+            if (biggest_align_bytes > abi_alignment_so_far) {
+                abi_alignment_so_far = biggest_align_bytes;
             }
         }
     }
 
+    union_type->data.unionation.abi_alignment = abi_alignment_so_far;
+
     if (union_type->data.unionation.is_invalid)
         return;
 
test/cases/struct.zig
@@ -404,3 +404,17 @@ test "native bit field understands endianness" {
     assert(bitfields.f6 == 0x6);
     assert(bitfields.f7 == 0x77);
 }
+
+test "align 1 field before self referential align 8 field as slice return type" {
+    const result = alloc(Expr);
+    assert(result.len == 0);
+}
+
+const Expr = union(enum) {
+    Literal: u8,
+    Question: &Expr,
+};
+
+fn alloc(comptime T: type) []T {
+    return []T{};
+}