mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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:
parent
1b12a2ca21
commit
da769814b8
3 changed files with 39 additions and 1 deletions
|
|
@ -90,6 +90,7 @@ func Test22906(t *testing.T) { test22906(t) }
|
||||||
func Test24206(t *testing.T) { test24206(t) }
|
func Test24206(t *testing.T) { test24206(t) }
|
||||||
func Test25143(t *testing.T) { test25143(t) }
|
func Test25143(t *testing.T) { test25143(t) }
|
||||||
func Test23356(t *testing.T) { test23356(t) }
|
func Test23356(t *testing.T) { test23356(t) }
|
||||||
|
func Test26066(t *testing.T) { test26066(t) }
|
||||||
|
|
||||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
||||||
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
|
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
|
||||||
|
|
|
||||||
19
misc/cgo/test/issue26066.go
Normal file
19
misc/cgo/test/issue26066.go
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
// Wrong type of constant with GCC 8 and newer.
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
// const unsigned long long int issue26066 = (const unsigned long long) -1;
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func test26066(t *testing.T) {
|
||||||
|
var i = int64(C.issue26066)
|
||||||
|
if i != -1 {
|
||||||
|
t.Errorf("got %d, want -1", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -586,7 +586,25 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "fconst":
|
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])
|
n.Const = fmt.Sprintf("%f", floats[i])
|
||||||
}
|
}
|
||||||
case "sconst":
|
case "sconst":
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue