Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/cgo: C struct bitfield is omitted #29611

Closed
brb opened this issue Jan 8, 2019 · 5 comments

Comments

@brb
Copy link

commented Jan 8, 2019

What version of Go are you using (go version)?

$ go version
go version go1.11.4 linux/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/brb/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/brb/sandbox/gopath"
GOPROXY=""
GORACE=""
GOROOT="/usr/lib/go"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build385861555=/tmp/go-build -gno-record-gcc-switches"

What did you do?

package main

// #include <stdint.h>
//
// struct foobar {
//     uint8_t      a;
//     uint8_t      b:3, c:5;
//     uint16_t     d[3];
// };
import "C"

import "fmt"

func main() {
	var s C.struct_foobar
	fmt.Println(s)
}

What did you expect to see?

When compiled with go version go1.11.3 linux/amd64, the underlying foobar representation is the following:

type _Ctype_struct_foobar struct {
	a	_Ctype_uint8_t
	_	[1]byte
	d	[3]_Ctype_uint16_t
}

What did you see instead?

When compiled with go version go1.11.4 linux/amd64, the foobar's second field (bitfield) is omitted:

type _Ctype_struct_foobar struct {
	a	_Ctype_uint8_t
	d	[3]_Ctype_uint16_t
}
@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 8, 2019

Yes, the cgo behavior has changed, but why is this a bug? You can't refer to the bitfield either way. The type alignments mean that the fields will continue to be at the correct offsets.

@mattn

This comment has been minimized.

Copy link
Member

commented Jan 8, 2019

var st C.MyStruct
C.fill_my_struct(&st)

Size of st is possibly differ to C's one.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 8, 2019

Try printing out the sizes and field offsets using the reflect package. They should be the same as the C sizes and offsets available using C sizeof and offsetof.

@mattn

This comment has been minimized.

Copy link
Member

commented Jan 8, 2019

Sorry, I mis-read description in this issue. What I expected is cgo generate _.

@brb

This comment has been minimized.

Copy link
Author

commented Jan 9, 2019

Yes, you are correct - the sizes and offsets are the same.

The main source of confusion was a difference in number of fields reported with:

var s C.struct_foobar
t := reflect.TypeOf(s)
for i := 0; i < t.NumField(); i++ {
	fmt.Println(i, ":", t.Field(i), ",", t.Field(i).Offset)
}

// go1.11.4
// 0 : {a main main._Ctype_uchar  0 [0] false} , 0
// 1 : {d main [3]main._Ctype_ushort  2 [1] false} , 2

// go1.11.3
// 0 : {a main main._Ctype_uchar  0 [0] false} , 0
// 1 : {_ main [1]uint8  1 [1] false} , 1
// 2 : {d main [3]main._Ctype_ushort  2 [2] false} , 2

Thanks.

@brb brb closed this Jan 9, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.