1
0
mirror of https://github.com/golang/go synced 2024-11-23 16:00:06 -07:00

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 <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>
This commit is contained in:
Cuong Manh Le 2020-09-16 15:42:00 +07:00
parent 1ee30d25c5
commit 0dc369b127
2 changed files with 60 additions and 81 deletions

View 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
}

View 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)