]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: handle GCC 8 change in errors about constant initializers
authorIan Lance Taylor <iant@golang.org>
Tue, 26 Jun 2018 21:40:51 +0000 (14:40 -0700)
committerIan Lance Taylor <iant@golang.org>
Fri, 29 Jun 2018 23:22:48 +0000 (23:22 +0000)
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>
misc/cgo/test/cgo_test.go
misc/cgo/test/issue26066.go [new file with mode: 0644]
src/cmd/cgo/gcc.go

index 4c7f676e0ba763520189034c7ca824ef29c52b45..ba2a89ef82f5aa804c1ed4a37e0d995c7fceaef0 100644 (file)
@@ -90,6 +90,7 @@ func Test22906(t *testing.T)                 { test22906(t) }
 func Test24206(t *testing.T)                 { test24206(t) }
 func Test25143(t *testing.T)                 { test25143(t) }
 func Test23356(t *testing.T)                 { test23356(t) }
+func Test26066(t *testing.T)                 { test26066(t) }
 
 func BenchmarkCgoCall(b *testing.B)  { benchCgoCall(b) }
 func BenchmarkGoString(b *testing.B) { benchGoString(b) }
diff --git a/misc/cgo/test/issue26066.go b/misc/cgo/test/issue26066.go
new file mode 100644 (file)
index 0000000..21028e7
--- /dev/null
@@ -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)
+       }
+}
index ae1df0d90f4f1c58c6493aeca8154fa7005f75e1..169894273bea10550b16a5a9d80dde1ea7eb0098 100644 (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":