]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: make typecheck set correct untyped type
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Wed, 16 Sep 2020 08:42:00 +0000 (15:42 +0700)
committerCuong Manh Le <cuong.manhle.vn@gmail.com>
Fri, 18 Sep 2020 04:03:27 +0000 (04:03 +0000)
Passes toolstash-check.

Change-Id: Ie631d8dacb1cc76613e1f50da8422850ac7119a1
Reviewed-on: https://go-review.googlesource.com/c/go/+/255217
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/const.go
src/cmd/compile/internal/gc/typecheck.go

index fe73df9d57422c94e9113088855b473614aef45c..59b2c56051ad549ff33bc76979942eddf1b4caa7 100644 (file)
@@ -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
 }
 
index 834c1a8ee68463eac2e979dfba204035e999f5ee..274787a22bf37a1d91e7bfa28d358de1b066ef77 100644 (file)
@@ -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)