summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorR?my Oudompheng <oudomphe@phare.normalesup.org>2013-03-04 16:51:42 +0100
committerR?my Oudompheng <oudomphe@phare.normalesup.org>2013-03-04 16:51:42 +0100
commit9140715de75311819e60469209ea3ea54100d6c7 (patch)
tree3f7993eecef61d6001da42f1aeda72a3710aad90
parent76576f813b9d1709f64977f480975188e1cd1195 (diff)
downloadgo-9140715de75311819e60469209ea3ea54100d6c7.tar.gz
cmd/gc: simplify and fix defaultlit.
Fixes issue 4882. Fixes issue 4936. Fixes issue 4937. R=golang-dev, dave, daniel.morsing, rsc CC=golang-dev https://codereview.appspot.com/7432044
-rw-r--r--src/cmd/gc/const.c149
-rw-r--r--test/shift1.go7
2 files changed, 86 insertions, 70 deletions
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index 92b87c024..4f1ff6778 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -1034,85 +1034,88 @@ nodcplxlit(Val r, Val i)
return n;
}
-// TODO(rsc): combine with convlit
+// idealkind returns a constant kind like consttype
+// but for an arbitrary "ideal" expression.
+static int
+idealkind(Node *n)
+{
+ int k1, k2;
+
+ if(n == N || !isideal(n->type))
+ return CTxxx;
+
+ switch(n->op) {
+ default:
+ return CTxxx;
+ case OLITERAL:
+ return n->val.ctype;
+ case OADD:
+ case OAND:
+ case OANDNOT:
+ case OCOM:
+ case ODIV:
+ case OMINUS:
+ case OMOD:
+ case OMUL:
+ case OSUB:
+ case OXOR:
+ case OOR:
+ case OPLUS:
+ // numeric kinds.
+ k1 = idealkind(n->left);
+ k2 = idealkind(n->right);
+ if(k1 > k2)
+ return k1;
+ else
+ return k2;
+ case OADDSTR:
+ return CTSTR;
+ case OANDAND:
+ case OEQ:
+ case OGE:
+ case OGT:
+ case OLE:
+ case OLT:
+ case ONE:
+ case ONOT:
+ case OOROR:
+ case OCMPSTR:
+ case OCMPIFACE:
+ return CTBOOL;
+ case OLSH:
+ case ORSH:
+ // shifts (beware!).
+ return idealkind(n->left);
+ }
+}
+
void
defaultlit(Node **np, Type *t)
{
int lno;
+ int ctype;
Node *n, *nn;
+ Type *t1;
n = *np;
if(n == N || !isideal(n->type))
return;
- switch(n->op) {
- case OLITERAL:
+ if(n->op == OLITERAL) {
nn = nod(OXXX, N, N);
*nn = *n;
n = nn;
*np = n;
- break;
- case OLSH:
- case ORSH:
- defaultlit(&n->left, t);
- t = n->left->type;
- if(t != T && !isint[t->etype]) {
- yyerror("invalid operation: %N (shift of type %T)", n, t);
- t = T;
- }
- n->type = t;
- return;
- case OCOM:
- case ONOT:
- defaultlit(&n->left, t);
- n->type = n->left->type;
- return;
- default:
- if(n->left == N || n->right == N) {
- dump("defaultlit", n);
- fatal("defaultlit");
- }
- // n is ideal, so left and right must both be ideal.
- // n has not been computed as a constant value,
- // so either left or right must not be constant.
- // The only 'ideal' non-constant expressions are shifts. Ugh.
- // If one of these is a shift and the other is not, use that type.
- // When compiling x := 1<<i + 3.14, this means we try to push
- // the float64 down into the 1<<i, producing the correct error
- // (cannot shift float64).
- //
- // If t is an interface type, we want the default type for the
- // value, so just do as if no type was given.
- if(t && t->etype == TINTER)
- t = T;
- if(t == T && (n->right->op == OLSH || n->right->op == ORSH)) {
- defaultlit(&n->left, T);
- defaultlit(&n->right, n->left->type);
- } else if(t == T && (n->left->op == OLSH || n->left->op == ORSH)) {
- defaultlit(&n->right, T);
- defaultlit(&n->left, n->right->type);
- } else if(iscmp[n->op]) {
- defaultlit2(&n->left, &n->right, 1);
- } else {
- defaultlit(&n->left, t);
- defaultlit(&n->right, t);
- }
- if(n->type == idealbool || n->type == idealstring) {
- if(t != T && t->etype == n->type->etype)
- n->type = t;
- else
- n->type = types[n->type->etype];
- } else
- n->type = n->left->type;
- return;
}
lno = setlineno(n);
- switch(n->val.ctype) {
+ ctype = idealkind(n);
+ t1 = T;
+ switch(ctype) {
default:
if(t != T) {
convlit(np, t);
- break;
+ return;
}
if(n->val.ctype == CTNIL) {
lineno = lno;
@@ -1121,46 +1124,52 @@ defaultlit(Node **np, Type *t)
break;
}
if(n->val.ctype == CTSTR) {
- n->type = types[TSTRING];
+ t1 = types[TSTRING];
+ convlit(np, t1);
break;
}
yyerror("defaultlit: unknown literal: %N", n);
break;
+ case CTxxx:
+ fatal("defaultlit: idealkind is CTxxx: %+N", n);
+ break;
case CTBOOL:
- n->type = types[TBOOL];
+ t1 = types[TBOOL];
if(t != T && t->etype == TBOOL)
- n->type = t;
+ t1 = t;
+ convlit(np, t1);
break;
case CTINT:
- n->type = types[TINT];
+ t1 = types[TINT];
goto num;
case CTRUNE:
- n->type = runetype;
+ t1 = runetype;
goto num;
case CTFLT:
- n->type = types[TFLOAT64];
+ t1 = types[TFLOAT64];
goto num;
case CTCPLX:
- n->type = types[TCOMPLEX128];
+ t1 = types[TCOMPLEX128];
goto num;
num:
if(t != T) {
if(isint[t->etype]) {
- n->type = t;
+ t1 = t;
n->val = toint(n->val);
}
else
if(isfloat[t->etype]) {
- n->type = t;
+ t1 = t;
n->val = toflt(n->val);
}
else
if(iscomplex[t->etype]) {
- n->type = t;
+ t1 = t;
n->val = tocplx(n->val);
}
}
- overflow(n->val, n->type);
+ overflow(n->val, t1);
+ convlit(np, t1);
break;
}
lineno = lno;
diff --git a/test/shift1.go b/test/shift1.go
index b33d22ff8..f1ec0bf58 100644
--- a/test/shift1.go
+++ b/test/shift1.go
@@ -36,3 +36,10 @@ var (
b2 = 1.0 << c // ERROR "overflow"
d2 = f(1.0 << c) // ERROR "overflow"
)
+
+var (
+ // issues 4882, 4936.
+ a3 = 1.0<<s + 0 // ERROR "invalid operation|shift of non-integer operand"
+ // issue 4937
+ b3 = 1<<s + 1 + 1.0 // ERROR "invalid operation|shift of non-integer operand"
+)