mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
cmd/cgo: fix initialization of empty argument types
CL 258938 changed the way C to Go calls work such that they now construct a C struct on the C side for the arguments and space for the results. Any pointers in the result space must be zeroed, so we just zero the whole struct. However, C makes it surprisingly hard to robustly zero any struct type. We had used a "{0}" initializer, which works in the vast majority of cases, but fails if the type is empty or effectively empty. This CL fixes this by changing how the cgo tool zero-initializes the argument struct to be more robust. Fixes #42495. Change-Id: Id1749b9d751e59eb7a02a9d44fec0698a2bf63cd Reviewed-on: https://go-review.googlesource.com/c/go/+/269337 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
35455fff0e
commit
f423d616b1
15
misc/cgo/test/issue42495.go
Normal file
15
misc/cgo/test/issue42495.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2020 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
|
||||
|
||||
// typedef struct { } T42495A;
|
||||
// typedef struct { int x[0]; } T42495B;
|
||||
import "C"
|
||||
|
||||
//export Issue42495A
|
||||
func Issue42495A(C.T42495A) {}
|
||||
|
||||
//export Issue42495B
|
||||
func Issue42495B(C.T42495B) {}
|
|
@ -985,7 +985,15 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||
// The results part of the argument structure must be
|
||||
// initialized to 0 so the write barriers generated by
|
||||
// the assignments to these fields in Go are safe.
|
||||
fmt.Fprintf(fgcc, "\t%s %v _cgo_a = {0};\n", ctype, p.packedAttribute())
|
||||
//
|
||||
// We use a local static variable to get the zeroed
|
||||
// value of the argument type. This avoids including
|
||||
// string.h for memset, and is also robust to C++
|
||||
// types with constructors. Both GCC and LLVM optimize
|
||||
// this into just zeroing _cgo_a.
|
||||
fmt.Fprintf(fgcc, "\ttypedef %s %v _cgo_argtype;\n", ctype, p.packedAttribute())
|
||||
fmt.Fprintf(fgcc, "\tstatic _cgo_argtype _cgo_zero;\n")
|
||||
fmt.Fprintf(fgcc, "\t_cgo_argtype _cgo_a = _cgo_zero;\n")
|
||||
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
|
||||
fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue