From 36409c74f9e6b61b88a979c72a5d53b744a27605 Mon Sep 17 00:00:00 2001 From: Evan Haas Date: Tue, 29 Dec 2020 11:07:04 -0800 Subject: [PATCH] Static function declarations with no prototype should not be variadic If a static function is defined with no argument list and no prototype is given, it should be treated as a function that takes no arguments rather than as a variadic function. Fixes #7594 --- src/translate_c.zig | 3 +-- test/run_translated_c.zig | 30 ++++++++++++++++++++++++++++++ test/translate_c.zig | 10 +++++++++- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/translate_c.zig b/src/translate_c.zig index 1b2aa4b2195d..21e9a25cd725 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -2168,7 +2168,6 @@ fn transCCast( // @boolToInt returns either a comptime_int or a u1 // TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast // instead of @as - const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1); builtin_node.params()[0] = expr; builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); @@ -5027,7 +5026,7 @@ fn transFnNoProto( is_pub: bool, ) !*ast.Node.FnProto { const cc = try transCC(rp, fn_ty, source_loc); - const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true; + const is_var_args = if (fn_decl_context) |ctx| (!ctx.is_export and ctx.storage_class != .Static) else true; return finishTransFnProto(rp, null, null, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub); } diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index 632601b70cc8..4fbb4b2a1ab0 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -657,4 +657,34 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { \\ return 0; \\} , ""); + + cases.add("static K&R-style no prototype function declaration (empty parameter list)", + \\#include + \\static int foo() { + \\ return 42; + \\} + \\int main() { + \\ if (foo() != 42) abort(); + \\ return 0; + \\} + , ""); + + cases.add("K&R-style static function prototype for unused function", + \\static int foo(); + \\int main() { + \\ return 0; + \\} + , ""); + + cases.add("K&R-style static function prototype + separate definition", + \\#include + \\static int foo(); + \\static int foo(int a, int b) { + \\ return a + b; + \\} + \\int main() { + \\ if (foo(40, 2) != 42) abort(); + \\ return 0; + \\} + , ""); } diff --git a/test/translate_c.zig b/test/translate_c.zig index 60f3d0e2c5da..6ebe27c0a795 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1375,11 +1375,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\void b(void) {} \\void c(); \\void d(void); + \\static void e() {} + \\static void f(void) {} + \\static void g(); + \\static void h(void); , &[_][]const u8{ \\pub export fn a() void {} \\pub export fn b() void {} \\pub extern fn c(...) void; \\pub extern fn d() void; + \\pub fn e() callconv(.C) void {} + \\pub fn f() callconv(.C) void {} + \\pub extern fn g() void; + \\pub extern fn h() void; }); cases.add("variable declarations", @@ -2938,7 +2946,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub fn a() callconv(.C) void {} \\pub fn b() callconv(.C) void {} \\pub export fn c() void {} - \\pub fn foo(...) callconv(.C) void {} + \\pub fn foo() callconv(.C) void {} }); cases.add("casting away const and volatile",