summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2014-08-05 17:10:15 -0700
committerIan Lance Taylor <iant@golang.org>2014-08-05 17:10:15 -0700
commit53f6f0a3f78b218b3aba77e39acb7c601c223957 (patch)
treed55478aa8b5554b7ced45fe73d8c654404526832
parent0ad1c6efce3e555ba5337b849fcc6295494a3be6 (diff)
downloadgo-53f6f0a3f78b218b3aba77e39acb7c601c223957.tar.gz
cmd/cgo: for -godefs, promote first field of anonymous union
Update issue 6677 When a struct contains an anonymous union, use the type and name of the first field in the union. This should make the glibc <sys/resource.h> file work; in that file struct rusage has fields like __extension__ union { long int ru_maxrss; __syscall_slong_t __ru_maxrss_word; }; in which the field that matters is ru_maxrss and __ru_maxrss_word just exists to advance to the next field on systems where the kernel uses long long fields but userspace expects long fields. LGTM=mikioh.mikioh R=golang-codereviews, mikioh.mikioh CC=golang-codereviews https://codereview.appspot.com/106260044
-rw-r--r--misc/cgo/testgodefs/anonunion.go26
-rw-r--r--misc/cgo/testgodefs/main.go12
-rwxr-xr-xmisc/cgo/testgodefs/test.bash20
-rw-r--r--src/cmd/cgo/gcc.go23
4 files changed, 79 insertions, 2 deletions
diff --git a/misc/cgo/testgodefs/anonunion.go b/misc/cgo/testgodefs/anonunion.go
new file mode 100644
index 000000000..7bc736b9d
--- /dev/null
+++ b/misc/cgo/testgodefs/anonunion.go
@@ -0,0 +1,26 @@
+// 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.
+//
+// +build ignore
+
+package main
+
+// This file tests that when cgo -godefs sees a struct with a field
+// that is an anonymous union, the first field in the union is
+// promoted to become a field of the struct. See issue 6677 for
+// background.
+
+/*
+typedef struct {
+ union {
+ long l;
+ int c;
+ };
+} t;
+*/
+import "C"
+
+// Input for cgo -godefs.
+
+type T C.t
diff --git a/misc/cgo/testgodefs/main.go b/misc/cgo/testgodefs/main.go
new file mode 100644
index 000000000..eaf91bc11
--- /dev/null
+++ b/misc/cgo/testgodefs/main.go
@@ -0,0 +1,12 @@
+// 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 main
+
+// Test that the struct field in anonunion.go was promoted.
+var v1 T
+var v2 = v1.L
+
+func main() {
+}
diff --git a/misc/cgo/testgodefs/test.bash b/misc/cgo/testgodefs/test.bash
new file mode 100755
index 000000000..cfbeae7dc
--- /dev/null
+++ b/misc/cgo/testgodefs/test.bash
@@ -0,0 +1,20 @@
+# 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.
+
+# We are testing cgo -godefs, which translates Go files that use
+# import "C" into Go files with Go definitions of types defined in the
+# import "C" block. Add more tests here.
+FILE_PREFIXES="anonunion"
+
+RM=
+for FP in $FILE_PREFIXES
+do
+ go tool cgo -godefs ${FP}.go > ${FP}_defs.go
+ RM="${RM} ${FP}_defs.go"
+done
+
+go build . && ./testgodefs
+EXIT=$?
+rm -rf _obj testgodefs ${RM}
+exit $EXIT
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index 7a802102d..13e834029 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -1548,7 +1548,27 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
fld = c.pad(fld, f.ByteOffset-off)
off = f.ByteOffset
}
- t := c.Type(f.Type, pos)
+
+ name := f.Name
+ ft := f.Type
+
+ // In godefs or cdefs mode, if this field is a C11
+ // anonymous union then treat the first field in the
+ // union as the field in the struct. This handles
+ // cases like the glibc <sys/resource.h> file; see
+ // issue 6677.
+ if *godefs || *cdefs {
+ if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
+ name = st.Field[0].Name
+ ident[name] = name
+ ft = st.Field[0].Type
+ }
+ }
+
+ // TODO: Handle fields that are anonymous structs by
+ // promoting the fields of the inner struct.
+
+ t := c.Type(ft, pos)
tgo := t.Go
size := t.Size
talign := t.Align
@@ -1577,7 +1597,6 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
}
n := len(fld)
fld = fld[0 : n+1]
- name := f.Name
if name == "" {
name = fmt.Sprintf("anon%d", anon)
anon++