zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 6b74fd2e12b117e90197db5f4fa1ea51aa246248 (tree)
parent 59a243ce24e858260d289c5c40f3430223b7d98b
Author: LemonBoy <thatlemon@gmail.com>
Date:   Sun, 16 Feb 2020 20:19:30 +0100

ir: Avoid invalidating the decl_table iterator

Collect the declarations to resolve first and run resolve_top_level_decl
on them later.

Closes #4310

Diffstat:
Msrc/ir.cpp | 43+++++++++++++++++++++++++++++++------------
Mtest/compile_errors.zig | 10+++++-----
2 files changed, 36 insertions(+), 17 deletions(-)

diff --git 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<Tld*> 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,16 +23669,36 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa return ErrorSemanticAnalyzeFail; } + // If the declaration is unresolved, force it to be resolved again. + if (curr_entry->value->resolution == TldResolutionUnresolved) + resolve_decl_queue.append(curr_entry->value); + } + + 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) { - if (curr_entry->value->id == TldIdFn) { - ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; - if (fn_entry->is_test) - continue; - } + if (curr_entry->value->id == TldIdCompTime) + continue; - declaration_count += 1; + 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<ZigValue>(); diff --git 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",