From a2afcae9ff1f2eed5c6a19a2bd63af288b9171ad Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 25 Nov 2017 18:16:33 -0500 Subject: [PATCH] fix crash when constant inside comptime function has compile error closes #625 --- src/all_types.hpp | 3 +++ src/ir.cpp | 27 +++++++++++++++++++++++---- test/compile_errors.zig | 19 +++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 2b09131be..2fccf08e8 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -36,6 +36,7 @@ struct IrInstructionCast; struct IrBasicBlock; struct ScopeDecls; struct ZigWindowsSDK; +struct Tld; struct IrGotoItem { AstNode *source_node; @@ -59,7 +60,9 @@ struct IrExecutable { Buf *c_import_buf; AstNode *source_node; IrExecutable *parent_exec; + IrExecutable *source_exec; Scope *begin_scope; + ZigList tld_list; }; enum OutType { diff --git a/src/ir.cpp b/src/ir.cpp index a58374dc8..f632a261f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -6332,6 +6332,9 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, } irb->codegen->resolve_queue.append(&tld_container->base); + // Add this to the list to mark as invalid if analyzing this exec fails. + irb->exec->tld_list.append(&tld_container->base); + return ir_build_const_type(irb, parent_scope, node, container_type); } @@ -6554,6 +6557,20 @@ static bool ir_goto_pass2(IrBuilder *irb) { return true; } +static void invalidate_exec(IrExecutable *exec) { + if (exec->invalid) + return; + + exec->invalid = true; + + for (size_t i = 0; i < exec->tld_list.length; i += 1) { + exec->tld_list.items[i]->resolution = TldResolutionInvalid; + } + + if (exec->source_exec != nullptr) + invalidate_exec(exec->source_exec); +} + bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_executable) { assert(node->owner); @@ -6577,7 +6594,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec } if (!ir_goto_pass2(irb)) { - irb->exec->invalid = true; + invalidate_exec(ir_executable); return false; } @@ -6603,7 +6620,7 @@ static void add_call_stack_errors(CodeGen *codegen, IrExecutable *exec, ErrorMsg } static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg) { - exec->invalid = true; + invalidate_exec(exec); ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); if (exec->parent_exec) { add_call_stack_errors(codegen, exec, err_msg, 10); @@ -8056,6 +8073,7 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node IrExecutable analyzed_executable = {0}; analyzed_executable.source_node = source_node; analyzed_executable.parent_exec = parent_exec; + analyzed_executable.source_exec = &ir_executable; analyzed_executable.name = exec_name; analyzed_executable.is_inline = true; analyzed_executable.fn_entry = fn_entry; @@ -10490,10 +10508,11 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec); - if (type_is_invalid(result->value.type)) - return ira->codegen->builtin_types.entry_invalid; ira->codegen->memoized_fn_eval_table.put(exec_scope, result); + + if (type_is_invalid(result->value.type)) + return ira->codegen->builtin_types.entry_invalid; } ConstExprValue *out_val = ir_build_const_from(ira, &call_instruction->base); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 9e1533375..3ef4a63e5 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2343,4 +2343,23 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\pub extern fn foo(format: &const u8, ...); , ".tmp_source.zig:2:9: error: expected type '&const u8', found '[5]u8'"); + + cases.add("constant inside comptime function has compile error", + \\const ContextAllocator = MemoryPool(usize); + \\ + \\pub fn MemoryPool(comptime T: type) -> type { + \\ const free_list_t = @compileError("aoeu"); + \\ + \\ struct { + \\ free_list: free_list_t, + \\ } + \\} + \\ + \\export fn entry() { + \\ var allocator: ContextAllocator = undefined; + \\} + , + ".tmp_source.zig:4:25: error: aoeu", + ".tmp_source.zig:1:36: note: called from here", + ".tmp_source.zig:12:20: note: referenced here"); }