blob: c4c1ef58cadb103a91c1a0e79d3c1aa6acd4cbda [file] [log] [blame]
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package typecheck
import (
"go/constant"
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
)
// tcArrayType typechecks an OTARRAY node.
func tcArrayType(n *ir.ArrayType) ir.Node {
n.Elem = typecheckNtype(n.Elem)
if n.Elem.Type() == nil {
return n
}
if n.Len == nil { // [...]T
if !n.Diag() {
n.SetDiag(true)
base.Errorf("use of [...] array outside of array literal")
}
return n
}
n.Len = indexlit(Expr(n.Len))
size := n.Len
if ir.ConstType(size) != constant.Int {
switch {
case size.Type() == nil:
// Error already reported elsewhere.
case size.Type().IsInteger() && size.Op() != ir.OLITERAL:
base.Errorf("non-constant array bound %v", size)
default:
base.Errorf("invalid array bound %v", size)
}
return n
}
v := size.Val()
if ir.ConstOverflow(v, types.Types[types.TINT]) {
base.Errorf("array bound is too large")
return n
}
if constant.Sign(v) < 0 {
base.Errorf("array bound must be non-negative")
return n
}
bound, _ := constant.Int64Val(v)
t := types.NewArray(n.Elem.Type(), bound)
n.SetOTYPE(t)
types.CheckSize(t)
return n
}
// tcChanType typechecks an OTCHAN node.
func tcChanType(n *ir.ChanType) ir.Node {
n.Elem = typecheckNtype(n.Elem)
l := n.Elem
if l.Type() == nil {
return n
}
if l.Type().NotInHeap() {
base.Errorf("chan of incomplete (or unallocatable) type not allowed")
}
n.SetOTYPE(types.NewChan(l.Type(), n.Dir))
return n
}
// tcFuncType typechecks an OTFUNC node.
func tcFuncType(n *ir.FuncType) ir.Node {
misc := func(f *types.Field, nf *ir.Field) {
f.SetIsDDD(nf.IsDDD)
if nf.Decl != nil {
nf.Decl.SetType(f.Type)
f.Nname = nf.Decl
}
}
lno := base.Pos
var recv *types.Field
if n.Recv != nil {
recv = tcField(n.Recv, misc)
}
t := types.NewSignature(types.LocalPkg, recv, nil, tcFields(n.Params, misc), tcFields(n.Results, misc))
checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())
base.Pos = lno
n.SetOTYPE(t)
return n
}
// tcInterfaceType typechecks an OTINTER node.
func tcInterfaceType(n *ir.InterfaceType) ir.Node {
if len(n.Methods) == 0 {
n.SetOTYPE(types.Types[types.TINTER])
return n
}
lno := base.Pos
methods := tcFields(n.Methods, nil)
base.Pos = lno
n.SetOTYPE(types.NewInterface(types.LocalPkg, methods, false))
return n
}
// tcMapType typechecks an OTMAP node.
func tcMapType(n *ir.MapType) ir.Node {
n.Key = typecheckNtype(n.Key)
n.Elem = typecheckNtype(n.Elem)
l := n.Key
r := n.Elem
if l.Type() == nil || r.Type() == nil {
return n
}
if l.Type().NotInHeap() {
base.Errorf("incomplete (or unallocatable) map key not allowed")
}
if r.Type().NotInHeap() {
base.Errorf("incomplete (or unallocatable) map value not allowed")
}
n.SetOTYPE(types.NewMap(l.Type(), r.Type()))
mapqueue = append(mapqueue, n) // check map keys when all types are settled
return n
}
// tcSliceType typechecks an OTSLICE node.
func tcSliceType(n *ir.SliceType) ir.Node {
n.Elem = typecheckNtype(n.Elem)
if n.Elem.Type() == nil {
return n
}
t := types.NewSlice(n.Elem.Type())
n.SetOTYPE(t)
types.CheckSize(t)
return n
}
// tcStructType typechecks an OTSTRUCT node.
func tcStructType(n *ir.StructType) ir.Node {
lno := base.Pos
fields := tcFields(n.Fields, func(f *types.Field, nf *ir.Field) {
if nf.Embedded {
checkembeddedtype(f.Type)
f.Embedded = 1
}
f.Note = nf.Note
})
checkdupfields("field", fields)
base.Pos = lno
n.SetOTYPE(types.NewStruct(types.LocalPkg, fields))
return n
}
// tcField typechecks a generic Field.
// misc can be provided to handle specialized typechecking.
func tcField(n *ir.Field, misc func(*types.Field, *ir.Field)) *types.Field {
base.Pos = n.Pos
if n.Ntype != nil {
n.Type = typecheckNtype(n.Ntype).Type()
n.Ntype = nil
}
f := types.NewField(n.Pos, n.Sym, n.Type)
if misc != nil {
misc(f, n)
}
return f
}
// tcFields typechecks a slice of generic Fields.
// misc can be provided to handle specialized typechecking.
func tcFields(l []*ir.Field, misc func(*types.Field, *ir.Field)) []*types.Field {
fields := make([]*types.Field, len(l))
for i, n := range l {
fields[i] = tcField(n, misc)
}
return fields
}