diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index d3de3906b48eb0..300ccae350b44d 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -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 } diff --git a/src/cmd/cgo/internal/test/cgo_test.go b/src/cmd/cgo/internal/test/cgo_test.go index 5393552e07a4d1..cf57e1b43289b7 100644 --- a/src/cmd/cgo/internal/test/cgo_test.go +++ b/src/cmd/cgo/internal/test/cgo_test.go @@ -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 TestAny(t *testing.T) { testAny(t) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } func BenchmarkGoString(b *testing.B) { benchGoString(b) } diff --git a/src/cmd/cgo/internal/test/test.go b/src/cmd/cgo/internal/test/test.go index 9626407d882ef2..e8e2af9a1b1f61 100644 --- a/src/cmd/cgo/internal/test/test.go +++ b/src/cmd/cgo/internal/test/test.go @@ -953,6 +953,18 @@ typedef struct { } issue69086struct; static int issue690861(issue69086struct* p) { p->b = 1234; return p->c; } static int issue690862(unsigned long ul1, unsigned long ul2, unsigned int u, issue69086struct s) { return (int)(s.b); } + +typedef struct { void *t; void *v; } GoInterface; +extern int exportAnyParam(GoInterface); +extern GoInterface exportAnyReturn(int); + +int testAnyFromC(GoInterface obj) { + return exportAnyParam(obj); +} + +GoInterface testAnyReturnFromC(int val) { + return exportAnyReturn(val); +} */ import "C" @@ -2396,3 +2408,21 @@ func test69086(t *testing.T) { t.Errorf("call: got %d, want 1234", got) } } + +func testAny(t *testing.T) { + var emptyInterface C.GoInterface + r1 := C.testAnyFromC(emptyInterface) + if r1 != 0 { + t.Errorf("testAnyFromC with nil interface: got %d, want 0", r1) + } + + r2 := C.testAnyReturnFromC(42) + if r2.t == nil && r2.v == nil { + t.Error("testAnyReturnFromC(42) returned nil interface") + } + + r3 := C.testAnyReturnFromC(0) + if r3.t != nil || r3.v != nil { + t.Errorf("testAnyReturnFromC(0) returned non-nil interface: got %v, want nil", r3) + } +} diff --git a/src/cmd/cgo/internal/test/testx.go b/src/cmd/cgo/internal/test/testx.go index 9a63b9e10087ad..1c19eeb4dac946 100644 --- a/src/cmd/cgo/internal/test/testx.go +++ b/src/cmd/cgo/internal/test/testx.go @@ -595,3 +595,21 @@ func test49633(t *testing.T) { t.Errorf("msg = %q, want 'hello'", v.msg) } } + +//export exportAnyParam +func exportAnyParam(obj any) C.int { + if obj == nil { + return 0 + } + + return 1 +} + +//export exportAnyReturn +func exportAnyReturn(val C.int) any { + if val == 0 { + return nil + } + + return int(val) +} diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 701a8530ffc984..d6406b5b8a422c 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -1528,6 +1528,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) } diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index a53fd6da340190..737aea930acca3 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -795,6 +795,9 @@ func cgoCheckResult(val any) { ep := efaceOf(&val) t := ep._type + if t == nil { + return + } cgoCheckArg(t, ep.data, !t.IsDirectIface(), false, cgoResultFail) }