From 8d9b8ab930d8633b9e9e77a80a36fa08a5e7f3f5 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 23 Jan 2020 22:40:12 +0100 Subject: [PATCH] More error checking for unresolved TLDs Closes #4274 --- src/ir.cpp | 44 ++++++++++++++++++++++++++--------------- test/compile_errors.zig | 6 ++++++ 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index db1faac37c..808bc2e90b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -264,6 +264,7 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type); static ResultLoc *no_result_loc(void); static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value); +static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *source_instr); static void destroy_instruction(IrInstruction *inst) { #ifdef ZIG_ENABLE_MEM_PROFILE @@ -20022,8 +20023,13 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira, resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false); if (tld->resolution == TldResolutionInvalid) return ira->codegen->invalid_instruction; + if (tld->resolution == TldResolutionResolving) + return ir_error_dependency_loop(ira, source_instr); + TldFn *tld_fn = (TldFn *)tld; ZigFn *fn_entry = tld_fn->fn_entry; + assert(fn_entry != nullptr); + if (type_is_invalid(fn_entry->type_entry)) return ira->codegen->invalid_instruction; @@ -20034,8 +20040,13 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira, resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false); if (tld->resolution == TldResolutionInvalid) return ira->codegen->invalid_instruction; + if (tld->resolution == TldResolutionResolving) + return ir_error_dependency_loop(ira, source_instr); + TldVar *tld_var = (TldVar *)tld; ZigVar *var = tld_var->var; + assert(var != nullptr); + if (type_is_invalid(var->var_type)) return ira->codegen->invalid_instruction; @@ -20369,9 +20380,10 @@ static IrInstruction *ir_error_dependency_loop(IrAnalyze *ira, IrInstruction *so static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) { resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node, true); - if (tld->resolution == TldResolutionInvalid) { + if (tld->resolution == TldResolutionInvalid) return ira->codegen->invalid_instruction; - } + if (tld->resolution == TldResolutionResolving) + return ir_error_dependency_loop(ira, source_instruction); switch (tld->id) { case TldIdContainer: @@ -20381,9 +20393,8 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_ case TldIdVar: { TldVar *tld_var = (TldVar *)tld; ZigVar *var = tld_var->var; - if (var == nullptr) { - return ir_error_dependency_loop(ira, source_instruction); - } + assert(var != nullptr); + if (tld_var->extern_lib_name != nullptr) { add_link_lib_symbol(ira, tld_var->extern_lib_name, buf_create_from_str(var->name), source_instruction->source_node); @@ -20394,7 +20405,7 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_ case TldIdFn: { TldFn *tld_fn = (TldFn *)tld; ZigFn *fn_entry = tld_fn->fn_entry; - assert(fn_entry->type_entry); + assert(fn_entry->type_entry != nullptr); if (type_is_invalid(fn_entry->type_entry)) return ira->codegen->invalid_instruction; @@ -22628,11 +22639,14 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr while ((curr_entry = decl_it.next()) != nullptr) { // If the declaration is unresolved, force it to be resolved again. - if (curr_entry->value->resolution == TldResolutionUnresolved) { - resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false); - if (curr_entry->value->resolution != TldResolutionOk) { - return ErrorSemanticAnalyzeFail; - } + resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false); + if (curr_entry->value->resolution == TldResolutionInvalid) { + return ErrorSemanticAnalyzeFail; + } + + if (curr_entry->value->resolution == TldResolutionResolving) { + ir_error_dependency_loop(ira, source_instr); + return ErrorSemanticAnalyzeFail; } // Skip comptime blocks and test functions. @@ -22689,6 +22703,8 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr case TldIdVar: { ZigVar *var = ((TldVar *)curr_entry->value)->var; + assert(var != nullptr); + if ((err = type_resolve(ira->codegen, var->const_value->type, ResolveStatusSizeKnown))) return ErrorSemanticAnalyzeFail; @@ -22719,11 +22735,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; assert(!fn_entry->is_test); - - if (fn_entry->type_entry == nullptr) { - ir_error_dependency_loop(ira, source_instr); - return ErrorSemanticAnalyzeFail; - } + assert(fn_entry->type_entry != nullptr); AstNodeFnProto *fn_node = &fn_entry->proto_node->data.fn_proto; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index be2a40d74d..ff0ad41996 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,12 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.addTest("dependency loop in top-level decl with @TypeInfo", + \\export const foo = @typeInfo(@This()); + , &[_][]const u8{ + "tmp.zig:1:20: error: dependency loop detected", + }); + cases.addTest("non-exhaustive enums", \\const A = enum { \\ a,