]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: explicitly use void for functions with no parameters
authorMauri de Souza Meneguzzo <mauri870@gmail.com>
Mon, 17 Feb 2025 13:57:12 +0000 (13:57 +0000)
committerGopher Robot <gobot@golang.org>
Tue, 18 Feb 2025 17:27:34 +0000 (09:27 -0800)
Currently, exported Go functions with no parameters generate C functions
with an empty parameter list. In C, a function with an empty parameter
list can accept any number of arguments, whereas a function with a single
void parameter explicitly declares that it takes no arguments.

To align the generated C functions with their Go prototypes, update the
code generation to explicitly include a void parameter for functions
with no parameters.

Fixes #68411

Change-Id: Iab9456aa0236200bf21d1181a2e18e82869df63f
GitHub-Last-Rev: 6ff21a98dfef81df649c76221d9c0858dc0e35e1
GitHub-Pull-Request: golang/go#70981
Reviewed-on: https://go-review.googlesource.com/c/go/+/638635
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/cmd/cgo/internal/testcshared/cshared_test.go
src/cmd/cgo/internal/testcshared/testdata/issue68411/issue68411.go [new file with mode: 0644]
src/cmd/cgo/out.go

index 7e9a274d05628ee3114f3881f3da3259dce6a23a..9fe5e791feb16f94092246fabd40801d5c6c65dc 100644 (file)
@@ -880,3 +880,44 @@ func TestIssue36233(t *testing.T) {
                t.Error("missing functions")
        }
 }
+
+func TestIssue68411(t *testing.T) {
+       globalSkip(t)
+       testenv.MustHaveCGO(t)
+
+       t.Parallel()
+
+       // Test that the export header uses a void function parameter for
+       // exported Go functions with no parameters.
+
+       tmpdir := t.TempDir()
+
+       const exportHeader = "issue68411.h"
+
+       run(t, nil, "go", "tool", "cgo", "-exportheader", exportHeader, "-objdir", tmpdir, "./issue68411/issue68411.go")
+       data, err := os.ReadFile(exportHeader)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       funcs := []struct{ name, signature string }{
+               {"exportFuncWithNoParams", "void exportFuncWithNoParams(void)"},
+               {"exportFuncWithParams", "exportFuncWithParams(GoInt a, GoInt b)"},
+       }
+
+       var found int
+       for line := range bytes.Lines(data) {
+               for _, fn := range funcs {
+                       if bytes.Contains(line, []byte(fn.name)) {
+                               found++
+                               if !bytes.Contains(line, []byte(fn.signature)) {
+                                       t.Errorf("function signature mismatch; got %q, want %q", line, fn.signature)
+                               }
+                       }
+               }
+       }
+
+       if found != len(funcs) {
+               t.Error("missing functions")
+       }
+}
diff --git a/src/cmd/cgo/internal/testcshared/testdata/issue68411/issue68411.go b/src/cmd/cgo/internal/testcshared/testdata/issue68411/issue68411.go
new file mode 100644 (file)
index 0000000..6a2be8b
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "C"
+
+//export exportFuncWithNoParams
+func exportFuncWithNoParams() {}
+
+//export exportFuncWithParams
+func exportFuncWithParams(a, b int) {}
+
+func main() {}
index 9e65dcbef7295c922c17801d650d164101f54402..43c30a200039a76363a26e4f756aa842a580c0aa 100644 (file)
@@ -1015,13 +1015,18 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
                        s.WriteString(p.cgoType(fn.Recv.List[0].Type).C.String())
                        s.WriteString(" recv")
                }
-               forFieldList(fntype.Params,
-                       func(i int, aname string, atype ast.Expr) {
-                               if i > 0 || fn.Recv != nil {
-                                       s.WriteString(", ")
-                               }
-                               fmt.Fprintf(&s, "%s %s", p.cgoType(atype).C, exportParamName(aname, i))
-                       })
+
+               if len(fntype.Params.List) > 0 {
+                       forFieldList(fntype.Params,
+                               func(i int, aname string, atype ast.Expr) {
+                                       if i > 0 || fn.Recv != nil {
+                                               s.WriteString(", ")
+                                       }
+                                       fmt.Fprintf(&s, "%s %s", p.cgoType(atype).C, exportParamName(aname, i))
+                               })
+               } else {
+                       s.WriteString("void")
+               }
                s.WriteByte(')')
 
                if len(exp.Doc) > 0 {