github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/typecheck/expr.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package typecheck
     6  
     7  import (
     8  	"fmt"
     9  	"go/constant"
    10  	"go/token"
    11  	"strings"
    12  
    13  	"github.com/go-asm/go/types/errors"
    14  
    15  	"github.com/go-asm/go/cmd/compile/base"
    16  	"github.com/go-asm/go/cmd/compile/ir"
    17  	"github.com/go-asm/go/cmd/compile/types"
    18  	"github.com/go-asm/go/cmd/src"
    19  )
    20  
    21  func tcShift(n, l, r ir.Node) (ir.Node, ir.Node, *types.Type) {
    22  	if l.Type() == nil || r.Type() == nil {
    23  		return l, r, nil
    24  	}
    25  
    26  	r = DefaultLit(r, types.Types[types.TUINT])
    27  	t := r.Type()
    28  	if !t.IsInteger() {
    29  		base.Errorf("invalid operation: %v (shift count type %v, must be integer)", n, r.Type())
    30  		return l, r, nil
    31  	}
    32  	t = l.Type()
    33  	if t != nil && t.Kind() != types.TIDEAL && !t.IsInteger() {
    34  		base.Errorf("invalid operation: %v (shift of type %v)", n, t)
    35  		return l, r, nil
    36  	}
    37  
    38  	// no DefaultLit for left
    39  	// the outer context gives the type
    40  	t = l.Type()
    41  	if (l.Type() == types.UntypedFloat || l.Type() == types.UntypedComplex) && r.Op() == ir.OLITERAL {
    42  		t = types.UntypedInt
    43  	}
    44  	return l, r, t
    45  }
    46  
    47  // tcArith typechecks operands of a binary arithmetic expression.
    48  // The result of tcArith MUST be assigned back to original operands,
    49  // t is the type of the expression, and should be set by the caller. e.g:
    50  //
    51  //	n.X, n.Y, t = tcArith(n, op, n.X, n.Y)
    52  //	n.SetType(t)
    53  func tcArith(n ir.Node, op ir.Op, l, r ir.Node) (ir.Node, ir.Node, *types.Type) {
    54  	l, r = defaultlit2(l, r, false)
    55  	if l.Type() == nil || r.Type() == nil {
    56  		return l, r, nil
    57  	}
    58  	t := l.Type()
    59  	if t.Kind() == types.TIDEAL {
    60  		t = r.Type()
    61  	}
    62  	aop := ir.OXXX
    63  	if n.Op().IsCmp() && t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) {
    64  		// comparison is okay as long as one side is
    65  		// assignable to the other.  convert so they have
    66  		// the same type.
    67  		//
    68  		// the only conversion that isn't a no-op is concrete == interface.
    69  		// in that case, check comparability of the concrete type.
    70  		// The conversion allocates, so only do it if the concrete type is huge.
    71  		converted := false
    72  		if r.Type().Kind() != types.TBLANK {
    73  			aop, _ = assignOp(l.Type(), r.Type())
    74  			if aop != ir.OXXX {
    75  				if r.Type().IsInterface() && !l.Type().IsInterface() && !types.IsComparable(l.Type()) {
    76  					base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(l.Type()))
    77  					return l, r, nil
    78  				}
    79  
    80  				types.CalcSize(l.Type())
    81  				if r.Type().IsInterface() == l.Type().IsInterface() || l.Type().Size() >= 1<<16 {
    82  					l = ir.NewConvExpr(base.Pos, aop, r.Type(), l)
    83  					l.SetTypecheck(1)
    84  				}
    85  
    86  				t = r.Type()
    87  				converted = true
    88  			}
    89  		}
    90  
    91  		if !converted && l.Type().Kind() != types.TBLANK {
    92  			aop, _ = assignOp(r.Type(), l.Type())
    93  			if aop != ir.OXXX {
    94  				if l.Type().IsInterface() && !r.Type().IsInterface() && !types.IsComparable(r.Type()) {
    95  					base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(r.Type()))
    96  					return l, r, nil
    97  				}
    98  
    99  				types.CalcSize(r.Type())
   100  				if r.Type().IsInterface() == l.Type().IsInterface() || r.Type().Size() >= 1<<16 {
   101  					r = ir.NewConvExpr(base.Pos, aop, l.Type(), r)
   102  					r.SetTypecheck(1)
   103  				}
   104  
   105  				t = l.Type()
   106  			}
   107  		}
   108  	}
   109  
   110  	if t.Kind() != types.TIDEAL && !types.Identical(l.Type(), r.Type()) {
   111  		l, r = defaultlit2(l, r, true)
   112  		if l.Type() == nil || r.Type() == nil {
   113  			return l, r, nil
   114  		}
   115  		if l.Type().IsInterface() == r.Type().IsInterface() || aop == 0 {
   116  			base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
   117  			return l, r, nil
   118  		}
   119  	}
   120  
   121  	if t.Kind() == types.TIDEAL {
   122  		t = mixUntyped(l.Type(), r.Type())
   123  	}
   124  	if dt := defaultType(t); !okfor[op][dt.Kind()] {
   125  		base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(t))
   126  		return l, r, nil
   127  	}
   128  
   129  	// okfor allows any array == array, map == map, func == func.
   130  	// restrict to slice/map/func == nil and nil == slice/map/func.
   131  	if l.Type().IsArray() && !types.IsComparable(l.Type()) {
   132  		base.Errorf("invalid operation: %v (%v cannot be compared)", n, l.Type())
   133  		return l, r, nil
   134  	}
   135  
   136  	if l.Type().IsSlice() && !ir.IsNil(l) && !ir.IsNil(r) {
   137  		base.Errorf("invalid operation: %v (slice can only be compared to nil)", n)
   138  		return l, r, nil
   139  	}
   140  
   141  	if l.Type().IsMap() && !ir.IsNil(l) && !ir.IsNil(r) {
   142  		base.Errorf("invalid operation: %v (map can only be compared to nil)", n)
   143  		return l, r, nil
   144  	}
   145  
   146  	if l.Type().Kind() == types.TFUNC && !ir.IsNil(l) && !ir.IsNil(r) {
   147  		base.Errorf("invalid operation: %v (func can only be compared to nil)", n)
   148  		return l, r, nil
   149  	}
   150  
   151  	if l.Type().IsStruct() {
   152  		if f := types.IncomparableField(l.Type()); f != nil {
   153  			base.Errorf("invalid operation: %v (struct containing %v cannot be compared)", n, f.Type)
   154  			return l, r, nil
   155  		}
   156  	}
   157  
   158  	return l, r, t
   159  }
   160  
   161  // The result of tcCompLit MUST be assigned back to n, e.g.
   162  //
   163  //	n.Left = tcCompLit(n.Left)
   164  func tcCompLit(n *ir.CompLitExpr) (res ir.Node) {
   165  	if base.EnableTrace && base.Flag.LowerT {
   166  		defer tracePrint("tcCompLit", n)(&res)
   167  	}
   168  
   169  	lno := base.Pos
   170  	defer func() {
   171  		base.Pos = lno
   172  	}()
   173  
   174  	ir.SetPos(n)
   175  
   176  	t := n.Type()
   177  	base.AssertfAt(t != nil, n.Pos(), "missing type in composite literal")
   178  
   179  	switch t.Kind() {
   180  	default:
   181  		base.Errorf("invalid composite literal type %v", t)
   182  		n.SetType(nil)
   183  
   184  	case types.TARRAY:
   185  		typecheckarraylit(t.Elem(), t.NumElem(), n.List, "array literal")
   186  		n.SetOp(ir.OARRAYLIT)
   187  
   188  	case types.TSLICE:
   189  		length := typecheckarraylit(t.Elem(), -1, n.List, "slice literal")
   190  		n.SetOp(ir.OSLICELIT)
   191  		n.Len = length
   192  
   193  	case types.TMAP:
   194  		for i3, l := range n.List {
   195  			ir.SetPos(l)
   196  			if l.Op() != ir.OKEY {
   197  				n.List[i3] = Expr(l)
   198  				base.Errorf("missing key in map literal")
   199  				continue
   200  			}
   201  			l := l.(*ir.KeyExpr)
   202  
   203  			r := l.Key
   204  			r = Expr(r)
   205  			l.Key = AssignConv(r, t.Key(), "map key")
   206  
   207  			r = l.Value
   208  			r = Expr(r)
   209  			l.Value = AssignConv(r, t.Elem(), "map value")
   210  		}
   211  
   212  		n.SetOp(ir.OMAPLIT)
   213  
   214  	case types.TSTRUCT:
   215  		// Need valid field offsets for Xoffset below.
   216  		types.CalcSize(t)
   217  
   218  		errored := false
   219  		if len(n.List) != 0 && nokeys(n.List) {
   220  			// simple list of variables
   221  			ls := n.List
   222  			for i, n1 := range ls {
   223  				ir.SetPos(n1)
   224  				n1 = Expr(n1)
   225  				ls[i] = n1
   226  				if i >= t.NumFields() {
   227  					if !errored {
   228  						base.Errorf("too many values in %v", n)
   229  						errored = true
   230  					}
   231  					continue
   232  				}
   233  
   234  				f := t.Field(i)
   235  				s := f.Sym
   236  
   237  				// Do the test for assigning to unexported fields.
   238  				// But if this is an instantiated function, then
   239  				// the function has already been typechecked. In
   240  				// that case, don't do the test, since it can fail
   241  				// for the closure structs created in
   242  				// walkClosure(), because the instantiated
   243  				// function is compiled as if in the source
   244  				// package of the generic function.
   245  				if !(ir.CurFunc != nil && strings.Contains(ir.CurFunc.Nname.Sym().Name, "[")) {
   246  					if s != nil && !types.IsExported(s.Name) && s.Pkg != types.LocalPkg {
   247  						base.Errorf("implicit assignment of unexported field '%s' in %v literal", s.Name, t)
   248  					}
   249  				}
   250  				// No pushtype allowed here. Must name fields for that.
   251  				n1 = AssignConv(n1, f.Type, "field value")
   252  				ls[i] = ir.NewStructKeyExpr(base.Pos, f, n1)
   253  			}
   254  			if len(ls) < t.NumFields() {
   255  				base.Errorf("too few values in %v", n)
   256  			}
   257  		} else {
   258  			hash := make(map[string]bool)
   259  
   260  			// keyed list
   261  			ls := n.List
   262  			for i, n := range ls {
   263  				ir.SetPos(n)
   264  
   265  				sk, ok := n.(*ir.StructKeyExpr)
   266  				if !ok {
   267  					kv, ok := n.(*ir.KeyExpr)
   268  					if !ok {
   269  						if !errored {
   270  							base.Errorf("mixture of field:value and value initializers")
   271  							errored = true
   272  						}
   273  						ls[i] = Expr(n)
   274  						continue
   275  					}
   276  
   277  					sk = tcStructLitKey(t, kv)
   278  					if sk == nil {
   279  						continue
   280  					}
   281  
   282  					fielddup(sk.Sym().Name, hash)
   283  				}
   284  
   285  				// No pushtype allowed here. Tried and rejected.
   286  				sk.Value = Expr(sk.Value)
   287  				sk.Value = AssignConv(sk.Value, sk.Field.Type, "field value")
   288  				ls[i] = sk
   289  			}
   290  		}
   291  
   292  		n.SetOp(ir.OSTRUCTLIT)
   293  	}
   294  
   295  	return n
   296  }
   297  
   298  // tcStructLitKey typechecks an OKEY node that appeared within a
   299  // struct literal.
   300  func tcStructLitKey(typ *types.Type, kv *ir.KeyExpr) *ir.StructKeyExpr {
   301  	key := kv.Key
   302  
   303  	sym := key.Sym()
   304  
   305  	// An OXDOT uses the Sym field to hold
   306  	// the field to the right of the dot,
   307  	// so s will be non-nil, but an OXDOT
   308  	// is never a valid struct literal key.
   309  	if sym == nil || sym.Pkg != types.LocalPkg || key.Op() == ir.OXDOT || sym.IsBlank() {
   310  		base.Errorf("invalid field name %v in struct initializer", key)
   311  		return nil
   312  	}
   313  
   314  	if f := Lookdot1(nil, sym, typ, typ.Fields(), 0); f != nil {
   315  		return ir.NewStructKeyExpr(kv.Pos(), f, kv.Value)
   316  	}
   317  
   318  	if ci := Lookdot1(nil, sym, typ, typ.Fields(), 2); ci != nil { // Case-insensitive lookup.
   319  		if visible(ci.Sym) {
   320  			base.Errorf("unknown field '%v' in struct literal of type %v (but does have %v)", sym, typ, ci.Sym)
   321  		} else if nonexported(sym) && sym.Name == ci.Sym.Name { // Ensure exactness before the suggestion.
   322  			base.Errorf("cannot refer to unexported field '%v' in struct literal of type %v", sym, typ)
   323  		} else {
   324  			base.Errorf("unknown field '%v' in struct literal of type %v", sym, typ)
   325  		}
   326  		return nil
   327  	}
   328  
   329  	var f *types.Field
   330  	p, _ := dotpath(sym, typ, &f, true)
   331  	if p == nil || f.IsMethod() {
   332  		base.Errorf("unknown field '%v' in struct literal of type %v", sym, typ)
   333  		return nil
   334  	}
   335  
   336  	// dotpath returns the parent embedded types in reverse order.
   337  	var ep []string
   338  	for ei := len(p) - 1; ei >= 0; ei-- {
   339  		ep = append(ep, p[ei].field.Sym.Name)
   340  	}
   341  	ep = append(ep, sym.Name)
   342  	base.Errorf("cannot use promoted field %v in struct literal of type %v", strings.Join(ep, "."), typ)
   343  	return nil
   344  }
   345  
   346  // tcConv typechecks an OCONV node.
   347  func tcConv(n *ir.ConvExpr) ir.Node {
   348  	types.CheckSize(n.Type()) // ensure width is calculated for backend
   349  	n.X = Expr(n.X)
   350  	n.X = convlit1(n.X, n.Type(), true, nil)
   351  	t := n.X.Type()
   352  	if t == nil || n.Type() == nil {
   353  		n.SetType(nil)
   354  		return n
   355  	}
   356  	op, why := convertOp(n.X.Op() == ir.OLITERAL, t, n.Type())
   357  	if op == ir.OXXX {
   358  		// Due to //go:nointerface, we may be stricter than types2 here (#63333).
   359  		base.ErrorfAt(n.Pos(), errors.InvalidConversion, "cannot convert %L to type %v%s", n.X, n.Type(), why)
   360  		n.SetType(nil)
   361  		return n
   362  	}
   363  
   364  	n.SetOp(op)
   365  	switch n.Op() {
   366  	case ir.OCONVNOP:
   367  		if t.Kind() == n.Type().Kind() {
   368  			switch t.Kind() {
   369  			case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128:
   370  				// Floating point casts imply rounding and
   371  				// so the conversion must be kept.
   372  				n.SetOp(ir.OCONV)
   373  			}
   374  		}
   375  
   376  	// do not convert to []byte literal. See CL 125796.
   377  	// generated code and compiler memory footprint is better without it.
   378  	case ir.OSTR2BYTES:
   379  		// ok
   380  
   381  	case ir.OSTR2RUNES:
   382  		if n.X.Op() == ir.OLITERAL {
   383  			return stringtoruneslit(n)
   384  		}
   385  
   386  	case ir.OBYTES2STR:
   387  		if t.Elem() != types.ByteType && t.Elem() != types.Types[types.TUINT8] {
   388  			// If t is a slice of a user-defined byte type B (not uint8
   389  			// or byte), then add an extra CONVNOP from []B to []byte, so
   390  			// that the call to slicebytetostring() added in walk will
   391  			// typecheck correctly.
   392  			n.X = ir.NewConvExpr(n.X.Pos(), ir.OCONVNOP, types.NewSlice(types.ByteType), n.X)
   393  			n.X.SetTypecheck(1)
   394  		}
   395  
   396  	case ir.ORUNES2STR:
   397  		if t.Elem() != types.RuneType && t.Elem() != types.Types[types.TINT32] {
   398  			// If t is a slice of a user-defined rune type B (not uint32
   399  			// or rune), then add an extra CONVNOP from []B to []rune, so
   400  			// that the call to slicerunetostring() added in walk will
   401  			// typecheck correctly.
   402  			n.X = ir.NewConvExpr(n.X.Pos(), ir.OCONVNOP, types.NewSlice(types.RuneType), n.X)
   403  			n.X.SetTypecheck(1)
   404  		}
   405  
   406  	}
   407  	return n
   408  }
   409  
   410  // DotField returns a field selector expression that selects the
   411  // index'th field of the given expression, which must be of struct or
   412  // pointer-to-struct type.
   413  func DotField(pos src.XPos, x ir.Node, index int) *ir.SelectorExpr {
   414  	op, typ := ir.ODOT, x.Type()
   415  	if typ.IsPtr() {
   416  		op, typ = ir.ODOTPTR, typ.Elem()
   417  	}
   418  	if !typ.IsStruct() {
   419  		base.FatalfAt(pos, "DotField of non-struct: %L", x)
   420  	}
   421  
   422  	// TODO(mdempsky): This is the backend's responsibility.
   423  	types.CalcSize(typ)
   424  
   425  	field := typ.Field(index)
   426  	return dot(pos, field.Type, op, x, field)
   427  }
   428  
   429  func dot(pos src.XPos, typ *types.Type, op ir.Op, x ir.Node, selection *types.Field) *ir.SelectorExpr {
   430  	n := ir.NewSelectorExpr(pos, op, x, selection.Sym)
   431  	n.Selection = selection
   432  	n.SetType(typ)
   433  	n.SetTypecheck(1)
   434  	return n
   435  }
   436  
   437  // XDotMethod returns an expression representing the field selection
   438  // x.sym. If any implicit field selection are necessary, those are
   439  // inserted too.
   440  func XDotField(pos src.XPos, x ir.Node, sym *types.Sym) *ir.SelectorExpr {
   441  	n := Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr)
   442  	if n.Op() != ir.ODOT && n.Op() != ir.ODOTPTR {
   443  		base.FatalfAt(pos, "unexpected result op: %v (%v)", n.Op(), n)
   444  	}
   445  	return n
   446  }
   447  
   448  // XDotMethod returns an expression representing the method value
   449  // x.sym (i.e., x is a value, not a type). If any implicit field
   450  // selection are necessary, those are inserted too.
   451  //
   452  // If callee is true, the result is an ODOTMETH/ODOTINTER, otherwise
   453  // an OMETHVALUE.
   454  func XDotMethod(pos src.XPos, x ir.Node, sym *types.Sym, callee bool) *ir.SelectorExpr {
   455  	n := ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)
   456  	if callee {
   457  		n = Callee(n).(*ir.SelectorExpr)
   458  		if n.Op() != ir.ODOTMETH && n.Op() != ir.ODOTINTER {
   459  			base.FatalfAt(pos, "unexpected result op: %v (%v)", n.Op(), n)
   460  		}
   461  	} else {
   462  		n = Expr(n).(*ir.SelectorExpr)
   463  		if n.Op() != ir.OMETHVALUE {
   464  			base.FatalfAt(pos, "unexpected result op: %v (%v)", n.Op(), n)
   465  		}
   466  	}
   467  	return n
   468  }
   469  
   470  // tcDot typechecks an OXDOT or ODOT node.
   471  func tcDot(n *ir.SelectorExpr, top int) ir.Node {
   472  	if n.Op() == ir.OXDOT {
   473  		n = AddImplicitDots(n)
   474  		n.SetOp(ir.ODOT)
   475  		if n.X == nil {
   476  			n.SetType(nil)
   477  			return n
   478  		}
   479  	}
   480  
   481  	n.X = Expr(n.X)
   482  	n.X = DefaultLit(n.X, nil)
   483  
   484  	t := n.X.Type()
   485  	if t == nil {
   486  		base.UpdateErrorDot(ir.Line(n), fmt.Sprint(n.X), fmt.Sprint(n))
   487  		n.SetType(nil)
   488  		return n
   489  	}
   490  
   491  	if n.X.Op() == ir.OTYPE {
   492  		base.FatalfAt(n.Pos(), "use NewMethodExpr to construct OMETHEXPR")
   493  	}
   494  
   495  	if t.IsPtr() && !t.Elem().IsInterface() {
   496  		t = t.Elem()
   497  		if t == nil {
   498  			n.SetType(nil)
   499  			return n
   500  		}
   501  		n.SetOp(ir.ODOTPTR)
   502  		types.CheckSize(t)
   503  	}
   504  
   505  	if n.Sel.IsBlank() {
   506  		base.Errorf("cannot refer to blank field or method")
   507  		n.SetType(nil)
   508  		return n
   509  	}
   510  
   511  	if Lookdot(n, t, 0) == nil {
   512  		// Legitimate field or method lookup failed, try to explain the error
   513  		switch {
   514  		case t.IsEmptyInterface():
   515  			base.Errorf("%v undefined (type %v is interface with no methods)", n, n.X.Type())
   516  
   517  		case t.IsPtr() && t.Elem().IsInterface():
   518  			// Pointer to interface is almost always a mistake.
   519  			base.Errorf("%v undefined (type %v is pointer to interface, not interface)", n, n.X.Type())
   520  
   521  		case Lookdot(n, t, 1) != nil:
   522  			// Field or method matches by name, but it is not exported.
   523  			base.Errorf("%v undefined (cannot refer to unexported field or method %v)", n, n.Sel)
   524  
   525  		default:
   526  			if mt := Lookdot(n, t, 2); mt != nil && visible(mt.Sym) { // Case-insensitive lookup.
   527  				base.Errorf("%v undefined (type %v has no field or method %v, but does have %v)", n, n.X.Type(), n.Sel, mt.Sym)
   528  			} else {
   529  				base.Errorf("%v undefined (type %v has no field or method %v)", n, n.X.Type(), n.Sel)
   530  			}
   531  		}
   532  		n.SetType(nil)
   533  		return n
   534  	}
   535  
   536  	if (n.Op() == ir.ODOTINTER || n.Op() == ir.ODOTMETH) && top&ctxCallee == 0 {
   537  		n.SetOp(ir.OMETHVALUE)
   538  		n.SetType(NewMethodType(n.Type(), nil))
   539  	}
   540  	return n
   541  }
   542  
   543  // tcDotType typechecks an ODOTTYPE node.
   544  func tcDotType(n *ir.TypeAssertExpr) ir.Node {
   545  	n.X = Expr(n.X)
   546  	n.X = DefaultLit(n.X, nil)
   547  	l := n.X
   548  	t := l.Type()
   549  	if t == nil {
   550  		n.SetType(nil)
   551  		return n
   552  	}
   553  	if !t.IsInterface() {
   554  		base.Errorf("invalid type assertion: %v (non-interface type %v on left)", n, t)
   555  		n.SetType(nil)
   556  		return n
   557  	}
   558  
   559  	base.AssertfAt(n.Type() != nil, n.Pos(), "missing type: %v", n)
   560  
   561  	if n.Type() != nil && !n.Type().IsInterface() {
   562  		why := ImplementsExplain(n.Type(), t)
   563  		if why != "" {
   564  			base.Fatalf("impossible type assertion:\n\t%s", why)
   565  			n.SetType(nil)
   566  			return n
   567  		}
   568  	}
   569  	return n
   570  }
   571  
   572  // tcITab typechecks an OITAB node.
   573  func tcITab(n *ir.UnaryExpr) ir.Node {
   574  	n.X = Expr(n.X)
   575  	t := n.X.Type()
   576  	if t == nil {
   577  		n.SetType(nil)
   578  		return n
   579  	}
   580  	if !t.IsInterface() {
   581  		base.Fatalf("OITAB of %v", t)
   582  	}
   583  	n.SetType(types.NewPtr(types.Types[types.TUINTPTR]))
   584  	return n
   585  }
   586  
   587  // tcIndex typechecks an OINDEX node.
   588  func tcIndex(n *ir.IndexExpr) ir.Node {
   589  	n.X = Expr(n.X)
   590  	n.X = DefaultLit(n.X, nil)
   591  	n.X = implicitstar(n.X)
   592  	l := n.X
   593  	n.Index = Expr(n.Index)
   594  	r := n.Index
   595  	t := l.Type()
   596  	if t == nil || r.Type() == nil {
   597  		n.SetType(nil)
   598  		return n
   599  	}
   600  	switch t.Kind() {
   601  	default:
   602  		base.Errorf("invalid operation: %v (type %v does not support indexing)", n, t)
   603  		n.SetType(nil)
   604  		return n
   605  
   606  	case types.TSTRING, types.TARRAY, types.TSLICE:
   607  		n.Index = indexlit(n.Index)
   608  		if t.IsString() {
   609  			n.SetType(types.ByteType)
   610  		} else {
   611  			n.SetType(t.Elem())
   612  		}
   613  		why := "string"
   614  		if t.IsArray() {
   615  			why = "array"
   616  		} else if t.IsSlice() {
   617  			why = "slice"
   618  		}
   619  
   620  		if n.Index.Type() != nil && !n.Index.Type().IsInteger() {
   621  			base.Errorf("non-integer %s index %v", why, n.Index)
   622  			return n
   623  		}
   624  
   625  		if !n.Bounded() && ir.IsConst(n.Index, constant.Int) {
   626  			x := n.Index.Val()
   627  			if constant.Sign(x) < 0 {
   628  				base.Errorf("invalid %s index %v (index must be non-negative)", why, n.Index)
   629  			} else if t.IsArray() && constant.Compare(x, token.GEQ, constant.MakeInt64(t.NumElem())) {
   630  				base.Errorf("invalid array index %v (out of bounds for %d-element array)", n.Index, t.NumElem())
   631  			} else if ir.IsConst(n.X, constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(ir.StringVal(n.X))))) {
   632  				base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Index, len(ir.StringVal(n.X)))
   633  			} else if ir.ConstOverflow(x, types.Types[types.TINT]) {
   634  				base.Errorf("invalid %s index %v (index too large)", why, n.Index)
   635  			}
   636  		}
   637  
   638  	case types.TMAP:
   639  		n.Index = AssignConv(n.Index, t.Key(), "map index")
   640  		n.SetType(t.Elem())
   641  		n.SetOp(ir.OINDEXMAP)
   642  		n.Assigned = false
   643  	}
   644  	return n
   645  }
   646  
   647  // tcLenCap typechecks an OLEN or OCAP node.
   648  func tcLenCap(n *ir.UnaryExpr) ir.Node {
   649  	n.X = Expr(n.X)
   650  	n.X = DefaultLit(n.X, nil)
   651  	n.X = implicitstar(n.X)
   652  	l := n.X
   653  	t := l.Type()
   654  	if t == nil {
   655  		n.SetType(nil)
   656  		return n
   657  	}
   658  
   659  	var ok bool
   660  	if n.Op() == ir.OLEN {
   661  		ok = okforlen[t.Kind()]
   662  	} else {
   663  		ok = okforcap[t.Kind()]
   664  	}
   665  	if !ok {
   666  		base.Errorf("invalid argument %L for %v", l, n.Op())
   667  		n.SetType(nil)
   668  		return n
   669  	}
   670  
   671  	n.SetType(types.Types[types.TINT])
   672  	return n
   673  }
   674  
   675  // tcUnsafeData typechecks an OUNSAFESLICEDATA or OUNSAFESTRINGDATA node.
   676  func tcUnsafeData(n *ir.UnaryExpr) ir.Node {
   677  	n.X = Expr(n.X)
   678  	n.X = DefaultLit(n.X, nil)
   679  	l := n.X
   680  	t := l.Type()
   681  	if t == nil {
   682  		n.SetType(nil)
   683  		return n
   684  	}
   685  
   686  	var kind types.Kind
   687  	if n.Op() == ir.OUNSAFESLICEDATA {
   688  		kind = types.TSLICE
   689  	} else {
   690  		/* kind is string */
   691  		kind = types.TSTRING
   692  	}
   693  
   694  	if t.Kind() != kind {
   695  		base.Errorf("invalid argument %L for %v", l, n.Op())
   696  		n.SetType(nil)
   697  		return n
   698  	}
   699  
   700  	if kind == types.TSTRING {
   701  		t = types.ByteType
   702  	} else {
   703  		t = t.Elem()
   704  	}
   705  	n.SetType(types.NewPtr(t))
   706  	return n
   707  }
   708  
   709  // tcRecv typechecks an ORECV node.
   710  func tcRecv(n *ir.UnaryExpr) ir.Node {
   711  	n.X = Expr(n.X)
   712  	n.X = DefaultLit(n.X, nil)
   713  	l := n.X
   714  	t := l.Type()
   715  	if t == nil {
   716  		n.SetType(nil)
   717  		return n
   718  	}
   719  	if !t.IsChan() {
   720  		base.Errorf("invalid operation: %v (receive from non-chan type %v)", n, t)
   721  		n.SetType(nil)
   722  		return n
   723  	}
   724  
   725  	if !t.ChanDir().CanRecv() {
   726  		base.Errorf("invalid operation: %v (receive from send-only type %v)", n, t)
   727  		n.SetType(nil)
   728  		return n
   729  	}
   730  
   731  	n.SetType(t.Elem())
   732  	return n
   733  }
   734  
   735  // tcSPtr typechecks an OSPTR node.
   736  func tcSPtr(n *ir.UnaryExpr) ir.Node {
   737  	n.X = Expr(n.X)
   738  	t := n.X.Type()
   739  	if t == nil {
   740  		n.SetType(nil)
   741  		return n
   742  	}
   743  	if !t.IsSlice() && !t.IsString() {
   744  		base.Fatalf("OSPTR of %v", t)
   745  	}
   746  	if t.IsString() {
   747  		n.SetType(types.NewPtr(types.Types[types.TUINT8]))
   748  	} else {
   749  		n.SetType(types.NewPtr(t.Elem()))
   750  	}
   751  	return n
   752  }
   753  
   754  // tcSlice typechecks an OSLICE or OSLICE3 node.
   755  func tcSlice(n *ir.SliceExpr) ir.Node {
   756  	n.X = DefaultLit(Expr(n.X), nil)
   757  	n.Low = indexlit(Expr(n.Low))
   758  	n.High = indexlit(Expr(n.High))
   759  	n.Max = indexlit(Expr(n.Max))
   760  	hasmax := n.Op().IsSlice3()
   761  	l := n.X
   762  	if l.Type() == nil {
   763  		n.SetType(nil)
   764  		return n
   765  	}
   766  	if l.Type().IsArray() {
   767  		if !ir.IsAddressable(n.X) {
   768  			base.Errorf("invalid operation %v (slice of unaddressable value)", n)
   769  			n.SetType(nil)
   770  			return n
   771  		}
   772  
   773  		addr := NodAddr(n.X)
   774  		addr.SetImplicit(true)
   775  		n.X = Expr(addr)
   776  		l = n.X
   777  	}
   778  	t := l.Type()
   779  	var tp *types.Type
   780  	if t.IsString() {
   781  		if hasmax {
   782  			base.Errorf("invalid operation %v (3-index slice of string)", n)
   783  			n.SetType(nil)
   784  			return n
   785  		}
   786  		n.SetType(t)
   787  		n.SetOp(ir.OSLICESTR)
   788  	} else if t.IsPtr() && t.Elem().IsArray() {
   789  		tp = t.Elem()
   790  		n.SetType(types.NewSlice(tp.Elem()))
   791  		types.CalcSize(n.Type())
   792  		if hasmax {
   793  			n.SetOp(ir.OSLICE3ARR)
   794  		} else {
   795  			n.SetOp(ir.OSLICEARR)
   796  		}
   797  	} else if t.IsSlice() {
   798  		n.SetType(t)
   799  	} else {
   800  		base.Errorf("cannot slice %v (type %v)", l, t)
   801  		n.SetType(nil)
   802  		return n
   803  	}
   804  
   805  	if n.Low != nil && !checksliceindex(l, n.Low, tp) {
   806  		n.SetType(nil)
   807  		return n
   808  	}
   809  	if n.High != nil && !checksliceindex(l, n.High, tp) {
   810  		n.SetType(nil)
   811  		return n
   812  	}
   813  	if n.Max != nil && !checksliceindex(l, n.Max, tp) {
   814  		n.SetType(nil)
   815  		return n
   816  	}
   817  	if !checksliceconst(n.Low, n.High) || !checksliceconst(n.Low, n.Max) || !checksliceconst(n.High, n.Max) {
   818  		n.SetType(nil)
   819  		return n
   820  	}
   821  	return n
   822  }
   823  
   824  // tcSliceHeader typechecks an OSLICEHEADER node.
   825  func tcSliceHeader(n *ir.SliceHeaderExpr) ir.Node {
   826  	// Errors here are Fatalf instead of Errorf because only the compiler
   827  	// can construct an OSLICEHEADER node.
   828  	// Components used in OSLICEHEADER that are supplied by parsed source code
   829  	// have already been typechecked in e.g. OMAKESLICE earlier.
   830  	t := n.Type()
   831  	if t == nil {
   832  		base.Fatalf("no type specified for OSLICEHEADER")
   833  	}
   834  
   835  	if !t.IsSlice() {
   836  		base.Fatalf("invalid type %v for OSLICEHEADER", n.Type())
   837  	}
   838  
   839  	if n.Ptr == nil || n.Ptr.Type() == nil || !n.Ptr.Type().IsUnsafePtr() {
   840  		base.Fatalf("need unsafe.Pointer for OSLICEHEADER")
   841  	}
   842  
   843  	n.Ptr = Expr(n.Ptr)
   844  	n.Len = DefaultLit(Expr(n.Len), types.Types[types.TINT])
   845  	n.Cap = DefaultLit(Expr(n.Cap), types.Types[types.TINT])
   846  
   847  	if ir.IsConst(n.Len, constant.Int) && ir.Int64Val(n.Len) < 0 {
   848  		base.Fatalf("len for OSLICEHEADER must be non-negative")
   849  	}
   850  
   851  	if ir.IsConst(n.Cap, constant.Int) && ir.Int64Val(n.Cap) < 0 {
   852  		base.Fatalf("cap for OSLICEHEADER must be non-negative")
   853  	}
   854  
   855  	if ir.IsConst(n.Len, constant.Int) && ir.IsConst(n.Cap, constant.Int) && constant.Compare(n.Len.Val(), token.GTR, n.Cap.Val()) {
   856  		base.Fatalf("len larger than cap for OSLICEHEADER")
   857  	}
   858  
   859  	return n
   860  }
   861  
   862  // tcStringHeader typechecks an OSTRINGHEADER node.
   863  func tcStringHeader(n *ir.StringHeaderExpr) ir.Node {
   864  	t := n.Type()
   865  	if t == nil {
   866  		base.Fatalf("no type specified for OSTRINGHEADER")
   867  	}
   868  
   869  	if !t.IsString() {
   870  		base.Fatalf("invalid type %v for OSTRINGHEADER", n.Type())
   871  	}
   872  
   873  	if n.Ptr == nil || n.Ptr.Type() == nil || !n.Ptr.Type().IsUnsafePtr() {
   874  		base.Fatalf("need unsafe.Pointer for OSTRINGHEADER")
   875  	}
   876  
   877  	n.Ptr = Expr(n.Ptr)
   878  	n.Len = DefaultLit(Expr(n.Len), types.Types[types.TINT])
   879  
   880  	if ir.IsConst(n.Len, constant.Int) && ir.Int64Val(n.Len) < 0 {
   881  		base.Fatalf("len for OSTRINGHEADER must be non-negative")
   882  	}
   883  
   884  	return n
   885  }
   886  
   887  // tcStar typechecks an ODEREF node, which may be an expression or a type.
   888  func tcStar(n *ir.StarExpr, top int) ir.Node {
   889  	n.X = typecheck(n.X, ctxExpr|ctxType)
   890  	l := n.X
   891  	t := l.Type()
   892  	if t == nil {
   893  		n.SetType(nil)
   894  		return n
   895  	}
   896  
   897  	// TODO(mdempsky): Remove (along with ctxType above) once I'm
   898  	// confident this code path isn't needed any more.
   899  	if l.Op() == ir.OTYPE {
   900  		base.Fatalf("unexpected type in deref expression: %v", l)
   901  	}
   902  
   903  	if !t.IsPtr() {
   904  		if top&(ctxExpr|ctxStmt) != 0 {
   905  			base.Errorf("invalid indirect of %L", n.X)
   906  			n.SetType(nil)
   907  			return n
   908  		}
   909  		base.Errorf("%v is not a type", l)
   910  		return n
   911  	}
   912  
   913  	n.SetType(t.Elem())
   914  	return n
   915  }
   916  
   917  // tcUnaryArith typechecks a unary arithmetic expression.
   918  func tcUnaryArith(n *ir.UnaryExpr) ir.Node {
   919  	n.X = Expr(n.X)
   920  	l := n.X
   921  	t := l.Type()
   922  	if t == nil {
   923  		n.SetType(nil)
   924  		return n
   925  	}
   926  	if !okfor[n.Op()][defaultType(t).Kind()] {
   927  		base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, n.Op(), typekind(t))
   928  		n.SetType(nil)
   929  		return n
   930  	}
   931  
   932  	n.SetType(t)
   933  	return n
   934  }