...

Source file src/cmd/compile/internal/typecheck/typecheck.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  	"go/constant"
    10  	"go/token"
    11  	"strings"
    12  
    13  	"cmd/compile/internal/base"
    14  	"cmd/compile/internal/ir"
    15  	"cmd/compile/internal/types"
    16  	"cmd/internal/src"
    17  )
    18  
    19  func AssignExpr(n ir.Node) ir.Node { return typecheck(n, ctxExpr|ctxAssign) }
    20  func Expr(n ir.Node) ir.Node       { return typecheck(n, ctxExpr) }
    21  func Stmt(n ir.Node) ir.Node       { return typecheck(n, ctxStmt) }
    22  
    23  func Exprs(exprs []ir.Node) { typecheckslice(exprs, ctxExpr) }
    24  func Stmts(stmts []ir.Node) { typecheckslice(stmts, ctxStmt) }
    25  
    26  func Call(pos src.XPos, callee ir.Node, args []ir.Node, dots bool) ir.Node {
    27  	call := ir.NewCallExpr(pos, ir.OCALL, callee, args)
    28  	call.IsDDD = dots
    29  	return typecheck(call, ctxStmt|ctxExpr)
    30  }
    31  
    32  func Callee(n ir.Node) ir.Node {
    33  	return typecheck(n, ctxExpr|ctxCallee)
    34  }
    35  
    36  var traceIndent []byte
    37  
    38  func tracePrint(title string, n ir.Node) func(np *ir.Node) {
    39  	indent := traceIndent
    40  
    41  	// guard against nil
    42  	var pos, op string
    43  	var tc uint8
    44  	if n != nil {
    45  		pos = base.FmtPos(n.Pos())
    46  		op = n.Op().String()
    47  		tc = n.Typecheck()
    48  	}
    49  
    50  	types.SkipSizeForTracing = true
    51  	defer func() { types.SkipSizeForTracing = false }()
    52  	fmt.Printf("%s: %s%s %p %s %v tc=%d\n", pos, indent, title, n, op, n, tc)
    53  	traceIndent = append(traceIndent, ". "...)
    54  
    55  	return func(np *ir.Node) {
    56  		traceIndent = traceIndent[:len(traceIndent)-2]
    57  
    58  		// if we have a result, use that
    59  		if np != nil {
    60  			n = *np
    61  		}
    62  
    63  		// guard against nil
    64  		// use outer pos, op so we don't get empty pos/op if n == nil (nicer output)
    65  		var tc uint8
    66  		var typ *types.Type
    67  		if n != nil {
    68  			pos = base.FmtPos(n.Pos())
    69  			op = n.Op().String()
    70  			tc = n.Typecheck()
    71  			typ = n.Type()
    72  		}
    73  
    74  		types.SkipSizeForTracing = true
    75  		defer func() { types.SkipSizeForTracing = false }()
    76  		fmt.Printf("%s: %s=> %p %s %v tc=%d type=%L\n", pos, indent, n, op, n, tc, typ)
    77  	}
    78  }
    79  
    80  const (
    81  	ctxStmt    = 1 << iota // evaluated at statement level
    82  	ctxExpr                // evaluated in value context
    83  	ctxType                // evaluated in type context
    84  	ctxCallee              // call-only expressions are ok
    85  	ctxMultiOK             // multivalue function returns are ok
    86  	ctxAssign              // assigning to expression
    87  )
    88  
    89  // type checks the whole tree of an expression.
    90  // calculates expression types.
    91  // evaluates compile time constants.
    92  // marks variables that escape the local frame.
    93  // rewrites n.Op to be more specific in some cases.
    94  
    95  func typecheckslice(l []ir.Node, top int) {
    96  	for i := range l {
    97  		l[i] = typecheck(l[i], top)
    98  	}
    99  }
   100  
   101  var _typekind = []string{
   102  	types.TINT:        "int",
   103  	types.TUINT:       "uint",
   104  	types.TINT8:       "int8",
   105  	types.TUINT8:      "uint8",
   106  	types.TINT16:      "int16",
   107  	types.TUINT16:     "uint16",
   108  	types.TINT32:      "int32",
   109  	types.TUINT32:     "uint32",
   110  	types.TINT64:      "int64",
   111  	types.TUINT64:     "uint64",
   112  	types.TUINTPTR:    "uintptr",
   113  	types.TCOMPLEX64:  "complex64",
   114  	types.TCOMPLEX128: "complex128",
   115  	types.TFLOAT32:    "float32",
   116  	types.TFLOAT64:    "float64",
   117  	types.TBOOL:       "bool",
   118  	types.TSTRING:     "string",
   119  	types.TPTR:        "pointer",
   120  	types.TUNSAFEPTR:  "unsafe.Pointer",
   121  	types.TSTRUCT:     "struct",
   122  	types.TINTER:      "interface",
   123  	types.TCHAN:       "chan",
   124  	types.TMAP:        "map",
   125  	types.TARRAY:      "array",
   126  	types.TSLICE:      "slice",
   127  	types.TFUNC:       "func",
   128  	types.TNIL:        "nil",
   129  	types.TIDEAL:      "untyped number",
   130  }
   131  
   132  func typekind(t *types.Type) string {
   133  	if t.IsUntyped() {
   134  		return fmt.Sprintf("%v", t)
   135  	}
   136  	et := t.Kind()
   137  	if int(et) < len(_typekind) {
   138  		s := _typekind[et]
   139  		if s != "" {
   140  			return s
   141  		}
   142  	}
   143  	return fmt.Sprintf("etype=%d", et)
   144  }
   145  
   146  // typecheck type checks node n.
   147  // The result of typecheck MUST be assigned back to n, e.g.
   148  //
   149  //	n.Left = typecheck(n.Left, top)
   150  func typecheck(n ir.Node, top int) (res ir.Node) {
   151  	if n == nil {
   152  		return nil
   153  	}
   154  
   155  	// only trace if there's work to do
   156  	if base.EnableTrace && base.Flag.LowerT {
   157  		defer tracePrint("typecheck", n)(&res)
   158  	}
   159  
   160  	lno := ir.SetPos(n)
   161  	defer func() { base.Pos = lno }()
   162  
   163  	// Skip typecheck if already done.
   164  	// But re-typecheck ONAME/OTYPE/OLITERAL/OPACK node in case context has changed.
   165  	if n.Typecheck() == 1 || n.Typecheck() == 3 {
   166  		switch n.Op() {
   167  		case ir.ONAME:
   168  			break
   169  
   170  		default:
   171  			return n
   172  		}
   173  	}
   174  
   175  	if n.Typecheck() == 2 {
   176  		base.FatalfAt(n.Pos(), "typechecking loop")
   177  	}
   178  
   179  	n.SetTypecheck(2)
   180  	n = typecheck1(n, top)
   181  	n.SetTypecheck(1)
   182  
   183  	t := n.Type()
   184  	if t != nil && !t.IsFuncArgStruct() && n.Op() != ir.OTYPE {
   185  		switch t.Kind() {
   186  		case types.TFUNC, // might have TANY; wait until it's called
   187  			types.TANY, types.TFORW, types.TIDEAL, types.TNIL, types.TBLANK:
   188  			break
   189  
   190  		default:
   191  			types.CheckSize(t)
   192  		}
   193  	}
   194  
   195  	return n
   196  }
   197  
   198  // indexlit implements typechecking of untyped values as
   199  // array/slice indexes. It is almost equivalent to DefaultLit
   200  // but also accepts untyped numeric values representable as
   201  // value of type int (see also checkmake for comparison).
   202  // The result of indexlit MUST be assigned back to n, e.g.
   203  //
   204  //	n.Left = indexlit(n.Left)
   205  func indexlit(n ir.Node) ir.Node {
   206  	if n != nil && n.Type() != nil && n.Type().Kind() == types.TIDEAL {
   207  		return DefaultLit(n, types.Types[types.TINT])
   208  	}
   209  	return n
   210  }
   211  
   212  // typecheck1 should ONLY be called from typecheck.
   213  func typecheck1(n ir.Node, top int) ir.Node {
   214  	// Skip over parens.
   215  	for n.Op() == ir.OPAREN {
   216  		n = n.(*ir.ParenExpr).X
   217  	}
   218  
   219  	switch n.Op() {
   220  	default:
   221  		ir.Dump("typecheck", n)
   222  		base.Fatalf("typecheck %v", n.Op())
   223  		panic("unreachable")
   224  
   225  	case ir.ONAME:
   226  		n := n.(*ir.Name)
   227  		if n.BuiltinOp != 0 {
   228  			if top&ctxCallee == 0 {
   229  				base.Errorf("use of builtin %v not in function call", n.Sym())
   230  				n.SetType(nil)
   231  				return n
   232  			}
   233  			return n
   234  		}
   235  		if top&ctxAssign == 0 {
   236  			// not a write to the variable
   237  			if ir.IsBlank(n) {
   238  				base.Errorf("cannot use _ as value")
   239  				n.SetType(nil)
   240  				return n
   241  			}
   242  			n.SetUsed(true)
   243  		}
   244  		return n
   245  
   246  	// type or expr
   247  	case ir.ODEREF:
   248  		n := n.(*ir.StarExpr)
   249  		return tcStar(n, top)
   250  
   251  	// x op= y
   252  	case ir.OASOP:
   253  		n := n.(*ir.AssignOpStmt)
   254  		n.X, n.Y = Expr(n.X), Expr(n.Y)
   255  		checkassign(n.X)
   256  		if n.IncDec && !okforarith[n.X.Type().Kind()] {
   257  			base.Errorf("invalid operation: %v (non-numeric type %v)", n, n.X.Type())
   258  			return n
   259  		}
   260  		switch n.AsOp {
   261  		case ir.OLSH, ir.ORSH:
   262  			n.X, n.Y, _ = tcShift(n, n.X, n.Y)
   263  		case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OMOD, ir.OMUL, ir.OOR, ir.OSUB, ir.OXOR:
   264  			n.X, n.Y, _ = tcArith(n, n.AsOp, n.X, n.Y)
   265  		default:
   266  			base.Fatalf("invalid assign op: %v", n.AsOp)
   267  		}
   268  		return n
   269  
   270  	// logical operators
   271  	case ir.OANDAND, ir.OOROR:
   272  		n := n.(*ir.LogicalExpr)
   273  		n.X, n.Y = Expr(n.X), Expr(n.Y)
   274  		if n.X.Type() == nil || n.Y.Type() == nil {
   275  			n.SetType(nil)
   276  			return n
   277  		}
   278  		// For "x == x && len(s)", it's better to report that "len(s)" (type int)
   279  		// can't be used with "&&" than to report that "x == x" (type untyped bool)
   280  		// can't be converted to int (see issue #41500).
   281  		if !n.X.Type().IsBoolean() {
   282  			base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, n.Op(), typekind(n.X.Type()))
   283  			n.SetType(nil)
   284  			return n
   285  		}
   286  		if !n.Y.Type().IsBoolean() {
   287  			base.Errorf("invalid operation: %v (operator %v not defined on %s)", n, n.Op(), typekind(n.Y.Type()))
   288  			n.SetType(nil)
   289  			return n
   290  		}
   291  		l, r, t := tcArith(n, n.Op(), n.X, n.Y)
   292  		n.X, n.Y = l, r
   293  		n.SetType(t)
   294  		return n
   295  
   296  	// shift operators
   297  	case ir.OLSH, ir.ORSH:
   298  		n := n.(*ir.BinaryExpr)
   299  		n.X, n.Y = Expr(n.X), Expr(n.Y)
   300  		l, r, t := tcShift(n, n.X, n.Y)
   301  		n.X, n.Y = l, r
   302  		n.SetType(t)
   303  		return n
   304  
   305  	// comparison operators
   306  	case ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT, ir.ONE:
   307  		n := n.(*ir.BinaryExpr)
   308  		n.X, n.Y = Expr(n.X), Expr(n.Y)
   309  		l, r, t := tcArith(n, n.Op(), n.X, n.Y)
   310  		if t != nil {
   311  			n.X, n.Y = l, r
   312  			n.SetType(types.UntypedBool)
   313  			n.X, n.Y = defaultlit2(l, r, true)
   314  		}
   315  		return n
   316  
   317  	// binary operators
   318  	case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OMOD, ir.OMUL, ir.OOR, ir.OSUB, ir.OXOR:
   319  		n := n.(*ir.BinaryExpr)
   320  		n.X, n.Y = Expr(n.X), Expr(n.Y)
   321  		l, r, t := tcArith(n, n.Op(), n.X, n.Y)
   322  		if t != nil && t.Kind() == types.TSTRING && n.Op() == ir.OADD {
   323  			// create or update OADDSTR node with list of strings in x + y + z + (w + v) + ...
   324  			var add *ir.AddStringExpr
   325  			if l.Op() == ir.OADDSTR {
   326  				add = l.(*ir.AddStringExpr)
   327  				add.SetPos(n.Pos())
   328  			} else {
   329  				add = ir.NewAddStringExpr(n.Pos(), []ir.Node{l})
   330  			}
   331  			if r.Op() == ir.OADDSTR {
   332  				r := r.(*ir.AddStringExpr)
   333  				add.List.Append(r.List.Take()...)
   334  			} else {
   335  				add.List.Append(r)
   336  			}
   337  			add.SetType(t)
   338  			return add
   339  		}
   340  		n.X, n.Y = l, r
   341  		n.SetType(t)
   342  		return n
   343  
   344  	case ir.OBITNOT, ir.ONEG, ir.ONOT, ir.OPLUS:
   345  		n := n.(*ir.UnaryExpr)
   346  		return tcUnaryArith(n)
   347  
   348  	// exprs
   349  	case ir.OCOMPLIT:
   350  		return tcCompLit(n.(*ir.CompLitExpr))
   351  
   352  	case ir.OXDOT, ir.ODOT:
   353  		n := n.(*ir.SelectorExpr)
   354  		return tcDot(n, top)
   355  
   356  	case ir.ODOTTYPE:
   357  		n := n.(*ir.TypeAssertExpr)
   358  		return tcDotType(n)
   359  
   360  	case ir.OINDEX:
   361  		n := n.(*ir.IndexExpr)
   362  		return tcIndex(n)
   363  
   364  	case ir.ORECV:
   365  		n := n.(*ir.UnaryExpr)
   366  		return tcRecv(n)
   367  
   368  	case ir.OSEND:
   369  		n := n.(*ir.SendStmt)
   370  		return tcSend(n)
   371  
   372  	case ir.OSLICEHEADER:
   373  		n := n.(*ir.SliceHeaderExpr)
   374  		return tcSliceHeader(n)
   375  
   376  	case ir.OSTRINGHEADER:
   377  		n := n.(*ir.StringHeaderExpr)
   378  		return tcStringHeader(n)
   379  
   380  	case ir.OMAKESLICECOPY:
   381  		n := n.(*ir.MakeExpr)
   382  		return tcMakeSliceCopy(n)
   383  
   384  	case ir.OSLICE, ir.OSLICE3:
   385  		n := n.(*ir.SliceExpr)
   386  		return tcSlice(n)
   387  
   388  	// call and call like
   389  	case ir.OCALL:
   390  		n := n.(*ir.CallExpr)
   391  		return tcCall(n, top)
   392  
   393  	case ir.OCAP, ir.OLEN:
   394  		n := n.(*ir.UnaryExpr)
   395  		return tcLenCap(n)
   396  
   397  	case ir.OMIN, ir.OMAX:
   398  		n := n.(*ir.CallExpr)
   399  		return tcMinMax(n)
   400  
   401  	case ir.OREAL, ir.OIMAG:
   402  		n := n.(*ir.UnaryExpr)
   403  		return tcRealImag(n)
   404  
   405  	case ir.OCOMPLEX:
   406  		n := n.(*ir.BinaryExpr)
   407  		return tcComplex(n)
   408  
   409  	case ir.OCLEAR:
   410  		n := n.(*ir.UnaryExpr)
   411  		return tcClear(n)
   412  
   413  	case ir.OCLOSE:
   414  		n := n.(*ir.UnaryExpr)
   415  		return tcClose(n)
   416  
   417  	case ir.ODELETE:
   418  		n := n.(*ir.CallExpr)
   419  		return tcDelete(n)
   420  
   421  	case ir.OAPPEND:
   422  		n := n.(*ir.CallExpr)
   423  		return tcAppend(n)
   424  
   425  	case ir.OCOPY:
   426  		n := n.(*ir.BinaryExpr)
   427  		return tcCopy(n)
   428  
   429  	case ir.OCONV:
   430  		n := n.(*ir.ConvExpr)
   431  		return tcConv(n)
   432  
   433  	case ir.OMAKE:
   434  		n := n.(*ir.CallExpr)
   435  		return tcMake(n)
   436  
   437  	case ir.ONEW:
   438  		n := n.(*ir.UnaryExpr)
   439  		return tcNew(n)
   440  
   441  	case ir.OPRINT, ir.OPRINTLN:
   442  		n := n.(*ir.CallExpr)
   443  		return tcPrint(n)
   444  
   445  	case ir.OPANIC:
   446  		n := n.(*ir.UnaryExpr)
   447  		return tcPanic(n)
   448  
   449  	case ir.ORECOVER:
   450  		n := n.(*ir.CallExpr)
   451  		return tcRecover(n)
   452  
   453  	case ir.OUNSAFEADD:
   454  		n := n.(*ir.BinaryExpr)
   455  		return tcUnsafeAdd(n)
   456  
   457  	case ir.OUNSAFESLICE:
   458  		n := n.(*ir.BinaryExpr)
   459  		return tcUnsafeSlice(n)
   460  
   461  	case ir.OUNSAFESLICEDATA:
   462  		n := n.(*ir.UnaryExpr)
   463  		return tcUnsafeData(n)
   464  
   465  	case ir.OUNSAFESTRING:
   466  		n := n.(*ir.BinaryExpr)
   467  		return tcUnsafeString(n)
   468  
   469  	case ir.OUNSAFESTRINGDATA:
   470  		n := n.(*ir.UnaryExpr)
   471  		return tcUnsafeData(n)
   472  
   473  	case ir.OITAB:
   474  		n := n.(*ir.UnaryExpr)
   475  		return tcITab(n)
   476  
   477  	case ir.OIDATA:
   478  		// Whoever creates the OIDATA node must know a priori the concrete type at that moment,
   479  		// usually by just having checked the OITAB.
   480  		n := n.(*ir.UnaryExpr)
   481  		base.Fatalf("cannot typecheck interface data %v", n)
   482  		panic("unreachable")
   483  
   484  	case ir.OSPTR:
   485  		n := n.(*ir.UnaryExpr)
   486  		return tcSPtr(n)
   487  
   488  	case ir.OCFUNC:
   489  		n := n.(*ir.UnaryExpr)
   490  		n.X = Expr(n.X)
   491  		n.SetType(types.Types[types.TUINTPTR])
   492  		return n
   493  
   494  	case ir.OGETCALLERPC, ir.OGETCALLERSP:
   495  		n := n.(*ir.CallExpr)
   496  		if len(n.Args) != 0 {
   497  			base.FatalfAt(n.Pos(), "unexpected arguments: %v", n)
   498  		}
   499  		n.SetType(types.Types[types.TUINTPTR])
   500  		return n
   501  
   502  	case ir.OCONVNOP:
   503  		n := n.(*ir.ConvExpr)
   504  		n.X = Expr(n.X)
   505  		return n
   506  
   507  	// statements
   508  	case ir.OAS:
   509  		n := n.(*ir.AssignStmt)
   510  		tcAssign(n)
   511  
   512  		// Code that creates temps does not bother to set defn, so do it here.
   513  		if n.X.Op() == ir.ONAME && ir.IsAutoTmp(n.X) {
   514  			n.X.Name().Defn = n
   515  		}
   516  		return n
   517  
   518  	case ir.OAS2:
   519  		tcAssignList(n.(*ir.AssignListStmt))
   520  		return n
   521  
   522  	case ir.OBREAK,
   523  		ir.OCONTINUE,
   524  		ir.ODCL,
   525  		ir.OGOTO,
   526  		ir.OFALL:
   527  		return n
   528  
   529  	case ir.OBLOCK:
   530  		n := n.(*ir.BlockStmt)
   531  		Stmts(n.List)
   532  		return n
   533  
   534  	case ir.OLABEL:
   535  		if n.Sym().IsBlank() {
   536  			// Empty identifier is valid but useless.
   537  			// Eliminate now to simplify life later.
   538  			// See issues 7538, 11589, 11593.
   539  			n = ir.NewBlockStmt(n.Pos(), nil)
   540  		}
   541  		return n
   542  
   543  	case ir.ODEFER, ir.OGO:
   544  		n := n.(*ir.GoDeferStmt)
   545  		n.Call = typecheck(n.Call, ctxStmt|ctxExpr)
   546  		tcGoDefer(n)
   547  		return n
   548  
   549  	case ir.OFOR:
   550  		n := n.(*ir.ForStmt)
   551  		return tcFor(n)
   552  
   553  	case ir.OIF:
   554  		n := n.(*ir.IfStmt)
   555  		return tcIf(n)
   556  
   557  	case ir.ORETURN:
   558  		n := n.(*ir.ReturnStmt)
   559  		return tcReturn(n)
   560  
   561  	case ir.OTAILCALL:
   562  		n := n.(*ir.TailCallStmt)
   563  		n.Call = typecheck(n.Call, ctxStmt|ctxExpr).(*ir.CallExpr)
   564  		return n
   565  
   566  	case ir.OCHECKNIL:
   567  		n := n.(*ir.UnaryExpr)
   568  		return tcCheckNil(n)
   569  
   570  	case ir.OSELECT:
   571  		tcSelect(n.(*ir.SelectStmt))
   572  		return n
   573  
   574  	case ir.OSWITCH:
   575  		tcSwitch(n.(*ir.SwitchStmt))
   576  		return n
   577  
   578  	case ir.ORANGE:
   579  		tcRange(n.(*ir.RangeStmt))
   580  		return n
   581  
   582  	case ir.OTYPESW:
   583  		n := n.(*ir.TypeSwitchGuard)
   584  		base.Fatalf("use of .(type) outside type switch")
   585  		return n
   586  
   587  	case ir.ODCLFUNC:
   588  		tcFunc(n.(*ir.Func))
   589  		return n
   590  	}
   591  
   592  	// No return n here!
   593  	// Individual cases can type-assert n, introducing a new one.
   594  	// Each must execute its own return n.
   595  }
   596  
   597  func typecheckargs(n ir.InitNode) {
   598  	var list []ir.Node
   599  	switch n := n.(type) {
   600  	default:
   601  		base.Fatalf("typecheckargs %+v", n.Op())
   602  	case *ir.CallExpr:
   603  		list = n.Args
   604  		if n.IsDDD {
   605  			Exprs(list)
   606  			return
   607  		}
   608  	case *ir.ReturnStmt:
   609  		list = n.Results
   610  	}
   611  	if len(list) != 1 {
   612  		Exprs(list)
   613  		return
   614  	}
   615  
   616  	typecheckslice(list, ctxExpr|ctxMultiOK)
   617  	t := list[0].Type()
   618  	if t == nil || !t.IsFuncArgStruct() {
   619  		return
   620  	}
   621  
   622  	// Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...).
   623  	RewriteMultiValueCall(n, list[0])
   624  }
   625  
   626  // RewriteNonNameCall replaces non-Name call expressions with temps,
   627  // rewriting f()(...) to t0 := f(); t0(...).
   628  func RewriteNonNameCall(n *ir.CallExpr) {
   629  	np := &n.Fun
   630  	if dot, ok := (*np).(*ir.SelectorExpr); ok && (dot.Op() == ir.ODOTMETH || dot.Op() == ir.ODOTINTER || dot.Op() == ir.OMETHVALUE) {
   631  		np = &dot.X // peel away method selector
   632  	}
   633  
   634  	// Check for side effects in the callee expression.
   635  	// We explicitly special case new(T) though, because it doesn't have
   636  	// observable side effects, and keeping it in place allows better escape analysis.
   637  	if !ir.Any(*np, func(n ir.Node) bool { return n.Op() != ir.ONEW && callOrChan(n) }) {
   638  		return
   639  	}
   640  
   641  	tmp := TempAt(base.Pos, ir.CurFunc, (*np).Type())
   642  	as := ir.NewAssignStmt(base.Pos, tmp, *np)
   643  	as.PtrInit().Append(Stmt(ir.NewDecl(n.Pos(), ir.ODCL, tmp)))
   644  	*np = tmp
   645  
   646  	n.PtrInit().Append(Stmt(as))
   647  }
   648  
   649  // RewriteMultiValueCall rewrites multi-valued f() to use temporaries,
   650  // so the backend wouldn't need to worry about tuple-valued expressions.
   651  func RewriteMultiValueCall(n ir.InitNode, call ir.Node) {
   652  	as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, []ir.Node{call})
   653  	results := call.Type().Fields()
   654  	list := make([]ir.Node, len(results))
   655  	for i, result := range results {
   656  		tmp := TempAt(base.Pos, ir.CurFunc, result.Type)
   657  		as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, tmp))
   658  		as.Lhs.Append(tmp)
   659  		list[i] = tmp
   660  	}
   661  
   662  	n.PtrInit().Append(Stmt(as))
   663  
   664  	switch n := n.(type) {
   665  	default:
   666  		base.Fatalf("RewriteMultiValueCall %+v", n.Op())
   667  	case *ir.CallExpr:
   668  		n.Args = list
   669  	case *ir.ReturnStmt:
   670  		n.Results = list
   671  	case *ir.AssignListStmt:
   672  		if n.Op() != ir.OAS2FUNC {
   673  			base.Fatalf("RewriteMultiValueCall: invalid op %v", n.Op())
   674  		}
   675  		as.SetOp(ir.OAS2FUNC)
   676  		n.SetOp(ir.OAS2)
   677  		n.Rhs = make([]ir.Node, len(list))
   678  		for i, tmp := range list {
   679  			n.Rhs[i] = AssignConv(tmp, n.Lhs[i].Type(), "assignment")
   680  		}
   681  	}
   682  }
   683  
   684  func checksliceindex(l ir.Node, r ir.Node, tp *types.Type) bool {
   685  	t := r.Type()
   686  	if t == nil {
   687  		return false
   688  	}
   689  	if !t.IsInteger() {
   690  		base.Errorf("invalid slice index %v (type %v)", r, t)
   691  		return false
   692  	}
   693  
   694  	if r.Op() == ir.OLITERAL {
   695  		x := r.Val()
   696  		if constant.Sign(x) < 0 {
   697  			base.Errorf("invalid slice index %v (index must be non-negative)", r)
   698  			return false
   699  		} else if tp != nil && tp.NumElem() >= 0 && constant.Compare(x, token.GTR, constant.MakeInt64(tp.NumElem())) {
   700  			base.Errorf("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem())
   701  			return false
   702  		} else if ir.IsConst(l, constant.String) && constant.Compare(x, token.GTR, constant.MakeInt64(int64(len(ir.StringVal(l))))) {
   703  			base.Errorf("invalid slice index %v (out of bounds for %d-byte string)", r, len(ir.StringVal(l)))
   704  			return false
   705  		} else if ir.ConstOverflow(x, types.Types[types.TINT]) {
   706  			base.Errorf("invalid slice index %v (index too large)", r)
   707  			return false
   708  		}
   709  	}
   710  
   711  	return true
   712  }
   713  
   714  func checksliceconst(lo ir.Node, hi ir.Node) bool {
   715  	if lo != nil && hi != nil && lo.Op() == ir.OLITERAL && hi.Op() == ir.OLITERAL && constant.Compare(lo.Val(), token.GTR, hi.Val()) {
   716  		base.Errorf("invalid slice index: %v > %v", lo, hi)
   717  		return false
   718  	}
   719  
   720  	return true
   721  }
   722  
   723  // The result of implicitstar MUST be assigned back to n, e.g.
   724  //
   725  //	n.Left = implicitstar(n.Left)
   726  func implicitstar(n ir.Node) ir.Node {
   727  	// insert implicit * if needed for fixed array
   728  	t := n.Type()
   729  	if t == nil || !t.IsPtr() {
   730  		return n
   731  	}
   732  	t = t.Elem()
   733  	if t == nil {
   734  		return n
   735  	}
   736  	if !t.IsArray() {
   737  		return n
   738  	}
   739  	star := ir.NewStarExpr(base.Pos, n)
   740  	star.SetImplicit(true)
   741  	return Expr(star)
   742  }
   743  
   744  func needOneArg(n *ir.CallExpr, f string, args ...interface{}) (ir.Node, bool) {
   745  	if len(n.Args) == 0 {
   746  		p := fmt.Sprintf(f, args...)
   747  		base.Errorf("missing argument to %s: %v", p, n)
   748  		return nil, false
   749  	}
   750  
   751  	if len(n.Args) > 1 {
   752  		p := fmt.Sprintf(f, args...)
   753  		base.Errorf("too many arguments to %s: %v", p, n)
   754  		return n.Args[0], false
   755  	}
   756  
   757  	return n.Args[0], true
   758  }
   759  
   760  func needTwoArgs(n *ir.CallExpr) (ir.Node, ir.Node, bool) {
   761  	if len(n.Args) != 2 {
   762  		if len(n.Args) < 2 {
   763  			base.Errorf("not enough arguments in call to %v", n)
   764  		} else {
   765  			base.Errorf("too many arguments in call to %v", n)
   766  		}
   767  		return nil, nil, false
   768  	}
   769  	return n.Args[0], n.Args[1], true
   770  }
   771  
   772  // Lookdot1 looks up the specified method s in the list fs of methods, returning
   773  // the matching field or nil. If dostrcmp is 0, it matches the symbols. If
   774  // dostrcmp is 1, it matches by name exactly. If dostrcmp is 2, it matches names
   775  // with case folding.
   776  func Lookdot1(errnode ir.Node, s *types.Sym, t *types.Type, fs []*types.Field, dostrcmp int) *types.Field {
   777  	var r *types.Field
   778  	for _, f := range fs {
   779  		if dostrcmp != 0 && f.Sym.Name == s.Name {
   780  			return f
   781  		}
   782  		if dostrcmp == 2 && strings.EqualFold(f.Sym.Name, s.Name) {
   783  			return f
   784  		}
   785  		if f.Sym != s {
   786  			continue
   787  		}
   788  		if r != nil {
   789  			if errnode != nil {
   790  				base.Errorf("ambiguous selector %v", errnode)
   791  			} else if t.IsPtr() {
   792  				base.Errorf("ambiguous selector (%v).%v", t, s)
   793  			} else {
   794  				base.Errorf("ambiguous selector %v.%v", t, s)
   795  			}
   796  			break
   797  		}
   798  
   799  		r = f
   800  	}
   801  
   802  	return r
   803  }
   804  
   805  // NewMethodExpr returns an OMETHEXPR node representing method
   806  // expression "recv.sym".
   807  func NewMethodExpr(pos src.XPos, recv *types.Type, sym *types.Sym) *ir.SelectorExpr {
   808  	// Compute the method set for recv.
   809  	var ms []*types.Field
   810  	if recv.IsInterface() {
   811  		ms = recv.AllMethods()
   812  	} else {
   813  		mt := types.ReceiverBaseType(recv)
   814  		if mt == nil {
   815  			base.FatalfAt(pos, "type %v has no receiver base type", recv)
   816  		}
   817  		CalcMethods(mt)
   818  		ms = mt.AllMethods()
   819  	}
   820  
   821  	m := Lookdot1(nil, sym, recv, ms, 0)
   822  	if m == nil {
   823  		base.FatalfAt(pos, "type %v has no method %v", recv, sym)
   824  	}
   825  
   826  	if !types.IsMethodApplicable(recv, m) {
   827  		base.FatalfAt(pos, "invalid method expression %v.%v (needs pointer receiver)", recv, sym)
   828  	}
   829  
   830  	n := ir.NewSelectorExpr(pos, ir.OMETHEXPR, ir.TypeNode(recv), sym)
   831  	n.Selection = m
   832  	n.SetType(NewMethodType(m.Type, recv))
   833  	n.SetTypecheck(1)
   834  	return n
   835  }
   836  
   837  func derefall(t *types.Type) *types.Type {
   838  	for t != nil && t.IsPtr() {
   839  		t = t.Elem()
   840  	}
   841  	return t
   842  }
   843  
   844  // Lookdot looks up field or method n.Sel in the type t and returns the matching
   845  // field. It transforms the op of node n to ODOTINTER or ODOTMETH, if appropriate.
   846  // It also may add a StarExpr node to n.X as needed for access to non-pointer
   847  // methods. If dostrcmp is 0, it matches the field/method with the exact symbol
   848  // as n.Sel (appropriate for exported fields). If dostrcmp is 1, it matches by name
   849  // exactly. If dostrcmp is 2, it matches names with case folding.
   850  func Lookdot(n *ir.SelectorExpr, t *types.Type, dostrcmp int) *types.Field {
   851  	s := n.Sel
   852  
   853  	types.CalcSize(t)
   854  	var f1 *types.Field
   855  	if t.IsStruct() {
   856  		f1 = Lookdot1(n, s, t, t.Fields(), dostrcmp)
   857  	} else if t.IsInterface() {
   858  		f1 = Lookdot1(n, s, t, t.AllMethods(), dostrcmp)
   859  	}
   860  
   861  	var f2 *types.Field
   862  	if n.X.Type() == t || n.X.Type().Sym() == nil {
   863  		mt := types.ReceiverBaseType(t)
   864  		if mt != nil {
   865  			f2 = Lookdot1(n, s, mt, mt.Methods(), dostrcmp)
   866  		}
   867  	}
   868  
   869  	if f1 != nil {
   870  		if dostrcmp > 1 {
   871  			// Already in the process of diagnosing an error.
   872  			return f1
   873  		}
   874  		if f2 != nil {
   875  			base.Errorf("%v is both field and method", n.Sel)
   876  		}
   877  		if f1.Offset == types.BADWIDTH {
   878  			base.Fatalf("Lookdot badwidth t=%v, f1=%v@%p", t, f1, f1)
   879  		}
   880  		n.Selection = f1
   881  		n.SetType(f1.Type)
   882  		if t.IsInterface() {
   883  			if n.X.Type().IsPtr() {
   884  				star := ir.NewStarExpr(base.Pos, n.X)
   885  				star.SetImplicit(true)
   886  				n.X = Expr(star)
   887  			}
   888  
   889  			n.SetOp(ir.ODOTINTER)
   890  		}
   891  		return f1
   892  	}
   893  
   894  	if f2 != nil {
   895  		if dostrcmp > 1 {
   896  			// Already in the process of diagnosing an error.
   897  			return f2
   898  		}
   899  		orig := n.X
   900  		tt := n.X.Type()
   901  		types.CalcSize(tt)
   902  		rcvr := f2.Type.Recv().Type
   903  		if !types.Identical(rcvr, tt) {
   904  			if rcvr.IsPtr() && types.Identical(rcvr.Elem(), tt) {
   905  				checklvalue(n.X, "call pointer method on")
   906  				addr := NodAddr(n.X)
   907  				addr.SetImplicit(true)
   908  				n.X = typecheck(addr, ctxType|ctxExpr)
   909  			} else if tt.IsPtr() && (!rcvr.IsPtr() || rcvr.IsPtr() && rcvr.Elem().NotInHeap()) && types.Identical(tt.Elem(), rcvr) {
   910  				star := ir.NewStarExpr(base.Pos, n.X)
   911  				star.SetImplicit(true)
   912  				n.X = typecheck(star, ctxType|ctxExpr)
   913  			} else if tt.IsPtr() && tt.Elem().IsPtr() && types.Identical(derefall(tt), derefall(rcvr)) {
   914  				base.Errorf("calling method %v with receiver %L requires explicit dereference", n.Sel, n.X)
   915  				for tt.IsPtr() {
   916  					// Stop one level early for method with pointer receiver.
   917  					if rcvr.IsPtr() && !tt.Elem().IsPtr() {
   918  						break
   919  					}
   920  					star := ir.NewStarExpr(base.Pos, n.X)
   921  					star.SetImplicit(true)
   922  					n.X = typecheck(star, ctxType|ctxExpr)
   923  					tt = tt.Elem()
   924  				}
   925  			} else {
   926  				base.Fatalf("method mismatch: %v for %v", rcvr, tt)
   927  			}
   928  		}
   929  
   930  		// Check that we haven't implicitly dereferenced any defined pointer types.
   931  		for x := n.X; ; {
   932  			var inner ir.Node
   933  			implicit := false
   934  			switch x := x.(type) {
   935  			case *ir.AddrExpr:
   936  				inner, implicit = x.X, x.Implicit()
   937  			case *ir.SelectorExpr:
   938  				inner, implicit = x.X, x.Implicit()
   939  			case *ir.StarExpr:
   940  				inner, implicit = x.X, x.Implicit()
   941  			}
   942  			if !implicit {
   943  				break
   944  			}
   945  			if inner.Type().Sym() != nil && (x.Op() == ir.ODEREF || x.Op() == ir.ODOTPTR) {
   946  				// Found an implicit dereference of a defined pointer type.
   947  				// Restore n.X for better error message.
   948  				n.X = orig
   949  				return nil
   950  			}
   951  			x = inner
   952  		}
   953  
   954  		n.Selection = f2
   955  		n.SetType(f2.Type)
   956  		n.SetOp(ir.ODOTMETH)
   957  
   958  		return f2
   959  	}
   960  
   961  	return nil
   962  }
   963  
   964  func nokeys(l ir.Nodes) bool {
   965  	for _, n := range l {
   966  		if n.Op() == ir.OKEY || n.Op() == ir.OSTRUCTKEY {
   967  			return false
   968  		}
   969  	}
   970  	return true
   971  }
   972  
   973  func hasddd(params []*types.Field) bool {
   974  	// TODO(mdempsky): Simply check the last param.
   975  	for _, tl := range params {
   976  		if tl.IsDDD() {
   977  			return true
   978  		}
   979  	}
   980  
   981  	return false
   982  }
   983  
   984  // typecheck assignment: type list = expression list
   985  func typecheckaste(op ir.Op, call ir.Node, isddd bool, params []*types.Field, nl ir.Nodes, desc func() string) {
   986  	var t *types.Type
   987  	var i int
   988  
   989  	lno := base.Pos
   990  	defer func() { base.Pos = lno }()
   991  
   992  	var n ir.Node
   993  	if len(nl) == 1 {
   994  		n = nl[0]
   995  	}
   996  
   997  	n1 := len(params)
   998  	n2 := len(nl)
   999  	if !hasddd(params) {
  1000  		if isddd {
  1001  			goto invalidddd
  1002  		}
  1003  		if n2 > n1 {
  1004  			goto toomany
  1005  		}
  1006  		if n2 < n1 {
  1007  			goto notenough
  1008  		}
  1009  	} else {
  1010  		if !isddd {
  1011  			if n2 < n1-1 {
  1012  				goto notenough
  1013  			}
  1014  		} else {
  1015  			if n2 > n1 {
  1016  				goto toomany
  1017  			}
  1018  			if n2 < n1 {
  1019  				goto notenough
  1020  			}
  1021  		}
  1022  	}
  1023  
  1024  	i = 0
  1025  	for _, tl := range params {
  1026  		t = tl.Type
  1027  		if tl.IsDDD() {
  1028  			if isddd {
  1029  				if i >= len(nl) {
  1030  					goto notenough
  1031  				}
  1032  				if len(nl)-i > 1 {
  1033  					goto toomany
  1034  				}
  1035  				n = nl[i]
  1036  				ir.SetPos(n)
  1037  				if n.Type() != nil {
  1038  					nl[i] = assignconvfn(n, t, desc)
  1039  				}
  1040  				return
  1041  			}
  1042  
  1043  			// TODO(mdempsky): Make into ... call with implicit slice.
  1044  			for ; i < len(nl); i++ {
  1045  				n = nl[i]
  1046  				ir.SetPos(n)
  1047  				if n.Type() != nil {
  1048  					nl[i] = assignconvfn(n, t.Elem(), desc)
  1049  				}
  1050  			}
  1051  			return
  1052  		}
  1053  
  1054  		if i >= len(nl) {
  1055  			goto notenough
  1056  		}
  1057  		n = nl[i]
  1058  		ir.SetPos(n)
  1059  		if n.Type() != nil {
  1060  			nl[i] = assignconvfn(n, t, desc)
  1061  		}
  1062  		i++
  1063  	}
  1064  
  1065  	if i < len(nl) {
  1066  		goto toomany
  1067  	}
  1068  
  1069  invalidddd:
  1070  	if isddd {
  1071  		if call != nil {
  1072  			base.Errorf("invalid use of ... in call to %v", call)
  1073  		} else {
  1074  			base.Errorf("invalid use of ... in %v", op)
  1075  		}
  1076  	}
  1077  	return
  1078  
  1079  notenough:
  1080  	if n == nil || n.Type() != nil {
  1081  		base.Fatalf("not enough arguments to %v", op)
  1082  	}
  1083  	return
  1084  
  1085  toomany:
  1086  	base.Fatalf("too many arguments to %v", op)
  1087  }
  1088  
  1089  // type check composite.
  1090  func fielddup(name string, hash map[string]bool) {
  1091  	if hash[name] {
  1092  		base.Errorf("duplicate field name in struct literal: %s", name)
  1093  		return
  1094  	}
  1095  	hash[name] = true
  1096  }
  1097  
  1098  // typecheckarraylit type-checks a sequence of slice/array literal elements.
  1099  func typecheckarraylit(elemType *types.Type, bound int64, elts []ir.Node, ctx string) int64 {
  1100  	// If there are key/value pairs, create a map to keep seen
  1101  	// keys so we can check for duplicate indices.
  1102  	var indices map[int64]bool
  1103  	for _, elt := range elts {
  1104  		if elt.Op() == ir.OKEY {
  1105  			indices = make(map[int64]bool)
  1106  			break
  1107  		}
  1108  	}
  1109  
  1110  	var key, length int64
  1111  	for i, elt := range elts {
  1112  		ir.SetPos(elt)
  1113  		r := elts[i]
  1114  		var kv *ir.KeyExpr
  1115  		if elt.Op() == ir.OKEY {
  1116  			elt := elt.(*ir.KeyExpr)
  1117  			elt.Key = Expr(elt.Key)
  1118  			key = IndexConst(elt.Key)
  1119  			if key < 0 {
  1120  				base.Fatalf("invalid index: %v", elt.Key)
  1121  			}
  1122  			kv = elt
  1123  			r = elt.Value
  1124  		}
  1125  
  1126  		r = Expr(r)
  1127  		r = AssignConv(r, elemType, ctx)
  1128  		if kv != nil {
  1129  			kv.Value = r
  1130  		} else {
  1131  			elts[i] = r
  1132  		}
  1133  
  1134  		if key >= 0 {
  1135  			if indices != nil {
  1136  				if indices[key] {
  1137  					base.Errorf("duplicate index in %s: %d", ctx, key)
  1138  				} else {
  1139  					indices[key] = true
  1140  				}
  1141  			}
  1142  
  1143  			if bound >= 0 && key >= bound {
  1144  				base.Errorf("array index %d out of bounds [0:%d]", key, bound)
  1145  				bound = -1
  1146  			}
  1147  		}
  1148  
  1149  		key++
  1150  		if key > length {
  1151  			length = key
  1152  		}
  1153  	}
  1154  
  1155  	return length
  1156  }
  1157  
  1158  // visible reports whether sym is exported or locally defined.
  1159  func visible(sym *types.Sym) bool {
  1160  	return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == types.LocalPkg)
  1161  }
  1162  
  1163  // nonexported reports whether sym is an unexported field.
  1164  func nonexported(sym *types.Sym) bool {
  1165  	return sym != nil && !types.IsExported(sym.Name)
  1166  }
  1167  
  1168  func checklvalue(n ir.Node, verb string) {
  1169  	if !ir.IsAddressable(n) {
  1170  		base.Errorf("cannot %s %v", verb, n)
  1171  	}
  1172  }
  1173  
  1174  func checkassign(n ir.Node) {
  1175  	// have already complained about n being invalid
  1176  	if n.Type() == nil {
  1177  		if base.Errors() == 0 {
  1178  			base.Fatalf("expected an error about %v", n)
  1179  		}
  1180  		return
  1181  	}
  1182  
  1183  	if ir.IsAddressable(n) {
  1184  		return
  1185  	}
  1186  	if n.Op() == ir.OINDEXMAP {
  1187  		n := n.(*ir.IndexExpr)
  1188  		n.Assigned = true
  1189  		return
  1190  	}
  1191  
  1192  	defer n.SetType(nil)
  1193  
  1194  	switch {
  1195  	case n.Op() == ir.ODOT && n.(*ir.SelectorExpr).X.Op() == ir.OINDEXMAP:
  1196  		base.Errorf("cannot assign to struct field %v in map", n)
  1197  	case (n.Op() == ir.OINDEX && n.(*ir.IndexExpr).X.Type().IsString()) || n.Op() == ir.OSLICESTR:
  1198  		base.Errorf("cannot assign to %v (strings are immutable)", n)
  1199  	case n.Op() == ir.OLITERAL && n.Sym() != nil && ir.IsConstNode(n):
  1200  		base.Errorf("cannot assign to %v (declared const)", n)
  1201  	default:
  1202  		base.Errorf("cannot assign to %v", n)
  1203  	}
  1204  }
  1205  
  1206  func checkassignto(src *types.Type, dst ir.Node) {
  1207  	// TODO(mdempsky): Handle all untyped types correctly.
  1208  	if src == types.UntypedBool && dst.Type().IsBoolean() {
  1209  		return
  1210  	}
  1211  
  1212  	if op, why := assignOp(src, dst.Type()); op == ir.OXXX {
  1213  		base.Errorf("cannot assign %v to %L in multiple assignment%s", src, dst, why)
  1214  		return
  1215  	}
  1216  }
  1217  
  1218  // The result of stringtoruneslit MUST be assigned back to n, e.g.
  1219  //
  1220  //	n.Left = stringtoruneslit(n.Left)
  1221  func stringtoruneslit(n *ir.ConvExpr) ir.Node {
  1222  	if n.X.Op() != ir.OLITERAL || n.X.Val().Kind() != constant.String {
  1223  		base.Fatalf("stringtoarraylit %v", n)
  1224  	}
  1225  
  1226  	var l []ir.Node
  1227  	i := 0
  1228  	for _, r := range ir.StringVal(n.X) {
  1229  		l = append(l, ir.NewKeyExpr(base.Pos, ir.NewInt(base.Pos, int64(i)), ir.NewInt(base.Pos, int64(r))))
  1230  		i++
  1231  	}
  1232  
  1233  	return Expr(ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, n.Type(), l))
  1234  }
  1235  
  1236  func checkmake(t *types.Type, arg string, np *ir.Node) bool {
  1237  	n := *np
  1238  	if !n.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
  1239  		base.Errorf("non-integer %s argument in make(%v) - %v", arg, t, n.Type())
  1240  		return false
  1241  	}
  1242  
  1243  	// Do range checks for constants before DefaultLit
  1244  	// to avoid redundant "constant NNN overflows int" errors.
  1245  	if n.Op() == ir.OLITERAL {
  1246  		v := toint(n.Val())
  1247  		if constant.Sign(v) < 0 {
  1248  			base.Errorf("negative %s argument in make(%v)", arg, t)
  1249  			return false
  1250  		}
  1251  		if ir.ConstOverflow(v, types.Types[types.TINT]) {
  1252  			base.Errorf("%s argument too large in make(%v)", arg, t)
  1253  			return false
  1254  		}
  1255  	}
  1256  
  1257  	// DefaultLit is necessary for non-constants too: n might be 1.1<<k.
  1258  	// TODO(gri) The length argument requirements for (array/slice) make
  1259  	// are the same as for index expressions. Factor the code better;
  1260  	// for instance, indexlit might be called here and incorporate some
  1261  	// of the bounds checks done for make.
  1262  	n = DefaultLit(n, types.Types[types.TINT])
  1263  	*np = n
  1264  
  1265  	return true
  1266  }
  1267  
  1268  // checkunsafesliceorstring is like checkmake but for unsafe.{Slice,String}.
  1269  func checkunsafesliceorstring(op ir.Op, np *ir.Node) bool {
  1270  	n := *np
  1271  	if !n.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
  1272  		base.Errorf("non-integer len argument in %v - %v", op, n.Type())
  1273  		return false
  1274  	}
  1275  
  1276  	// Do range checks for constants before DefaultLit
  1277  	// to avoid redundant "constant NNN overflows int" errors.
  1278  	if n.Op() == ir.OLITERAL {
  1279  		v := toint(n.Val())
  1280  		if constant.Sign(v) < 0 {
  1281  			base.Errorf("negative len argument in %v", op)
  1282  			return false
  1283  		}
  1284  		if ir.ConstOverflow(v, types.Types[types.TINT]) {
  1285  			base.Errorf("len argument too large in %v", op)
  1286  			return false
  1287  		}
  1288  	}
  1289  
  1290  	// DefaultLit is necessary for non-constants too: n might be 1.1<<k.
  1291  	n = DefaultLit(n, types.Types[types.TINT])
  1292  	*np = n
  1293  
  1294  	return true
  1295  }
  1296  
  1297  func Conv(n ir.Node, t *types.Type) ir.Node {
  1298  	if types.IdenticalStrict(n.Type(), t) {
  1299  		return n
  1300  	}
  1301  	n = ir.NewConvExpr(base.Pos, ir.OCONV, nil, n)
  1302  	n.SetType(t)
  1303  	n = Expr(n)
  1304  	return n
  1305  }
  1306  
  1307  // ConvNop converts node n to type t using the OCONVNOP op
  1308  // and typechecks the result with ctxExpr.
  1309  func ConvNop(n ir.Node, t *types.Type) ir.Node {
  1310  	if types.IdenticalStrict(n.Type(), t) {
  1311  		return n
  1312  	}
  1313  	n = ir.NewConvExpr(base.Pos, ir.OCONVNOP, nil, n)
  1314  	n.SetType(t)
  1315  	n = Expr(n)
  1316  	return n
  1317  }
  1318  

View as plain text