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:
parent
1ee30d25c5
commit
0dc369b127
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user