| author | |
| committer | |
| log | 7b57454cc11371b71097967656e19f0a1736d733 |
| tree | 4eff514fcb0a0c1f95ac253624c4f705fe95b03e |
| parent | d973b40884be1c7874805c81981cac7edca5605b |
* error return tracing is disabled in release-fast mode
* add @errorReturnTrace
* zig build API changes build return type from `void` to `%void`
* allow `void`, `noreturn`, and `u8` from main. closes #53522 files changed, 198 insertions(+), 112 deletions(-)
doc/langref.html.in+8| ... | @@ -142,6 +142,7 @@ | ... | @@ -142,6 +142,7 @@ |
| 142 | <li><a href="#builtin-TagType">@TagType</a></li> | 142 | <li><a href="#builtin-TagType">@TagType</a></li> |
| 143 | <li><a href="#builtin-EnumTagType">@EnumTagType</a></li> | 143 | <li><a href="#builtin-EnumTagType">@EnumTagType</a></li> |
| 144 | <li><a href="#builtin-errorName">@errorName</a></li> | 144 | <li><a href="#builtin-errorName">@errorName</a></li> |
| 145 | <li><a href="#builtin-errorReturnTrace">@errorReturnTrace</a></li> | ||
| 145 | <li><a href="#builtin-fence">@fence</a></li> | 146 | <li><a href="#builtin-fence">@fence</a></li> |
| 146 | <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li> | 147 | <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li> |
| 147 | <li><a href="#builtin-frameAddress">@frameAddress</a></li> | 148 | <li><a href="#builtin-frameAddress">@frameAddress</a></li> |
| ... | @@ -4412,6 +4413,13 @@ test.zig:6:2: error: found compile log statement | ... | @@ -4412,6 +4413,13 @@ test.zig:6:2: error: found compile log statement |
| 4412 | or all calls have a compile-time known value for <code>err</code>, then no | 4413 | or all calls have a compile-time known value for <code>err</code>, then no |
| 4413 | error name table will be generated. | 4414 | error name table will be generated. |
| 4414 | </p> | 4415 | </p> |
| 4416 | <h3 id="builtin-errorReturnTrace">@errorReturnTrace</h3> | ||
| 4417 | <pre><code class="zig">@errorReturnTrace() -&gt; ?&amp;builtin.StackTrace</code></pre> | ||
| 4418 | <p> | ||
| 4419 | If the binary is built with error return tracing, and this function is invoked in a | ||
| 4420 | function that calls a function with an error or error union return type, returns a | ||
| 4421 | stack trace object. Otherwise returns `null`. | ||
| 4422 | </p> | ||
| 4415 | <h3 id="builtin-fence">@fence</h3> | 4423 | <h3 id="builtin-fence">@fence</h3> |
| 4416 | <pre><code class="zig">@fence(order: AtomicOrder)</code></pre> | 4424 | <pre><code class="zig">@fence(order: AtomicOrder)</code></pre> |
| 4417 | <p> | 4425 | <p> |
example/mix_o_files/build.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | ||
| 3 | pub fn build(b: &Builder) { | 3 | pub fn build(b: &Builder) -> %void { |
| 4 | const obj = b.addObject("base64", "base64.zig"); | 4 | const obj = b.addObject("base64", "base64.zig"); |
| 5 | 5 | ||
| 6 | const exe = b.addCExecutable("test"); | 6 | const exe = b.addCExecutable("test"); |
example/shared_library/build.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | ||
| 3 | pub fn build(b: &Builder) { | 3 | pub fn build(b: &Builder) -> %void { |
| 4 | const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0)); | 4 | const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0)); |
| 5 | 5 | ||
| 6 | const exe = b.addCExecutable("test"); | 6 | const exe = b.addCExecutable("test"); |
src/all_types.hpp+7| ... | @@ -1274,6 +1274,7 @@ enum BuiltinFnId { | ... | @@ -1274,6 +1274,7 @@ enum BuiltinFnId { |
| 1274 | BuiltinFnIdSetAlignStack, | 1274 | BuiltinFnIdSetAlignStack, |
| 1275 | BuiltinFnIdArgType, | 1275 | BuiltinFnIdArgType, |
| 1276 | BuiltinFnIdExport, | 1276 | BuiltinFnIdExport, |
| 1277 | BuiltinFnIdErrorReturnTrace, | ||
| 1277 | }; | 1278 | }; |
| 1278 | 1279 | ||
| 1279 | struct BuiltinFnEntry { | 1280 | struct BuiltinFnEntry { |
| ... | @@ -1499,6 +1500,7 @@ struct CodeGen { | ... | @@ -1499,6 +1500,7 @@ struct CodeGen { |
| 1499 | Buf triple_str; | 1500 | Buf triple_str; |
| 1500 | BuildMode build_mode; | 1501 | BuildMode build_mode; |
| 1501 | bool is_test_build; | 1502 | bool is_test_build; |
| 1503 | bool have_err_ret_tracing; | ||
| 1502 | uint32_t target_os_index; | 1504 | uint32_t target_os_index; |
| 1503 | uint32_t target_arch_index; | 1505 | uint32_t target_arch_index; |
| 1504 | uint32_t target_environ_index; | 1506 | uint32_t target_environ_index; |
| ... | @@ -1902,6 +1904,7 @@ enum IrInstructionId { | ... | @@ -1902,6 +1904,7 @@ enum IrInstructionId { |
| 1902 | IrInstructionIdSetAlignStack, | 1904 | IrInstructionIdSetAlignStack, |
| 1903 | IrInstructionIdArgType, | 1905 | IrInstructionIdArgType, |
| 1904 | IrInstructionIdExport, | 1906 | IrInstructionIdExport, |
| 1907 | IrInstructionIdErrorReturnTrace, | ||
| 1905 | }; | 1908 | }; |
| 1906 | 1909 | ||
| 1907 | struct IrInstruction { | 1910 | struct IrInstruction { |
| ... | @@ -2723,6 +2726,10 @@ struct IrInstructionExport { | ... | @@ -2723,6 +2726,10 @@ struct IrInstructionExport { |
| 2723 | IrInstruction *target; | 2726 | IrInstruction *target; |
| 2724 | }; | 2727 | }; |
| 2725 | 2728 | ||
| 2729 | struct IrInstructionErrorReturnTrace { | ||
| 2730 | IrInstruction base; | ||
| 2731 | }; | ||
| 2732 | |||
| 2726 | static const size_t slice_ptr_index = 0; | 2733 | static const size_t slice_ptr_index = 0; |
| 2727 | static const size_t slice_len_index = 1; | 2734 | static const size_t slice_len_index = 1; |
| 2728 | 2735 |
src/analyze.cpp+3-9| ... | @@ -925,8 +925,9 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -925,8 +925,9 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 925 | if (!skip_debug_info) { | 925 | if (!skip_debug_info) { |
| 926 | bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) && | 926 | bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) && |
| 927 | handle_is_ptr(fn_type_id->return_type); | 927 | handle_is_ptr(fn_type_id->return_type); |
| 928 | bool prefix_arg_error_return_trace = fn_type_id->return_type->id == TypeTableEntryIdErrorUnion || | 928 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && |
| 929 | fn_type_id->return_type->id == TypeTableEntryIdPureError; | 929 | (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion || |
| 930 | fn_type_id->return_type->id == TypeTableEntryIdPureError); | ||
| 930 | // +1 for maybe making the first argument the return value | 931 | // +1 for maybe making the first argument the return value |
| 931 | // +1 for maybe last argument the error return trace | 932 | // +1 for maybe last argument the error return trace |
| 932 | LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count); | 933 | LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count); |
| ... | @@ -2711,13 +2712,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { | ... | @@ -2711,13 +2712,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2711 | { | 2712 | { |
| 2712 | if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { | 2713 | if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { |
| 2713 | g->main_fn = fn_table_entry; | 2714 | g->main_fn = fn_table_entry; |
| 2714 | TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void); | ||
| 2715 | TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type; | ||
| 2716 | if (actual_return_type != err_void) { | ||
| 2717 | add_node_error(g, fn_proto->return_type, | ||
| 2718 | buf_sprintf("expected return type of main to be '%%void', instead is '%s'", | ||
| 2719 | buf_ptr(&actual_return_type->name))); | ||
| 2720 | } | ||
| 2721 | } else if ((import->package == g->panic_package || g->have_pub_panic) && | 2715 | } else if ((import->package == g->panic_package || g->have_pub_panic) && |
| 2722 | buf_eql_str(&fn_table_entry->symbol_name, "panic")) | 2716 | buf_eql_str(&fn_table_entry->symbol_name, "panic")) |
| 2723 | { | 2717 | { |
src/codegen.cpp+49-29| ... | @@ -404,7 +404,10 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { | ... | @@ -404,7 +404,10 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { |
| 404 | zig_unreachable(); | 404 | zig_unreachable(); |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | static uint32_t get_err_ret_trace_arg_index(FnTableEntry *fn_table_entry) { | 407 | static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 408 | if (!g->have_err_ret_tracing) { | ||
| 409 | return UINT32_MAX; | ||
| 410 | } | ||
| 408 | TypeTableEntry *fn_type = fn_table_entry->type_entry; | 411 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 409 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; | 412 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; |
| 410 | if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdPureError) { | 413 | if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdPureError) { |
| ... | @@ -572,7 +575,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { | ... | @@ -572,7 +575,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 572 | } | 575 | } |
| 573 | } | 576 | } |
| 574 | 577 | ||
| 575 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(fn_table_entry); | 578 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); |
| 576 | if (err_ret_trace_arg_index != UINT32_MAX) { | 579 | if (err_ret_trace_arg_index != UINT32_MAX) { |
| 577 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull"); | 580 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull"); |
| 578 | } | 581 | } |
| ... | @@ -1415,31 +1418,33 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns | ... | @@ -1415,31 +1418,33 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns |
| 1415 | LLVMValueRef value = ir_llvm_value(g, return_instruction->value); | 1418 | LLVMValueRef value = ir_llvm_value(g, return_instruction->value); |
| 1416 | TypeTableEntry *return_type = return_instruction->value->value.type; | 1419 | TypeTableEntry *return_type = return_instruction->value->value.type; |
| 1417 | 1420 | ||
| 1418 | bool is_err_return = false; | 1421 | if (g->have_err_ret_tracing) { |
| 1419 | if (return_type->id == TypeTableEntryIdErrorUnion) { | 1422 | bool is_err_return = false; |
| 1420 | if (return_instruction->value->value.special == ConstValSpecialStatic) { | 1423 | if (return_type->id == TypeTableEntryIdErrorUnion) { |
| 1421 | is_err_return = return_instruction->value->value.data.x_err_union.err != nullptr; | 1424 | if (return_instruction->value->value.special == ConstValSpecialStatic) { |
| 1422 | } else if (return_instruction->value->value.special == ConstValSpecialRuntime) { | 1425 | is_err_return = return_instruction->value->value.data.x_err_union.err != nullptr; |
| 1423 | is_err_return = return_instruction->value->value.data.rh_error_union == RuntimeHintErrorUnionError; | 1426 | } else if (return_instruction->value->value.special == ConstValSpecialRuntime) { |
| 1424 | // TODO: emit a branch to check if the return value is an error | 1427 | is_err_return = return_instruction->value->value.data.rh_error_union == RuntimeHintErrorUnionError; |
| 1428 | // TODO: emit a branch to check if the return value is an error | ||
| 1429 | } | ||
| 1430 | } else if (return_type->id == TypeTableEntryIdPureError) { | ||
| 1431 | is_err_return = true; | ||
| 1432 | } | ||
| 1433 | if (is_err_return) { | ||
| 1434 | LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn_val, "ReturnError"); | ||
| 1435 | LLVMValueRef block_address = LLVMBlockAddress(g->cur_fn_val, return_block); | ||
| 1436 | |||
| 1437 | LLVMValueRef return_err_fn = get_return_err_fn(g); | ||
| 1438 | LLVMValueRef args[] = { | ||
| 1439 | g->cur_err_ret_trace_val, | ||
| 1440 | block_address, | ||
| 1441 | }; | ||
| 1442 | LLVMBuildBr(g->builder, return_block); | ||
| 1443 | LLVMPositionBuilderAtEnd(g->builder, return_block); | ||
| 1444 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 2, | ||
| 1445 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); | ||
| 1446 | LLVMSetTailCall(call_instruction, true); | ||
| 1425 | } | 1447 | } |
| 1426 | } else if (return_type->id == TypeTableEntryIdPureError) { | ||
| 1427 | is_err_return = true; | ||
| 1428 | } | ||
| 1429 | if (is_err_return) { | ||
| 1430 | LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn_val, "ReturnError"); | ||
| 1431 | LLVMValueRef block_address = LLVMBlockAddress(g->cur_fn_val, return_block); | ||
| 1432 | |||
| 1433 | LLVMValueRef return_err_fn = get_return_err_fn(g); | ||
| 1434 | LLVMValueRef args[] = { | ||
| 1435 | g->cur_err_ret_trace_val, | ||
| 1436 | block_address, | ||
| 1437 | }; | ||
| 1438 | LLVMBuildBr(g->builder, return_block); | ||
| 1439 | LLVMPositionBuilderAtEnd(g->builder, return_block); | ||
| 1440 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 2, | ||
| 1441 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); | ||
| 1442 | LLVMSetTailCall(call_instruction, true); | ||
| 1443 | } | 1448 | } |
| 1444 | if (handle_is_ptr(return_type)) { | 1449 | if (handle_is_ptr(return_type)) { |
| 1445 | if (calling_convention_does_first_arg_return(g->cur_fn->type_entry->data.fn.fn_type_id.cc)) { | 1450 | if (calling_convention_does_first_arg_return(g->cur_fn->type_entry->data.fn.fn_type_id.cc)) { |
| ... | @@ -2475,7 +2480,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -2475,7 +2480,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2475 | TypeTableEntry *src_return_type = fn_type_id->return_type; | 2480 | TypeTableEntry *src_return_type = fn_type_id->return_type; |
| 2476 | bool ret_has_bits = type_has_bits(src_return_type); | 2481 | bool ret_has_bits = type_has_bits(src_return_type); |
| 2477 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); | 2482 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); |
| 2478 | bool prefix_arg_err_ret_stack = src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError; | 2483 | bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError); |
| 2479 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0); | 2484 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0); |
| 2480 | bool is_var_args = fn_type_id->is_var_args; | 2485 | bool is_var_args = fn_type_id->is_var_args; |
| 2481 | LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); | 2486 | LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); |
| ... | @@ -3031,6 +3036,16 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I | ... | @@ -3031,6 +3036,16 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I |
| 3031 | return target_val; | 3036 | return target_val; |
| 3032 | } | 3037 | } |
| 3033 | 3038 | ||
| 3039 | static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *executable, | ||
| 3040 | IrInstructionErrorReturnTrace *instruction) | ||
| 3041 | { | ||
| 3042 | TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g); | ||
| 3043 | if (g->cur_err_ret_trace_val == nullptr) { | ||
| 3044 | return LLVMConstNull(ptr_to_stack_trace_type->type_ref); | ||
| 3045 | } | ||
| 3046 | return g->cur_err_ret_trace_val; | ||
| 3047 | } | ||
| 3048 | |||
| 3034 | static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { | 3049 | static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { |
| 3035 | switch (atomic_order) { | 3050 | switch (atomic_order) { |
| 3036 | case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered; | 3051 | case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered; |
| ... | @@ -3804,6 +3819,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3804,6 +3819,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3804 | return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction); | 3819 | return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction); |
| 3805 | case IrInstructionIdAlignCast: | 3820 | case IrInstructionIdAlignCast: |
| 3806 | return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction); | 3821 | return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction); |
| 3822 | case IrInstructionIdErrorReturnTrace: | ||
| 3823 | return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction); | ||
| 3807 | } | 3824 | } |
| 3808 | zig_unreachable(); | 3825 | zig_unreachable(); |
| 3809 | } | 3826 | } |
| ... | @@ -4653,10 +4670,10 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -4653,10 +4670,10 @@ static void do_code_gen(CodeGen *g) { |
| 4653 | build_all_basic_blocks(g, fn_table_entry); | 4670 | build_all_basic_blocks(g, fn_table_entry); |
| 4654 | clear_debug_source_node(g); | 4671 | clear_debug_source_node(g); |
| 4655 | 4672 | ||
| 4656 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(fn_table_entry); | 4673 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); |
| 4657 | if (err_ret_trace_arg_index != UINT32_MAX) { | 4674 | if (err_ret_trace_arg_index != UINT32_MAX) { |
| 4658 | g->cur_err_ret_trace_val = LLVMGetParam(fn, err_ret_trace_arg_index); | 4675 | g->cur_err_ret_trace_val = LLVMGetParam(fn, err_ret_trace_arg_index); |
| 4659 | } else if (fn_table_entry->calls_errorable_function) { | 4676 | } else if (g->have_err_ret_tracing && fn_table_entry->calls_errorable_function) { |
| 4660 | // TODO call graph analysis to find out what this number needs to be for every function | 4677 | // TODO call graph analysis to find out what this number needs to be for every function |
| 4661 | static const size_t stack_trace_ptr_count = 30; | 4678 | static const size_t stack_trace_ptr_count = 30; |
| 4662 | 4679 | ||
| ... | @@ -5251,6 +5268,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -5251,6 +5268,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 5251 | create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1); | 5268 | create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1); |
| 5252 | create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2); | 5269 | create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2); |
| 5253 | create_builtin_fn(g, BuiltinFnIdExport, "export", 3); | 5270 | create_builtin_fn(g, BuiltinFnIdExport, "export", 3); |
| 5271 | create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0); | ||
| 5254 | } | 5272 | } |
| 5255 | 5273 | ||
| 5256 | static const char *bool_to_str(bool b) { | 5274 | static const char *bool_to_str(bool b) { |
| ... | @@ -5553,6 +5571,8 @@ static void init(CodeGen *g) { | ... | @@ -5553,6 +5571,8 @@ static void init(CodeGen *g) { |
| 5553 | } | 5571 | } |
| 5554 | } | 5572 | } |
| 5555 | 5573 | ||
| 5574 | g->have_err_ret_tracing = g->build_mode != BuildModeFastRelease; | ||
| 5575 | |||
| 5556 | define_builtin_fns(g); | 5576 | define_builtin_fns(g); |
| 5557 | define_builtin_compile_vars(g); | 5577 | define_builtin_compile_vars(g); |
| 5558 | } | 5578 | } |
src/ir.cpp+35| ... | @@ -572,6 +572,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArgType *) { | ... | @@ -572,6 +572,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArgType *) { |
| 572 | return IrInstructionIdArgType; | 572 | return IrInstructionIdArgType; |
| 573 | } | 573 | } |
| 574 | 574 | ||
| 575 | static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorReturnTrace *) { | ||
| 576 | return IrInstructionIdErrorReturnTrace; | ||
| 577 | } | ||
| 578 | |||
| 575 | template<typename T> | 579 | template<typename T> |
| 576 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 580 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 577 | T *special_instruction = allocate<T>(1); | 581 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2305,6 +2309,12 @@ static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *s | ... | @@ -2305,6 +2309,12 @@ static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *s |
| 2305 | return &instruction->base; | 2309 | return &instruction->base; |
| 2306 | } | 2310 | } |
| 2307 | 2311 | ||
| 2312 | static IrInstruction *ir_build_error_return_trace(IrBuilder *irb, Scope *scope, AstNode *source_node) { | ||
| 2313 | IrInstructionErrorReturnTrace *instruction = ir_build_instruction<IrInstructionErrorReturnTrace>(irb, scope, source_node); | ||
| 2314 | |||
| 2315 | return &instruction->base; | ||
| 2316 | } | ||
| 2317 | |||
| 2308 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2318 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2309 | results[ReturnKindUnconditional] = 0; | 2319 | results[ReturnKindUnconditional] = 0; |
| 2310 | results[ReturnKindError] = 0; | 2320 | results[ReturnKindError] = 0; |
| ... | @@ -3731,6 +3741,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -3731,6 +3741,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 3731 | 3741 | ||
| 3732 | return ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value); | 3742 | return ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value); |
| 3733 | } | 3743 | } |
| 3744 | case BuiltinFnIdErrorReturnTrace: | ||
| 3745 | { | ||
| 3746 | return ir_build_error_return_trace(irb, scope, node); | ||
| 3747 | } | ||
| 3734 | } | 3748 | } |
| 3735 | zig_unreachable(); | 3749 | zig_unreachable(); |
| 3736 | } | 3750 | } |
| ... | @@ -9568,6 +9582,24 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi | ... | @@ -9568,6 +9582,24 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi |
| 9568 | return ira->codegen->builtin_types.entry_void; | 9582 | return ira->codegen->builtin_types.entry_void; |
| 9569 | } | 9583 | } |
| 9570 | 9584 | ||
| 9585 | static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, | ||
| 9586 | IrInstructionErrorReturnTrace *instruction) | ||
| 9587 | { | ||
| 9588 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); | ||
| 9589 | TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen); | ||
| 9590 | TypeTableEntry *nullable_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type); | ||
| 9591 | if (fn_entry == nullptr || !fn_entry->calls_errorable_function || !ira->codegen->have_err_ret_tracing) { | ||
| 9592 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 9593 | out_val->data.x_maybe = nullptr; | ||
| 9594 | return nullable_type; | ||
| 9595 | } | ||
| 9596 | |||
| 9597 | IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope, | ||
| 9598 | instruction->base.source_node); | ||
| 9599 | ir_link_new_instruction(new_instruction, &instruction->base); | ||
| 9600 | return nullable_type; | ||
| 9601 | } | ||
| 9602 | |||
| 9571 | static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, | 9603 | static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, |
| 9572 | IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i) | 9604 | IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i) |
| 9573 | { | 9605 | { |
| ... | @@ -15324,6 +15356,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -15324,6 +15356,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 15324 | return ir_analyze_instruction_tag_type(ira, (IrInstructionTagType *)instruction); | 15356 | return ir_analyze_instruction_tag_type(ira, (IrInstructionTagType *)instruction); |
| 15325 | case IrInstructionIdExport: | 15357 | case IrInstructionIdExport: |
| 15326 | return ir_analyze_instruction_export(ira, (IrInstructionExport *)instruction); | 15358 | return ir_analyze_instruction_export(ira, (IrInstructionExport *)instruction); |
| 15359 | case IrInstructionIdErrorReturnTrace: | ||
| 15360 | return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction); | ||
| 15327 | } | 15361 | } |
| 15328 | zig_unreachable(); | 15362 | zig_unreachable(); |
| 15329 | } | 15363 | } |
| ... | @@ -15507,6 +15541,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -15507,6 +15541,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15507 | case IrInstructionIdOpaqueType: | 15541 | case IrInstructionIdOpaqueType: |
| 15508 | case IrInstructionIdArgType: | 15542 | case IrInstructionIdArgType: |
| 15509 | case IrInstructionIdTagType: | 15543 | case IrInstructionIdTagType: |
| 15544 | case IrInstructionIdErrorReturnTrace: | ||
| 15510 | return false; | 15545 | return false; |
| 15511 | case IrInstructionIdAsm: | 15546 | case IrInstructionIdAsm: |
| 15512 | { | 15547 | { |
src/ir_print.cpp+7| ... | @@ -996,6 +996,10 @@ static void ir_print_export(IrPrint *irp, IrInstructionExport *instruction) { | ... | @@ -996,6 +996,10 @@ static void ir_print_export(IrPrint *irp, IrInstructionExport *instruction) { |
| 996 | } | 996 | } |
| 997 | } | 997 | } |
| 998 | 998 | ||
| 999 | static void ir_print_error_return_trace(IrPrint *irp, IrInstructionErrorReturnTrace *instruction) { | ||
| 1000 | fprintf(irp->f, "@errorReturnTrace()"); | ||
| 1001 | } | ||
| 1002 | |||
| 999 | 1003 | ||
| 1000 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 1004 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1001 | ir_print_prefix(irp, instruction); | 1005 | ir_print_prefix(irp, instruction); |
| ... | @@ -1308,6 +1312,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1308,6 +1312,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1308 | case IrInstructionIdExport: | 1312 | case IrInstructionIdExport: |
| 1309 | ir_print_export(irp, (IrInstructionExport *)instruction); | 1313 | ir_print_export(irp, (IrInstructionExport *)instruction); |
| 1310 | break; | 1314 | break; |
| 1315 | case IrInstructionIdErrorReturnTrace: | ||
| 1316 | ir_print_error_return_trace(irp, (IrInstructionErrorReturnTrace *)instruction); | ||
| 1317 | break; | ||
| 1311 | } | 1318 | } |
| 1312 | fprintf(irp->f, "\n"); | 1319 | fprintf(irp->f, "\n"); |
| 1313 | } | 1320 | } |
std/build.zig+2-2| ... | @@ -247,11 +247,11 @@ pub const Builder = struct { | ... | @@ -247,11 +247,11 @@ pub const Builder = struct { |
| 247 | defer wanted_steps.deinit(); | 247 | defer wanted_steps.deinit(); |
| 248 | 248 | ||
| 249 | if (step_names.len == 0) { | 249 | if (step_names.len == 0) { |
| 250 | wanted_steps.append(&self.default_step) catch unreachable; | 250 | try wanted_steps.append(&self.default_step); |
| 251 | } else { | 251 | } else { |
| 252 | for (step_names) |step_name| { | 252 | for (step_names) |step_name| { |
| 253 | const s = try self.getTopLevelStepByName(step_name); | 253 | const s = try self.getTopLevelStepByName(step_name); |
| 254 | wanted_steps.append(s) catch unreachable; | 254 | try wanted_steps.append(s); |
| 255 | } | 255 | } |
| 256 | } | 256 | } |
| 257 | 257 |
std/debug/index.zig+6-3| ... | @@ -56,7 +56,7 @@ pub fn dumpCurrentStackTrace() { | ... | @@ -56,7 +56,7 @@ pub fn dumpCurrentStackTrace() { |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. | 58 | /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. |
| 59 | pub fn dumpStackTrace(stack_trace: &builtin.StackTrace) { | 59 | pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) { |
| 60 | const stderr = getStderrStream() catch return; | 60 | const stderr = getStderrStream() catch return; |
| 61 | const debug_info = openSelfDebugInfo(global_allocator) catch |err| { | 61 | const debug_info = openSelfDebugInfo(global_allocator) catch |err| { |
| 62 | stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return; | 62 | stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return; |
| ... | @@ -127,7 +127,7 @@ const RESET = "\x1b[0m"; | ... | @@ -127,7 +127,7 @@ const RESET = "\x1b[0m"; |
| 127 | error PathNotFound; | 127 | error PathNotFound; |
| 128 | error InvalidDebugInfo; | 128 | error InvalidDebugInfo; |
| 129 | 129 | ||
| 130 | pub fn writeStackTrace(stack_trace: &builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator, | 130 | pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator, |
| 131 | debug_info: &ElfStackTrace, tty_color: bool) -> %void | 131 | debug_info: &ElfStackTrace, tty_color: bool) -> %void |
| 132 | { | 132 | { |
| 133 | var frame_index: usize = undefined; | 133 | var frame_index: usize = undefined; |
| ... | @@ -167,6 +167,9 @@ pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocat | ... | @@ -167,6 +167,9 @@ pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocat |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) -> %void { | 169 | fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) -> %void { |
| 170 | if (builtin.os == builtin.Os.windows) { | ||
| 171 | return error.UnsupportedDebugInfo; | ||
| 172 | } | ||
| 170 | // TODO we really should be able to convert @sizeOf(usize) * 2 to a string literal | 173 | // TODO we really should be able to convert @sizeOf(usize) * 2 to a string literal |
| 171 | // at compile time. I'll call it issue #313 | 174 | // at compile time. I'll call it issue #313 |
| 172 | const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}"; | 175 | const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}"; |
| ... | @@ -177,7 +180,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, a | ... | @@ -177,7 +180,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, a |
| 177 | return; | 180 | return; |
| 178 | }; | 181 | }; |
| 179 | const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); | 182 | const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); |
| 180 | if (getLineNumberInfo(debug_info, compile_unit, usize(address) - 1)) |line_info| { | 183 | if (getLineNumberInfo(debug_info, compile_unit, address - 1)) |line_info| { |
| 181 | defer line_info.deinit(); | 184 | defer line_info.deinit(); |
| 182 | try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ | 185 | try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ |
| 183 | DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", | 186 | DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", |
std/io.zig+1-1| ... | @@ -224,7 +224,7 @@ pub const File = struct { | ... | @@ -224,7 +224,7 @@ pub const File = struct { |
| 224 | }; | 224 | }; |
| 225 | } | 225 | } |
| 226 | }, | 226 | }, |
| 227 | else => @compileError("unsupported OS"), | 227 | else => @compileError("unsupported OS: " ++ @tagName(builtin.os)), |
| 228 | } | 228 | } |
| 229 | } | 229 | } |
| 230 | 230 |
std/os/index.zig+2-9| ... | @@ -148,7 +148,7 @@ pub coldcc fn abort() -> noreturn { | ... | @@ -148,7 +148,7 @@ pub coldcc fn abort() -> noreturn { |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | /// Exits the program cleanly with the specified status code. | 150 | /// Exits the program cleanly with the specified status code. |
| 151 | pub coldcc fn exit(status: i32) -> noreturn { | 151 | pub coldcc fn exit(status: u8) -> noreturn { |
| 152 | if (builtin.link_libc) { | 152 | if (builtin.link_libc) { |
| 153 | c.exit(status); | 153 | c.exit(status); |
| 154 | } | 154 | } |
| ... | @@ -157,14 +157,7 @@ pub coldcc fn exit(status: i32) -> noreturn { | ... | @@ -157,14 +157,7 @@ pub coldcc fn exit(status: i32) -> noreturn { |
| 157 | posix.exit(status); | 157 | posix.exit(status); |
| 158 | }, | 158 | }, |
| 159 | Os.windows => { | 159 | Os.windows => { |
| 160 | // Map a possibly negative status code to a non-negative status for the systems default | 160 | windows.ExitProcess(status); |
| 161 | // integer width. | ||
| 162 | const p_status = if (@sizeOf(c_uint) < @sizeOf(u32)) | ||
| 163 | @truncate(c_uint, @bitCast(u32, status)) | ||
| 164 | else | ||
| 165 | c_uint(@bitCast(u32, status)); | ||
| 166 | |||
| 167 | windows.ExitProcess(p_status); | ||
| 168 | }, | 161 | }, |
| 169 | else => @compileError("Unsupported OS"), | 162 | else => @compileError("Unsupported OS"), |
| 170 | } | 163 | } |
std/special/bootstrap.zig+35-10| ... | @@ -21,8 +21,7 @@ comptime { | ... | @@ -21,8 +21,7 @@ comptime { |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | extern fn zenMain() -> noreturn { | 23 | extern fn zenMain() -> noreturn { |
| 24 | root.main() catch std.os.posix.exit(1); | 24 | std.os.posix.exit(callMain()); |
| 25 | std.os.posix.exit(0); | ||
| 26 | } | 25 | } |
| 27 | 26 | ||
| 28 | nakedcc fn _start() -> noreturn { | 27 | nakedcc fn _start() -> noreturn { |
| ... | @@ -43,29 +42,55 @@ nakedcc fn _start() -> noreturn { | ... | @@ -43,29 +42,55 @@ nakedcc fn _start() -> noreturn { |
| 43 | extern fn WinMainCRTStartup() -> noreturn { | 42 | extern fn WinMainCRTStartup() -> noreturn { |
| 44 | @setAlignStack(16); | 43 | @setAlignStack(16); |
| 45 | 44 | ||
| 46 | root.main() catch std.os.windows.ExitProcess(1); | 45 | std.os.windows.ExitProcess(callMain()); |
| 47 | std.os.windows.ExitProcess(0); | ||
| 48 | } | 46 | } |
| 49 | 47 | ||
| 50 | fn posixCallMainAndExit() -> noreturn { | 48 | fn posixCallMainAndExit() -> noreturn { |
| 51 | const argc = *argc_ptr; | 49 | const argc = *argc_ptr; |
| 52 | const argv = @ptrCast(&&u8, &argc_ptr[1]); | 50 | const argv = @ptrCast(&&u8, &argc_ptr[1]); |
| 53 | const envp = @ptrCast(&?&u8, &argv[argc + 1]); | 51 | const envp = @ptrCast(&?&u8, &argv[argc + 1]); |
| 54 | callMain(argc, argv, envp) catch std.os.posix.exit(1); | 52 | std.os.posix.exit(callMainWithArgs(argc, argv, envp)); |
| 55 | std.os.posix.exit(0); | ||
| 56 | } | 53 | } |
| 57 | 54 | ||
| 58 | fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void { | 55 | fn callMainWithArgs(argc: usize, argv: &&u8, envp: &?&u8) -> u8 { |
| 59 | std.os.ArgIteratorPosix.raw = argv[0..argc]; | 56 | std.os.ArgIteratorPosix.raw = argv[0..argc]; |
| 60 | 57 | ||
| 61 | var env_count: usize = 0; | 58 | var env_count: usize = 0; |
| 62 | while (envp[env_count] != null) : (env_count += 1) {} | 59 | while (envp[env_count] != null) : (env_count += 1) {} |
| 63 | std.os.posix_environ_raw = @ptrCast(&&u8, envp)[0..env_count]; | 60 | std.os.posix_environ_raw = @ptrCast(&&u8, envp)[0..env_count]; |
| 64 | 61 | ||
| 65 | return root.main(); | 62 | return callMain(); |
| 66 | } | 63 | } |
| 67 | 64 | ||
| 68 | extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 { | 65 | extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 { |
| 69 | callMain(usize(c_argc), c_argv, c_envp) catch return 1; | 66 | return callMainWithArgs(usize(c_argc), c_argv, c_envp); |
| 70 | return 0; | 67 | } |
| 68 | |||
| 69 | fn callMain() -> u8 { | ||
| 70 | switch (@typeId(@typeOf(root.main).ReturnType)) { | ||
| 71 | builtin.TypeId.NoReturn => { | ||
| 72 | root.main(); | ||
| 73 | }, | ||
| 74 | builtin.TypeId.Void => { | ||
| 75 | root.main(); | ||
| 76 | return 0; | ||
| 77 | }, | ||
| 78 | builtin.TypeId.Int => { | ||
| 79 | if (@typeOf(root.main).ReturnType.bit_count != 8) { | ||
| 80 | @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"); | ||
| 81 | } | ||
| 82 | return root.main(); | ||
| 83 | }, | ||
| 84 | builtin.TypeId.ErrorUnion => { | ||
| 85 | root.main() catch |err| { | ||
| 86 | std.debug.warn("error: {}\n", @errorName(err)); | ||
| 87 | if (@errorReturnTrace()) |trace| { | ||
| 88 | std.debug.dumpStackTrace(trace); | ||
| 89 | } | ||
| 90 | return 1; | ||
| 91 | }; | ||
| 92 | return 0; | ||
| 93 | }, | ||
| 94 | else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"), | ||
| 95 | } | ||
| 71 | } | 96 | } |
std/special/build_runner.zig+4-4| ... | @@ -14,7 +14,7 @@ pub fn main() -> %void { | ... | @@ -14,7 +14,7 @@ pub fn main() -> %void { |
| 14 | var arg_it = os.args(); | 14 | var arg_it = os.args(); |
| 15 | 15 | ||
| 16 | // TODO use a more general purpose allocator here | 16 | // TODO use a more general purpose allocator here |
| 17 | var inc_allocator = std.heap.IncrementingAllocator.init(40 * 1024 * 1024) catch unreachable; | 17 | var inc_allocator = try std.heap.IncrementingAllocator.init(40 * 1024 * 1024); |
| 18 | defer inc_allocator.deinit(); | 18 | defer inc_allocator.deinit(); |
| 19 | 19 | ||
| 20 | const allocator = &inc_allocator.allocator; | 20 | const allocator = &inc_allocator.allocator; |
| ... | @@ -107,12 +107,12 @@ pub fn main() -> %void { | ... | @@ -107,12 +107,12 @@ pub fn main() -> %void { |
| 107 | return usageAndErr(&builder, false, try stderr_stream); | 107 | return usageAndErr(&builder, false, try stderr_stream); |
| 108 | } | 108 | } |
| 109 | } else { | 109 | } else { |
| 110 | targets.append(arg) catch unreachable; | 110 | try targets.append(arg); |
| 111 | } | 111 | } |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | builder.setInstallPrefix(prefix); | 114 | builder.setInstallPrefix(prefix); |
| 115 | root.build(&builder) catch unreachable; | 115 | try root.build(&builder); |
| 116 | 116 | ||
| 117 | if (builder.validateUserInputDidItFail()) | 117 | if (builder.validateUserInputDidItFail()) |
| 118 | return usageAndErr(&builder, true, try stderr_stream); | 118 | return usageAndErr(&builder, true, try stderr_stream); |
| ... | @@ -129,7 +129,7 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) | ... | @@ -129,7 +129,7 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) |
| 129 | // run the build script to collect the options | 129 | // run the build script to collect the options |
| 130 | if (!already_ran_build) { | 130 | if (!already_ran_build) { |
| 131 | builder.setInstallPrefix(null); | 131 | builder.setInstallPrefix(null); |
| 132 | root.build(builder) catch unreachable; | 132 | try root.build(builder); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | // This usage text has to be synchronized with src/main.cpp | 135 | // This usage text has to be synchronized with src/main.cpp |
std/special/test_runner.zig+1-8| ... | @@ -8,14 +8,7 @@ pub fn main() -> %void { | ... | @@ -8,14 +8,7 @@ pub fn main() -> %void { |
| 8 | for (test_fn_list) |test_fn, i| { | 8 | for (test_fn_list) |test_fn, i| { |
| 9 | warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); | 9 | warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); |
| 10 | 10 | ||
| 11 | if (builtin.is_test) { | 11 | try test_fn.func(); |
| 12 | test_fn.func() catch unreachable; | ||
| 13 | } else { | ||
| 14 | test_fn.func() catch |err| { | ||
| 15 | warn("{}\n", err); | ||
| 16 | return err; | ||
| 17 | }; | ||
| 18 | } | ||
| 19 | 12 | ||
| 20 | warn("OK\n"); | 13 | warn("OK\n"); |
| 21 | } | 14 | } |
test/compile_errors.zig+9-9| ... | @@ -1,6 +1,15 @@ | ... | @@ -1,6 +1,15 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: &tests.CompileErrorContext) { | 3 | pub fn addCases(cases: &tests.CompileErrorContext) { |
| 4 | cases.add("wrong return type for main", | ||
| 5 | \\pub fn main() -> f32 { } | ||
| 6 | , "error: expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"); | ||
| 7 | |||
| 8 | cases.add("double ?? on main return value", | ||
| 9 | \\pub fn main() -> ??void { | ||
| 10 | \\} | ||
| 11 | , "error: expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"); | ||
| 12 | |||
| 4 | cases.add("bad identifier in function with struct defined inside function which references local const", | 13 | cases.add("bad identifier in function with struct defined inside function which references local const", |
| 5 | \\export fn entry() { | 14 | \\export fn entry() { |
| 6 | \\ const BlockKind = u32; | 15 | \\ const BlockKind = u32; |
| ... | @@ -1059,15 +1068,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -1059,15 +1068,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1059 | , | 1068 | , |
| 1060 | ".tmp_source.zig:2:5: error: expected type 'void', found 'error'"); | 1069 | ".tmp_source.zig:2:5: error: expected type 'void', found 'error'"); |
| 1061 | 1070 | ||
| 1062 | cases.add("wrong return type for main", | ||
| 1063 | \\pub fn main() { } | ||
| 1064 | , ".tmp_source.zig:1:15: error: expected return type of main to be '%void', instead is 'void'"); | ||
| 1065 | |||
| 1066 | cases.add("double ?? on main return value", | ||
| 1067 | \\pub fn main() -> ??void { | ||
| 1068 | \\} | ||
| 1069 | , ".tmp_source.zig:1:18: error: expected return type of main to be '%void', instead is '??void'"); | ||
| 1070 | |||
| 1071 | cases.add("invalid pointer for var type", | 1071 | cases.add("invalid pointer for var type", |
| 1072 | \\extern fn ext() -> usize; | 1072 | \\extern fn ext() -> usize; |
| 1073 | \\var bytes: [ext()]u8 = undefined; | 1073 | \\var bytes: [ext()]u8 = undefined; |
test/debug_safety.zig+20-20| ... | @@ -2,7 +2,7 @@ const tests = @import("tests.zig"); | ... | @@ -2,7 +2,7 @@ const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: &tests.CompareOutputContext) { | 3 | pub fn addCases(cases: &tests.CompareOutputContext) { |
| 4 | cases.addDebugSafety("calling panic", | 4 | cases.addDebugSafety("calling panic", |
| 5 | \\pub fn panic(message: []const u8) -> noreturn { | 5 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 6 | \\ @import("std").os.exit(126); | 6 | \\ @import("std").os.exit(126); |
| 7 | \\} | 7 | \\} |
| 8 | \\pub fn main() -> %void { | 8 | \\pub fn main() -> %void { |
| ... | @@ -11,7 +11,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -11,7 +11,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 11 | ); | 11 | ); |
| 12 | 12 | ||
| 13 | cases.addDebugSafety("out of bounds slice access", | 13 | cases.addDebugSafety("out of bounds slice access", |
| 14 | \\pub fn panic(message: []const u8) -> noreturn { | 14 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 15 | \\ @import("std").os.exit(126); | 15 | \\ @import("std").os.exit(126); |
| 16 | \\} | 16 | \\} |
| 17 | \\pub fn main() -> %void { | 17 | \\pub fn main() -> %void { |
| ... | @@ -25,7 +25,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -25,7 +25,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 25 | ); | 25 | ); |
| 26 | 26 | ||
| 27 | cases.addDebugSafety("integer addition overflow", | 27 | cases.addDebugSafety("integer addition overflow", |
| 28 | \\pub fn panic(message: []const u8) -> noreturn { | 28 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 29 | \\ @import("std").os.exit(126); | 29 | \\ @import("std").os.exit(126); |
| 30 | \\} | 30 | \\} |
| 31 | \\error Whatever; | 31 | \\error Whatever; |
| ... | @@ -39,7 +39,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -39,7 +39,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 39 | ); | 39 | ); |
| 40 | 40 | ||
| 41 | cases.addDebugSafety("integer subtraction overflow", | 41 | cases.addDebugSafety("integer subtraction overflow", |
| 42 | \\pub fn panic(message: []const u8) -> noreturn { | 42 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 43 | \\ @import("std").os.exit(126); | 43 | \\ @import("std").os.exit(126); |
| 44 | \\} | 44 | \\} |
| 45 | \\error Whatever; | 45 | \\error Whatever; |
| ... | @@ -53,7 +53,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -53,7 +53,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 53 | ); | 53 | ); |
| 54 | 54 | ||
| 55 | cases.addDebugSafety("integer multiplication overflow", | 55 | cases.addDebugSafety("integer multiplication overflow", |
| 56 | \\pub fn panic(message: []const u8) -> noreturn { | 56 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 57 | \\ @import("std").os.exit(126); | 57 | \\ @import("std").os.exit(126); |
| 58 | \\} | 58 | \\} |
| 59 | \\error Whatever; | 59 | \\error Whatever; |
| ... | @@ -67,7 +67,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -67,7 +67,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 67 | ); | 67 | ); |
| 68 | 68 | ||
| 69 | cases.addDebugSafety("integer negation overflow", | 69 | cases.addDebugSafety("integer negation overflow", |
| 70 | \\pub fn panic(message: []const u8) -> noreturn { | 70 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 71 | \\ @import("std").os.exit(126); | 71 | \\ @import("std").os.exit(126); |
| 72 | \\} | 72 | \\} |
| 73 | \\error Whatever; | 73 | \\error Whatever; |
| ... | @@ -81,7 +81,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -81,7 +81,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 81 | ); | 81 | ); |
| 82 | 82 | ||
| 83 | cases.addDebugSafety("signed integer division overflow", | 83 | cases.addDebugSafety("signed integer division overflow", |
| 84 | \\pub fn panic(message: []const u8) -> noreturn { | 84 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 85 | \\ @import("std").os.exit(126); | 85 | \\ @import("std").os.exit(126); |
| 86 | \\} | 86 | \\} |
| 87 | \\error Whatever; | 87 | \\error Whatever; |
| ... | @@ -95,7 +95,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -95,7 +95,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 95 | ); | 95 | ); |
| 96 | 96 | ||
| 97 | cases.addDebugSafety("signed shift left overflow", | 97 | cases.addDebugSafety("signed shift left overflow", |
| 98 | \\pub fn panic(message: []const u8) -> noreturn { | 98 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 99 | \\ @import("std").os.exit(126); | 99 | \\ @import("std").os.exit(126); |
| 100 | \\} | 100 | \\} |
| 101 | \\error Whatever; | 101 | \\error Whatever; |
| ... | @@ -109,7 +109,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -109,7 +109,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 109 | ); | 109 | ); |
| 110 | 110 | ||
| 111 | cases.addDebugSafety("unsigned shift left overflow", | 111 | cases.addDebugSafety("unsigned shift left overflow", |
| 112 | \\pub fn panic(message: []const u8) -> noreturn { | 112 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 113 | \\ @import("std").os.exit(126); | 113 | \\ @import("std").os.exit(126); |
| 114 | \\} | 114 | \\} |
| 115 | \\error Whatever; | 115 | \\error Whatever; |
| ... | @@ -123,7 +123,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -123,7 +123,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 123 | ); | 123 | ); |
| 124 | 124 | ||
| 125 | cases.addDebugSafety("signed shift right overflow", | 125 | cases.addDebugSafety("signed shift right overflow", |
| 126 | \\pub fn panic(message: []const u8) -> noreturn { | 126 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 127 | \\ @import("std").os.exit(126); | 127 | \\ @import("std").os.exit(126); |
| 128 | \\} | 128 | \\} |
| 129 | \\error Whatever; | 129 | \\error Whatever; |
| ... | @@ -137,7 +137,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -137,7 +137,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 137 | ); | 137 | ); |
| 138 | 138 | ||
| 139 | cases.addDebugSafety("unsigned shift right overflow", | 139 | cases.addDebugSafety("unsigned shift right overflow", |
| 140 | \\pub fn panic(message: []const u8) -> noreturn { | 140 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 141 | \\ @import("std").os.exit(126); | 141 | \\ @import("std").os.exit(126); |
| 142 | \\} | 142 | \\} |
| 143 | \\error Whatever; | 143 | \\error Whatever; |
| ... | @@ -151,7 +151,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -151,7 +151,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 151 | ); | 151 | ); |
| 152 | 152 | ||
| 153 | cases.addDebugSafety("integer division by zero", | 153 | cases.addDebugSafety("integer division by zero", |
| 154 | \\pub fn panic(message: []const u8) -> noreturn { | 154 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 155 | \\ @import("std").os.exit(126); | 155 | \\ @import("std").os.exit(126); |
| 156 | \\} | 156 | \\} |
| 157 | \\error Whatever; | 157 | \\error Whatever; |
| ... | @@ -164,7 +164,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -164,7 +164,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 164 | ); | 164 | ); |
| 165 | 165 | ||
| 166 | cases.addDebugSafety("exact division failure", | 166 | cases.addDebugSafety("exact division failure", |
| 167 | \\pub fn panic(message: []const u8) -> noreturn { | 167 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 168 | \\ @import("std").os.exit(126); | 168 | \\ @import("std").os.exit(126); |
| 169 | \\} | 169 | \\} |
| 170 | \\error Whatever; | 170 | \\error Whatever; |
| ... | @@ -178,7 +178,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -178,7 +178,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 178 | ); | 178 | ); |
| 179 | 179 | ||
| 180 | cases.addDebugSafety("cast []u8 to bigger slice of wrong size", | 180 | cases.addDebugSafety("cast []u8 to bigger slice of wrong size", |
| 181 | \\pub fn panic(message: []const u8) -> noreturn { | 181 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 182 | \\ @import("std").os.exit(126); | 182 | \\ @import("std").os.exit(126); |
| 183 | \\} | 183 | \\} |
| 184 | \\error Whatever; | 184 | \\error Whatever; |
| ... | @@ -192,7 +192,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -192,7 +192,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 192 | ); | 192 | ); |
| 193 | 193 | ||
| 194 | cases.addDebugSafety("value does not fit in shortening cast", | 194 | cases.addDebugSafety("value does not fit in shortening cast", |
| 195 | \\pub fn panic(message: []const u8) -> noreturn { | 195 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 196 | \\ @import("std").os.exit(126); | 196 | \\ @import("std").os.exit(126); |
| 197 | \\} | 197 | \\} |
| 198 | \\error Whatever; | 198 | \\error Whatever; |
| ... | @@ -206,7 +206,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -206,7 +206,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 206 | ); | 206 | ); |
| 207 | 207 | ||
| 208 | cases.addDebugSafety("signed integer not fitting in cast to unsigned integer", | 208 | cases.addDebugSafety("signed integer not fitting in cast to unsigned integer", |
| 209 | \\pub fn panic(message: []const u8) -> noreturn { | 209 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 210 | \\ @import("std").os.exit(126); | 210 | \\ @import("std").os.exit(126); |
| 211 | \\} | 211 | \\} |
| 212 | \\error Whatever; | 212 | \\error Whatever; |
| ... | @@ -220,7 +220,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -220,7 +220,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 220 | ); | 220 | ); |
| 221 | 221 | ||
| 222 | cases.addDebugSafety("unwrap error", | 222 | cases.addDebugSafety("unwrap error", |
| 223 | \\pub fn panic(message: []const u8) -> noreturn { | 223 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 224 | \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { | 224 | \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { |
| 225 | \\ @import("std").os.exit(126); // good | 225 | \\ @import("std").os.exit(126); // good |
| 226 | \\ } | 226 | \\ } |
| ... | @@ -236,7 +236,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -236,7 +236,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 236 | ); | 236 | ); |
| 237 | 237 | ||
| 238 | cases.addDebugSafety("cast integer to error and no code matches", | 238 | cases.addDebugSafety("cast integer to error and no code matches", |
| 239 | \\pub fn panic(message: []const u8) -> noreturn { | 239 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 240 | \\ @import("std").os.exit(126); | 240 | \\ @import("std").os.exit(126); |
| 241 | \\} | 241 | \\} |
| 242 | \\pub fn main() -> %void { | 242 | \\pub fn main() -> %void { |
| ... | @@ -248,7 +248,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -248,7 +248,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 248 | ); | 248 | ); |
| 249 | 249 | ||
| 250 | cases.addDebugSafety("@alignCast misaligned", | 250 | cases.addDebugSafety("@alignCast misaligned", |
| 251 | \\pub fn panic(message: []const u8) -> noreturn { | 251 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 252 | \\ @import("std").os.exit(126); | 252 | \\ @import("std").os.exit(126); |
| 253 | \\} | 253 | \\} |
| 254 | \\error Wrong; | 254 | \\error Wrong; |
| ... | @@ -265,7 +265,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -265,7 +265,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 265 | ); | 265 | ); |
| 266 | 266 | ||
| 267 | cases.addDebugSafety("bad union field access", | 267 | cases.addDebugSafety("bad union field access", |
| 268 | \\pub fn panic(message: []const u8) -> noreturn { | 268 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 269 | \\ @import("std").os.exit(126); | 269 | \\ @import("std").os.exit(126); |
| 270 | \\} | 270 | \\} |
| 271 | \\ | 271 | \\ |
test/standalone/issue_339/build.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | ||
| 3 | pub fn build(b: &Builder) { | 3 | pub fn build(b: &Builder) -> %void { |
| 4 | const obj = b.addObject("test", "test.zig"); | 4 | const obj = b.addObject("test", "test.zig"); |
| 5 | 5 | ||
| 6 | const test_step = b.step("test", "Test the program"); | 6 | const test_step = b.step("test", "Test the program"); |
test/standalone/issue_339/test.zig+2-1| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | pub fn panic(msg: []const u8) -> noreturn { @breakpoint(); while (true) {} } | 1 | const StackTrace = @import("builtin").StackTrace; |
| 2 | pub fn panic(msg: []const u8, stack_trace: ?&StackTrace) -> noreturn { @breakpoint(); while (true) {} } | ||
| 2 | 3 | ||
| 3 | fn bar() -> %void {} | 4 | fn bar() -> %void {} |
| 4 | 5 |
test/standalone/pkg_import/build.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | ||
| 3 | pub fn build(b: &Builder) { | 3 | pub fn build(b: &Builder) -> %void { |
| 4 | const exe = b.addExecutable("test", "test.zig"); | 4 | const exe = b.addExecutable("test", "test.zig"); |
| 5 | exe.addPackagePath("my_pkg", "pkg.zig"); | 5 | exe.addPackagePath("my_pkg", "pkg.zig"); |
| 6 | 6 |
test/standalone/use_alias/build.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | ||
| 3 | pub fn build(b: &Builder) { | 3 | pub fn build(b: &Builder) -> %void { |
| 4 | b.addCIncludePath("."); | 4 | b.addCIncludePath("."); |
| 5 | 5 | ||
| 6 | const main = b.addTest("main.zig"); | 6 | const main = b.addTest("main.zig"); |
test/tests.zig+2-2| ... | @@ -50,6 +50,7 @@ const test_targets = []TestTarget { | ... | @@ -50,6 +50,7 @@ const test_targets = []TestTarget { |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | error TestFailed; | 52 | error TestFailed; |
| 53 | error CompilationIncorrectlySucceeded; | ||
| 53 | 54 | ||
| 54 | const max_stdout_size = 1 * 1024 * 1024; // 1 MB | 55 | const max_stdout_size = 1 * 1024 * 1024; // 1 MB |
| 55 | 56 | ||
| ... | @@ -607,8 +608,7 @@ pub const CompileErrorContext = struct { | ... | @@ -607,8 +608,7 @@ pub const CompileErrorContext = struct { |
| 607 | switch (term) { | 608 | switch (term) { |
| 608 | Term.Exited => |code| { | 609 | Term.Exited => |code| { |
| 609 | if (code == 0) { | 610 | if (code == 0) { |
| 610 | warn("Compilation incorrectly succeeded\n"); | 611 | return error.CompilationIncorrectlySucceeded; |
| 611 | return error.TestFailed; | ||
| 612 | } | 612 | } |
| 613 | }, | 613 | }, |
| 614 | else => { | 614 | else => { |