authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-20 12:36:30-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-20 12:36:30-05:00
log459045aa40d64ac883d3908ddcbfcb8aa3867c0d
tree5d421882b9195d98e530e1374f0d0db14275f271
parent8768816d69ddf3253d2598923643f390cc18082c
parent0f54194e6ab2b0cbdc798b84cc4213a07ed1d0c1
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'kristate-zig-backport-issue1832'


3 files changed, 86 insertions(+), 22 deletions(-)

src/analyze.cpp+33-22
......@@ -2681,39 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
26812681 assert(decl_node->type == NodeTypeContainerDecl);
26822682 assert(struct_type->di_type);
26832683
2684 size_t field_count = struct_type->data.structure.src_field_count;
26842685 if (struct_type->data.structure.layout == ContainerLayoutPacked) {
26852686 struct_type->data.structure.abi_alignment = 1;
2686 }
2687
2688 size_t field_count = struct_type->data.structure.src_field_count;
2689 for (size_t i = 0; i < field_count; i += 1) {
2690 TypeStructField *field = &struct_type->data.structure.fields[i];
2691
2692 // If this assertion trips, look up the call stack. Probably something is
2693 // calling type_resolve with ResolveStatusAlignmentKnown when it should only
2694 // be resolving ResolveStatusZeroBitsKnown
2695 assert(field->type_entry != nullptr);
2696
2697 if (type_is_invalid(field->type_entry)) {
2698 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2699 break;
2687 for (size_t i = 0; i < field_count; i += 1) {
2688 TypeStructField *field = &struct_type->data.structure.fields[i];
2689 if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) {
2690 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2691 break;
2692 }
27002693 }
2694 } else for (size_t i = 0; i < field_count; i += 1) {
2695 TypeStructField *field = &struct_type->data.structure.fields[i];
2696 uint32_t this_field_align;
2697
2698 // TODO If we have no type_entry for the field, we've already failed to
2699 // compile the program correctly. This stage1 compiler needs a deeper
2700 // reworking to make this correct, or we can ignore the problem
2701 // and make sure it is fixed in stage2. This workaround is for when
2702 // there is a false positive of a dependency loop, of alignment depending
2703 // on itself. When this false positive happens we assume a pointer-aligned
2704 // field, which is usually fine but could be incorrectly over-aligned or
2705 // even under-aligned. See https://github.com/ziglang/zig/issues/1512
2706 if (field->type_entry == nullptr) {
2707 this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));
2708 } else {
2709 if (type_is_invalid(field->type_entry)) {
2710 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2711 break;
2712 }
27012713
2702 if (!type_has_bits(field->type_entry))
2703 continue;
2714 if (!type_has_bits(field->type_entry))
2715 continue;
27042716
2705 // alignment of structs is the alignment of the most-aligned field
2706 if (struct_type->data.structure.layout != ContainerLayoutPacked) {
27072717 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
27082718 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
27092719 break;
27102720 }
27112721
2712 uint32_t this_field_align = get_abi_alignment(g, field->type_entry);
2722 this_field_align = get_abi_alignment(g, field->type_entry);
27132723 assert(this_field_align != 0);
2714 if (this_field_align > struct_type->data.structure.abi_alignment) {
2715 struct_type->data.structure.abi_alignment = this_field_align;
2716 }
2724 }
2725 // alignment of structs is the alignment of the most-aligned field
2726 if (this_field_align > struct_type->data.structure.abi_alignment) {
2727 struct_type->data.structure.abi_alignment = this_field_align;
27172728 }
27182729 }
27192730
std/array_list.zig+11
......@@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" {
398398 assert(list.len == 6);
399399 assert(list.items[0] == 1);
400400}
401
402const Item = struct {
403 integer: i32,
404 sub_items: ArrayList(Item),
405};
406
407test "std.ArrayList: ArrayList(T) of struct T" {
408 var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(debug.global_allocator) };
409 try root.sub_items.append( Item{ .integer = 42, .sub_items = ArrayList(Item).init(debug.global_allocator) } );
410 assert(root.sub_items.items[0].integer == 42);
411}
test/cases/struct_contains_slice_of_itself.zig+42
......@@ -5,6 +5,11 @@ const Node = struct {
55 children: []Node,
66};
77
8const NodeAligned = struct {
9 payload: i32,
10 children: []align(@alignOf(NodeAligned)) NodeAligned,
11};
12
813test "struct contains slice of itself" {
914 var other_nodes = []Node{
1015 Node{
......@@ -41,3 +46,40 @@ test "struct contains slice of itself" {
4146 assert(root.children[2].children[0].payload == 31);
4247 assert(root.children[2].children[1].payload == 32);
4348}
49
50test "struct contains aligned slice of itself" {
51 var other_nodes = []NodeAligned{
52 NodeAligned{
53 .payload = 31,
54 .children = []NodeAligned{},
55 },
56 NodeAligned{
57 .payload = 32,
58 .children = []NodeAligned{},
59 },
60 };
61 var nodes = []NodeAligned{
62 NodeAligned{
63 .payload = 1,
64 .children = []NodeAligned{},
65 },
66 NodeAligned{
67 .payload = 2,
68 .children = []NodeAligned{},
69 },
70 NodeAligned{
71 .payload = 3,
72 .children = other_nodes[0..],
73 },
74 };
75 const root = NodeAligned{
76 .payload = 1234,
77 .children = nodes[0..],
78 };
79 assert(root.payload == 1234);
80 assert(root.children[0].payload == 1);
81 assert(root.children[1].payload == 2);
82 assert(root.children[2].payload == 3);
83 assert(root.children[2].children[0].payload == 31);
84 assert(root.children[2].children[1].payload == 32);
85}