| author | |
| committer | |
| log | bfa1d12fbad2031402fbafe51c3a0c481fe69351 |
| tree | ff1e8878a8f6dc8a7d70d0716b3ab1d94e51726d |
| parent | 8be95af48011f71f1902dff4ffbf5ea95cf1bcf4 |
| signature |
4 files changed, 49 insertions(+), 6 deletions(-)
src/analyze.cpp+8-3| ... | @@ -5179,11 +5179,14 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | ... | @@ -5179,11 +5179,14 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5179 | if (fn->anal_state == FnAnalStateInvalid) | 5179 | if (fn->anal_state == FnAnalStateInvalid) |
| 5180 | return ErrorSemanticAnalyzeFail; | 5180 | return ErrorSemanticAnalyzeFail; |
| 5181 | break; | 5181 | break; |
| 5182 | case FnAnalStateProbing: | 5182 | case FnAnalStateProbing: { |
| 5183 | add_node_error(g, fn->proto_node, | 5183 | ErrorMsg *msg = add_node_error(g, fn->proto_node, |
| 5184 | buf_sprintf("cannot resolve '%s': function not fully analyzed yet", | 5184 | buf_sprintf("cannot resolve '%s': function not fully analyzed yet", |
| 5185 | buf_ptr(&frame_type->name))); | 5185 | buf_ptr(&frame_type->name))); |
| 5186 | ir_add_analysis_trace(fn->ir_executable.analysis, msg, | ||
| 5187 | buf_sprintf("depends on its own frame here")); | ||
| 5186 | return ErrorSemanticAnalyzeFail; | 5188 | return ErrorSemanticAnalyzeFail; |
| 5189 | } | ||
| 5187 | } | 5190 | } |
| 5188 | ZigType *fn_type = get_async_fn_type(g, fn->type_entry); | 5191 | ZigType *fn_type = get_async_fn_type(g, fn->type_entry); |
| 5189 | 5192 | ||
| ... | @@ -5201,8 +5204,10 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | ... | @@ -5201,8 +5204,10 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5201 | if (callee->anal_state == FnAnalStateProbing) { | 5204 | if (callee->anal_state == FnAnalStateProbing) { |
| 5202 | ErrorMsg *msg = add_node_error(g, fn->proto_node, | 5205 | ErrorMsg *msg = add_node_error(g, fn->proto_node, |
| 5203 | buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name))); | 5206 | buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name))); |
| 5204 | add_error_note(g, msg, call->base.source_node, | 5207 | ErrorMsg *note = add_error_note(g, msg, call->base.source_node, |
| 5205 | buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name))); | 5208 | buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name))); |
| 5209 | ir_add_analysis_trace(callee->ir_executable.analysis, note, | ||
| 5210 | buf_sprintf("depends on the frame here")); | ||
| 5206 | return ErrorSemanticAnalyzeFail; | 5211 | return ErrorSemanticAnalyzeFail; |
| 5207 | } | 5212 | } |
| 5208 | 5213 |
src/ir.cpp+9-3| ... | @@ -8217,18 +8217,24 @@ bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { | ... | @@ -8217,18 +8217,24 @@ bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { |
| 8217 | return ir_gen(codegen, body_node, fn_entry->child_scope, ir_executable); | 8217 | return ir_gen(codegen, body_node, fn_entry->child_scope, ir_executable); |
| 8218 | } | 8218 | } |
| 8219 | 8219 | ||
| 8220 | static void add_call_stack_errors(CodeGen *codegen, IrExecutable *exec, ErrorMsg *err_msg, int limit) { | 8220 | static void ir_add_call_stack_errors(CodeGen *codegen, IrExecutable *exec, ErrorMsg *err_msg, int limit) { |
| 8221 | if (!exec || !exec->source_node || limit < 0) return; | 8221 | if (!exec || !exec->source_node || limit < 0) return; |
| 8222 | add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); | 8222 | add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); |
| 8223 | 8223 | ||
| 8224 | add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1); | 8224 | ir_add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1); |
| 8225 | } | ||
| 8226 | |||
| 8227 | void ir_add_analysis_trace(IrAnalyze *ira, ErrorMsg *err_msg, Buf *text) { | ||
| 8228 | IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); | ||
| 8229 | add_error_note(ira->codegen, err_msg, old_instruction->source_node, text); | ||
| 8230 | ir_add_call_stack_errors(ira->codegen, ira->new_irb.exec, err_msg, 10); | ||
| 8225 | } | 8231 | } |
| 8226 | 8232 | ||
| 8227 | static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg) { | 8233 | static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg) { |
| 8228 | invalidate_exec(exec); | 8234 | invalidate_exec(exec); |
| 8229 | ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); | 8235 | ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); |
| 8230 | if (exec->parent_exec) { | 8236 | if (exec->parent_exec) { |
| 8231 | add_call_stack_errors(codegen, exec, err_msg, 10); | 8237 | ir_add_call_stack_errors(codegen, exec, err_msg, 10); |
| 8232 | } | 8238 | } |
| 8233 | return err_msg; | 8239 | return err_msg; |
| 8234 | } | 8240 | } |
src/ir.hpp+2| ... | @@ -28,4 +28,6 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal | ... | @@ -28,4 +28,6 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal |
| 28 | AstNode *source_node); | 28 | AstNode *source_node); |
| 29 | const char *float_op_to_name(BuiltinFnId op, bool llvm_name); | 29 | const char *float_op_to_name(BuiltinFnId op, bool llvm_name); |
| 30 | 30 | ||
| 31 | void ir_add_analysis_trace(IrAnalyze *ira, ErrorMsg *err_msg, Buf *text); | ||
| 32 | |||
| 31 | #endif | 33 | #endif |
test/compile_errors.zig+30| ... | @@ -2,6 +2,36 @@ const tests = @import("tests.zig"); | ... | @@ -2,6 +2,36 @@ const tests = @import("tests.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.add( | ||
| 6 | "async function indirectly depends on its own frame", | ||
| 7 | \\export fn entry() void { | ||
| 8 | \\ _ = async amain(); | ||
| 9 | \\} | ||
| 10 | \\async fn amain() void { | ||
| 11 | \\ other(); | ||
| 12 | \\} | ||
| 13 | \\fn other() void { | ||
| 14 | \\ var x: [@sizeOf(@Frame(amain))]u8 = undefined; | ||
| 15 | \\} | ||
| 16 | , | ||
| 17 | "tmp.zig:4:1: error: unable to determine async function frame of 'amain'", | ||
| 18 | "tmp.zig:5:10: note: analysis of function 'other' depends on the frame", | ||
| 19 | "tmp.zig:8:13: note: depends on the frame here", | ||
| 20 | ); | ||
| 21 | |||
| 22 | cases.add( | ||
| 23 | "async function depends on its own frame", | ||
| 24 | \\export fn entry() void { | ||
| 25 | \\ _ = async amain(); | ||
| 26 | \\} | ||
| 27 | \\async fn amain() void { | ||
| 28 | \\ var x: [@sizeOf(@Frame(amain))]u8 = undefined; | ||
| 29 | \\} | ||
| 30 | , | ||
| 31 | "tmp.zig:4:1: error: cannot resolve '@Frame(amain)': function not fully analyzed yet", | ||
| 32 | "tmp.zig:5:13: note: depends on its own frame here", | ||
| 33 | ); | ||
| 34 | |||
| 5 | cases.add( | 35 | cases.add( |
| 6 | "non async function pointer passed to @asyncCall", | 36 | "non async function pointer passed to @asyncCall", |
| 7 | \\export fn entry() void { | 37 | \\export fn entry() void { |