]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: for -godefs, promote first field of anonymous union
authorIan Lance Taylor <iant@golang.org>
Wed, 6 Aug 2014 00:10:15 +0000 (17:10 -0700)
committerIan Lance Taylor <iant@golang.org>
Wed, 6 Aug 2014 00:10:15 +0000 (17:10 -0700)
Update #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://golang.org/cl/106260044

misc/cgo/testgodefs/anonunion.go [new file with mode: 0644]
misc/cgo/testgodefs/main.go [new file with mode: 0644]
misc/cgo/testgodefs/test.bash [new file with mode: 0755]
src/cmd/cgo/gcc.go

diff --git a/misc/cgo/testgodefs/anonunion.go b/misc/cgo/testgodefs/anonunion.go
new file mode 100644 (file)
index 0000000..7bc736b
--- /dev/null
@@ -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 (file)
index 0000000..eaf91bc
--- /dev/null
@@ -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 (executable)
index 0000000..cfbeae7
--- /dev/null
@@ -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
index 7a802102d946f279f5f6d6f3a1021d8c05a679ae..13e83402919b46983c9963bbdeb08bc9cd17d94c 100644 (file)
@@ -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++