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  )
    16  
    17  // MakeDotArgs package all the arguments that match a ... T parameter into a []T.
    18  func MakeDotArgs(pos src.XPos, typ *types.Type, args []ir.Node) ir.Node {
    19  	if len(args) == 0 {
    20  		return ir.NewNilExpr(pos, typ)
    21  	}
    22  
    23  	args = append([]ir.Node(nil), args...)
    24  	lit := ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, args)
    25  	lit.SetImplicit(true)
    26  
    27  	n := Expr(lit)
    28  	if n.Type() == nil {
    29  		base.FatalfAt(pos, "mkdotargslice: typecheck failed")
    30  	}
    31  	return n
    32  }
    33  
    34  // FixVariadicCall rewrites calls to variadic functions to use an
    35  // explicit ... argument if one is not already present.
    36  func FixVariadicCall(call *ir.CallExpr) {
    37  	fntype := call.Fun.Type()
    38  	if !fntype.IsVariadic() || call.IsDDD {
    39  		return
    40  	}
    41  
    42  	vi := fntype.NumParams() - 1
    43  	vt := fntype.Param(vi).Type
    44  
    45  	args := call.Args
    46  	extra := args[vi:]
    47  	slice := MakeDotArgs(call.Pos(), vt, extra)
    48  	for i := range extra {
    49  		extra[i] = nil // allow GC
    50  	}
    51  
    52  	call.Args = append(args[:vi], slice)
    53  	call.IsDDD = true
    54  }
    55  
    56  // FixMethodCall rewrites a method call t.M(...) into a function call T.M(t, ...).
    57  func FixMethodCall(call *ir.CallExpr) {
    58  	if call.Fun.Op() != ir.ODOTMETH {
    59  		return
    60  	}
    61  
    62  	dot := call.Fun.(*ir.SelectorExpr)
    63  
    64  	fn := NewMethodExpr(dot.Pos(), dot.X.Type(), dot.Selection.Sym)
    65  
    66  	args := make([]ir.Node, 1+len(call.Args))
    67  	args[0] = dot.X
    68  	copy(args[1:], call.Args)
    69  
    70  	call.SetOp(ir.OCALLFUNC)
    71  	call.Fun = fn
    72  	call.Args = args
    73  }
    74  
    75  func AssertFixedCall(call *ir.CallExpr) {
    76  	if call.Fun.Type().IsVariadic() && !call.IsDDD {
    77  		base.FatalfAt(call.Pos(), "missed FixVariadicCall")
    78  	}
    79  	if call.Op() == ir.OCALLMETH {
    80  		base.FatalfAt(call.Pos(), "missed FixMethodCall")
    81  	}
    82  }
    83  
    84  // ClosureType returns the struct type used to hold all the information
    85  // needed in the closure for clo (clo must be a OCLOSURE node).
    86  // The address of a variable of the returned type can be cast to a func.
    87  func ClosureType(clo *ir.ClosureExpr) *types.Type {
    88  	// Create closure in the form of a composite literal.
    89  	// supposing the closure captures an int i and a string s
    90  	// and has one float64 argument and no results,
    91  	// the generated code looks like:
    92  	//
    93  	//	clos = &struct{F uintptr; X0 *int; X1 *string}{func.1, &i, &s}
    94  	//
    95  	// The use of the struct provides type information to the garbage
    96  	// collector so that it can walk the closure. We could use (in this
    97  	// case) [3]unsafe.Pointer instead, but that would leave the gc in
    98  	// the dark. The information appears in the binary in the form of
    99  	// type descriptors; the struct is unnamed and uses exported field
   100  	// names so that closures in multiple packages with the same struct
   101  	// type can share the descriptor.
   102  
   103  	fields := make([]*types.Field, 1+len(clo.Func.ClosureVars))
   104  	fields[0] = types.NewField(base.AutogeneratedPos, types.LocalPkg.Lookup("F"), types.Types[types.TUINTPTR])
   105  	it := NewClosureStructIter(clo.Func.ClosureVars)
   106  	i := 0
   107  	for {
   108  		n, typ, _ := it.Next()
   109  		if n == nil {
   110  			break
   111  		}
   112  		fields[1+i] = types.NewField(base.AutogeneratedPos, types.LocalPkg.LookupNum("X", i), typ)
   113  		i++
   114  	}
   115  	typ := types.NewStruct(fields)
   116  	typ.SetNoalg(true)
   117  	return typ
   118  }
   119  
   120  // MethodValueType returns the struct type used to hold all the information
   121  // needed in the closure for a OMETHVALUE node. The address of a variable of
   122  // the returned type can be cast to a func.
   123  func MethodValueType(n *ir.SelectorExpr) *types.Type {
   124  	t := types.NewStruct([]*types.Field{
   125  		types.NewField(base.Pos, Lookup("F"), types.Types[types.TUINTPTR]),
   126  		types.NewField(base.Pos, Lookup("R"), n.X.Type()),
   127  	})
   128  	t.SetNoalg(true)
   129  	return t
   130  }
   131  
   132  // type check function definition
   133  // To be called by typecheck, not directly.
   134  // (Call typecheck.Func instead.)
   135  func tcFunc(n *ir.Func) {
   136  	if base.EnableTrace && base.Flag.LowerT {
   137  		defer tracePrint("tcFunc", n)(nil)
   138  	}
   139  
   140  	if name := n.Nname; name.Typecheck() == 0 {
   141  		base.AssertfAt(name.Type() != nil, n.Pos(), "missing type: %v", name)
   142  		name.SetTypecheck(1)
   143  	}
   144  }
   145  
   146  // tcCall typechecks an OCALL node.
   147  func tcCall(n *ir.CallExpr, top int) ir.Node {
   148  	Stmts(n.Init()) // imported rewritten f(g()) calls (#30907)
   149  	n.Fun = typecheck(n.Fun, ctxExpr|ctxType|ctxCallee)
   150  
   151  	l := n.Fun
   152  
   153  	if l.Op() == ir.ONAME && l.(*ir.Name).BuiltinOp != 0 {
   154  		l := l.(*ir.Name)
   155  		if n.IsDDD && l.BuiltinOp != ir.OAPPEND {
   156  			base.Errorf("invalid use of ... with builtin %v", l)
   157  		}
   158  
   159  		// builtin: OLEN, OCAP, etc.
   160  		switch l.BuiltinOp {
   161  		default:
   162  			base.Fatalf("unknown builtin %v", l)
   163  
   164  		case ir.OAPPEND, ir.ODELETE, ir.OMAKE, ir.OMAX, ir.OMIN, ir.OPRINT, ir.OPRINTLN, ir.ORECOVER:
   165  			n.SetOp(l.BuiltinOp)
   166  			n.Fun = nil
   167  			n.SetTypecheck(0) // re-typechecking new op is OK, not a loop
   168  			return typecheck(n, top)
   169  
   170  		case ir.OCAP, ir.OCLEAR, ir.OCLOSE, ir.OIMAG, ir.OLEN, ir.OPANIC, ir.OREAL, ir.OUNSAFESTRINGDATA, ir.OUNSAFESLICEDATA:
   171  			typecheckargs(n)
   172  			fallthrough
   173  		case ir.ONEW:
   174  			arg, ok := needOneArg(n, "%v", n.Op())
   175  			if !ok {
   176  				n.SetType(nil)
   177  				return n
   178  			}
   179  			u := ir.NewUnaryExpr(n.Pos(), l.BuiltinOp, arg)
   180  			return typecheck(ir.InitExpr(n.Init(), u), top) // typecheckargs can add to old.Init
   181  
   182  		case ir.OCOMPLEX, ir.OCOPY, ir.OUNSAFEADD, ir.OUNSAFESLICE, ir.OUNSAFESTRING:
   183  			typecheckargs(n)
   184  			arg1, arg2, ok := needTwoArgs(n)
   185  			if !ok {
   186  				n.SetType(nil)
   187  				return n
   188  			}
   189  			b := ir.NewBinaryExpr(n.Pos(), l.BuiltinOp, arg1, arg2)
   190  			return typecheck(ir.InitExpr(n.Init(), b), top) // typecheckargs can add to old.Init
   191  		}
   192  		panic("unreachable")
   193  	}
   194  
   195  	n.Fun = DefaultLit(n.Fun, nil)
   196  	l = n.Fun
   197  	if l.Op() == ir.OTYPE {
   198  		if n.IsDDD {
   199  			base.Fatalf("invalid use of ... in type conversion to %v", l.Type())
   200  		}
   201  
   202  		// pick off before type-checking arguments
   203  		arg, ok := needOneArg(n, "conversion to %v", l.Type())
   204  		if !ok {
   205  			n.SetType(nil)
   206  			return n
   207  		}
   208  
   209  		n := ir.NewConvExpr(n.Pos(), ir.OCONV, nil, arg)
   210  		n.SetType(l.Type())
   211  		return tcConv(n)
   212  	}
   213  
   214  	RewriteNonNameCall(n)
   215  	typecheckargs(n)
   216  	t := l.Type()
   217  	if t == nil {
   218  		n.SetType(nil)
   219  		return n
   220  	}
   221  	types.CheckSize(t)
   222  
   223  	switch l.Op() {
   224  	case ir.ODOTINTER:
   225  		n.SetOp(ir.OCALLINTER)
   226  
   227  	case ir.ODOTMETH:
   228  		l := l.(*ir.SelectorExpr)
   229  		n.SetOp(ir.OCALLMETH)
   230  
   231  		// typecheckaste was used here but there wasn't enough
   232  		// information further down the call chain to know if we
   233  		// were testing a method receiver for unexported fields.
   234  		// It isn't necessary, so just do a sanity check.
   235  		tp := t.Recv().Type
   236  
   237  		if l.X == nil || !types.Identical(l.X.Type(), tp) {
   238  			base.Fatalf("method receiver")
   239  		}
   240  
   241  	default:
   242  		n.SetOp(ir.OCALLFUNC)
   243  		if t.Kind() != types.TFUNC {
   244  			if o := l; o.Name() != nil && types.BuiltinPkg.Lookup(o.Sym().Name).Def != nil {
   245  				// be more specific when the non-function
   246  				// name matches a predeclared function
   247  				base.Errorf("cannot call non-function %L, declared at %s",
   248  					l, base.FmtPos(o.Name().Pos()))
   249  			} else {
   250  				base.Errorf("cannot call non-function %L", l)
   251  			}
   252  			n.SetType(nil)
   253  			return n
   254  		}
   255  	}
   256  
   257  	typecheckaste(ir.OCALL, n.Fun, n.IsDDD, t.Params(), n.Args, func() string { return fmt.Sprintf("argument to %v", n.Fun) })
   258  	FixVariadicCall(n)
   259  	FixMethodCall(n)
   260  	if t.NumResults() == 0 {
   261  		return n
   262  	}
   263  	if t.NumResults() == 1 {
   264  		n.SetType(l.Type().Result(0).Type)
   265  
   266  		if n.Op() == ir.OCALLFUNC && n.Fun.Op() == ir.ONAME {
   267  			if sym := n.Fun.(*ir.Name).Sym(); types.RuntimeSymName(sym) == "getg" {
   268  				// Emit code for runtime.getg() directly instead of calling function.
   269  				// Most such rewrites (for example the similar one for math.Sqrt) should be done in walk,
   270  				// so that the ordering pass can make sure to preserve the semantics of the original code
   271  				// (in particular, the exact time of the function call) by introducing temporaries.
   272  				// In this case, we know getg() always returns the same result within a given function
   273  				// and we want to avoid the temporaries, so we do the rewrite earlier than is typical.
   274  				n.SetOp(ir.OGETG)
   275  			}
   276  		}
   277  		return n
   278  	}
   279  
   280  	// multiple return
   281  	if top&(ctxMultiOK|ctxStmt) == 0 {
   282  		base.Errorf("multiple-value %v() in single-value context", l)
   283  		return n
   284  	}
   285  
   286  	n.SetType(l.Type().ResultsTuple())
   287  	return n
   288  }
   289  
   290  // tcAppend typechecks an OAPPEND node.
   291  func tcAppend(n *ir.CallExpr) ir.Node {
   292  	typecheckargs(n)
   293  	args := n.Args
   294  	if len(args) == 0 {
   295  		base.Errorf("missing arguments to append")
   296  		n.SetType(nil)
   297  		return n
   298  	}
   299  
   300  	t := args[0].Type()
   301  	if t == nil {
   302  		n.SetType(nil)
   303  		return n
   304  	}
   305  
   306  	n.SetType(t)
   307  	if !t.IsSlice() {
   308  		if ir.IsNil(args[0]) {
   309  			base.Errorf("first argument to append must be typed slice; have untyped nil")
   310  			n.SetType(nil)
   311  			return n
   312  		}
   313  
   314  		base.Errorf("first argument to append must be slice; have %L", t)
   315  		n.SetType(nil)
   316  		return n
   317  	}
   318  
   319  	if n.IsDDD {
   320  		if len(args) == 1 {
   321  			base.Errorf("cannot use ... on first argument to append")
   322  			n.SetType(nil)
   323  			return n
   324  		}
   325  
   326  		if len(args) != 2 {
   327  			base.Errorf("too many arguments to append")
   328  			n.SetType(nil)
   329  			return n
   330  		}
   331  
   332  		// AssignConv is of args[1] not required here, as the
   333  		// types of args[0] and args[1] don't need to match
   334  		// (They will both have an underlying type which are
   335  		// slices of identical base types, or be []byte and string.)
   336  		// See issue 53888.
   337  		return n
   338  	}
   339  
   340  	as := args[1:]
   341  	for i, n := range as {
   342  		if n.Type() == nil {
   343  			continue
   344  		}
   345  		as[i] = AssignConv(n, t.Elem(), "append")
   346  		types.CheckSize(as[i].Type()) // ensure width is calculated for backend
   347  	}
   348  	return n
   349  }
   350  
   351  // tcClear typechecks an OCLEAR node.
   352  func tcClear(n *ir.UnaryExpr) ir.Node {
   353  	n.X = Expr(n.X)
   354  	n.X = DefaultLit(n.X, nil)
   355  	l := n.X
   356  	t := l.Type()
   357  	if t == nil {
   358  		n.SetType(nil)
   359  		return n
   360  	}
   361  
   362  	switch {
   363  	case t.IsMap(), t.IsSlice():
   364  	default:
   365  		base.Errorf("invalid operation: %v (argument must be a map or slice)", n)
   366  		n.SetType(nil)
   367  		return n
   368  	}
   369  
   370  	return n
   371  }
   372  
   373  // tcClose typechecks an OCLOSE node.
   374  func tcClose(n *ir.UnaryExpr) ir.Node {
   375  	n.X = Expr(n.X)
   376  	n.X = DefaultLit(n.X, nil)
   377  	l := n.X
   378  	t := l.Type()
   379  	if t == nil {
   380  		n.SetType(nil)
   381  		return n
   382  	}
   383  	if !t.IsChan() {
   384  		base.Errorf("invalid operation: %v (non-chan type %v)", n, t)
   385  		n.SetType(nil)
   386  		return n
   387  	}
   388  
   389  	if !t.ChanDir().CanSend() {
   390  		base.Errorf("invalid operation: %v (cannot close receive-only channel)", n)
   391  		n.SetType(nil)
   392  		return n
   393  	}
   394  	return n
   395  }
   396  
   397  // tcComplex typechecks an OCOMPLEX node.
   398  func tcComplex(n *ir.BinaryExpr) ir.Node {
   399  	l := Expr(n.X)
   400  	r := Expr(n.Y)
   401  	if l.Type() == nil || r.Type() == nil {
   402  		n.SetType(nil)
   403  		return n
   404  	}
   405  	l, r = defaultlit2(l, r, false)
   406  	if l.Type() == nil || r.Type() == nil {
   407  		n.SetType(nil)
   408  		return n
   409  	}
   410  	n.X = l
   411  	n.Y = r
   412  
   413  	if !types.Identical(l.Type(), r.Type()) {
   414  		base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
   415  		n.SetType(nil)
   416  		return n
   417  	}
   418  
   419  	var t *types.Type
   420  	switch l.Type().Kind() {
   421  	default:
   422  		base.Errorf("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type())
   423  		n.SetType(nil)
   424  		return n
   425  
   426  	case types.TIDEAL:
   427  		t = types.UntypedComplex
   428  
   429  	case types.TFLOAT32:
   430  		t = types.Types[types.TCOMPLEX64]
   431  
   432  	case types.TFLOAT64:
   433  		t = types.Types[types.TCOMPLEX128]
   434  	}
   435  	n.SetType(t)
   436  	return n
   437  }
   438  
   439  // tcCopy typechecks an OCOPY node.
   440  func tcCopy(n *ir.BinaryExpr) ir.Node {
   441  	n.SetType(types.Types[types.TINT])
   442  	n.X = Expr(n.X)
   443  	n.X = DefaultLit(n.X, nil)
   444  	n.Y = Expr(n.Y)
   445  	n.Y = DefaultLit(n.Y, nil)
   446  	if n.X.Type() == nil || n.Y.Type() == nil {
   447  		n.SetType(nil)
   448  		return n
   449  	}
   450  
   451  	// copy([]byte, string)
   452  	if n.X.Type().IsSlice() && n.Y.Type().IsString() {
   453  		if types.Identical(n.X.Type().Elem(), types.ByteType) {
   454  			return n
   455  		}
   456  		base.Errorf("arguments to copy have different element types: %L and string", n.X.Type())
   457  		n.SetType(nil)
   458  		return n
   459  	}
   460  
   461  	if !n.X.Type().IsSlice() || !n.Y.Type().IsSlice() {
   462  		if !n.X.Type().IsSlice() && !n.Y.Type().IsSlice() {
   463  			base.Errorf("arguments to copy must be slices; have %L, %L", n.X.Type(), n.Y.Type())
   464  		} else if !n.X.Type().IsSlice() {
   465  			base.Errorf("first argument to copy should be slice; have %L", n.X.Type())
   466  		} else {
   467  			base.Errorf("second argument to copy should be slice or string; have %L", n.Y.Type())
   468  		}
   469  		n.SetType(nil)
   470  		return n
   471  	}
   472  
   473  	if !types.Identical(n.X.Type().Elem(), n.Y.Type().Elem()) {
   474  		base.Errorf("arguments to copy have different element types: %L and %L", n.X.Type(), n.Y.Type())
   475  		n.SetType(nil)
   476  		return n
   477  	}
   478  	return n
   479  }
   480  
   481  // tcDelete typechecks an ODELETE node.
   482  func tcDelete(n *ir.CallExpr) ir.Node {
   483  	typecheckargs(n)
   484  	args := n.Args
   485  	if len(args) == 0 {
   486  		base.Errorf("missing arguments to delete")
   487  		n.SetType(nil)
   488  		return n
   489  	}
   490  
   491  	if len(args) == 1 {
   492  		base.Errorf("missing second (key) argument to delete")
   493  		n.SetType(nil)
   494  		return n
   495  	}
   496  
   497  	if len(args) != 2 {
   498  		base.Errorf("too many arguments to delete")
   499  		n.SetType(nil)
   500  		return n
   501  	}
   502  
   503  	l := args[0]
   504  	r := args[1]
   505  	if l.Type() != nil && !l.Type().IsMap() {
   506  		base.Errorf("first argument to delete must be map; have %L", l.Type())
   507  		n.SetType(nil)
   508  		return n
   509  	}
   510  
   511  	args[1] = AssignConv(r, l.Type().Key(), "delete")
   512  	return n
   513  }
   514  
   515  // tcMake typechecks an OMAKE node.
   516  func tcMake(n *ir.CallExpr) ir.Node {
   517  	args := n.Args
   518  	if len(args) == 0 {
   519  		base.Errorf("missing argument to make")
   520  		n.SetType(nil)
   521  		return n
   522  	}
   523  
   524  	n.Args = nil
   525  	l := args[0]
   526  	l = typecheck(l, ctxType)
   527  	t := l.Type()
   528  	if t == nil {
   529  		n.SetType(nil)
   530  		return n
   531  	}
   532  
   533  	i := 1
   534  	var nn ir.Node
   535  	switch t.Kind() {
   536  	default:
   537  		base.Errorf("cannot make type %v", t)
   538  		n.SetType(nil)
   539  		return n
   540  
   541  	case types.TSLICE:
   542  		if i >= len(args) {
   543  			base.Errorf("missing len argument to make(%v)", t)
   544  			n.SetType(nil)
   545  			return n
   546  		}
   547  
   548  		l = args[i]
   549  		i++
   550  		l = Expr(l)
   551  		var r ir.Node
   552  		if i < len(args) {
   553  			r = args[i]
   554  			i++
   555  			r = Expr(r)
   556  		}
   557  
   558  		if l.Type() == nil || (r != nil && r.Type() == nil) {
   559  			n.SetType(nil)
   560  			return n
   561  		}
   562  		if !checkmake(t, "len", &l) || r != nil && !checkmake(t, "cap", &r) {
   563  			n.SetType(nil)
   564  			return n
   565  		}
   566  		nn = ir.NewMakeExpr(n.Pos(), ir.OMAKESLICE, l, r)
   567  
   568  	case types.TMAP:
   569  		if i < len(args) {
   570  			l = args[i]
   571  			i++
   572  			l = Expr(l)
   573  			l = DefaultLit(l, types.Types[types.TINT])
   574  			if l.Type() == nil {
   575  				n.SetType(nil)
   576  				return n
   577  			}
   578  			if !checkmake(t, "size", &l) {
   579  				n.SetType(nil)
   580  				return n
   581  			}
   582  		} else {
   583  			l = ir.NewInt(base.Pos, 0)
   584  		}
   585  		nn = ir.NewMakeExpr(n.Pos(), ir.OMAKEMAP, l, nil)
   586  		nn.SetEsc(n.Esc())
   587  
   588  	case types.TCHAN:
   589  		l = nil
   590  		if i < len(args) {
   591  			l = args[i]
   592  			i++
   593  			l = Expr(l)
   594  			l = DefaultLit(l, types.Types[types.TINT])
   595  			if l.Type() == nil {
   596  				n.SetType(nil)
   597  				return n
   598  			}
   599  			if !checkmake(t, "buffer", &l) {
   600  				n.SetType(nil)
   601  				return n
   602  			}
   603  		} else {
   604  			l = ir.NewInt(base.Pos, 0)
   605  		}
   606  		nn = ir.NewMakeExpr(n.Pos(), ir.OMAKECHAN, l, nil)
   607  	}
   608  
   609  	if i < len(args) {
   610  		base.Errorf("too many arguments to make(%v)", t)
   611  		n.SetType(nil)
   612  		return n
   613  	}
   614  
   615  	nn.SetType(t)
   616  	return nn
   617  }
   618  
   619  // tcMakeSliceCopy typechecks an OMAKESLICECOPY node.
   620  func tcMakeSliceCopy(n *ir.MakeExpr) ir.Node {
   621  	// Errors here are Fatalf instead of Errorf because only the compiler
   622  	// can construct an OMAKESLICECOPY node.
   623  	// Components used in OMAKESCLICECOPY that are supplied by parsed source code
   624  	// have already been typechecked in OMAKE and OCOPY earlier.
   625  	t := n.Type()
   626  
   627  	if t == nil {
   628  		base.Fatalf("no type specified for OMAKESLICECOPY")
   629  	}
   630  
   631  	if !t.IsSlice() {
   632  		base.Fatalf("invalid type %v for OMAKESLICECOPY", n.Type())
   633  	}
   634  
   635  	if n.Len == nil {
   636  		base.Fatalf("missing len argument for OMAKESLICECOPY")
   637  	}
   638  
   639  	if n.Cap == nil {
   640  		base.Fatalf("missing slice argument to copy for OMAKESLICECOPY")
   641  	}
   642  
   643  	n.Len = Expr(n.Len)
   644  	n.Cap = Expr(n.Cap)
   645  
   646  	n.Len = DefaultLit(n.Len, types.Types[types.TINT])
   647  
   648  	if !n.Len.Type().IsInteger() && n.Type().Kind() != types.TIDEAL {
   649  		base.Errorf("non-integer len argument in OMAKESLICECOPY")
   650  	}
   651  
   652  	return n
   653  }
   654  
   655  // tcNew typechecks an ONEW node.
   656  func tcNew(n *ir.UnaryExpr) ir.Node {
   657  	if n.X == nil {
   658  		// Fatalf because the OCALL above checked for us,
   659  		// so this must be an internally-generated mistake.
   660  		base.Fatalf("missing argument to new")
   661  	}
   662  	l := n.X
   663  	l = typecheck(l, ctxType)
   664  	t := l.Type()
   665  	if t == nil {
   666  		n.SetType(nil)
   667  		return n
   668  	}
   669  	n.X = l
   670  	n.SetType(types.NewPtr(t))
   671  	return n
   672  }
   673  
   674  // tcPanic typechecks an OPANIC node.
   675  func tcPanic(n *ir.UnaryExpr) ir.Node {
   676  	n.X = Expr(n.X)
   677  	n.X = AssignConv(n.X, types.Types[types.TINTER], "argument to panic")
   678  	if n.X.Type() == nil {
   679  		n.SetType(nil)
   680  		return n
   681  	}
   682  	return n
   683  }
   684  
   685  // tcPrint typechecks an OPRINT or OPRINTN node.
   686  func tcPrint(n *ir.CallExpr) ir.Node {
   687  	typecheckargs(n)
   688  	ls := n.Args
   689  	for i1, n1 := range ls {
   690  		// Special case for print: int constant is int64, not int.
   691  		if ir.IsConst(n1, constant.Int) {
   692  			ls[i1] = DefaultLit(ls[i1], types.Types[types.TINT64])
   693  		} else {
   694  			ls[i1] = DefaultLit(ls[i1], nil)
   695  		}
   696  	}
   697  	return n
   698  }
   699  
   700  // tcMinMax typechecks an OMIN or OMAX node.
   701  func tcMinMax(n *ir.CallExpr) ir.Node {
   702  	typecheckargs(n)
   703  	arg0 := n.Args[0]
   704  	for _, arg := range n.Args[1:] {
   705  		if !types.Identical(arg.Type(), arg0.Type()) {
   706  			base.FatalfAt(n.Pos(), "mismatched arguments: %L and %L", arg0, arg)
   707  		}
   708  	}
   709  	n.SetType(arg0.Type())
   710  	return n
   711  }
   712  
   713  // tcRealImag typechecks an OREAL or OIMAG node.
   714  func tcRealImag(n *ir.UnaryExpr) ir.Node {
   715  	n.X = Expr(n.X)
   716  	l := n.X
   717  	t := l.Type()
   718  	if t == nil {
   719  		n.SetType(nil)
   720  		return n
   721  	}
   722  
   723  	// Determine result type.
   724  	switch t.Kind() {
   725  	case types.TIDEAL:
   726  		n.SetType(types.UntypedFloat)
   727  	case types.TCOMPLEX64:
   728  		n.SetType(types.Types[types.TFLOAT32])
   729  	case types.TCOMPLEX128:
   730  		n.SetType(types.Types[types.TFLOAT64])
   731  	default:
   732  		base.Errorf("invalid argument %L for %v", l, n.Op())
   733  		n.SetType(nil)
   734  		return n
   735  	}
   736  	return n
   737  }
   738  
   739  // tcRecover typechecks an ORECOVER node.
   740  func tcRecover(n *ir.CallExpr) ir.Node {
   741  	if len(n.Args) != 0 {
   742  		base.Errorf("too many arguments to recover")
   743  		n.SetType(nil)
   744  		return n
   745  	}
   746  
   747  	n.SetType(types.Types[types.TINTER])
   748  	return n
   749  }
   750  
   751  // tcUnsafeAdd typechecks an OUNSAFEADD node.
   752  func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
   753  	n.X = AssignConv(Expr(n.X), types.Types[types.TUNSAFEPTR], "argument to unsafe.Add")
   754  	n.Y = DefaultLit(Expr(n.Y), types.Types[types.TINT])
   755  	if n.X.Type() == nil || n.Y.Type() == nil {
   756  		n.SetType(nil)
   757  		return n
   758  	}
   759  	if !n.Y.Type().IsInteger() {
   760  		n.SetType(nil)
   761  		return n
   762  	}
   763  	n.SetType(n.X.Type())
   764  	return n
   765  }
   766  
   767  // tcUnsafeSlice typechecks an OUNSAFESLICE node.
   768  func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
   769  	n.X = Expr(n.X)
   770  	n.Y = Expr(n.Y)
   771  	if n.X.Type() == nil || n.Y.Type() == nil {
   772  		n.SetType(nil)
   773  		return n
   774  	}
   775  	t := n.X.Type()
   776  	if !t.IsPtr() {
   777  		base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t)
   778  	} else if t.Elem().NotInHeap() {
   779  		// TODO(mdempsky): This can be relaxed, but should only affect the
   780  		// Go runtime itself. End users should only see not-in-heap
   781  		// types due to incomplete C structs in cgo, and those types don't
   782  		// have a meaningful size anyway.
   783  		base.Errorf("unsafe.Slice of incomplete (or unallocatable) type not allowed")
   784  	}
   785  
   786  	if !checkunsafesliceorstring(n.Op(), &n.Y) {
   787  		n.SetType(nil)
   788  		return n
   789  	}
   790  	n.SetType(types.NewSlice(t.Elem()))
   791  	return n
   792  }
   793  
   794  // tcUnsafeString typechecks an OUNSAFESTRING node.
   795  func tcUnsafeString(n *ir.BinaryExpr) *ir.BinaryExpr {
   796  	n.X = Expr(n.X)
   797  	n.Y = Expr(n.Y)
   798  	if n.X.Type() == nil || n.Y.Type() == nil {
   799  		n.SetType(nil)
   800  		return n
   801  	}
   802  	t := n.X.Type()
   803  	if !t.IsPtr() || !types.Identical(t.Elem(), types.Types[types.TUINT8]) {
   804  		base.Errorf("first argument to unsafe.String must be *byte; have %L", t)
   805  	}
   806  
   807  	if !checkunsafesliceorstring(n.Op(), &n.Y) {
   808  		n.SetType(nil)
   809  		return n
   810  	}
   811  	n.SetType(types.Types[types.TSTRING])
   812  	return n
   813  }
   814  
   815  // ClosureStructIter iterates through a slice of closure variables returning
   816  // their type and offset in the closure struct.
   817  type ClosureStructIter struct {
   818  	closureVars []*ir.Name
   819  	offset      int64
   820  	next        int
   821  }
   822  
   823  // NewClosureStructIter creates a new ClosureStructIter for closureVars.
   824  func NewClosureStructIter(closureVars []*ir.Name) *ClosureStructIter {
   825  	return &ClosureStructIter{
   826  		closureVars: closureVars,
   827  		offset:      int64(types.PtrSize), // PtrSize to skip past function entry PC field
   828  		next:        0,
   829  	}
   830  }
   831  
   832  // Next returns the next name, type and offset of the next closure variable.
   833  // A nil name is returned after the last closure variable.
   834  func (iter *ClosureStructIter) Next() (n *ir.Name, typ *types.Type, offset int64) {
   835  	if iter.next >= len(iter.closureVars) {
   836  		return nil, nil, 0
   837  	}
   838  	n = iter.closureVars[iter.next]
   839  	typ = n.Type()
   840  	if !n.Byval() {
   841  		typ = types.NewPtr(typ)
   842  	}
   843  	iter.next++
   844  	offset = types.RoundUp(iter.offset, typ.Alignment())
   845  	iter.offset = offset + typ.Size()
   846  	return n, typ, offset
   847  }
   848  

View as plain text