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

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

View as plain text