fix crash when incomplete struct used as argument

closes #107
This commit is contained in:
Andrew Kelley 2016-02-02 19:09:53 -07:00
parent 79adf55699
commit 8058b5e0a9
3 changed files with 70 additions and 1 deletions

View File

@ -153,6 +153,34 @@ static int bits_needed_for_unsigned(uint64_t x) {
}
}
static bool type_is_complete(TypeTableEntry *type_entry) {
switch (type_entry->id) {
case TypeTableEntryIdInvalid:
zig_unreachable();
case TypeTableEntryIdStruct:
return type_entry->data.structure.complete;
case TypeTableEntryIdEnum:
return type_entry->data.enumeration.complete;
case TypeTableEntryIdMetaType:
case TypeTableEntryIdVoid:
case TypeTableEntryIdBool:
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdInt:
case TypeTableEntryIdFloat:
case TypeTableEntryIdPointer:
case TypeTableEntryIdArray:
case TypeTableEntryIdNumLitFloat:
case TypeTableEntryIdNumLitInt:
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdMaybe:
case TypeTableEntryIdErrorUnion:
case TypeTableEntryIdPureError:
case TypeTableEntryIdFn:
case TypeTableEntryIdTypeDecl:
return true;
}
}
TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
return get_int_type(g, false, bits_needed_for_unsigned(x));
}
@ -391,6 +419,7 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *c
entry->type_ref = var_peer->type_ref;
entry->di_type = var_peer->di_type;
entry->data.structure.complete = true;
*parent_pointer = entry;
return entry;
@ -421,6 +450,8 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *c
buf_ptr(&entry->name), g->dummy_di_file, 0, entry->size_in_bits, entry->align_in_bits, 0,
nullptr, di_element_types, element_count, 0, nullptr, "");
entry->data.structure.complete = true;
*parent_pointer = entry;
return entry;
}
@ -527,6 +558,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId fn_type_id) {
gen_param_info->src_index = i;
gen_param_info->gen_index = -1;
assert(type_is_complete(type_entry));
if (type_entry->size_in_bits > 0) {
TypeTableEntry *gen_type;
if (handle_is_ptr(type_entry)) {
@ -4751,7 +4783,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
if (!table_entry) {
table_entry = import->block_context->type_table.maybe_get(name);
}
if (!table_entry) {
if (!table_entry || !type_is_complete(table_entry->value)) {
decl_node->deps.put(name, node);
}
break;

View File

@ -2830,6 +2830,7 @@ static void do_code_gen(CodeGen *g) {
arg_no = var->gen_arg_index + 1;
var->is_ptr = false;
assert(var->gen_arg_index >= 0);
var->value_ref = LLVMGetParam(fn, var->gen_arg_index);
} else {
tag = LLVMZigTag_DW_auto_variable();

View File

@ -1513,6 +1513,42 @@ pub fn main(args: [][]u8) -> %void {
%%stdout.printf("OK\n");
}
)SOURCE", "OK\n");
add_simple_case("incomplete struct parameter top level decl", R"SOURCE(
import "std.zig";
struct A {
b: B,
}
struct B {
c: C,
}
struct C {
x: i32,
fn d(c: C) {
%%stdout.printf("OK\n");
}
}
fn foo(a: A) {
a.b.c.d();
}
pub fn main(args: [][]u8) -> %void {
const a = A {
.b = B {
.c = C {
.x = 13,
},
},
};
foo(a);
}
)SOURCE", "OK\n");
}