Skip to content

Commit

Permalink
cmd/cgo: for -godefs, promote first field of anonymous union
Browse files Browse the repository at this point in the history
Update golang#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
  • Loading branch information
ianlancetaylor authored and wheatman committed Jun 28, 2018
1 parent 88a5ef0 commit 138caf7
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 2 deletions.
26 changes: 26 additions & 0 deletions 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
12 changes: 12 additions & 0 deletions 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() {
}
20 changes: 20 additions & 0 deletions 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
23 changes: 21 additions & 2 deletions src/cmd/cgo/gcc.go
Expand Up @@ -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
Expand Down Expand Up @@ -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++
Expand Down

0 comments on commit 138caf7

Please sign in to comment.