From dc59469f5178a0715a582cbfcc4cf9c06a2c9e82 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 17 Sep 2020 22:53:39 +0700 Subject: [PATCH] cmd/compile: move validation from unary/binaryOp to typecheck CL 254400 makes typecheck set untyped type correctly. We now have enough information to check valid operators for a type in typecheck. Passes toolstash-check. Change-Id: I01a7606ee6ce9964ec52430d53eaa886442bd17f Reviewed-on: https://go-review.googlesource.com/c/go/+/255617 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/const.go | 19 +--------- src/cmd/compile/internal/gc/typecheck.go | 44 ++++++++++-------------- 2 files changed, 19 insertions(+), 44 deletions(-) diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index 59b2c56051..399d0148bb 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -838,10 +838,6 @@ Outer: return Val{} } u.Quo(y) - case OMOD, OOR, OAND, OANDNOT, OXOR: - // TODO(mdempsky): Move to typecheck; see #31060. - yyerror("invalid operation: operator %v not defined on untyped float", op) - return Val{} default: break Outer } @@ -867,10 +863,6 @@ Outer: yyerror("complex division by zero") return Val{} } - case OMOD, OOR, OAND, OANDNOT, OXOR: - // TODO(mdempsky): Move to typecheck; see #31060. - yyerror("invalid operation: operator %v not defined on untyped complex", op) - return Val{} default: break Outer } @@ -932,15 +924,6 @@ func unaryOp(op Op, x Val, t *types.Type) Val { } u.Xor(x) return Val{U: u} - - case CTFLT: - // TODO(mdempsky): Move to typecheck; see #31060. - yyerror("invalid operation: operator %v not defined on untyped float", op) - return Val{} - case CTCPLX: - // TODO(mdempsky): Move to typecheck; see #31060. - yyerror("invalid operation: operator %v not defined on untyped complex", op) - return Val{} } case ONOT: @@ -1120,7 +1103,7 @@ func ctype(t *types.Type) Ctype { } func defaultType(t *types.Type) *types.Type { - if !t.IsUntyped() { + if !t.IsUntyped() || t.Etype == TNIL { return t } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 274787a22b..faa13d72f9 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -716,8 +716,22 @@ func typecheck1(n *Node, top int) (res *Node) { } } - if !okfor[op][et] { - yyerror("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(t)) + if t.Etype == TIDEAL { + switch { + case l.Type == types.Idealcomplex || r.Type == types.Idealcomplex: + t = types.Idealcomplex + case l.Type == types.Idealfloat || r.Type == types.Idealfloat: + t = types.Idealfloat + case l.Type == types.Idealrune || r.Type == types.Idealrune: + t = types.Idealrune + case l.Type == types.Idealint || r.Type == types.Idealint: + t = types.Idealint + default: + Fatalf("bad untyped type: %v", t) + } + } + if dt := defaultType(t); !okfor[op][dt.Etype] { + yyerror("invalid operation: %v (operator %v not defined on %v)", n, op, t) n.Type = nil return n } @@ -756,15 +770,7 @@ func typecheck1(n *Node, top int) (res *Node) { } } - t = l.Type if iscmp[n.Op] { - // TIDEAL includes complex constant, but only OEQ and ONE are defined for complex, - // so check that the n.op is available for complex here before doing evconst. - if !okfor[n.Op][TCOMPLEX128] && (Isconst(l, CTCPLX) || Isconst(r, CTCPLX)) { - yyerror("invalid operation: %v (operator %v not defined on untyped complex)", n, n.Op) - n.Type = nil - return n - } evconst(n) t = types.Idealbool if n.Op != OLITERAL { @@ -801,20 +807,6 @@ func typecheck1(n *Node, top int) (res *Node) { } n.Type = t - if t.Etype == TIDEAL { - switch { - case l.Type == types.Idealcomplex || r.Type == types.Idealcomplex: - n.Type = types.Idealcomplex - case l.Type == types.Idealfloat || r.Type == types.Idealfloat: - n.Type = types.Idealfloat - case l.Type == types.Idealrune || r.Type == types.Idealrune: - n.Type = types.Idealrune - case l.Type == types.Idealint || r.Type == types.Idealint: - n.Type = types.Idealint - default: - Fatalf("bad untyped type: %v", t) - } - } case OBITNOT, ONEG, ONOT, OPLUS: ok |= ctxExpr @@ -825,8 +817,8 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = nil return n } - if !okfor[n.Op][t.Etype] { - yyerror("invalid operation: %v %v", n.Op, t) + if !okfor[n.Op][defaultType(t).Etype] { + yyerror("invalid operation: %v (operator %v not defined on %s)", n, n.Op, typekind(t)) n.Type = nil return n } -- 2.50.0