Skip to content

Commit 6b74fd2

Browse files
committed
ir: Avoid invalidating the decl_table iterator
Collect the declarations to resolve first and run resolve_top_level_decl on them later. Closes #4310
1 parent 59a243c commit 6b74fd2

File tree

2 files changed

+36
-17
lines changed

2 files changed

+36
-17
lines changed

src/ir.cpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23653,14 +23653,13 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa
2365323653
if ((err = type_resolve(ira->codegen, type_info_fn_decl_inline_type, ResolveStatusSizeKnown)))
2365423654
return err;
2365523655

23656-
// Loop through our declarations once to figure out how many declarations we will generate info for.
23656+
// The unresolved declarations are collected in a separate queue to avoid
23657+
// modifying decl_table while iterating over it
23658+
ZigList<Tld*> resolve_decl_queue{};
23659+
2365723660
auto decl_it = decls_scope->decl_table.entry_iterator();
2365823661
decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr;
23659-
int declaration_count = 0;
23660-
2366123662
while ((curr_entry = decl_it.next()) != nullptr) {
23662-
// If the declaration is unresolved, force it to be resolved again.
23663-
resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false);
2366423663
if (curr_entry->value->resolution == TldResolutionInvalid) {
2366523664
return ErrorSemanticAnalyzeFail;
2366623665
}
@@ -23670,16 +23669,36 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa
2367023669
return ErrorSemanticAnalyzeFail;
2367123670
}
2367223671

23672+
// If the declaration is unresolved, force it to be resolved again.
23673+
if (curr_entry->value->resolution == TldResolutionUnresolved)
23674+
resolve_decl_queue.append(curr_entry->value);
23675+
}
23676+
23677+
for (size_t i = 0; i < resolve_decl_queue.length; i++) {
23678+
Tld *decl = resolve_decl_queue.at(i);
23679+
resolve_top_level_decl(ira->codegen, decl, decl->source_node, false);
23680+
if (decl->resolution == TldResolutionInvalid) {
23681+
return ErrorSemanticAnalyzeFail;
23682+
}
23683+
}
23684+
23685+
resolve_decl_queue.deinit();
23686+
23687+
// Loop through our declarations once to figure out how many declarations we will generate info for.
23688+
int declaration_count = 0;
23689+
decl_it = decls_scope->decl_table.entry_iterator();
23690+
while ((curr_entry = decl_it.next()) != nullptr) {
2367323691
// Skip comptime blocks and test functions.
23674-
if (curr_entry->value->id != TldIdCompTime) {
23675-
if (curr_entry->value->id == TldIdFn) {
23676-
ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
23677-
if (fn_entry->is_test)
23678-
continue;
23679-
}
23692+
if (curr_entry->value->id == TldIdCompTime)
23693+
continue;
2368023694

23681-
declaration_count += 1;
23695+
if (curr_entry->value->id == TldIdFn) {
23696+
ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
23697+
if (fn_entry->is_test)
23698+
continue;
2368223699
}
23700+
23701+
declaration_count += 1;
2368323702
}
2368423703

2368523704
ZigValue *declaration_array = ira->codegen->pass1_arena->create<ZigValue>();

test/compile_errors.zig

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ const builtin = @import("builtin");
33
const Target = @import("std").Target;
44

55
pub fn addCases(cases: *tests.CompileErrorContext) void {
6-
cases.addTest("access of undefined pointer to array",
7-
\\const ram_u32: *[4096]u32 = undefined;
8-
\\export fn entry() void {
9-
\\ @ptrCast(*u32, &(ram_u32[0])) = &(ram_u32[0]);
6+
cases.addTest("",
7+
\\const A = B;
8+
\\test "Crash" {
9+
\\ _ = @typeInfo(@This()).Struct.decls;
1010
\\}
1111
, &[_][]const u8{
12-
"tmp.zig:3:29: error: use of undefined value here causes undefined behavior",
12+
"tmp.zig:1:11: error: use of undeclared identifier 'B'",
1313
});
1414

1515
cases.addTest("duplicate field in anonymous struct literal",

0 commit comments

Comments
 (0)