cmd/cgo: handle GCC 8 change in errors about constant initializers

Before GCC 8 C code like

const unsigned long long int neg = (const unsigned long long) -1;
void f(void) { static const double x = (neg); }

would get an error "initializer element is not constant". In GCC 8 and
later it does not.

Because a value like neg, above, can not be used as a general integer
constant, this causes cgo to conclude that it is a floating point
constant. The way that cgo handles floating point values then causes
it to get the wrong value for it: 18446744073709551615 rather than -1.
These are of course the same value when converted to int64, but Go
does not permit that kind of conversion for an out-of-range constant.

This CL side-steps the problem by treating floating point constants
with integer type as they would up being treated before GCC 8: as
variables rather than constants.

Fixes #26066

Change-Id: I6f2f9ac2fa8a4b8218481b474f0b539758eb3b79
Reviewed-on: https://go-review.googlesource.com/121035
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Ian Lance Taylor 2018-06-26 14:40:51 -07:00
parent 1b12a2ca21
commit da769814b8
3 changed files with 39 additions and 1 deletions

View file

@ -586,7 +586,25 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
}
}
case "fconst":
if i < len(floats) {
if i >= len(floats) {
break
}
switch base(types[i]).(type) {
case *dwarf.IntType, *dwarf.UintType:
// This has an integer type so it's
// not really a floating point
// constant. This can happen when the
// C compiler complains about using
// the value as an integer constant,
// but not as a general constant.
// Treat this as a variable of the
// appropriate type, not a constant,
// to get C-style type handling,
// avoiding the problem that C permits
// uint64(-1) but Go does not.
// See issue 26066.
n.Kind = "var"
default:
n.Const = fmt.Sprintf("%f", floats[i])
}
case "sconst":