From: Mauri de Souza Meneguzzo Date: Mon, 17 Feb 2025 13:57:12 +0000 (+0000) Subject: cmd/cgo: explicitly use void for functions with no parameters X-Git-Tag: go1.25rc1~998 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=896de17f8069626f8e52b662c0d5a46ee9cac699;p=gostls13.git cmd/cgo: explicitly use void for functions with no parameters 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 Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor --- diff --git a/src/cmd/cgo/internal/testcshared/cshared_test.go b/src/cmd/cgo/internal/testcshared/cshared_test.go index 7e9a274d05..9fe5e791fe 100644 --- a/src/cmd/cgo/internal/testcshared/cshared_test.go +++ b/src/cmd/cgo/internal/testcshared/cshared_test.go @@ -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 index 0000000000..6a2be8b53c --- /dev/null +++ b/src/cmd/cgo/internal/testcshared/testdata/issue68411/issue68411.go @@ -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() {} diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 9e65dcbef7..43c30a2000 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -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 {