diff --git a/README.md b/README.md index 7099c1baa7..4bb149bbc5 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,6 @@ make ## Roadmap * parseh: unreachable <--> noreturn attribute - * error for extern function with void parameter * unused label error * loops * structs diff --git a/src/analyze.cpp b/src/analyze.cpp index 3bad09a4d9..82d37de109 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -115,7 +115,16 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { AstNode *child = node->data.fn_proto.params.at(i); assert(child->type == NodeTypeParamDecl); - resolve_type(g, child->data.param_decl.type); + TypeTableEntry *type_entry = resolve_type(g, child->data.param_decl.type); + if (type_entry == g->builtin_types.entry_unreachable) { + add_node_error(g, child->data.param_decl.type, + buf_sprintf("parameter of type 'unreachable' not allowed")); + } else if (type_entry == g->builtin_types.entry_void) { + if (node->data.fn_proto.visib_mod == FnProtoVisibModExport) { + add_node_error(g, child->data.param_decl.type, + buf_sprintf("parameter of type 'void' not allowed on exported functions")); + } + } } resolve_type(g, node->data.fn_proto.return_type); @@ -423,18 +432,18 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, resolve_type(g, variable_declaration->type) : nullptr; if (explicit_type == g->builtin_types.entry_unreachable) { add_node_error(g, variable_declaration->type, - buf_sprintf("variable of type 'unreachable' is not allowed.")); + buf_sprintf("variable of type 'unreachable' not allowed")); } TypeTableEntry *implicit_type = variable_declaration->expr != nullptr ? analyze_expression(g, import, context, explicit_type, variable_declaration->expr) : nullptr; if (implicit_type == g->builtin_types.entry_unreachable) { add_node_error(g, node, - buf_sprintf("variable initialization is unreachable.")); + buf_sprintf("variable initialization is unreachable")); } if (implicit_type == nullptr) { - add_node_error(g, node, buf_sprintf("initial values are required for variable declaration.")); + add_node_error(g, node, buf_sprintf("initial values are required for variable declaration")); } TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type; @@ -443,7 +452,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, LocalVariableTableEntry *existing_variable = find_local_variable(context, &variable_declaration->symbol); if (existing_variable) { add_node_error(g, node, - buf_sprintf("redeclaration of variable '%s'.", buf_ptr(&variable_declaration->symbol))); + buf_sprintf("redeclaration of variable '%s'", buf_ptr(&variable_declaration->symbol))); } else { LocalVariableTableEntry *variable_entry = allocate(1); buf_init_from_buf(&variable_entry->name, &variable_declaration->symbol); @@ -723,11 +732,6 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, assert(param_decl->type->type == NodeTypeType); TypeTableEntry *type = param_decl->type->codegen_node->data.type_node.entry; - if (type == g->builtin_types.entry_unreachable) { - add_node_error(g, param_decl->type, - buf_sprintf("parameter of type 'unreachable' is not allowed.")); - } - LocalVariableTableEntry *variable_entry = allocate(1); buf_init_from_buf(&variable_entry->name, ¶m_decl->name); variable_entry->type = type; diff --git a/src/errmsg.cpp b/src/errmsg.cpp index 00557e0214..e2722f8d50 100644 --- a/src/errmsg.cpp +++ b/src/errmsg.cpp @@ -19,7 +19,9 @@ void print_err_msg(ErrorMsg *err, ErrColor color) { assert(err->line_offsets); int line_start_offset = err->line_offsets->at(err->line_start); - int line_end_offset = err->line_offsets->at(err->line_start + 1); + int end_line = err->line_start + 1; + int line_end_offset = (end_line >= err->line_offsets->length) ? + buf_len(err->source) : err->line_offsets->at(err->line_start + 1); fwrite(buf_ptr(err->source) + line_start_offset, 1, line_end_offset - line_start_offset - 1, stderr); fprintf(stderr, "\n"); diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 6d32322ede..14840b76b5 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -418,20 +418,20 @@ fn b() {} add_compile_fail_case("parameter redeclaration", R"SOURCE( fn f(a : i32, a : i32) { } - )SOURCE", 1, ".tmp_source.zig:2:1: error: redeclaration of parameter 'a'."); + )SOURCE", 1, ".tmp_source.zig:2:1: error: redeclaration of parameter 'a'"); add_compile_fail_case("local variable redeclaration", R"SOURCE( fn f() { let a : i32 = 0; let a = 0; } - )SOURCE", 1, ".tmp_source.zig:4:5: error: redeclaration of variable 'a'."); + )SOURCE", 1, ".tmp_source.zig:4:5: error: redeclaration of variable 'a'"); add_compile_fail_case("local variable redeclares parameter", R"SOURCE( fn f(a : i32) { let a = 0; } - )SOURCE", 1, ".tmp_source.zig:3:5: error: redeclaration of variable 'a'."); + )SOURCE", 1, ".tmp_source.zig:3:5: error: redeclaration of variable 'a'"); add_compile_fail_case("variable has wrong type", R"SOURCE( fn f() -> i32 { @@ -450,17 +450,21 @@ fn f() { fn f() { let a = return; } - )SOURCE", 1, ".tmp_source.zig:3:5: error: variable initialization is unreachable."); + )SOURCE", 1, ".tmp_source.zig:3:5: error: variable initialization is unreachable"); add_compile_fail_case("unreachable variable", R"SOURCE( fn f() { let a : unreachable = return; } - )SOURCE", 1, ".tmp_source.zig:3:13: error: variable of type 'unreachable' is not allowed."); + )SOURCE", 1, ".tmp_source.zig:3:13: error: variable of type 'unreachable' not allowed"); add_compile_fail_case("unreachable parameter", R"SOURCE( fn f(a : unreachable) {} - )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' is not allowed."); + )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed"); + + add_compile_fail_case("exporting a void parameter", R"SOURCE( +export fn f(a : void) {} + )SOURCE", 1, ".tmp_source.zig:2:17: error: parameter of type 'void' not allowed on exported functions"); }