]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: omit misaligned struct fields, like we omit bitfields
authorRuss Cox <rsc@golang.org>
Tue, 13 May 2014 03:48:20 +0000 (23:48 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 13 May 2014 03:48:20 +0000 (23:48 -0400)
Fixes #7560.

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/96300045

misc/cgo/test/cgo_test.go
misc/cgo/test/issue7560.go [new file with mode: 0644]
src/cmd/cgo/doc.go
src/cmd/cgo/gcc.go

index f015ec9fa31de9d6dc6d7e8828a70ea760e9ef21..eb237725a4f4e49485700c3c30c55ebc5a0b95d9 100644 (file)
@@ -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) }
diff --git a/misc/cgo/test/issue7560.go b/misc/cgo/test/issue7560.go
new file mode 100644 (file)
index 0000000..4bea6e3
--- /dev/null
@@ -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))
+               }
+       }
+}
index 605bab6d2e1842d6ccbacf022b9871e1e0ea4d6b..057d25f5b42845b987e95a708710fd983ad6aca0 100644 (file)
@@ -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),
index b8b783051da82eb2ca3e46e8409752f428d69729..c5fcdfc3df57e2217e7ca5535efa77a582c891fb 100644 (file)
@@ -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 {