diff --git a/src/analyze.cpp b/src/analyze.cpp index bf7b6e363f..c16a5d462a 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2278,17 +2278,16 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { return; if (struct_type->data.structure.zero_bits_loop_flag) { - // If we get here it's due to recursion. From this we conclude that the struct is - // not zero bits, and if abi_alignment == 0 we further conclude that the first field - // is a pointer to this very struct, or a function pointer with parameters that - // reference such a type. + // If we get here it's due to recursion. This is a design flaw in the compiler, + // we should be able to still figure out alignment, but here we give up and say that + // the alignment is pointer width, then assert that the first field is within that + // alignment struct_type->data.structure.zero_bits_known = true; if (struct_type->data.structure.abi_alignment == 0) { if (struct_type->data.structure.layout == ContainerLayoutPacked) { struct_type->data.structure.abi_alignment = 1; } else { - struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, - LLVMPointerType(LLVMInt8Type(), 0)); + struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0)); } } return; @@ -2352,11 +2351,17 @@ static void resolve_struct_zero_bits(CodeGen *g, TypeTableEntry *struct_type) { if (gen_field_index == 0) { if (struct_type->data.structure.layout == ContainerLayoutPacked) { struct_type->data.structure.abi_alignment = 1; - } else { + } else if (struct_type->data.structure.abi_alignment == 0) { // Alignment of structs is the alignment of the first field, for now. // TODO change this when we re-order struct fields (issue #168) struct_type->data.structure.abi_alignment = get_abi_alignment(g, field_type); assert(struct_type->data.structure.abi_alignment != 0); + } else { + // due to a design flaw in the compiler we assumed that alignment was + // pointer width, so we assert that this wasn't violated. + if (get_abi_alignment(g, field_type) > struct_type->data.structure.abi_alignment) { + zig_panic("compiler design flaw: incorrect alignment assumption"); + } } } diff --git a/test/behavior.zig b/test/behavior.zig index 96a323a6c8..e718ba6c86 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -35,6 +35,7 @@ comptime { _ = @import("cases/slice.zig"); _ = @import("cases/struct.zig"); _ = @import("cases/struct_contains_slice_of_itself.zig"); + _ = @import("cases/struct_contains_null_ptr_itself.zig"); _ = @import("cases/switch.zig"); _ = @import("cases/switch_prong_err_enum.zig"); _ = @import("cases/switch_prong_implicit_cast.zig"); diff --git a/test/cases/struct_contains_null_ptr_itself.zig b/test/cases/struct_contains_null_ptr_itself.zig new file mode 100644 index 0000000000..5864ef4038 --- /dev/null +++ b/test/cases/struct_contains_null_ptr_itself.zig @@ -0,0 +1,22 @@ +const std = @import("std"); +const assert = std.debug.assert; + +test "struct contains null pointer which contains original struct" { + var x: ?&NodeLineComment = null; + assert(x == null); +} + +pub const Node = struct { + id: Id, + comment: ?&NodeLineComment, + + pub const Id = enum { + Root, + LineComment, + }; +}; + +pub const NodeLineComment = struct { + base: Node, +}; +