From 0dc369b127651830edef453938dfb5c149aa37cf Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 16 Sep 2020 15:42:00 +0700 Subject: [PATCH] cmd/compile: make typecheck set correct untyped type Passes toolstash-check. Change-Id: Ie631d8dacb1cc76613e1f50da8422850ac7119a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/255217 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/const.go | 122 ++++++++--------------- src/cmd/compile/internal/gc/typecheck.go | 19 +++- 2 files changed, 60 insertions(+), 81 deletions(-) diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index fe73df9d57..59b2c56051 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -44,7 +44,7 @@ func (v Val) Ctype() Ctype { Fatalf("unexpected Ctype for %T", v.U) panic("unreachable") case nil: - return 0 + return CTxxx case *NilVal: return CTNIL case bool: @@ -261,7 +261,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod } if t == nil || !okforconst[t.Etype] { - t = defaultType(idealkind(n)) + t = defaultType(n.Type) } switch n.Op { @@ -994,10 +994,8 @@ func setconst(n *Node, v Val) { Xoffset: BADWIDTH, } n.SetVal(v) - if n.Type.IsUntyped() { - // TODO(mdempsky): Make typecheck responsible for setting - // the correct untyped type. - n.Type = idealType(v.Ctype()) + if vt := idealType(v.Ctype()); n.Type.IsUntyped() && n.Type != vt { + Fatalf("untyped type mismatch, have: %v, want: %v", n.Type, vt) } // Check range. @@ -1056,67 +1054,6 @@ func idealType(ct Ctype) *types.Type { return nil } -// idealkind returns a constant kind like consttype -// but for an arbitrary "ideal" (untyped constant) expression. -func idealkind(n *Node) Ctype { - if n == nil || !n.Type.IsUntyped() { - return CTxxx - } - - switch n.Op { - default: - return CTxxx - - case OLITERAL: - return n.Val().Ctype() - - // numeric kinds. - case OADD, - OAND, - OANDNOT, - OBITNOT, - ODIV, - ONEG, - OMOD, - OMUL, - OSUB, - OXOR, - OOR, - OPLUS: - k1 := idealkind(n.Left) - k2 := idealkind(n.Right) - if k1 > k2 { - return k1 - } else { - return k2 - } - - case OREAL, OIMAG: - return CTFLT - - case OCOMPLEX: - return CTCPLX - - case OADDSTR: - return CTSTR - - case OANDAND, - OEQ, - OGE, - OGT, - OLE, - OLT, - ONE, - ONOT, - OOROR: - return CTBOOL - - // shifts (beware!). - case OLSH, ORSH: - return idealkind(n.Left) - } -} - // defaultlit on both nodes simultaneously; // if they're both ideal going in they better // get the same type going out. @@ -1152,32 +1089,57 @@ func defaultlit2(l *Node, r *Node, force bool) (*Node, *Node) { return l, r } - k := idealkind(l) - if rk := idealkind(r); rk > k { - k = rk + nn := l + if ctype(r.Type) > ctype(l.Type) { + nn = r } - t := defaultType(k) + + t := defaultType(nn.Type) l = convlit(l, t) r = convlit(r, t) return l, r } -func defaultType(k Ctype) *types.Type { - switch k { - case CTBOOL: +func ctype(t *types.Type) Ctype { + switch t { + case types.Idealbool: + return CTBOOL + case types.Idealstring: + return CTSTR + case types.Idealint: + return CTINT + case types.Idealrune: + return CTRUNE + case types.Idealfloat: + return CTFLT + case types.Idealcomplex: + return CTCPLX + } + Fatalf("bad type %v", t) + panic("unreachable") +} + +func defaultType(t *types.Type) *types.Type { + if !t.IsUntyped() { + return t + } + + switch t { + case types.Idealbool: return types.Types[TBOOL] - case CTSTR: + case types.Idealstring: return types.Types[TSTRING] - case CTINT: + case types.Idealint: return types.Types[TINT] - case CTRUNE: + case types.Idealrune: return types.Runetype - case CTFLT: + case types.Idealfloat: return types.Types[TFLOAT64] - case CTCPLX: + case types.Idealcomplex: return types.Types[TCOMPLEX128] } - Fatalf("bad idealkind: %v", k) + + Fatalf("bad type %v", t) return nil } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 834c1a8ee6..274787a22b 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -623,6 +623,9 @@ func typecheck1(n *Node, top int) (res *Node) { // no defaultlit for left // the outer context gives the type n.Type = l.Type + if (l.Type == types.Idealfloat || l.Type == types.Idealcomplex) && r.Op == OLITERAL { + n.Type = types.Idealint + } break } @@ -798,6 +801,20 @@ 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 @@ -1678,7 +1695,7 @@ func typecheck1(n *Node, top int) (res *Node) { } var why string n.Op = convertop(n.Left.Op == OLITERAL, t, n.Type, &why) - if n.Op == 0 { + if n.Op == OXXX { if !n.Diag() && !n.Type.Broke() && !n.Left.Diag() { yyerror("cannot convert %L to type %v%s", n.Left, n.Type, why) n.SetDiag(true)