Commit 45217825 authored by Gustavo Niemeyer's avatar Gustavo Niemeyer Committed by Russ Cox

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
parent 2aaabfc8
...@@ -774,6 +774,8 @@ var dwarfToName = map[string]string{ ...@@ -774,6 +774,8 @@ var dwarfToName = map[string]string{
"double complex": "complexdouble", "double complex": "complexdouble",
} }
const signedDelta = 64
// Type returns a *Type with the same memory layout as // Type returns a *Type with the same memory layout as
// dtype when used as the type of a variable or a struct field. // dtype when used as the type of a variable or a struct field.
func (c *typeConv) Type(dtype dwarf.Type) *Type { func (c *typeConv) Type(dtype dwarf.Type) *Type {
...@@ -839,7 +841,19 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { ...@@ -839,7 +841,19 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
t.Align = 1 t.Align = 1
case *dwarf.EnumType: 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: default:
fatal("unexpected: %d-byte enum type - %s", t.Size, dtype) fatal("unexpected: %d-byte enum type - %s", t.Size, dtype)
case 1: case 1:
...@@ -850,14 +864,14 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { ...@@ -850,14 +864,14 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
t.Go = c.uint32 t.Go = c.uint32
case 8: case 8:
t.Go = c.uint64 t.Go = c.uint64
} case 1 + signedDelta:
if t.Align = t.Size; t.Align >= c.ptrSize { t.Go = c.int8
t.Align = c.ptrSize case 2 + signedDelta:
} t.Go = c.int16
t.C = "enum " + dt.EnumName case 4 + signedDelta:
t.EnumValues = make(map[string]int64) t.Go = c.int32
for _, ev := range dt.Val { case 8 + signedDelta:
t.EnumValues[ev.Name] = ev.Val t.Go = c.int64
} }
case *dwarf.FloatType: case *dwarf.FloatType:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment