Skip to content

Commit

Permalink
fix compiler crash when struct contains...
Browse files Browse the repository at this point in the history
ptr to another struct which contains original struct
  • Loading branch information
andrewrk committed Feb 15, 2018
1 parent 1c1c069 commit cc26148
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 7 deletions.
19 changes: 12 additions & 7 deletions src/analyze.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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");
}
}
}

Expand Down
1 change: 1 addition & 0 deletions test/behavior.zig
Expand Up @@ -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");
Expand Down
22 changes: 22 additions & 0 deletions 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,
};

0 comments on commit cc26148

Please sign in to comment.