mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/cgo: don't translate bitfields into Go fields
The cgo tool would sometimes emit a bitfield at an offset that did not correspond to the C offset, such as for the example in the new test. Change-Id: I61b2ca10ee44a42f81c13ed12865f2060168fed5 Reviewed-on: https://go-review.googlesource.com/c/go/+/252378 Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
parent
b6dbaef68f
commit
eaa97fbf20
5 changed files with 75 additions and 15 deletions
|
|
@ -86,6 +86,16 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
by <code>go</code> <code>mod</code> <code>vendor</code> since Go 1.11.
|
by <code>go</code> <code>mod</code> <code>vendor</code> since Go 1.11.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3 id="cgo">Cgo</h3>
|
||||||
|
|
||||||
|
<p> <!-- CL 252378 -->
|
||||||
|
The <a href="/cmd/cgo">cgo</a> tool will no longer try to translate
|
||||||
|
C struct bitfields into Go struct fields, even if their size can be
|
||||||
|
represented in Go. The order in which C bitfields appear in memory
|
||||||
|
is implementation dependent, so in some cases the cgo tool produced
|
||||||
|
results that were silently incorrect.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
TODO
|
TODO
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
31
misc/cgo/testgodefs/testdata/bitfields.go
vendored
Normal file
31
misc/cgo/testgodefs/testdata/bitfields.go
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
// This file tests that we don't generate an incorrect field location
|
||||||
|
// for a bitfield that appears aligned.
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct bitfields {
|
||||||
|
unsigned int B1 : 5;
|
||||||
|
unsigned int B2 : 1;
|
||||||
|
unsigned int B3 : 1;
|
||||||
|
unsigned int B4 : 1;
|
||||||
|
unsigned int Short1 : 16; // misaligned on 8 bit boundary
|
||||||
|
unsigned int B5 : 1;
|
||||||
|
unsigned int B6 : 1;
|
||||||
|
unsigned int B7 : 1;
|
||||||
|
unsigned int B8 : 1;
|
||||||
|
unsigned int B9 : 1;
|
||||||
|
unsigned int B10 : 3;
|
||||||
|
unsigned int Short2 : 16; // alignment is OK
|
||||||
|
unsigned int Short3 : 16; // alignment is OK
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type bitfields C.struct_bitfields
|
||||||
28
misc/cgo/testgodefs/testdata/main.go
vendored
28
misc/cgo/testgodefs/testdata/main.go
vendored
|
|
@ -4,6 +4,12 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
// Test that the struct field in anonunion.go was promoted.
|
// Test that the struct field in anonunion.go was promoted.
|
||||||
var v1 T
|
var v1 T
|
||||||
var v2 = v1.L
|
var v2 = v1.L
|
||||||
|
|
@ -23,4 +29,26 @@ var v7 = S{}
|
||||||
var _ = issue38649{X: 0}
|
var _ = issue38649{X: 0}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
pass := true
|
||||||
|
|
||||||
|
// The Go translation of bitfields should not have any of the
|
||||||
|
// bitfield types. The order in which bitfields are laid out
|
||||||
|
// in memory is implementation defined, so we can't easily
|
||||||
|
// know how a bitfield should correspond to a Go type, even if
|
||||||
|
// it appears to be aligned correctly.
|
||||||
|
bitfieldType := reflect.TypeOf(bitfields{})
|
||||||
|
check := func(name string) {
|
||||||
|
_, ok := bitfieldType.FieldByName(name)
|
||||||
|
if ok {
|
||||||
|
fmt.Fprintf(os.Stderr, "found unexpected bitfields field %s\n", name)
|
||||||
|
pass = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check("Short1")
|
||||||
|
check("Short2")
|
||||||
|
check("Short3")
|
||||||
|
|
||||||
|
if !pass {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import (
|
||||||
// import "C" block. Add more tests here.
|
// import "C" block. Add more tests here.
|
||||||
var filePrefixes = []string{
|
var filePrefixes = []string{
|
||||||
"anonunion",
|
"anonunion",
|
||||||
|
"bitfields",
|
||||||
"issue8478",
|
"issue8478",
|
||||||
"fieldtypedef",
|
"fieldtypedef",
|
||||||
"issue37479",
|
"issue37479",
|
||||||
|
|
|
||||||
|
|
@ -2831,21 +2831,11 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
|
||||||
tgo := t.Go
|
tgo := t.Go
|
||||||
size := t.Size
|
size := t.Size
|
||||||
talign := t.Align
|
talign := t.Align
|
||||||
if f.BitSize > 0 {
|
if f.BitOffset > 0 || f.BitSize > 0 {
|
||||||
switch f.BitSize {
|
// The layout of bitfields is implementation defined,
|
||||||
case 8, 16, 32, 64:
|
// so we don't know how they correspond to Go fields
|
||||||
default:
|
// even if they are aligned at byte boundaries.
|
||||||
continue
|
continue
|
||||||
}
|
|
||||||
size = f.BitSize / 8
|
|
||||||
name := tgo.(*ast.Ident).String()
|
|
||||||
if strings.HasPrefix(name, "int") {
|
|
||||||
name = "int"
|
|
||||||
} else {
|
|
||||||
name = "uint"
|
|
||||||
}
|
|
||||||
tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
|
|
||||||
talign = size
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if talign > 0 && f.ByteOffset%talign != 0 {
|
if talign > 0 && f.ByteOffset%talign != 0 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue