Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/compile/internal/typecheck/func.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  	"cmd/compile/internal/base"
     9  	"cmd/compile/internal/ir"
    10  	"cmd/compile/internal/types"
    11  
    12  	"fmt"
    13  	"go/constant"
    14  	"go/token"
    15  )
    16  
    17  // package all the arguments that match a ... T parameter into a []T.
    18  func MakeDotArgs(typ *types.Type, args []ir.Node) ir.Node {
    19  	var n ir.Node
    20  	if len(args) == 0 {
    21  		n = NodNil()
    22  		n.SetType(typ)
    23  	} else {
    24  		lit := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil)
    25  		lit.List.Append(args...)
    26  		lit.SetImplicit(true)
    27  		n = lit
    28  	}
    29  
    30  	n = Expr(n)
    31  	if n.Type() == nil {
    32  		base.Fatalf("mkdotargslice: typecheck failed")
    33  	}
    34  	return n
    35  }
    36  
    37  // FixVariadicCall rewrites calls to variadic functions to use an
    38  // explicit ... argument if one is not already present.
    39  func FixVariadicCall(call *ir.CallExpr) {
    40  	fntype := call.X.Type()
    41  	if !fntype.IsVariadic() || call.IsDDD {
    42  		return
    43  	}
    44  
    45  	vi := fntype.NumParams() - 1
    46  	vt := fntype.Params().Field(vi).Type
    47  
    48  	args := call.Args
    49  	extra := args[vi:]
    50  	slice := MakeDotArgs(vt, extra)
    51  	for i := range extra {
    52  		extra[i] = nil // allow GC
    53  	}
    54  
    55  	call.Args = append(args[:vi], slice)
    56  	call.IsDDD = true
    57  }
    58  
    59  // ClosureType returns the struct type used to hold all the information
    60  // needed in the closure for clo (clo must be a OCLOSURE node).
    61  // The address of a variable of the returned type can be cast to a func.
    62  func ClosureType(clo *ir.ClosureExpr) *types.Type {
    63  	// Create closure in the form of a composite literal.
    64  	// supposing the closure captures an int i and a string s
    65  	// and has one float64 argument and no results,
    66  	// the generated code looks like:
    67  	//
    68  	//	clos = &struct{.F uintptr; i *int; s *string}{func.1, &i, &s}
    69  	//
    70  	// The use of the struct provides type information to the garbage
    71  	// collector so that it can walk the closure. We could use (in this case)
    72  	// [3]unsafe.Pointer instead, but that would leave the gc in the dark.
    73  	// The information appears in the binary in the form of type descriptors;
    74  	// the struct is unnamed so that closures in multiple packages with the
    75  	// same struct type can share the descriptor.
    76  	fields := []*types.Field{
    77  		types.NewField(base.Pos, Lookup(".F"), types.Types[types.TUINTPTR]),
    78  	}
    79  	for _, v := range clo.Func.ClosureVars {
    80  		typ := v.Type()
    81  		if !v.Byval() {
    82  			typ = types.NewPtr(typ)
    83  		}
    84  		fields = append(fields, types.NewField(base.Pos, v.Sym(), typ))
    85  	}
    86  	typ := types.NewStruct(types.NoPkg, fields)
    87  	typ.SetNoalg(true)
    88  	return typ
    89  }
    90  
    91  // PartialCallType returns the struct type used to hold all the information
    92  // needed in the closure for n (n must be a OCALLPART node).
    93  // The address of a variable of the returned type can be cast to a func.
    94  func PartialCallType(n *ir.SelectorExpr) *types.Type {
    95  	t := types.NewStruct(types.NoPkg, []*types.Field{
    96  		types.NewField(base.Pos, Lookup("F"), types.Types[types.TUINTPTR]),
    97  		types.NewField(base.Pos, Lookup("R"), n.X.Type()),
    98  	})
    99  	t.SetNoalg(true)
   100  	return t
   101  }
   102  
   103  // True if we are typechecking an inline body in ImportedBody below. We use this
   104  // flag to not create a new closure function in tcClosure when we are just
   105  // typechecking an inline body, as opposed to the body of a real function.
   106  var inTypeCheckInl bool
   107  
   108  // ImportedBody returns immediately if the inlining information for fn is
   109  // populated. Otherwise, fn must be an imported function. If so, ImportedBody
   110  // loads in the dcls and body for fn, and typechecks as needed.
   111  func ImportedBody(fn *ir.Func) {
   112  	if fn.Inl.Body != nil {
   113  		return
   114  	}
   115  	lno := ir.SetPos(fn.Nname)
   116  
   117  	// When we load an inlined body, we need to allow OADDR
   118  	// operations on untyped expressions. We will fix the
   119  	// addrtaken flags on all the arguments of the OADDR with the
   120  	// computeAddrtaken call below (after we typecheck the body).
   121  	// TODO: export/import types and addrtaken marks along with inlined bodies,
   122  	// so this will be unnecessary.
   123  	IncrementalAddrtaken = false
   124  	defer func() {
   125  		if DirtyAddrtaken {
   126  			ComputeAddrtaken(fn.Inl.Body) // compute addrtaken marks once types are available
   127  			DirtyAddrtaken = false
   128  		}
   129  		IncrementalAddrtaken = true
   130  	}()
   131  
   132  	ImportBody(fn)
   133  
   134  	// Stmts(fn.Inl.Body) below is only for imported functions;
   135  	// their bodies may refer to unsafe as long as the package
   136  	// was marked safe during import (which was checked then).
   137  	// the ->inl of a local function has been typechecked before CanInline copied it.
   138  	pkg := fnpkg(fn.Nname)
   139  
   140  	if pkg == types.LocalPkg || pkg == nil {
   141  		return // ImportedBody on local function
   142  	}
   143  
   144  	if base.Flag.LowerM > 2 || base.Debug.Export != 0 {
   145  		fmt.Printf("typecheck import [%v] %L { %v }\n", fn.Sym(), fn, ir.Nodes(fn.Inl.Body))
   146  	}
   147  
   148  	if !go117ExportTypes {
   149  		// If we didn't export & import types, typecheck the code here.
   150  		savefn := ir.CurFunc
   151  		ir.CurFunc = fn
   152  		if inTypeCheckInl {
   153  			base.Fatalf("inTypeCheckInl should not be set recursively")
   154  		}
   155  		inTypeCheckInl = true
   156  		Stmts(fn.Inl.Body)
   157  		inTypeCheckInl = false
   158  		ir.CurFunc = savefn
   159  	}
   160  
   161  	base.Pos = lno
   162  }
   163  
   164  // Get the function's package. For ordinary functions it's on the ->sym, but for imported methods
   165  // the ->sym can be re-used in the local package, so peel it off the receiver's type.
   166  func fnpkg(fn *ir.Name) *types.Pkg {
   167  	if ir.IsMethod(fn) {
   168  		// method
   169  		rcvr := fn.Type().Recv().Type
   170  
   171  		if rcvr.IsPtr() {
   172  			rcvr = rcvr.Elem()
   173  		}
   174  		if rcvr.Sym() == nil {
   175  			base.Fatalf("receiver with no sym: [%v] %L  (%v)", fn.Sym(), fn, rcvr)
   176  		}
   177  		return rcvr.Sym().Pkg
   178  	}
   179  
   180  	// non-method
   181  	return fn.Sym().Pkg
   182  }
   183  
   184  // ClosureName generates a new unique name for a closure within
   185  // outerfunc.
   186  func ClosureName(outerfunc *ir.Func) *types.Sym {
   187  	outer := "glob."
   188  	prefix := "func"
   189  	gen := &globClosgen
   190  
   191  	if outerfunc != nil {
   192  		if outerfunc.OClosure != nil {
   193  			prefix = ""
   194  		}
   195  
   196  		outer = ir.FuncName(outerfunc)
   197  
   198  		// There may be multiple functions named "_". In those
   199  		// cases, we can't use their individual Closgens as it
   200  		// would lead to name clashes.
   201  		if !ir.IsBlank(outerfunc.Nname) {
   202  			gen = &outerfunc.Closgen
   203  		}
   204  	}
   205  
   206  	*gen++
   207  	return Lookup(fmt.Sprintf("%s.%s%d", outer, prefix, *gen))
   208  }
   209  
   210  // globClosgen is like Func.Closgen, but for the global scope.
   211  var globClosgen int32
   212  
   213  // MethodValueWrapper returns the DCLFUNC node representing the
   214  // wrapper function (*-fm) needed for the given method value. If the
   215  // wrapper function hasn't already been created yet, it's created and
   216  // added to Target.Decls.
   217  //
   218  // TODO(mdempsky): Move into walk. This isn't part of type checking.
   219  func MethodValueWrapper(dot *ir.SelectorExpr) *ir.Func {
   220  	if dot.Op() != ir.OCALLPART {
   221  		base.Fatalf("MethodValueWrapper: unexpected %v (%v)", dot, dot.Op())
   222  	}
   223  
   224  	t0 := dot.Type()
   225  	meth := dot.Sel
   226  	rcvrtype := dot.X.Type()
   227  	sym := ir.MethodSymSuffix(rcvrtype, meth, "-fm")
   228  
   229  	if sym.Uniq() {
   230  		return sym.Def.(*ir.Func)
   231  	}
   232  	sym.SetUniq(true)
   233  
   234  	savecurfn := ir.CurFunc
   235  	saveLineNo := base.Pos
   236  	ir.CurFunc = nil
   237  
   238  	// Set line number equal to the line number where the method is declared.
   239  	if pos := dot.Selection.Pos; pos.IsKnown() {
   240  		base.Pos = pos
   241  	}
   242  	// Note: !dot.Selection.Pos.IsKnown() happens for method expressions where
   243  	// the method is implicitly declared. The Error method of the
   244  	// built-in error type is one such method.  We leave the line
   245  	// number at the use of the method expression in this
   246  	// case. See issue 29389.
   247  
   248  	tfn := ir.NewFuncType(base.Pos, nil,
   249  		NewFuncParams(t0.Params(), true),
   250  		NewFuncParams(t0.Results(), false))
   251  
   252  	fn := DeclFunc(sym, tfn)
   253  	fn.SetDupok(true)
   254  	fn.SetNeedctxt(true)
   255  	fn.SetWrapper(true)
   256  
   257  	// Declare and initialize variable holding receiver.
   258  	ptr := ir.NewNameAt(base.Pos, Lookup(".this"))
   259  	ptr.Class = ir.PAUTOHEAP
   260  	ptr.SetType(rcvrtype)
   261  	ptr.Curfn = fn
   262  	ptr.SetIsClosureVar(true)
   263  	ptr.SetByval(true)
   264  	fn.ClosureVars = append(fn.ClosureVars, ptr)
   265  
   266  	call := ir.NewCallExpr(base.Pos, ir.OCALL, ir.NewSelectorExpr(base.Pos, ir.OXDOT, ptr, meth), nil)
   267  	call.Args = ir.ParamNames(tfn.Type())
   268  	call.IsDDD = tfn.Type().IsVariadic()
   269  
   270  	var body ir.Node = call
   271  	if t0.NumResults() != 0 {
   272  		ret := ir.NewReturnStmt(base.Pos, nil)
   273  		ret.Results = []ir.Node{call}
   274  		body = ret
   275  	}
   276  
   277  	fn.Body = []ir.Node{body}
   278  	FinishFuncBody()
   279  
   280  	Func(fn)
   281  	// Need to typecheck the body of the just-generated wrapper.
   282  	// typecheckslice() requires that Curfn is set when processing an ORETURN.
   283  	ir.CurFunc = fn
   284  	Stmts(fn.Body)
   285  	sym.Def = fn
   286  	Target.Decls = append(Target.Decls, fn)
   287  	ir.CurFunc = savecurfn
   288  	base.Pos = saveLineNo
   289  
   290  	return fn
   291  }
   292  
   293  // tcClosure typechecks an OCLOSURE node. It also creates the named
   294  // function associated with the closure.
   295  // TODO: This creation of the named function should probably really be done in a
   296  // separate pass from type-checking.
   297  func tcClosure(clo *ir.ClosureExpr, top int) {
   298  	fn := clo.Func
   299  	// Set current associated iota value, so iota can be used inside
   300  	// function in ConstSpec, see issue #22344
   301  	if x := getIotaValue(); x >= 0 {
   302  		fn.Iota = x
   303  	}
   304  
   305  	fn.SetClosureCalled(top&ctxCallee != 0)
   306  
   307  	// Do not typecheck fn twice, otherwise, we will end up pushing
   308  	// fn to Target.Decls multiple times, causing InitLSym called twice.
   309  	// See #30709
   310  	if fn.Typecheck() == 1 {
   311  		clo.SetType(fn.Type())
   312  		return
   313  	}
   314  
   315  	// Don't give a name and add to Target.Decls if we are typechecking an inlined
   316  	// body in ImportedBody(), since we only want to create the named function
   317  	// when the closure is actually inlined (and then we force a typecheck
   318  	// explicitly in (*inlsubst).node()).
   319  	if !inTypeCheckInl {
   320  		fn.Nname.SetSym(ClosureName(ir.CurFunc))
   321  		ir.MarkFunc(fn.Nname)
   322  	}
   323  	Func(fn)
   324  	clo.SetType(fn.Type())
   325  
   326  	// Type check the body now, but only if we're inside a function.
   327  	// At top level (in a variable initialization: curfn==nil) we're not
   328  	// ready to type check code yet; we'll check it later, because the
   329  	// underlying closure function we create is added to Target.Decls.
   330  	if ir.CurFunc != nil && clo.Type() != nil {
   331  		oldfn := ir.CurFunc
   332  		ir.CurFunc = fn
   333  		Stmts(fn.Body)
   334  		ir.CurFunc = oldfn
   335  	}
   336  
   337  	out := 0
   338  	for _, v := range fn.ClosureVars {
   339  		if v.Type() == nil {
   340  			// If v.Type is nil, it means v looked like it was going to be
   341  			// used in the closure, but isn't. This happens in struct
   342  			// literals like s{f: x} where we can't distinguish whether f is
   343  			// a field identifier or expression until resolving s.
   344  			continue
   345  		}
   346  
   347  		// type check closed variables outside the closure, so that the
   348  		// outer frame also captures them.
   349  		Expr(v.Outer)
   350  
   351  		fn.ClosureVars[out] = v
   352  		out++
   353  	}
   354  	fn.ClosureVars = fn.ClosureVars[:out]
   355  
   356  	if base.Flag.W > 1 {
   357  		s := fmt.Sprintf("New closure func: %s", ir.FuncName(fn))
   358  		ir.Dump(s, fn)
   359  	}
   360  	if !inTypeCheckInl {
   361  		// Add function to Target.Decls once only when we give it a name
   362  		Target.Decls = append(Target.Decls, fn)
   363  	}
   364  }
   365  
   366  // type check function definition
   367  // To be called by typecheck, not directly.
   368  // (Call typecheck.Func instead.)
   369  func tcFunc(n *ir.Func) {
   370  	if base.EnableTrace && base.Flag.LowerT {
   371  		defer tracePrint("tcFunc", n)(nil)
   372  	}
   373  
   374  	n.Nname = AssignExpr(n.Nname).(*ir.Name)
   375  	t := n.Nname.Type()
   376  	if t == nil {
   377  		return
   378  	}
   379  	rcvr := t.Recv()
   380  	if rcvr != nil && n.Shortname != nil {
   381  		m := addmethod(n, n.Shortname, t, true, n.Pragma&ir.Nointerface != 0)
   382  		if m == nil {
   383  			return
   384  		}
   385  
   386  		n.Nname.SetSym(ir.MethodSym(rcvr.Type, n.Shortname))
   387  		Declare(n.Nname, ir.PFUNC)
   388  	}
   389  }
   390  
   391  // tcCall typechecks an OCALL node.
   392  func tcCall(n *ir.CallExpr, top int) ir.Node {
   393  	n.Use = ir.CallUseExpr
   394  	if top == ctxStmt {
   395  		n.Use = ir.CallUseStmt
   396  	}
   397  	Stmts(n.Init()) // imported rewritten f(g()) calls (#30907)
   398  	n.X = typecheck(n.X, ctxExpr|ctxType|ctxCallee)
   399  	if n.X.Diag() {
   400  		n.SetDiag(true)
   401  	}
   402  
   403  	l := n.X
   404  
   405  	if l.Op() == ir.ONAME && l.(*ir.Name).BuiltinOp != 0 {
   406  		l := l.(*ir.Name)
   407  		if n.IsDDD && l.BuiltinOp != ir.OAPPEND {
   408  			base.Errorf("invalid use of ... with builtin %v", l)
   409  		}
   410  
   411  		// builtin: OLEN, OCAP, etc.
   412  		switch l.BuiltinOp {
   413  		default:
   414  			base.Fatalf("unknown builtin %v", l)
   415  
   416  		case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
   417  			n.SetOp(l.BuiltinOp)
   418  			n.X = nil
   419  			n.SetTypecheck(0) // re-typechecking new op is OK, not a loop
   420  			return typecheck(n, top)
   421  
   422  		case ir.OCAP, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL:
   423  			typecheckargs(n)
   424  			fallthrough
   425  		case ir.ONEW, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
   426  			arg, ok := needOneArg(n, "%v", n.Op())
   427  			if !ok {
   428  				n.SetType(nil)
   429  				return n
   430  			}
   431  			u := ir.NewUnaryExpr(n.Pos(), l.BuiltinOp, arg)
   432  			return typecheck(ir.InitExpr(n.Init(), u), top) // typecheckargs can add to old.Init
   433  
   434  		case ir.OCOMPLEX, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE:
   435  			typecheckargs(n)
   436  			arg1, arg2, ok := needTwoArgs(n)
   437  			if !ok {
   438  				n.SetType(nil)
   439  				return n
   440  			}
   441  			b := ir.NewBinaryExpr(n.Pos(), l.BuiltinOp, arg1, arg2)
   442  			return typecheck(ir.InitExpr(n.Init(), b), top) // typecheckargs can add to old.Init
   443  		}
   444  		panic("unreachable")
   445  	}
   446  
   447  	n.X = DefaultLit(n.X, nil)
   448  	l = n.X
   449  	if l.Op() == ir.OTYPE {
   450  		if n.IsDDD {
   451  			if !l.Type().Broke() {
   452  				base.Errorf("invalid use of ... in type conversion to %v", l.Type())
   453  			}
   454  			n.SetDiag(true)
   455  		}
   456  
   457  		// pick off before type-checking arguments
   458  		arg, ok := needOneArg(n, "conversion to %v", l.Type())
   459  		if !ok {
   460  			n.SetType(nil)
   461  			return n
   462  		}
   463  
   464  		n := ir.NewConvExpr(n.Pos(), ir.OCONV, nil, arg)
   465  		n.SetType(l.Type())
   466  		return tcConv(n)
   467  	}
   468  
   469  	typecheckargs(n)
   470  	t := l.Type()
   471  	if t == nil {
   472  		n.SetType(nil)
   473  		return n
   474  	}
   475  	types.CheckSize(t)
   476  
   477  	switch l.Op() {
   478  	case ir.ODOTINTER:
   479  		n.SetOp(ir.OCALLINTER)
   480  
   481  	case ir.ODOTMETH:
   482  		l := l.(*ir.SelectorExpr)
   483  		n.SetOp(ir.OCALLMETH)
   484  
   485  		// typecheckaste was used here but there wasn't enough
   486  		// information further down the call chain to know if we
   487  		// were testing a method receiver for unexported fields.
   488  		// It isn't necessary, so just do a sanity check.
   489  		tp := t.Recv().Type
   490  
   491  		if l.X == nil || !types.Identical(l.X.Type(), tp) {
   492  			base.Fatalf("method receiver")
   493  		}
   494  
   495  	default:
   496  		n.SetOp(ir.OCALLFUNC)
   497  		if t.Kind() != types.TFUNC {
   498  			if o := ir.Orig(l); o.Name() != nil && types.BuiltinPkg.Lookup(o.Sym().Name).Def != nil {
   499  				// be more specific when the non-function
   500  				// name matches a predeclared function
   501  				base.Errorf("cannot call non-function %L, declared at %s",
   502  					l, base.FmtPos(o.Name().Pos()))
   503  			} else {
   504  				base.Errorf("cannot call non-function %L", l)
   505  			}
   506  			n.SetType(nil)
   507  			return n
   508  		}
   509  	}
   510  
   511  	typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.X) })
   512  	if t.NumResults() == 0 {
   513  		return n
   514  	}
   515  	if t.NumResults() == 1 {
   516  		n.SetType(l.Type().Results().Field(0).Type)
   517  
   518  		if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.ONAME {
   519  			if sym := n.X.(*ir.Name).Sym(); types.IsRuntimePkg(sym.Pkg) && sym.Name == "getg" {
   520  				// Emit code for runtime.getg() directly instead of calling function.
   521  				// Most such rewrites (for example the similar one for math.Sqrt) should be done in walk,
   522  				// so that the ordering pass can make sure to preserve the semantics of the original code
   523  				// (in particular, the exact time of the function call) by introducing temporaries.
   524  				// In this case, we know getg() always returns the same result within a given function
   525  				// and we want to avoid the temporaries, so we do the rewrite earlier than is typical.
   526  				n.SetOp(ir.OGETG)
   527  			}
   528  		}
   529  		return n
   530  	}
   531  
   532  	// multiple return
   533  	if top&(ctxMultiOK|ctxStmt) == 0 {
   534  		base.Errorf("multiple-value %v() in single-value context", l)
   535  		return n
   536  	}
   537  
   538  	n.SetType(l.Type().Results())
   539  	return n
   540  }
   541  
   542  // tcAppend typechecks an OAPPEND node.
   543  func tcAppend(n *ir.CallExpr) ir.Node {
   544  	typecheckargs(n)
   545  	args := n.Args
   546  	if len(args) == 0 {
   547  		base.Errorf("missing arguments to append")
   548  		n.SetType(nil)
   549  		return n
   550  	}
   551  
   552  	t := args[0].Type()
   553  	if t == nil {
   554  		n.SetType(nil)
   555  		return n
   556  	}
   557  
   558  	n.SetType(t)
   559  	if !t.IsSlice() {
   560  		if ir.IsNil(args[0]) {
   561  			base.Errorf("first argument to append must be typed slice; have untyped nil")
   562  			n.SetType(nil)
   563  			return n
   564  		}
   565  
   566  		base.Errorf("first argument to append must be slice; have %L", t)
   567  		n.SetType(nil)
   568  		return n
   569  	}
   570  
   571  	if n.IsDDD {
   572  		if len(args) == 1 {
   573  			base.Errorf("cannot use ... on first argument to append")
   574  			n.SetType(nil)
   575  			return n
   576  		}
   577  
   578  		if len(args) != 2 {
   579  			base.Errorf("too many arguments to append")
   580  			n.SetType(nil)
   581  			return n
   582  		}
   583  
   584  		if t.Elem().IsKind(types.TUINT8) && args[1].Type().IsString() {
   585  			args[1] = DefaultLit(args[1], types.Types[types.TSTRING])
   586  			return n
   587  		}
   588  
   589  		args[1] = AssignConv(args[1], t.Underlying(), "append")
   590  		return n
   591  	}
   592  
   593  	as := args[1:]
   594  	for i, n := range as {
   595  		if n.Type() == nil {
   596  			continue
   597  		}
   598  		as[i] = AssignConv(n, t.Elem(), "append")
   599  		types.CheckSize(as[i].Type()) // ensure width is calculated for backend
   600  	}
   601  	return n
   602  }
   603  
   604  // tcClose typechecks an OCLOSE node.
   605  func tcClose(n *ir.UnaryExpr) ir.Node {
   606  	n.X = Expr(n.X)
   607  	n.X = DefaultLit(n.X, nil)
   608  	l := n.X
   609  	t := l.Type()
   610  	if t == nil {
   611  		n.SetType(nil)
   612  		return n
   613  	}
   614  	if !t.IsChan() {
   615  		base.Errorf("invalid operation: %v (non-chan type %v)", n, t)
   616  		n.SetType(nil)
   617  		return n
   618  	}
   619  
   620  	if !t.ChanDir().CanSend() {
   621  		base.Errorf("invalid operation: %v (cannot close receive-only channel)", n)
   622  		n.SetType(nil)
   623  		return n
   624  	}
   625  	return n
   626  }
   627  
   628  // tcComplex typechecks an OCOMPLEX node.
   629  func tcComplex(n *ir.BinaryExpr) ir.Node {
   630  	l := Expr(n.X)
   631  	r := Expr(n.Y)
   632  	if l.Type() == nil || r.Type() == nil {
   633  		n.SetType(nil)
   634  		return n
   635  	}
   636  	l, r = defaultlit2(l, r, false)
   637  	if l.Type() == nil || r.Type() == nil {
   638  		n.SetType(nil)
   639  		return n
   640  	}
   641  	n.X = l
   642  	n.Y = r
   643  
   644  	if !types.Identical(l.Type(), r.Type()) {
   645  		base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
   646  		n.SetType(nil)
   647  		return n
   648  	}
   649  
   650  	var t *types.Type
   651  	switch l.Type().Kind() {
   652  	default:
   653  		base.Errorf("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type())
   654  		n.SetType(nil)
   655  		return n
   656  
   657  	case types.TIDEAL:
   658  		t = types.UntypedComplex
   659  
   660  	case types.TFLOAT32:
   661  		t = types.Types[types.TCOMPLEX64]
   662  
   663  	case types.TFLOAT64:
   664  		t = types.Types[types.TCOMPLEX128]
   665  	}
   666  	n.SetType(t)
   667  	return n
   668  }
   669  
   670  // tcCopy typechecks an OCOPY node.
   671  func tcCopy(n *ir.BinaryExpr) ir.Node {
   672  	n.SetType(types.Types[types.TINT])
   673  	n.X = Expr(n.X)
   674  	n.X = DefaultLit(n.X, nil)
   675  	n.Y = Expr(n.Y)
   676  	n.Y = DefaultLit(n.Y, nil)
   677  	if n.X.Type() == nil || n.Y.Type() == nil {
   678  		n.SetType(nil)
   679  		return n
   680  	}
   681  
   682  	// copy([]byte, string)
   683  	if n.X.Type().IsSlice() && n.Y.Type().IsString() {
   684  		if types.Identical(n.X.Type().Elem(), types.ByteType) {
   685  			return n
   686  		}
   687  		base.Errorf("arguments to copy have different element types: %L and string", n.X.Type())
   688  		n.SetType(nil)
   689  		return n
   690  	}
   691  
   692  	if !n.X.Type().IsSlice() || !n.Y.Type().IsSlice() {
   693  		if !n.X.Type().IsSlice() && !n.Y.Type().IsSlice() {
   694  			base.Errorf("arguments to copy must be slices; have %L, %L", n.X.Type(), n.Y.Type())
   695  		} else if !n.X.Type().IsSlice() {
   696  			base.Errorf("first argument to copy should be slice; have %L", n.X.Type())
   697  		} else {
   698  			base.Errorf("second argument to copy should be slice or string; have %L", n.Y.Type())
   699  		}
   700  		n.SetType(nil)
   701  		return n
   702  	}
   703  
   704  	if !types.Identical(n.X.Type().Elem(), n.Y.Type().Elem()) {
   705  		base.Errorf("arguments to copy have different element types: %L and %L", n.X.Type(), n.Y.Type())
   706  		n.SetType(nil)
   707  		return n
   708  	}
   709  	return n
   710  }
   711  
   712  // tcDelete typechecks an ODELETE node.
   713  func tcDelete(n *ir.CallExpr) ir.Node {
   714  	typecheckargs(n)
   715  	args := n.Args
   716  	if len(args) == 0 {
   717  		base.Errorf("missing arguments to delete")
   718  		n.SetType(nil)
   719  		return n
   720  	}
   721  
   722  	if len(args) == 1 {
   723  		base.Errorf("missing second (key) argument to delete")
   724  		n.SetType(nil)
   725  		return n
   726  	}
   727  
   728  	if len(args) != 2 {
   729  		base.Errorf("too many arguments to delete")
   730  		n.SetType(nil)
   731  		return n
   732  	}
   733  
   734  	l := args[0]
   735  	r := args[1]
   736  	if l.Type() != nil && !l.Type().IsMap() {
   737  		base.Errorf("first argument to delete must be map; have %L", l.Type())
   738  		n.SetType(nil)
   739  		return n
   740  	}
   741  
   742  	args[1] = AssignConv(r, l.Type().Key(), "delete")
   743  	return n
   744  }
   745  
   746  // tcMake typechecks an OMAKE node.
   747  func tcMake(n *ir.CallExpr) ir.Node {
   748  	args := n.Args
   749  	if len(args) == 0 {
   750  		base.Errorf("missing argument to make")
   751  		n.SetType(nil)
   752  		return n
   753  	}
   754  
   755  	n.Args = nil
   756  	l := args[0]
   757  	l = typecheck(l, ctxType)
   758  	t := l.Type()
   759  	if t == nil {
   760  		n.SetType(nil)
   761  		return n
   762  	}
   763  
   764  	i := 1
   765  	var nn ir.Node
   766  	switch t.Kind() {
   767  	default:
   768  		base.Errorf("cannot make type %v", t)
   769  		n.SetType(nil)
   770  		return n
   771  
   772  	case types.TSLICE:
   773  		if i >= len(args) {
   774  			base.Errorf("missing len argument to make(%v)", t)
   775  			n.SetType(nil)
   776  			return n
   777  		}
   778  
   779  		l = args[i]
   780  		i++
   781  		l = Expr(l)
   782  		var r ir.Node
   783  		if i < len(args) {
   784  			r = args[i]
   785  			i++
   786  			r = Expr(r)
   787  		}
   788  
   789  		if l.Type() == nil || (r != nil && r.Type() == nil) {
   790  			n.SetType(nil)
   791  			return n
   792  		}
   793  		if !checkmake(t, "len", &l) || r != nil && !checkmake(t, "cap", &r) {
   794  			n.SetType(nil)
   795  			return n
   796  		}
   797  		if ir.IsConst(l, constant.Int) && r != nil && ir.IsConst(r, constant.Int) && constant.Compare(l.Val(), token.GTR, r.Val()) {
   798  			base.Errorf("len larger than cap in make(%v)", t)
   799  			n.SetType(nil)
   800  			return n
   801  		}
   802  		nn = ir.NewMakeExpr(n.Pos(), ir.OMAKESLICE, l, r)
   803  
   804  	case types.TMAP:
   805  		if i < len(args) {
   806  			l = args[i]
   807  			i++
   808  			l = Expr(l)
   809  			l = DefaultLit(l, types.Types[types.TINT])
   810  			if l.Type() == nil {
   811  				n.SetType(nil)
   812  				return n
   813  			}
   814  			if !checkmake(t, "size", &l) {
   815  				n.SetType(nil)
   816  				return n
   817  			}
   818  		} else {
   819  			l = ir.NewInt(0)
   820  		}
   821  		nn = ir.NewMakeExpr(n.Pos(), ir.OMAKEMAP, l, nil)
   822  		nn.SetEsc(n.Esc())
   823  
   824  	case types.TCHAN:
   825  		l = nil
   826  		if i < len(args) {
   827  			l = args[i]
   828  			i++
   829  			l = Expr(l)
   830  			l = DefaultLit(l, types.Types[types.TINT])
   831  			if l.Type() == nil {
   832  				n.SetType(nil)
   833  				return n
   834  			}
   835  			if !checkmake(t, "buffer", &l) {
   836  				n.SetType(nil)
   837  				return n
   838  			}
   839  		} else {
   840  			l = ir.NewInt(0)
   841  		}
   842  		nn = ir.NewMakeExpr(n.Pos(), ir.OMAKECHAN, l, nil)
   843  	}
   844  
   845  	if i < len(args) {
   846  		base.Errorf("too many arguments to make(%v)", t)
   847  		n.SetType(nil)
   848  		return n
   849  	}
   850  
   851  	nn.SetType(t)
   852  	return nn
   853  }
   854  
   855  // tcMakeSliceCopy typechecks an OMAKESLICECOPY node.
   856  func tcMakeSliceCopy(n *ir.MakeExpr) ir.Node {
   857  	// Errors here are Fatalf instead of Errorf because only the compiler
   858  	// can construct an OMAKESLICECOPY node.
   859  	// Components used in OMAKESCLICECOPY that are supplied by parsed source code
   860  	// have already been typechecked in OMAKE and OCOPY earlier.
   861  	t := n.Type()
   862  
   863  	if t == nil {
   864  		base.Fatalf("no type specified for OMAKESLICECOPY")
   865  	}
   866  
   867  	if !t.IsSlice() {
   868  		base.Fatalf("invalid type %v for OMAKESLICECOPY", n.Type())
   869  	}
   870  
   871  	if n.Len == nil {
   872  		base.Fatalf("missing len argument for OMAKESLICECOPY")
   873  	}
   874  
   875  	if n.Cap == nil {
   876  		base.Fatalf("missing slice argument to copy for OMAKESLICECOPY")
   877  	}
   878  
   879  	n.Len = Expr(n.Len)
   880  	n.Cap = Expr(n.Cap)
   881  
   882  	n.Len = DefaultLit(n.Len, types.Types[types.TINT])
   883  
   884  	if !n.Len.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
   885  		base.Errorf("non-integer len argument in OMAKESLICECOPY")
   886  	}
   887  
   888  	if ir.IsConst(n.Len, constant.Int) {
   889  		if ir.ConstOverflow(n.Len.Val(), types.Types[types.TINT]) {
   890  			base.Fatalf("len for OMAKESLICECOPY too large")
   891  		}
   892  		if constant.Sign(n.Len.Val()) < 0 {
   893  			base.Fatalf("len for OMAKESLICECOPY must be non-negative")
   894  		}
   895  	}
   896  	return n
   897  }
   898  
   899  // tcNew typechecks an ONEW node.
   900  func tcNew(n *ir.UnaryExpr) ir.Node {
   901  	if n.X == nil {
   902  		// Fatalf because the OCALL above checked for us,
   903  		// so this must be an internally-generated mistake.
   904  		base.Fatalf("missing argument to new")
   905  	}
   906  	l := n.X
   907  	l = typecheck(l, ctxType)
   908  	t := l.Type()
   909  	if t == nil {
   910  		n.SetType(nil)
   911  		return n
   912  	}
   913  	n.X = l
   914  	n.SetType(types.NewPtr(t))
   915  	return n
   916  }
   917  
   918  // tcPanic typechecks an OPANIC node.
   919  func tcPanic(n *ir.UnaryExpr) ir.Node {
   920  	n.X = Expr(n.X)
   921  	n.X = AssignConv(n.X, types.Types[types.TINTER], "argument to panic")
   922  	if n.X.Type() == nil {
   923  		n.SetType(nil)
   924  		return n
   925  	}
   926  	return n
   927  }
   928  
   929  // tcPrint typechecks an OPRINT or OPRINTN node.
   930  func tcPrint(n *ir.CallExpr) ir.Node {
   931  	typecheckargs(n)
   932  	ls := n.Args
   933  	for i1, n1 := range ls {
   934  		// Special case for print: int constant is int64, not int.
   935  		if ir.IsConst(n1, constant.Int) {
   936  			ls[i1] = DefaultLit(ls[i1], types.Types[types.TINT64])
   937  		} else {
   938  			ls[i1] = DefaultLit(ls[i1], nil)
   939  		}
   940  	}
   941  	return n
   942  }
   943  
   944  // tcRealImag typechecks an OREAL or OIMAG node.
   945  func tcRealImag(n *ir.UnaryExpr) ir.Node {
   946  	n.X = Expr(n.X)
   947  	l := n.X
   948  	t := l.Type()
   949  	if t == nil {
   950  		n.SetType(nil)
   951  		return n
   952  	}
   953  
   954  	// Determine result type.
   955  	switch t.Kind() {
   956  	case types.TIDEAL:
   957  		n.SetType(types.UntypedFloat)
   958  	case types.TCOMPLEX64:
   959  		n.SetType(types.Types[types.TFLOAT32])
   960  	case types.TCOMPLEX128:
   961  		n.SetType(types.Types[types.TFLOAT64])
   962  	default:
   963  		base.Errorf("invalid argument %L for %v", l, n.Op())
   964  		n.SetType(nil)
   965  		return n
   966  	}
   967  	return n
   968  }
   969  
   970  // tcRecover typechecks an ORECOVER node.
   971  func tcRecover(n *ir.CallExpr) ir.Node {
   972  	if len(n.Args) != 0 {
   973  		base.Errorf("too many arguments to recover")
   974  		n.SetType(nil)
   975  		return n
   976  	}
   977  
   978  	n.SetType(types.Types[types.TINTER])
   979  	return n
   980  }
   981  
   982  // tcUnsafeAdd typechecks an OUNSAFEADD node.
   983  func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
   984  	if !types.AllowsGoVersion(curpkg(), 1, 17) {
   985  		base.ErrorfVers("go1.17", "unsafe.Add")
   986  		n.SetType(nil)
   987  		return n
   988  	}
   989  
   990  	n.X = AssignConv(Expr(n.X), types.Types[types.TUNSAFEPTR], "argument to unsafe.Add")
   991  	n.Y = DefaultLit(Expr(n.Y), types.Types[types.TINT])
   992  	if n.X.Type() == nil || n.Y.Type() == nil {
   993  		n.SetType(nil)
   994  		return n
   995  	}
   996  	if !n.Y.Type().IsInteger() {
   997  		n.SetType(nil)
   998  		return n
   999  	}
  1000  	n.SetType(n.X.Type())
  1001  	return n
  1002  }
  1003  
  1004  // tcUnsafeSlice typechecks an OUNSAFESLICE node.
  1005  func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
  1006  	if !types.AllowsGoVersion(curpkg(), 1, 17) {
  1007  		base.ErrorfVers("go1.17", "unsafe.Slice")
  1008  		n.SetType(nil)
  1009  		return n
  1010  	}
  1011  
  1012  	n.X = Expr(n.X)
  1013  	n.Y = Expr(n.Y)
  1014  	if n.X.Type() == nil || n.Y.Type() == nil {
  1015  		n.SetType(nil)
  1016  		return n
  1017  	}
  1018  	t := n.X.Type()
  1019  	if !t.IsPtr() {
  1020  		base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t)
  1021  	} else if t.Elem().NotInHeap() {
  1022  		// TODO(mdempsky): This can be relaxed, but should only affect the
  1023  		// Go runtime itself. End users should only see //go:notinheap
  1024  		// types due to incomplete C structs in cgo, and those types don't
  1025  		// have a meaningful size anyway.
  1026  		base.Errorf("unsafe.Slice of incomplete (or unallocatable) type not allowed")
  1027  	}
  1028  
  1029  	if !checkunsafeslice(&n.Y) {
  1030  		n.SetType(nil)
  1031  		return n
  1032  	}
  1033  	n.SetType(types.NewSlice(t.Elem()))
  1034  	return n
  1035  }
  1036  

View as plain text