From e5b90651ba118cb0d3293c83bdfbc62c40f4c266 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 3 Jun 2017 15:09:40 -0400 Subject: [PATCH] compileError builtin includes "referenced by" notes to help track down the cause closes #278 --- src/all_types.hpp | 3 +-- src/analyze.cpp | 12 +++++++----- src/analyze.hpp | 2 +- src/ir.cpp | 26 +++++++++++++++++++------- std/special/bootstrap.zig | 15 ++++++++++++--- test/compile_errors.zig | 14 ++++++++++++++ 6 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 52fe96fbf4..090f4f4371 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1453,8 +1453,6 @@ struct CodeGen { FnTableEntry *extern_panic_fn; LLVMValueRef cur_ret_ptr; LLVMValueRef cur_fn_val; - ZigList break_block_stack; - ZigList continue_block_stack; bool c_want_stdint; bool c_want_stdbool; AstNode *root_export_decl; @@ -1510,6 +1508,7 @@ struct CodeGen { Buf *out_h_path; ZigList inline_fns; + ZigList tld_ref_source_node_stack; }; enum VarLinkage { diff --git a/src/analyze.cpp b/src/analyze.cpp index a2c847848c..ecc1712fc8 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2086,7 +2086,7 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) { Tld *tld = g->compile_var_import->decls_scope->decl_table.get(name); - resolve_top_level_decl(g, tld, false); + resolve_top_level_decl(g, tld, false, tld->source_node); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; tld_var->var->value = value; @@ -2399,7 +2399,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { g->global_vars.append(tld_var); } -void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only) { +void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node) { if (tld->resolution != TldResolutionUnresolved) return; @@ -2407,10 +2407,11 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only) { add_node_error(g, tld->source_node, buf_sprintf("'%s' depends on itself", buf_ptr(tld->name))); tld->resolution = TldResolutionInvalid; return; - } else { - tld->dep_loop_flag = true; } + tld->dep_loop_flag = true; + g->tld_ref_source_node_stack.append(source_node); + switch (tld->id) { case TldIdVar: { @@ -2440,6 +2441,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only) { tld->resolution = TldResolutionOk; tld->dep_loop_flag = false; + g->tld_ref_source_node_stack.pop(); } bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type) { @@ -3056,7 +3058,7 @@ void semantic_analyze(CodeGen *g) { for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) { Tld *tld = g->resolve_queue.at(g->resolve_queue_index); bool pointer_only = false; - resolve_top_level_decl(g, tld, pointer_only); + resolve_top_level_decl(g, tld, pointer_only, nullptr); } for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) { diff --git a/src/analyze.hpp b/src/analyze.hpp index 5666f203b2..214227d388 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -50,7 +50,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type); VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name); Tld *find_decl(CodeGen *g, Scope *scope, Buf *name); -void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only); +void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node); bool type_is_codegen_pointer(TypeTableEntry *type); TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry); TypeTableEntry *container_ref_type(TypeTableEntry *type_entry); diff --git a/src/ir.cpp b/src/ir.cpp index 7658db47fe..3b324352bf 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7909,7 +7909,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { static ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { Tld *tld = codegen->compile_var_import->decls_scope->decl_table.get(buf_create_from_str(name)); - resolve_top_level_decl(codegen, tld, false); + resolve_top_level_decl(codegen, tld, false, nullptr); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; ConstExprValue *var_value = tld_var->var->value; @@ -10032,7 +10032,7 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, auto entry = container_scope->decl_table.maybe_get(field_name); Tld *tld = entry ? entry->value : nullptr; if (tld && tld->id == TldIdFn) { - resolve_top_level_decl(ira->codegen, tld, false); + resolve_top_level_decl(ira->codegen, tld, false, field_ptr_instruction->base.source_node); if (tld->resolution == TldResolutionInvalid) return ira->codegen->builtin_types.entry_invalid; TldFn *tld_fn = (TldFn *)tld; @@ -10117,7 +10117,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) { bool pointer_only = false; - resolve_top_level_decl(ira->codegen, tld, pointer_only); + resolve_top_level_decl(ira->codegen, tld, pointer_only, source_instruction->source_node); if (tld->resolution == TldResolutionInvalid) return ira->codegen->builtin_types.entry_invalid; @@ -10539,7 +10539,7 @@ static TypeTableEntry *ir_analyze_instruction_set_global_align(IrAnalyze *ira, Tld *tld = instruction->tld; IrInstruction *align_value = instruction->value->other; - resolve_top_level_decl(ira->codegen, tld, true); + resolve_top_level_decl(ira->codegen, tld, true, instruction->base.source_node); if (tld->resolution == TldResolutionInvalid) return ira->codegen->builtin_types.entry_invalid; @@ -10602,7 +10602,7 @@ static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira, Tld *tld = instruction->tld; IrInstruction *section_value = instruction->value->other; - resolve_top_level_decl(ira->codegen, tld, true); + resolve_top_level_decl(ira->codegen, tld, true, instruction->base.source_node); if (tld->resolution == TldResolutionInvalid) return ira->codegen->builtin_types.entry_invalid; @@ -11932,7 +11932,19 @@ static TypeTableEntry *ir_analyze_instruction_compile_err(IrAnalyze *ira, if (!msg_buf) return ira->codegen->builtin_types.entry_invalid; - ir_add_error(ira, &instruction->base, msg_buf); + ErrorMsg *msg = ir_add_error(ira, &instruction->base, msg_buf); + size_t i = ira->codegen->tld_ref_source_node_stack.length; + for (;;) { + if (i == 0) + break; + i -= 1; + AstNode *source_node = ira->codegen->tld_ref_source_node_stack.at(i); + if (source_node) { + add_error_note(ira->codegen, msg, source_node, + buf_sprintf("referenced here")); + } + } + return ira->codegen->builtin_types.entry_invalid; } @@ -13454,7 +13466,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira, Tld *tld = instruction->tld; LVal lval = instruction->lval; - resolve_top_level_decl(ira->codegen, tld, lval.is_ptr); + resolve_top_level_decl(ira->codegen, tld, lval.is_ptr, instruction->base.source_node); if (tld->resolution == TldResolutionInvalid) return ira->codegen->builtin_types.entry_invalid; diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig index 3afae1096b..3d15fe9c59 100644 --- a/std/special/bootstrap.zig +++ b/std/special/bootstrap.zig @@ -8,7 +8,8 @@ const builtin = @import("builtin"); const want_main_symbol = std.target.linking_libc; const want_start_symbol = !want_main_symbol; -const exit = std.os.posix.exit; +const posix_exit = std.os.posix.exit; +extern fn ExitProcess(exit_code: c_uint) -> noreturn; var argc_ptr: &usize = undefined; @@ -34,8 +35,16 @@ fn callMainAndExit() -> noreturn { const argc = *argc_ptr; const argv = @ptrCast(&&u8, &argc_ptr[1]); const envp = @ptrCast(&?&u8, &argv[argc + 1]); - callMain(argc, argv, envp) %% exit(1); - exit(0); + callMain(argc, argv, envp) %% exit(true); + exit(false); +} + +fn exit(failure: bool) -> noreturn { + if (builtin.os == builtin.Os.windows) { + ExitProcess(c_uint(failure)); + } else { + posix_exit(i32(failure)); + } } fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index d67f474fb7..fd07dbb2b1 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1916,4 +1916,18 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\} , ".tmp_source.zig:7:9: error: calling a generic function requires compile-time known function value"); + + cases.add("@compileError shows traceback of references that caused it", + \\const foo = @compileError("aoeu"); + \\ + \\const bar = baz + foo; + \\const baz = 1; + \\ + \\export fn entry() -> i32 { + \\ return bar; + \\} + , + ".tmp_source.zig:1:13: error: aoeu", + ".tmp_source.zig:3:19: note: referenced here", + ".tmp_source.zig:7:12: note: referenced here"); }