mirror of
https://github.com/golang/go
synced 2024-11-22 01:44:40 -07:00
cgo: fix handling of signed enumerations
Structs defined in C as containing a field with an enum type are currently translated to Go as a struct with an unsigned integer field, even if some of the values contained in the enum are negative. This modification takes in consideration the values defined in the enum, and conditionally defines the Go type as signed if necessary. The logic introduced was tested with gcc, which will increase the type size if it contains both negative numbers and values greater than 2^b/2-1, and refuses to compile values which would be problematic (2^64-1, but in fact the ISO C restricts the range to the size of int). R=rsc CC=golang-dev https://golang.org/cl/4119058
This commit is contained in:
parent
2aaabfc828
commit
4521782514
@ -774,6 +774,8 @@ var dwarfToName = map[string]string{
|
||||
"double complex": "complexdouble",
|
||||
}
|
||||
|
||||
const signedDelta = 64
|
||||
|
||||
// Type returns a *Type with the same memory layout as
|
||||
// dtype when used as the type of a variable or a struct field.
|
||||
func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||
@ -839,7 +841,19 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||
t.Align = 1
|
||||
|
||||
case *dwarf.EnumType:
|
||||
switch t.Size {
|
||||
if t.Align = t.Size; t.Align >= c.ptrSize {
|
||||
t.Align = c.ptrSize
|
||||
}
|
||||
t.C = "enum " + dt.EnumName
|
||||
signed := 0
|
||||
t.EnumValues = make(map[string]int64)
|
||||
for _, ev := range dt.Val {
|
||||
t.EnumValues[ev.Name] = ev.Val
|
||||
if ev.Val < 0 {
|
||||
signed = signedDelta
|
||||
}
|
||||
}
|
||||
switch t.Size + int64(signed) {
|
||||
default:
|
||||
fatal("unexpected: %d-byte enum type - %s", t.Size, dtype)
|
||||
case 1:
|
||||
@ -850,14 +864,14 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
|
||||
t.Go = c.uint32
|
||||
case 8:
|
||||
t.Go = c.uint64
|
||||
}
|
||||
if t.Align = t.Size; t.Align >= c.ptrSize {
|
||||
t.Align = c.ptrSize
|
||||
}
|
||||
t.C = "enum " + dt.EnumName
|
||||
t.EnumValues = make(map[string]int64)
|
||||
for _, ev := range dt.Val {
|
||||
t.EnumValues[ev.Name] = ev.Val
|
||||
case 1 + signedDelta:
|
||||
t.Go = c.int8
|
||||
case 2 + signedDelta:
|
||||
t.Go = c.int16
|
||||
case 4 + signedDelta:
|
||||
t.Go = c.int32
|
||||
case 8 + signedDelta:
|
||||
t.Go = c.int64
|
||||
}
|
||||
|
||||
case *dwarf.FloatType:
|
||||
|
Loading…
Reference in New Issue
Block a user