...

Source file src/cmd/compile/internal/typecheck/expr.go

Documentation: cmd/compile/internal/typecheck

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

View as plain text