From bad4b040cca553ae6845b18f268313f02077f6c1 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 26 Aug 2019 18:35:36 -0400 Subject: [PATCH] miscellaneous fixes regarding compile errors --- src/all_types.hpp | 3 ++ src/analyze.cpp | 14 ++++---- src/analyze.hpp | 2 +- src/ir.cpp | 43 +++++++++++++++++++----- test/compile_errors.zig | 72 +++++++++++++++++++++-------------------- 5 files changed, 84 insertions(+), 50 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 61e71c236..3145635b4 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -363,8 +363,10 @@ struct LazyValueFnType { AstNode *proto_node; ConstExprValue **param_types; + AstNode **param_type_src_nodes; ConstExprValue *align_val; // can be null ConstExprValue *return_type; + AstNode *return_type_src_node; }; struct ConstExprValue { @@ -1026,6 +1028,7 @@ struct AstNodeEnumLiteral { struct AstNode { enum NodeType type; + bool already_traced_this_node; size_t line; size_t column; ZigType *owner; diff --git a/src/analyze.cpp b/src/analyze.cpp index b9b8cae8a..366cb5979 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -63,10 +63,11 @@ ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg) { return err; } -ErrorMsg *add_node_error(CodeGen *g, const AstNode *node, Buf *msg) { +ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { Token fake_token; fake_token.start_line = node->line; fake_token.start_column = node->column; + node->already_traced_this_node = true; return add_token_error(g, node->owner, &fake_token, msg); } @@ -1782,7 +1783,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; add_node_error(g, decl_node, - buf_sprintf("struct '%s' depends on its own size", buf_ptr(&struct_type->name))); + buf_sprintf("struct '%s' depends on itself", buf_ptr(&struct_type->name))); } return ErrorSemanticAnalyzeFail; } @@ -1936,7 +1937,7 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) { if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) { union_type->data.unionation.resolve_status = ResolveStatusInvalid; add_node_error(g, decl_node, - buf_sprintf("union '%s' depends on its own alignment", buf_ptr(&union_type->name))); + buf_sprintf("union '%s' depends on itself", buf_ptr(&union_type->name))); } return ErrorSemanticAnalyzeFail; } @@ -2047,7 +2048,7 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { if (union_type->data.unionation.resolve_status != ResolveStatusInvalid) { union_type->data.unionation.resolve_status = ResolveStatusInvalid; add_node_error(g, decl_node, - buf_sprintf("union '%s' depends on its own size", buf_ptr(&union_type->name))); + buf_sprintf("union '%s' depends on itself", buf_ptr(&union_type->name))); } return ErrorSemanticAnalyzeFail; } @@ -2452,7 +2453,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; add_node_error(g, decl_node, - buf_sprintf("struct '%s' depends on its own alignment", buf_ptr(&struct_type->name))); + buf_sprintf("struct '%s' depends on itself", buf_ptr(&struct_type->name))); } return ErrorSemanticAnalyzeFail; } @@ -3661,8 +3662,9 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool all } } - if (g->trace_err != nullptr && source_node != nullptr) { + if (g->trace_err != nullptr && source_node != nullptr && !source_node->already_traced_this_node) { g->trace_err = add_error_note(g, g->trace_err, source_node, buf_create_from_str("referenced here")); + source_node->already_traced_this_node = true; } } diff --git a/src/analyze.hpp b/src/analyze.hpp index d3c1df4a0..63ad90579 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -11,7 +11,7 @@ #include "all_types.hpp" void semantic_analyze(CodeGen *g); -ErrorMsg *add_node_error(CodeGen *g, const AstNode *node, Buf *msg); +ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg); ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg); ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg); ZigType *new_type_table_entry(ZigTypeId id); diff --git a/src/ir.cpp b/src/ir.cpp index 832983dbf..f9f64d678 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10818,6 +10818,8 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod } ConstExprValue *result = ir_exec_const_result(codegen, analyzed_executable); + if (type_is_invalid(result->type)) + return &codegen->invalid_instruction->value; if ((err = ir_resolve_const_val(codegen, analyzed_executable, node, result, undef_allowed))) return &codegen->invalid_instruction->value; @@ -14330,6 +14332,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, // since it's a comptime val there are no instructions for it. // we memcpy the init value here IrInstruction *deref = ir_get_deref(ira, var_ptr, var_ptr, nullptr); + if (type_is_invalid(deref->value.type)) { + var->var_type = ira->codegen->builtin_types.entry_invalid; + return ira->codegen->invalid_instruction; + } // If this assertion trips, something is wrong with the IR instructions, because // we expected the above deref to return a constant value, but it created a runtime // instruction. @@ -21957,6 +21963,11 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction if (slice_ptr == nullptr) return ira->codegen->invalid_instruction; + if (slice_ptr->special == ConstValSpecialUndef) { + ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined")); + return ira->codegen->invalid_instruction; + } + parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index]; if (parent_ptr->special == ConstValSpecialUndef) { ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined")); @@ -22836,6 +22847,7 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct size_t param_count = proto_node->data.fn_proto.params.length; lazy_fn_type->proto_node = proto_node; lazy_fn_type->param_types = allocate(param_count); + lazy_fn_type->param_type_src_nodes = allocate(param_count); for (size_t param_index = 0; param_index < param_count; param_index += 1) { AstNode *param_node = proto_node->data.fn_proto.params.at(param_index); @@ -22865,6 +22877,7 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct if (param_type_val == nullptr) return ira->codegen->invalid_instruction; lazy_fn_type->param_types[param_index] = param_type_val; + lazy_fn_type->param_type_src_nodes[param_index] = instruction->param_types[param_index]->source_node; } if (instruction->align_value != nullptr) { @@ -22876,6 +22889,7 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct lazy_fn_type->return_type = ir_resolve_const(ira, instruction->return_type->child, LazyOk); if (lazy_fn_type->return_type == nullptr) return ira->codegen->invalid_instruction; + lazy_fn_type->return_type_src_node = instruction->return_type->source_node; return result; } @@ -25187,7 +25201,10 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ } else { new_exec->first_err_trace_msg = ira->codegen->trace_err; } - if (new_exec->first_err_trace_msg != nullptr) { + if (new_exec->first_err_trace_msg != nullptr && + !old_instruction->source_node->already_traced_this_node) + { + old_instruction->source_node->already_traced_this_node = true; new_exec->first_err_trace_msg = add_error_note(ira->codegen, new_exec->first_err_trace_msg, old_instruction->source_node, buf_create_from_str("referenced here")); } @@ -25204,7 +25221,10 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_ if (new_exec->first_err_trace_msg != nullptr) { codegen->trace_err = new_exec->first_err_trace_msg; - if (codegen->trace_err != nullptr) { + if (codegen->trace_err != nullptr && new_exec->source_node != nullptr && + !new_exec->source_node->already_traced_this_node) + { + new_exec->source_node->already_traced_this_node = true; codegen->trace_err = add_error_note(codegen, codegen->trace_err, new_exec->source_node, buf_create_from_str("referenced here")); } @@ -25435,14 +25455,15 @@ static ZigType *ir_resolve_lazy_fn_type(CodeGen *codegen, IrExecutable *exec, As param_info->type = nullptr; return get_generic_fn_type(codegen, &fn_type_id); } else { - ZigType *param_type = ir_resolve_const_type(codegen, exec, source_node, + AstNode *param_src_node = lazy_fn_type->param_type_src_nodes[fn_type_id.next_param_index]; + ZigType *param_type = ir_resolve_const_type(codegen, exec, param_src_node, lazy_fn_type->param_types[fn_type_id.next_param_index]); if (type_is_invalid(param_type)) return nullptr; switch (type_requires_comptime(codegen, param_type)) { case ReqCompTimeYes: if (!calling_convention_allows_zig_types(fn_type_id.cc)) { - exec_add_error_node(codegen, exec, source_node, + exec_add_error_node(codegen, exec, param_src_node, buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); return nullptr; @@ -25459,7 +25480,7 @@ static ZigType *ir_resolve_lazy_fn_type(CodeGen *codegen, IrExecutable *exec, As if ((err = type_resolve(codegen, param_type, ResolveStatusZeroBitsKnown))) return nullptr; if (!type_has_bits(param_type)) { - exec_add_error_node(codegen, exec, source_node, + exec_add_error_node(codegen, exec, param_src_node, buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'", buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); return nullptr; @@ -25474,11 +25495,13 @@ static ZigType *ir_resolve_lazy_fn_type(CodeGen *codegen, IrExecutable *exec, As return nullptr; } - fn_type_id.return_type = ir_resolve_const_type(codegen, exec, source_node, lazy_fn_type->return_type); + fn_type_id.return_type = ir_resolve_const_type(codegen, exec, lazy_fn_type->return_type_src_node, + lazy_fn_type->return_type); if (type_is_invalid(fn_type_id.return_type)) return nullptr; if (fn_type_id.return_type->id == ZigTypeIdOpaque) { - exec_add_error_node(codegen, exec, source_node, buf_create_from_str("return type cannot be opaque")); + exec_add_error_node(codegen, exec, lazy_fn_type->return_type_src_node, + buf_create_from_str("return type cannot be opaque")); return nullptr; } @@ -25653,11 +25676,15 @@ static Error ir_resolve_lazy_raw(CodeGen *codegen, AstNode *source_node, ConstEx Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) { Error err; if ((err = ir_resolve_lazy_raw(codegen, source_node, val))) { - if (codegen->trace_err != nullptr) { + if (codegen->trace_err != nullptr && !source_node->already_traced_this_node) { + source_node->already_traced_this_node = true; codegen->trace_err = add_error_note(codegen, codegen->trace_err, source_node, buf_create_from_str("referenced here")); } return err; } + if (type_is_invalid(val->type)) { + return ErrorSemanticAnalyzeFail; + } return ErrorNone; } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 7e5e3dd60..49c836f6a 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -481,7 +481,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\} , "tmp.zig:1:29: error: evaluation exceeded 1000 backwards branches", - "tmp.zig:1:29: note: called from here", + "tmp.zig:1:29: note: referenced here", + "tmp.zig:5:18: note: referenced here", ); cases.add( @@ -645,7 +646,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\const A = struct { a : A, }; \\export fn entry() usize { return @sizeOf(A); } , - "tmp.zig:1:11: error: struct 'A' contains itself", + "tmp.zig:1:11: error: struct 'A' depends on itself", ); cases.add( @@ -655,7 +656,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\const C = struct { a : A, }; \\export fn entry() usize { return @sizeOf(A); } , - "tmp.zig:1:11: error: struct 'A' contains itself", + "tmp.zig:1:11: error: struct 'A' depends on itself", ); cases.add( @@ -670,7 +671,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ return @sizeOf(@typeOf(foo.x)); \\} , - "tmp.zig:1:13: error: struct 'Foo' contains itself", + "tmp.zig:1:13: error: struct 'Foo' depends on itself", "tmp.zig:8:28: note: referenced here", ); @@ -689,7 +690,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\} , "tmp.zig:7:9: error: dependency loop detected", - "tmp.zig:2:19: note: called from here", + "tmp.zig:2:19: note: referenced here", "tmp.zig:10:21: note: referenced here", ); @@ -703,7 +704,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var s: Foo = Foo.E; \\} , - "tmp.zig:1:17: error: 'Foo' depends on itself", + "tmp.zig:1:17: error: enum 'Foo' depends on itself", ); cases.add( @@ -866,7 +867,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { break :x tc; }); - cases.addTest( + cases.add( "export generic function", \\export fn foo(num: var) i32 { \\ return 0; @@ -875,17 +876,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:1:15: error: parameter of type 'var' not allowed in function with calling convention 'ccc'", ); - cases.addTest( + cases.add( "C pointer to c_void", \\export fn a() void { \\ var x: *c_void = undefined; \\ var y: [*c]c_void = x; \\} , - "tmp.zig:3:12: error: C pointers cannot point opaque types", + "tmp.zig:3:16: error: C pointers cannot point opaque types", ); - cases.addTest( + cases.add( "directly embedding opaque type in struct and union", \\const O = @OpaqueType(); \\const Foo = struct { @@ -906,7 +907,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions", ); - cases.addTest( + cases.add( "implicit cast between C pointer and Zig pointer - bad const/align/child", \\export fn a() void { \\ var x: [*c]u8 = undefined; @@ -942,7 +943,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:23:22: error: expected type '[*c]u32', found '*u8'", ); - cases.addTest( + cases.add( "implicit casting null c pointer to zig pointer", \\comptime { \\ var c_ptr: [*c]u8 = 0; @@ -952,7 +953,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:3:24: error: null pointer casted to type '*u8'", ); - cases.addTest( + cases.add( "implicit casting undefined c pointer to zig pointer", \\comptime { \\ var c_ptr: [*c]u8 = undefined; @@ -962,7 +963,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:3:24: error: use of undefined value here causes undefined behavior", ); - cases.addTest( + cases.add( "implicit casting C pointers which would mess up null semantics", \\export fn entry() void { \\ var slice: []const u8 = "aoeu"; @@ -987,7 +988,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:13:35: note: mutable '[*c]const u8' allows illegal null values stored to type '[*]u8'", ); - cases.addTest( + cases.add( "implicit casting too big integers to C pointers", \\export fn a() void { \\ var ptr: [*c]u8 = (1 << 64) + 1; @@ -1001,14 +1002,14 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:6:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'", ); - cases.addTest( + cases.add( "C pointer pointing to non C ABI compatible type or has align attr", \\const Foo = struct {}; \\export fn a() void { \\ const T = [*c]Foo; \\} , - "tmp.zig:3:15: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'", + "tmp.zig:3:19: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'", ); cases.addCase(x: { @@ -1029,7 +1030,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { break :x tc; }); - cases.addTest( + cases.add( "assign to invalid dereference", \\export fn entry() void { \\ 'a'.* = 1; @@ -1038,7 +1039,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:8: error: attempt to dereference non-pointer type 'comptime_int'", ); - cases.addTest( + cases.add( "take slice of invalid dereference", \\export fn entry() void { \\ const x = 'a'.*[0..]; @@ -1047,7 +1048,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:18: error: attempt to dereference non-pointer type 'comptime_int'", ); - cases.addTest( + cases.add( "@truncate undefined value", \\export fn entry() void { \\ var z = @truncate(u8, u16(undefined)); @@ -1935,7 +1936,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "unknown length pointer to opaque", \\export const T = [*]@OpaqueType(); , - "tmp.zig:1:18: error: unknown-length pointer to opaque", + "tmp.zig:1:21: error: unknown-length pointer to opaque", ); cases.add( @@ -2924,7 +2925,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\fn a() *noreturn {} \\export fn entry() void { _ = a(); } , - "tmp.zig:1:8: error: pointer to noreturn not allowed", + "tmp.zig:1:9: error: pointer to noreturn not allowed", ); cases.add( @@ -3606,8 +3607,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); } , "tmp.zig:5:25: error: unable to evaluate constant expression", - "tmp.zig:2:12: note: called from here", - "tmp.zig:2:8: note: called from here", + "tmp.zig:2:12: note: referenced here", + "tmp.zig:2:8: note: referenced here", ); cases.add( @@ -3701,7 +3702,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() usize { return @sizeOf(@typeOf(y)); } , "tmp.zig:3:14: error: division by zero", - "tmp.zig:1:14: note: called from here", + "tmp.zig:1:14: note: referenced here", ); cases.add( @@ -4133,7 +4134,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() usize { return @sizeOf(@typeOf(seventh_fib_number)); } , "tmp.zig:3:21: error: evaluation exceeded 1000 backwards branches", - "tmp.zig:3:21: note: called from here", + "tmp.zig:1:37: note: referenced here", + "tmp.zig:6:50: note: referenced here", ); cases.add( @@ -4174,7 +4176,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() usize { return @sizeOf(@typeOf(a)); } , "tmp.zig:6:26: error: unable to evaluate constant expression", - "tmp.zig:4:17: note: called from here", + "tmp.zig:4:17: note: referenced here", ); cases.add( @@ -4257,7 +4259,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() usize { return @sizeOf(@typeOf(y)); } , "tmp.zig:3:12: error: negation caused overflow", - "tmp.zig:1:14: note: called from here", + "tmp.zig:1:14: note: referenced here", ); cases.add( @@ -4270,7 +4272,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() usize { return @sizeOf(@typeOf(y)); } , "tmp.zig:3:14: error: operation caused overflow", - "tmp.zig:1:14: note: called from here", + "tmp.zig:1:14: note: referenced here", ); cases.add( @@ -4283,7 +4285,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() usize { return @sizeOf(@typeOf(y)); } , "tmp.zig:3:14: error: operation caused overflow", - "tmp.zig:1:14: note: called from here", + "tmp.zig:1:14: note: referenced here", ); cases.add( @@ -4296,7 +4298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() usize { return @sizeOf(@typeOf(y)); } , "tmp.zig:3:14: error: operation caused overflow", - "tmp.zig:1:14: note: called from here", + "tmp.zig:1:14: note: referenced here", ); cases.add( @@ -4388,7 +4390,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\} , "tmp.zig:3:7: error: unable to evaluate constant expression", - "tmp.zig:16:19: note: called from here", + "tmp.zig:16:19: note: referenced here", ); cases.add( @@ -4618,7 +4620,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } , "tmp.zig:2:26: error: index 1 outside argument list of size 1", - "tmp.zig:6:15: note: called from here", + "tmp.zig:6:15: note: referenced here", ); cases.add( @@ -4717,7 +4719,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\} , "tmp.zig:10:14: error: unable to evaluate constant expression", - "tmp.zig:6:20: note: called from here", + "tmp.zig:6:20: note: referenced here", ); cases.add( @@ -5864,7 +5866,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\} , "tmp.zig:4:25: error: aoeu", - "tmp.zig:1:36: note: called from here", + "tmp.zig:1:36: note: referenced here", "tmp.zig:12:20: note: referenced here", );