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
5package typecheck
6
7import (
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.
19func 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.
40func 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, ...).
61func 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.
82func 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.
131func 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.
143var 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.
148func 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.
208func 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.
230func 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.)
299func 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.
322func 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.
470func 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.
532func 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.
556func 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.
598func 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.
640func 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.
674func 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.
783func 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.
827func 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.
846func 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.
857func 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.
872func 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.
898func 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.
910func 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.
925func 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.
947func 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