diff --git a/misc/cgo/test/issue24161_darwin_test.go b/misc/cgo/test/issue24161_darwin_test.go new file mode 100644 index 0000000000..cb15b3c5a0 --- /dev/null +++ b/misc/cgo/test/issue24161_darwin_test.go @@ -0,0 +1,19 @@ +// Copyright 2018 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 cgotest + +import ( + "testing" + + "./issue24161arg" + "./issue24161res" +) + +func Test24161Arg(t *testing.T) { + issue24161arg.Test(t) +} +func Test24161Res(t *testing.T) { + issue24161res.Test(t) +} diff --git a/misc/cgo/test/issue24161arg/def.go b/misc/cgo/test/issue24161arg/def.go new file mode 100644 index 0000000000..d33479a891 --- /dev/null +++ b/misc/cgo/test/issue24161arg/def.go @@ -0,0 +1,17 @@ +// Copyright 2018 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. + +// +build darwin + +package issue24161arg + +/* +#cgo LDFLAGS: -framework CoreFoundation +#include +*/ +import "C" + +func test24161array() C.CFArrayRef { + return C.CFArrayCreate(0, nil, 0, nil) +} diff --git a/misc/cgo/test/issue24161arg/use.go b/misc/cgo/test/issue24161arg/use.go new file mode 100644 index 0000000000..3e74944013 --- /dev/null +++ b/misc/cgo/test/issue24161arg/use.go @@ -0,0 +1,19 @@ +// Copyright 2018 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. + +// +build darwin + +package issue24161arg + +/* +#cgo LDFLAGS: -framework CoreFoundation +#include +*/ +import "C" +import "testing" + +func Test(t *testing.T) { + a := test24161array() + C.CFArrayCreateCopy(0, a) +} diff --git a/misc/cgo/test/issue24161res/restype.go b/misc/cgo/test/issue24161res/restype.go new file mode 100644 index 0000000000..e5719f22a4 --- /dev/null +++ b/misc/cgo/test/issue24161res/restype.go @@ -0,0 +1,23 @@ +// Copyright 2018 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. + +// +build darwin + +package issue24161res + +/* +#cgo LDFLAGS: -framework CoreFoundation +#include +*/ +import "C" +import ( + "reflect" + "testing" +) + +func Test(t *testing.T) { + if k := reflect.TypeOf(C.CFArrayCreate(0, nil, 0, nil)).Kind(); k != reflect.Uintptr { + t.Fatalf("bad kind %s\n", k) + } +} diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 169894273b..9f4a611f19 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -167,6 +167,21 @@ func (p *Package) Translate(f *File) { needType := p.guessKinds(f) if len(needType) > 0 { p.loadDWARF(f, needType) + // If there are typedefs used as arguments, add those + // types to the list of types we're interested in, and + // try again. + if len(p.ArgTypedefs) > 0 { + for _, a := range p.ArgTypedefs { + f.Name[a] = &Name{ + Go: a, + C: a, + } + } + needType := p.guessKinds(f) + if len(needType) > 0 { + p.loadDWARF(f, needType) + } + } } if p.rewriteCalls(f) { // Add `import _cgo_unsafe "unsafe"` after the package statement. @@ -615,6 +630,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) { } conv.FinishType(pos) } + p.ArgTypedefs = conv.argTypedefs } // mangleName does name mangling to translate names @@ -1696,6 +1712,9 @@ type typeConv struct { ptrSize int64 intSize int64 + + // Typedefs used as argument types for C calls. + argTypedefs []string } var tagGen int @@ -2103,6 +2122,10 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { s := *sub s.Go = c.uintptr sub = &s + // Make sure we update any previously computed type. + if oldType := typedef[name.Name]; oldType != nil { + oldType.Go = sub.Go + } } t.Go = name if unionWithPointer[sub.Go] { @@ -2252,6 +2275,9 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { C: tr, } case *dwarf.TypedefType: + // Keep track of all the typedefs used as arguments. + c.argTypedefs = append(c.argTypedefs, dt.Name) + // C has much more relaxed rules than Go for // implicit type conversions. When the parameter // is type T defined as *X, simulate a little of the @@ -2308,6 +2334,9 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType { gr = []*ast.Field{{Type: c.goVoid}} } else if dtype.ReturnType != nil { r = c.Type(unqual(dtype.ReturnType), pos) + if dt, ok := dtype.ReturnType.(*dwarf.TypedefType); ok { + c.argTypedefs = append(c.argTypedefs, dt.Name) + } gr = []*ast.Field{{Type: r.Go}} } return &FuncType{ diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index 09c0624adb..84b1daadbe 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -46,6 +46,7 @@ type Package struct { GoFiles []string // list of Go files GccFiles []string // list of gcc output files Preamble string // collected preamble for _cgo_export.h + ArgTypedefs []string // typedefs used as arguments to or results of C functions } // A File collects information about a single Go input file.