mirror of
https://github.com/golang/go
synced 2024-11-23 16:40:03 -07:00
cmd/vet: avoid crash in cgo test on recursive type
This CL also re-enables the cgo tests that were accidentally disabled in CL 32754. Fixes #18389. Change-Id: I2fdc4fe3ec1f92b7da3db3fa66f4e0f806fc899f Reviewed-on: https://go-review.googlesource.com/34660 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
9c6a5ef922
commit
27fb26c77c
@ -44,7 +44,7 @@ func checkCgoCall(f *File, node ast.Node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, arg := range x.Args {
|
for _, arg := range x.Args {
|
||||||
if !typeOKForCgoCall(cgoBaseType(f, arg)) {
|
if !typeOKForCgoCall(cgoBaseType(f, arg), make(map[types.Type]bool)) {
|
||||||
f.Badf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
|
f.Badf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ func checkCgoCall(f *File, node ast.Node) {
|
|||||||
arg = conv.Args[0]
|
arg = conv.Args[0]
|
||||||
}
|
}
|
||||||
if u, ok := arg.(*ast.UnaryExpr); ok && u.Op == token.AND {
|
if u, ok := arg.(*ast.UnaryExpr); ok && u.Op == token.AND {
|
||||||
if !typeOKForCgoCall(cgoBaseType(f, u.X)) {
|
if !typeOKForCgoCall(cgoBaseType(f, u.X), make(map[types.Type]bool)) {
|
||||||
f.Badf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
|
f.Badf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,23 +110,24 @@ func cgoBaseType(f *File, arg ast.Expr) types.Type {
|
|||||||
return f.pkg.types[arg].Type
|
return f.pkg.types[arg].Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// typeOKForCgoCall returns true if the type of arg is OK to pass to a
|
// typeOKForCgoCall reports whether the type of arg is OK to pass to a
|
||||||
// C function using cgo. This is not true for Go types with embedded
|
// C function using cgo. This is not true for Go types with embedded
|
||||||
// pointers.
|
// pointers. m is used to avoid infinite recursion on recursive types.
|
||||||
func typeOKForCgoCall(t types.Type) bool {
|
func typeOKForCgoCall(t types.Type, m map[types.Type]bool) bool {
|
||||||
if t == nil {
|
if t == nil || m[t] {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
m[t] = true
|
||||||
switch t := t.Underlying().(type) {
|
switch t := t.Underlying().(type) {
|
||||||
case *types.Chan, *types.Map, *types.Signature, *types.Slice:
|
case *types.Chan, *types.Map, *types.Signature, *types.Slice:
|
||||||
return false
|
return false
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
return typeOKForCgoCall(t.Elem())
|
return typeOKForCgoCall(t.Elem(), m)
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
return typeOKForCgoCall(t.Elem())
|
return typeOKForCgoCall(t.Elem(), m)
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
for i := 0; i < t.NumFields(); i++ {
|
for i := 0; i < t.NumFields(); i++ {
|
||||||
if !typeOKForCgoCall(t.Field(i).Type()) {
|
if !typeOKForCgoCall(t.Field(i).Type(), m) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
src/cmd/vet/testdata/cgo/cgo.go
vendored
3
src/cmd/vet/testdata/cgo/cgo.go
vendored
@ -52,5 +52,8 @@ func CgoTests() {
|
|||||||
C.f(*(*unsafe.Pointer)(unsafe.Pointer(&st2)))
|
C.f(*(*unsafe.Pointer)(unsafe.Pointer(&st2)))
|
||||||
C.f(unsafe.Pointer(&st2))
|
C.f(unsafe.Pointer(&st2))
|
||||||
|
|
||||||
|
type cgoStruct struct{ p *cgoStruct }
|
||||||
|
C.f(unsafe.Pointer(&cgoStruct{}))
|
||||||
|
|
||||||
C.CBytes([]byte("hello"))
|
C.CBytes([]byte("hello"))
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,7 @@ func TestVetDirs(t *testing.T) {
|
|||||||
"divergent",
|
"divergent",
|
||||||
"buildtag",
|
"buildtag",
|
||||||
"incomplete", // incomplete examples
|
"incomplete", // incomplete examples
|
||||||
|
"cgo",
|
||||||
} {
|
} {
|
||||||
dir := dir
|
dir := dir
|
||||||
t.Run(dir, func(t *testing.T) {
|
t.Run(dir, func(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user