diff --git a/doc/langref.html.in b/doc/langref.html.in index 47f13f9e05..71f97b3f06 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -7399,7 +7399,7 @@ comptime { @export(internalName, .{ .name = "foo", .linkage = .Strong }); } -extern fn internalName() void {} +fn internalName() callconv(.C) void {} {#code_end#}
This is equivalent to:
{#code_begin|obj#} diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 28bf0c9ed5..5f28dd3b06 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -92,10 +92,12 @@ test "zig fmt: convert extern/nakedcc/stdcallcc into callconv(...)" { \\nakedcc fn foo1() void {} \\stdcallcc fn foo2() void {} \\extern fn foo3() void {} + \\extern "mylib" fn foo4() void {} , \\fn foo1() callconv(.Naked) void {} \\fn foo2() callconv(.Stdcall) void {} \\fn foo3() callconv(.C) void {} + \\fn foo4() callconv(.C) void {} \\ ); } diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index e322a91dc4..069635d42e 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1396,6 +1396,7 @@ fn renderExpression( try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export } else { cc_rewrite_str = ".C"; + fn_proto.lib_name = null; } } diff --git a/src/parser.cpp b/src/parser.cpp index c8c53e81b7..275fa90167 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -689,6 +689,9 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B AstNode *res = fn_proto; if (body != nullptr) { + if (fn_proto->data.fn_proto.is_extern) { + ast_error(pc, first, "Extern functions have no body"); + } res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); res->data.fn_def.fn_proto = fn_proto; res->data.fn_def.body = body; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 2c52ee2c67..c5f5b6f9da 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3,15 +3,23 @@ const builtin = @import("builtin"); const Target = @import("std").Target; pub fn addCases(cases: *tests.CompileErrorContext) void { - cases.addTest("", + cases.addTest("access invalid @typeInfo decl", \\const A = B; \\test "Crash" { - \\ _ = @typeInfo(@This()).Struct.decls; + \\ _ = @typeInfo(@This()).Struct.decls[0]; \\} , &[_][]const u8{ "tmp.zig:1:11: error: use of undeclared identifier 'B'", }); + cases.addTest("reject extern function definitions with body", + \\extern "c" fn definitelyNotInLibC(a: i32, b: i32) i32 { + \\ return a + b; + \\} + , &[_][]const u8{ + "tmp.zig:1:1: error: Extern functions have no body", + }); + cases.addTest("duplicate field in anonymous struct literal", \\export fn entry() void { \\ const anon = .{