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")
+ }
+}
--- /dev/null
+// 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() {}
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 {