mirror of
https://github.com/golang/go
synced 2024-10-14 03:43:28 +00:00
cmd/cgo: for -godefs, promote first field of anonymous union
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
This commit is contained in:
parent
f6f2f77142
commit
f2f17c0ff2
26
misc/cgo/testgodefs/anonunion.go
Normal file
26
misc/cgo/testgodefs/anonunion.go
Normal file
|
@ -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
misc/cgo/testgodefs/main.go
Normal file
12
misc/cgo/testgodefs/main.go
Normal file
|
@ -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
misc/cgo/testgodefs/test.bash
Executable file
20
misc/cgo/testgodefs/test.bash
Executable file
|
@ -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
|
|
@ -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++
|
||||
|
|
Loading…
Reference in a new issue