From d96dd5bc329b69c410ef4d4def763ddb2bab13f0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 6 Mar 2018 21:44:27 -0500 Subject: [PATCH] fix missing compile error for returning error from void async function closes #799 --- src/analyze.cpp | 28 +++++++++++++++++----------- src/ir.cpp | 29 +++++++++++------------------ test/compile_errors.zig | 11 +++++++++++ 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 801852f2cf..66d2963425 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -464,9 +464,8 @@ TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type) TypeTableEntry *result_ptr_type = get_pointer_to_type(g, return_type, false); const char *field_names[] = {AWAITER_HANDLE_FIELD_NAME, RESULT_FIELD_NAME, RESULT_PTR_FIELD_NAME}; TypeTableEntry *field_types[] = {awaiter_handle_type, return_type, result_ptr_type}; - size_t field_count = type_has_bits(result_ptr_type) ? 3 : 1; Buf *name = buf_sprintf("AsyncFramePromise(%s)", buf_ptr(&return_type->name)); - TypeTableEntry *entry = get_struct_type(g, buf_ptr(name), field_names, field_types, field_count); + TypeTableEntry *entry = get_struct_type(g, buf_ptr(name), field_names, field_types, 3); return_type->promise_frame_parent = entry; return entry; @@ -1715,7 +1714,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f buf_init_from_str(&struct_type->name, type_name); struct_type->data.structure.src_field_count = field_count; - struct_type->data.structure.gen_field_count = field_count; + struct_type->data.structure.gen_field_count = 0; struct_type->data.structure.zero_bits_known = true; struct_type->data.structure.complete = true; struct_type->data.structure.fields = allocate(field_count); @@ -1724,22 +1723,26 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f ZigLLVMDIType **di_element_types = allocate(field_count); LLVMTypeRef *element_types = allocate(field_count); for (size_t i = 0; i < field_count; i += 1) { - element_types[i] = field_types[i]->type_ref; + element_types[struct_type->data.structure.gen_field_count] = field_types[i]->type_ref; TypeStructField *field = &struct_type->data.structure.fields[i]; field->name = buf_create_from_str(field_names[i]); field->type_entry = field_types[i]; field->src_index = i; - field->gen_index = i; - assert(type_has_bits(field->type_entry)); + if (type_has_bits(field->type_entry)) { + field->gen_index = struct_type->data.structure.gen_field_count; + struct_type->data.structure.gen_field_count += 1; + } else { + field->gen_index = SIZE_MAX; + } auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field); assert(prev_entry == nullptr); } struct_type->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), type_name); - LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false); + LLVMStructSetBody(struct_type->type_ref, element_types, struct_type->data.structure.gen_field_count, false); struct_type->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, ZigLLVMTag_DW_structure_type(), type_name, @@ -1747,11 +1750,14 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f for (size_t i = 0; i < field_count; i += 1) { TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; + if (type_struct_field->gen_index == SIZE_MAX) { + continue; + } TypeTableEntry *field_type = type_struct_field->type_entry; uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); - uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, i); - di_element_types[i] = ZigLLVMCreateDebugMemberType(g->dbuilder, + uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, type_struct_field->gen_index); + di_element_types[type_struct_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), nullptr, 0, debug_size_in_bits, @@ -1759,7 +1765,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f debug_offset_in_bits, 0, field_type->di_type); - assert(di_element_types[i]); + assert(di_element_types[type_struct_field->gen_index]); } uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref); @@ -1770,7 +1776,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f debug_size_in_bits, debug_align_in_bits, 0, - nullptr, di_element_types, field_count, 0, nullptr, ""); + nullptr, di_element_types, struct_type->data.structure.gen_field_count, 0, nullptr, ""); ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); struct_type->di_type = replacement_di_type; diff --git a/src/ir.cpp b/src/ir.cpp index c52ab7388f..cdb8201b2b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -948,12 +948,10 @@ static IrInstruction *ir_build_const_promise_init(IrBuilder *irb, Scope *scope, const_instruction->base.value.data.x_struct.fields[0].type = struct_type->data.structure.fields[0].type_entry; const_instruction->base.value.data.x_struct.fields[0].special = ConstValSpecialStatic; const_instruction->base.value.data.x_struct.fields[0].data.x_maybe = nullptr; - if (struct_type->data.structure.src_field_count > 1) { - const_instruction->base.value.data.x_struct.fields[1].type = return_type; - const_instruction->base.value.data.x_struct.fields[1].special = ConstValSpecialUndef; - const_instruction->base.value.data.x_struct.fields[2].type = struct_type->data.structure.fields[2].type_entry; - const_instruction->base.value.data.x_struct.fields[2].special = ConstValSpecialUndef; - } + const_instruction->base.value.data.x_struct.fields[1].type = return_type; + const_instruction->base.value.data.x_struct.fields[1].special = ConstValSpecialUndef; + const_instruction->base.value.data.x_struct.fields[2].type = struct_type->data.structure.fields[2].type_entry; + const_instruction->base.value.data.x_struct.fields[2].special = ConstValSpecialUndef; return &const_instruction->base; } @@ -2741,10 +2739,8 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode return return_inst; } - if (irb->exec->coro_result_ptr_field_ptr) { - IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); - ir_build_store_ptr(irb, scope, node, result_ptr, return_value); - } + IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); + ir_build_store_ptr(irb, scope, node, result_ptr, return_value); IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise)); // TODO replace replacement_value with @intToPtr(?promise, 0x1) when it doesn't crash zig @@ -6328,14 +6324,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME); irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, awaiter_handle_field_name); - if (type_has_bits(return_type)) { - Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME); - coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name); - result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME); - irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, - result_ptr_field_name); - ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, coro_result_field_ptr); - } + Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME); + coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name); + result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME); + irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name); + ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, coro_result_field_ptr); irb->exec->coro_early_final = ir_create_basic_block(irb, scope, "CoroEarlyFinal"); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 0ad6787552..1bca093e79 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,17 @@ const tests = @import("tests.zig"); pub fn addCases(cases: &tests.CompileErrorContext) void { + cases.add("returning error from void async function", + \\const std = @import("std"); + \\export fn entry() void { + \\ const p = async(std.debug.global_allocator) amain() catch unreachable; + \\} + \\async fn amain() void { + \\ return error.ShouldBeCompileError; + \\} + , + ".tmp_source.zig:6:17: error: expected type 'void', found 'error{ShouldBeCompileError}'"); + cases.add("var not allowed in structs", \\export fn entry() void { \\ var s = (struct{v: var}){.v=i32(10)};