mirror of
https://github.com/golang/go
synced 2024-11-23 05:40:04 -07:00
cmd/cgo: omit misaligned struct fields, like we omit bitfields
Fixes #7560. LGTM=iant R=golang-codereviews, iant CC=golang-codereviews https://golang.org/cl/96300045
This commit is contained in:
parent
211618c26e
commit
2d1a9510ed
@ -52,5 +52,6 @@ func Test6390(t *testing.T) { test6390(t) }
|
||||
func Test5986(t *testing.T) { test5986(t) }
|
||||
func Test7665(t *testing.T) { test7665(t) }
|
||||
func TestNaming(t *testing.T) { testNaming(t) }
|
||||
func Test7560(t *testing.T) { test7560(t) }
|
||||
|
||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
||||
|
44
misc/cgo/test/issue7560.go
Normal file
44
misc/cgo/test/issue7560.go
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2014 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
|
||||
|
||||
/*
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
char x;
|
||||
long y;
|
||||
} __attribute__((__packed__)) misaligned;
|
||||
|
||||
int
|
||||
offset7560(void)
|
||||
{
|
||||
return (uintptr_t)&((misaligned*)0)->y;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func test7560(t *testing.T) {
|
||||
// some mingw don't implement __packed__ correctly.
|
||||
if C.offset7560() != 1 {
|
||||
t.Skip("C compiler did not pack struct")
|
||||
}
|
||||
|
||||
// C.misaligned should have x but then a padding field to get to the end of the struct.
|
||||
// There should not be a field named 'y'.
|
||||
var v C.misaligned
|
||||
rt := reflect.TypeOf(&v).Elem()
|
||||
if rt.NumField() != 2 || rt.Field(0).Name != "x" || rt.Field(1).Name != "_" {
|
||||
t.Errorf("unexpected fields in C.misaligned:\n")
|
||||
for i := 0; i < rt.NumField(); i++ {
|
||||
t.Logf("%+v\n", rt.Field(i))
|
||||
}
|
||||
}
|
||||
}
|
@ -68,6 +68,9 @@ Go references to C
|
||||
Within the Go file, C's struct field names that are keywords in Go
|
||||
can be accessed by prefixing them with an underscore: if x points at a C
|
||||
struct with a field named "type", x._type accesses the field.
|
||||
C struct fields that cannot be expressed in Go, such as bit fields
|
||||
or misaligned data, are omitted in the Go struct, replaced by
|
||||
appropriate padding to reach the next field or the end of the struct.
|
||||
|
||||
The standard C numeric types are available under the names
|
||||
C.char, C.schar (signed char), C.uchar (unsigned char),
|
||||
|
@ -1499,7 +1499,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
|
||||
t := c.Type(f.Type, pos)
|
||||
tgo := t.Go
|
||||
size := t.Size
|
||||
|
||||
talign := t.Align
|
||||
if f.BitSize > 0 {
|
||||
if f.BitSize%8 != 0 {
|
||||
continue
|
||||
@ -1512,8 +1512,17 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
|
||||
name = "uint"
|
||||
}
|
||||
tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
|
||||
talign = size
|
||||
}
|
||||
|
||||
if talign > 0 && f.ByteOffset%talign != 0 {
|
||||
// Drop misaligned fields, the same way we drop integer bit fields.
|
||||
// The goal is to make available what can be made available.
|
||||
// Otherwise one bad and unneeded field in an otherwise okay struct
|
||||
// makes the whole program not compile. Much of the time these
|
||||
// structs are in system headers that cannot be corrected.
|
||||
continue
|
||||
}
|
||||
n := len(fld)
|
||||
fld = fld[0 : n+1]
|
||||
name := f.Name
|
||||
@ -1528,8 +1537,8 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(name)
|
||||
buf.WriteString("; ")
|
||||
if t.Align > align {
|
||||
align = t.Align
|
||||
if talign > align {
|
||||
align = talign
|
||||
}
|
||||
}
|
||||
if off < dt.ByteSize {
|
||||
|
Loading…
Reference in New Issue
Block a user