From 6b74fd2e12b117e90197db5f4fa1ea51aa246248 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 16 Feb 2020 20:19:30 +0100 Subject: [PATCH] ir: Avoid invalidating the decl_table iterator Collect the declarations to resolve first and run resolve_top_level_decl on them later. Closes #4310 --- src/ir.cpp | 45 +++++++++++++++++++++++++++++------------ test/compile_errors.zig | 10 ++++----- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index a29a5b6948..8544fe1758 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -23653,14 +23653,13 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa if ((err = type_resolve(ira->codegen, type_info_fn_decl_inline_type, ResolveStatusSizeKnown))) return err; - // Loop through our declarations once to figure out how many declarations we will generate info for. + // The unresolved declarations are collected in a separate queue to avoid + // modifying decl_table while iterating over it + ZigList resolve_decl_queue{}; + auto decl_it = decls_scope->decl_table.entry_iterator(); decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr; - int declaration_count = 0; - while ((curr_entry = decl_it.next()) != nullptr) { - // If the declaration is unresolved, force it to be resolved again. - resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false); if (curr_entry->value->resolution == TldResolutionInvalid) { return ErrorSemanticAnalyzeFail; } @@ -23670,18 +23669,38 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa return ErrorSemanticAnalyzeFail; } - // Skip comptime blocks and test functions. - if (curr_entry->value->id != TldIdCompTime) { - if (curr_entry->value->id == TldIdFn) { - ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; - if (fn_entry->is_test) - continue; - } + // If the declaration is unresolved, force it to be resolved again. + if (curr_entry->value->resolution == TldResolutionUnresolved) + resolve_decl_queue.append(curr_entry->value); + } - declaration_count += 1; + for (size_t i = 0; i < resolve_decl_queue.length; i++) { + Tld *decl = resolve_decl_queue.at(i); + resolve_top_level_decl(ira->codegen, decl, decl->source_node, false); + if (decl->resolution == TldResolutionInvalid) { + return ErrorSemanticAnalyzeFail; } } + resolve_decl_queue.deinit(); + + // Loop through our declarations once to figure out how many declarations we will generate info for. + int declaration_count = 0; + decl_it = decls_scope->decl_table.entry_iterator(); + while ((curr_entry = decl_it.next()) != nullptr) { + // Skip comptime blocks and test functions. + if (curr_entry->value->id == TldIdCompTime) + continue; + + if (curr_entry->value->id == TldIdFn) { + ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; + if (fn_entry->is_test) + continue; + } + + declaration_count += 1; + } + ZigValue *declaration_array = ira->codegen->pass1_arena->create(); declaration_array->special = ConstValSpecialStatic; declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count, nullptr); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 6d46afc979..febc936486 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3,13 +3,13 @@ const builtin = @import("builtin"); const Target = @import("std").Target; pub fn addCases(cases: *tests.CompileErrorContext) void { - cases.addTest("access of undefined pointer to array", - \\const ram_u32: *[4096]u32 = undefined; - \\export fn entry() void { - \\ @ptrCast(*u32, &(ram_u32[0])) = &(ram_u32[0]); + cases.addTest("", + \\const A = B; + \\test "Crash" { + \\ _ = @typeInfo(@This()).Struct.decls; \\} , &[_][]const u8{ - "tmp.zig:3:29: error: use of undefined value here causes undefined behavior", + "tmp.zig:1:11: error: use of undeclared identifier 'B'", }); cases.addTest("duplicate field in anonymous struct literal",