authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-15 12:14:20-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-15 12:14:20-05:00
logcc26148ba776f713bb81b5ac06fc646eb323e6dc
treebc044a383521ce427fd7f8072c2989d6b0e32555
parent1c1c0691cc4d47a39f382aec29654ae94cdf524c

fix compiler crash when struct contains...

ptr to another struct which contains original struct

3 files changed, 35 insertions(+), 7 deletions(-)

src/analyze.cpp+12-7
......@@ -2278,17 +2278,16 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
22782278 return;
22792279
22802280 if (struct_type->data.structure.zero_bits_loop_flag) {
2281 // If we get here it's due to recursion. From this we conclude that the struct is
2282 // not zero bits, and if abi_alignment == 0 we further conclude that the first field
2283 // is a pointer to this very struct, or a function pointer with parameters that
2284 // reference such a type.
2281 // If we get here it's due to recursion. This is a design flaw in the compiler,
2282 // we should be able to still figure out alignment, but here we give up and say that
2283 // the alignment is pointer width, then assert that the first field is within that
2284 // alignment
22852285 struct_type->data.structure.zero_bits_known = true;
22862286 if (struct_type->data.structure.abi_alignment == 0) {
22872287 if (struct_type->data.structure.layout == ContainerLayoutPacked) {
22882288 struct_type->data.structure.abi_alignment = 1;
22892289 } else {
2290 struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref,
2291 LLVMPointerType(LLVMInt8Type(), 0));
2290 struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));
22922291 }
22932292 }
22942293 return;
......@@ -2352,11 +2351,17 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) {
23522351 if (gen_field_index == 0) {
23532352 if (struct_type->data.structure.layout == ContainerLayoutPacked) {
23542353 struct_type->data.structure.abi_alignment = 1;
2355 } else {
2354 } else if (struct_type->data.structure.abi_alignment == 0) {
23562355 // Alignment of structs is the alignment of the first field, for now.
23572356 // TODO change this when we re-order struct fields (issue #168)
23582357 struct_type->data.structure.abi_alignment = get_abi_alignment(g, field_type);
23592358 assert(struct_type->data.structure.abi_alignment != 0);
2359 } else {
2360 // due to a design flaw in the compiler we assumed that alignment was
2361 // pointer width, so we assert that this wasn't violated.
2362 if (get_abi_alignment(g, field_type) > struct_type->data.structure.abi_alignment) {
2363 zig_panic("compiler design flaw: incorrect alignment assumption");
2364 }
23602365 }
23612366 }
23622367
test/behavior.zig+1
......@@ -35,6 +35,7 @@ comptime {
3535 _ = @import("cases/slice.zig");
3636 _ = @import("cases/struct.zig");
3737 _ = @import("cases/struct_contains_slice_of_itself.zig");
38 _ = @import("cases/struct_contains_null_ptr_itself.zig");
3839 _ = @import("cases/switch.zig");
3940 _ = @import("cases/switch_prong_err_enum.zig");
4041 _ = @import("cases/switch_prong_implicit_cast.zig");
test/cases/struct_contains_null_ptr_itself.zig created+22
......@@ -0,0 +1,22 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "struct contains null pointer which contains original struct" {
5 var x: ?&NodeLineComment = null;
6 assert(x == null);
7}
8
9pub const Node = struct {
10 id: Id,
11 comment: ?&NodeLineComment,
12
13 pub const Id = enum {
14 Root,
15 LineComment,
16 };
17};
18
19pub const NodeLineComment = struct {
20 base: Node,
21};
22