-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
Test case:
package main
import "fmt"
/*
const unsigned long long int neg = (const unsigned long long) -1;
*/
import "C"
func main() {
var i int64
i = int64(C.neg)
fmt.Println(C.neg)
fmt.Println(i)
}Building that test case with GCC versions before GCC 8 works. With GCC 8 and later, it gets
# command-line-arguments
../../foo8.go:12:6: error: integer constant overflow
i = int64(C.neg)
^
What has changed is the handling of this C program, similar to that generated by cgo.
const unsigned long long int neg = (const unsigned long long) -1;
void f1(void) { enum { x = (neg)*1 }; }
void f2(void) { static const double x = (neg); }
Before GCC 8, compiling this program gets
foo.c: In function ‘f1’:
foo.c:2:24: error: enumerator value for ‘x’ is not an integer constant
void f1(void) { enum { x = (neg)*1 }; }
^
foo.c: In function ‘f2’:
foo.c:3:41: error: initializer element is not constant
void f2(void) { static const double x = (neg); }
^
In GCC 8 and later, it gets
foo.c: In function ‘f1’:
foo.c:2:24: error: enumerator value for ‘x’ is not an integer constant
void f1(void) { enum { x = (neg)*1 }; }
^
In other words, static const double x = (neg); is now accepted without warning. This appears to be due to the fix for https://gcc.gnu.org/PR69960. See also https://gcc.gnu.org/PR83222 and https://gcc.gnu.org/PR86289.
This effect of this warning change on cgo is that in the original test case neg now appears to be a floating point constant. cgo represents this constant as 18446744073709551616.000000. This leads to the integer constant overflow error shown above.
We're going to need to figure this out.