Commit 5cc131030c

Evan Haas <evan@lagerdata.com>
2020-12-29 20:07:04
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
1 parent 5aac2fc
src/translate_c.zig
@@ -5027,7 +5027,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);
 }
 
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 <stdlib.h>
+        \\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 <stdlib.h>
+        \\static int foo();
+        \\static int foo(int a, int b) {
+        \\    return a + b;
+        \\}
+        \\int main() {
+        \\    if (foo(40, 2) != 42) abort();
+        \\    return 0;
+        \\}
+    , "");
 }
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",