cmd/gc: error on constant shift overflows.
Fixes #3019.
R=golang-dev, rsc
CC=golang-dev, remy
https://golang.org/cl/5674044
diff --git a/src/cmd/gc/mparith2.c b/src/cmd/gc/mparith2.c
index c802e44..8e52ff2 100644
--- a/src/cmd/gc/mparith2.c
+++ b/src/cmd/gc/mparith2.c
@@ -27,10 +27,10 @@
//
// left shift mpint by one
-// ignores sign and overflow
+// ignores sign
//
static void
-mplsh(Mpint *a)
+mplsh(Mpint *a, int quiet)
{
long *a1, x;
int i, c;
@@ -46,19 +46,27 @@
}
*a1++ = x;
}
+ a->ovf = c;
+ if(a->ovf && !quiet)
+ yyerror("constant shift overflow");
}
//
// left shift mpint by Mpscale
-// ignores sign and overflow
+// ignores sign
//
static void
-mplshw(Mpint *a)
+mplshw(Mpint *a, int quiet)
{
long *a1;
int i;
a1 = &a->a[Mpprec-1];
+ if(*a1) {
+ a->ovf = 1;
+ if(!quiet)
+ yyerror("constant shift overflow");
+ }
for(i=1; i<Mpprec; i++) {
a1[0] = a1[-1];
a1--;
@@ -168,11 +176,11 @@
{
if(s >= 0) {
while(s >= Mpscale) {
- mplshw(a);
+ mplshw(a, 0);
s -= Mpscale;
}
while(s > 0) {
- mplsh(a);
+ mplsh(a, 0);
s--;
}
} else {
@@ -294,7 +302,7 @@
for(j=0; j<Mpscale; j++) {
if(x & 1)
mpaddfixfix(&q, &s, 1);
- mplsh(&s);
+ mplsh(&s, 1);
x >>= 1;
}
}
@@ -606,7 +614,7 @@
for(i=0; i<Mpprec*Mpscale; i++) {
if(mpcmp(d, r) > 0)
break;
- mplsh(d);
+ mplsh(d, 1);
}
// if it never happens
@@ -625,7 +633,7 @@
// when done the remaining numerator
// will be the remainder
for(; i>0; i--) {
- mplsh(q);
+ mplsh(q, 1);
mprsh(d);
if(mpcmp(d, r) <= 0) {
mpaddcfix(q, 1);
diff --git a/test/const2.go b/test/const2.go
index b083735..12c5c24 100644
--- a/test/const2.go
+++ b/test/const2.go
@@ -13,4 +13,6 @@
const LargeA = 1000000000000000000
const LargeB = LargeA * LargeA * LargeA
-const LargeC = LargeB * LargeB * LargeB // ERROR "constant multiplication overflow"
+const LargeC = LargeB * LargeB * LargeB // ERROR "constant multiplication overflow"
+
+const AlsoLargeA = LargeA << 400 << 400 >> 400 >> 400 // ERROR "constant shift overflow"