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