runtime/cgo: add support for any param and return type

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: 7dfbccfa58
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>
This commit is contained in:
Alexandre Daubois 2025-11-24 08:14:18 +00:00 committed by Gopher Robot
parent 89552911b3
commit a593ca9d65
6 changed files with 59 additions and 0 deletions

View file

@ -1121,6 +1121,9 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
if t.Name == "error" { if t.Name == "error" {
return true return true
} }
if t.Name == "any" {
return true
}
if goTypes[t.Name] != nil { if goTypes[t.Name] != nil {
return false return false
} }

View file

@ -106,6 +106,7 @@ func TestSetEnv(t *testing.T) { testSetEnv(t) }
func TestThreadLock(t *testing.T) { testThreadLockFunc(t) } func TestThreadLock(t *testing.T) { testThreadLockFunc(t) }
func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) } func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) }
func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) } func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
func Test76340(t *testing.T) { test76340(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
func BenchmarkGoString(b *testing.B) { benchGoString(b) } func BenchmarkGoString(b *testing.B) { benchGoString(b) }

View file

@ -959,6 +959,18 @@ char * const issue75751p = &issue75751v;
#define issue75751m issue75751p #define issue75751m issue75751p
char * const volatile issue75751p2 = &issue75751v; char * const volatile issue75751p2 = &issue75751v;
#define issue75751m2 issue75751p2 #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" import "C"
@ -2407,3 +2419,22 @@ func test69086(t *testing.T) {
func test75751() int { func test75751() int {
return int(*C.issue75751m) + int(*C.issue75751m2) 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)
}
}

View file

@ -595,3 +595,21 @@ func test49633(t *testing.T) {
t.Errorf("msg = %q, want 'hello'", v.msg) 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)
}

View file

@ -1558,6 +1558,9 @@ func (p *Package) doCgoType(e ast.Expr, m map[ast.Expr]bool) *Type {
if t.Name == "error" { if t.Name == "error" {
return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")} 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 { if r, ok := goTypes[t.Name]; ok {
return goTypesFixup(r) return goTypesFixup(r)
} }

View file

@ -796,6 +796,9 @@ func cgoCheckResult(val any) {
ep := efaceOf(&val) ep := efaceOf(&val)
t := ep._type t := ep._type
if t == nil {
return
}
cgoCheckArg(t, ep.data, !t.IsDirectIface(), false, cgoResultFail) cgoCheckArg(t, ep.data, !t.IsDirectIface(), false, cgoResultFail)
} }