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