]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/cgo: add support for `any` param and return type
authorAlexandre Daubois <alex.daubois@gmail.com>
Mon, 24 Nov 2025 08:14:18 +0000 (08:14 +0000)
committerGopher Robot <gobot@golang.org>
Mon, 24 Nov 2025 19:58:55 +0000 (11:58 -0800)
When using `any` as param or return type of an exported
function, we currently have the error `unrecognized Go
type any`. `any` is an alias of `interface{}` which is
already supported.

This would avoid such change: https://github.com/php/frankenphp/pull/1976

Fixes #76340

Change-Id: I301838ff72e99ae78b035a8eff2405f6a145ed1a
GitHub-Last-Rev: 7dfbccfa582bbc6e79ed29677391b9ae81a9b5bd
GitHub-Pull-Request: golang/go#76325
Reviewed-on: https://go-review.googlesource.com/c/go/+/720960
Reviewed-by: Mark Freeman <markfreeman@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/cgo/gcc.go
src/cmd/cgo/internal/test/cgo_test.go
src/cmd/cgo/internal/test/test.go
src/cmd/cgo/internal/test/testx.go
src/cmd/cgo/out.go
src/runtime/cgocall.go

index d3de3906b48eb0cd8ee130d1be6369718083dd9a..300ccae350b44db48fd862ab9447816b46e78123 100644 (file)
@@ -1121,6 +1121,9 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
                if t.Name == "error" {
                        return true
                }
+               if t.Name == "any" {
+                       return true
+               }
                if goTypes[t.Name] != nil {
                        return false
                }
index 5393552e07a4d1130267f1bdc19627a51060cb3f..04e06cf95ec55086ec3a606b4f9fe4e4b716f83f 100644 (file)
@@ -106,6 +106,7 @@ func TestSetEnv(t *testing.T)                { testSetEnv(t) }
 func TestThreadLock(t *testing.T)            { testThreadLockFunc(t) }
 func TestUnsignedInt(t *testing.T)           { testUnsignedInt(t) }
 func TestZeroArgCallback(t *testing.T)       { testZeroArgCallback(t) }
+func Test76340(t *testing.T)                 { test76340(t) }
 
 func BenchmarkCgoCall(b *testing.B)      { benchCgoCall(b) }
 func BenchmarkGoString(b *testing.B)     { benchGoString(b) }
index e83e367174aa4f240bb85e5575aa145a30fb1a8a..4dd14facb50e6b88b1ab124b81209d03d2fb1b62 100644 (file)
@@ -959,6 +959,18 @@ char * const issue75751p = &issue75751v;
 #define issue75751m issue75751p
 char * const volatile issue75751p2 = &issue75751v;
 #define issue75751m2 issue75751p2
+
+typedef struct { void *t; void *v; } GoInterface;
+extern int exportAny76340Param(GoInterface);
+extern GoInterface exportAny76340Return(int);
+
+int issue76340testFromC(GoInterface obj) {
+       return exportAny76340Param(obj);
+}
+
+GoInterface issue76340returnFromC(int val) {
+       return exportAny76340Return(val);
+}
 */
 import "C"
 
@@ -2407,3 +2419,22 @@ func test69086(t *testing.T) {
 func test75751() int {
        return int(*C.issue75751m) + int(*C.issue75751m2)
 }
+
+// Issue 76340.
+func test76340(t *testing.T) {
+       var emptyInterface C.GoInterface
+       r1 := C.issue76340testFromC(emptyInterface)
+       if r1 != 0 {
+               t.Errorf("issue76340testFromC with nil interface: got %d, want 0", r1)
+       }
+
+       r2 := C.issue76340returnFromC(42)
+       if r2.t == nil && r2.v == nil {
+               t.Error("issue76340returnFromC(42) returned nil interface")
+       }
+
+       r3 := C.issue76340returnFromC(0)
+       if r3.t != nil || r3.v != nil {
+               t.Errorf("issue76340returnFromC(0) returned non-nil interface: got %v, want nil", r3)
+       }
+}
index 9a63b9e10087ad3f3a986130b0ec2114d6216398..21ba52260ef893e2e5f5a620de6de63e61b3eb0a 100644 (file)
@@ -595,3 +595,21 @@ func test49633(t *testing.T) {
                t.Errorf("msg = %q, want 'hello'", v.msg)
        }
 }
+
+//export exportAny76340Param
+func exportAny76340Param(obj any) C.int {
+       if obj == nil {
+               return 0
+       }
+
+       return 1
+}
+
+//export exportAny76340Return
+func exportAny76340Return(val C.int) any {
+       if val == 0 {
+               return nil
+       }
+
+       return int(val)
+}
index 00c9e8c9a3ec61a483486579f26c8b2014472e0c..dc1e5b29e592484eed13a83dea3abeb63aaba580 100644 (file)
@@ -1558,6 +1558,9 @@ func (p *Package) doCgoType(e ast.Expr, m map[ast.Expr]bool) *Type {
                if t.Name == "error" {
                        return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
                }
+               if t.Name == "any" {
+                       return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
+               }
                if r, ok := goTypes[t.Name]; ok {
                        return goTypesFixup(r)
                }
index f01353ffa6c49f9850f7f1af36572250a0d368a7..55e7bdbdb55f7956e8ae5bd4cc24d8c3b9edda02 100644 (file)
@@ -796,6 +796,9 @@ func cgoCheckResult(val any) {
 
        ep := efaceOf(&val)
        t := ep._type
+       if t == nil {
+               return
+       }
        cgoCheckArg(t, ep.data, !t.IsDirectIface(), false, cgoResultFail)
 }