]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/typecheck/dcl.go
[dev.typeparams] all: merge master (c8f4e61) into dev.typeparams
[gostls13.git] / src / cmd / compile / internal / typecheck / dcl.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         "fmt"
9         "sync"
10
11         "cmd/compile/internal/base"
12         "cmd/compile/internal/ir"
13         "cmd/compile/internal/types"
14         "cmd/internal/src"
15 )
16
17 var DeclContext ir.Class = ir.PEXTERN // PEXTERN/PAUTO
18
19 func DeclFunc(sym *types.Sym, tfn ir.Ntype) *ir.Func {
20         if tfn.Op() != ir.OTFUNC {
21                 base.Fatalf("expected OTFUNC node, got %v", tfn)
22         }
23
24         fn := ir.NewFunc(base.Pos)
25         fn.Nname = ir.NewNameAt(base.Pos, sym)
26         fn.Nname.Func = fn
27         fn.Nname.Defn = fn
28         fn.Nname.Ntype = tfn
29         ir.MarkFunc(fn.Nname)
30         StartFuncBody(fn)
31         fn.Nname.Ntype = typecheckNtype(fn.Nname.Ntype)
32         return fn
33 }
34
35 // Declare records that Node n declares symbol n.Sym in the specified
36 // declaration context.
37 func Declare(n *ir.Name, ctxt ir.Class) {
38         if ir.IsBlank(n) {
39                 return
40         }
41
42         s := n.Sym()
43
44         // kludgy: TypecheckAllowed means we're past parsing. Eg reflectdata.methodWrapper may declare out of package names later.
45         if !inimport && !TypecheckAllowed && s.Pkg != types.LocalPkg {
46                 base.ErrorfAt(n.Pos(), "cannot declare name %v", s)
47         }
48
49         if ctxt == ir.PEXTERN {
50                 if s.Name == "init" {
51                         base.ErrorfAt(n.Pos(), "cannot declare init - must be func")
52                 }
53                 if s.Name == "main" && s.Pkg.Name == "main" {
54                         base.ErrorfAt(n.Pos(), "cannot declare main - must be func")
55                 }
56                 Target.Externs = append(Target.Externs, n)
57         } else {
58                 if ir.CurFunc == nil && ctxt == ir.PAUTO {
59                         base.Pos = n.Pos()
60                         base.Fatalf("automatic outside function")
61                 }
62                 if ir.CurFunc != nil && ctxt != ir.PFUNC && n.Op() == ir.ONAME {
63                         ir.CurFunc.Dcl = append(ir.CurFunc.Dcl, n)
64                 }
65                 types.Pushdcl(s)
66                 n.Curfn = ir.CurFunc
67         }
68
69         if ctxt == ir.PAUTO {
70                 n.SetFrameOffset(0)
71         }
72
73         if s.Block == types.Block {
74                 // functype will print errors about duplicate function arguments.
75                 // Don't repeat the error here.
76                 if ctxt != ir.PPARAM && ctxt != ir.PPARAMOUT {
77                         Redeclared(n.Pos(), s, "in this block")
78                 }
79         }
80
81         s.Block = types.Block
82         s.Lastlineno = base.Pos
83         s.Def = n
84         n.Class = ctxt
85         if ctxt == ir.PFUNC {
86                 n.Sym().SetFunc(true)
87         }
88
89         autoexport(n, ctxt)
90 }
91
92 // Export marks n for export (or reexport).
93 func Export(n *ir.Name) {
94         if n.Sym().OnExportList() {
95                 return
96         }
97         n.Sym().SetOnExportList(true)
98
99         if base.Flag.E != 0 {
100                 fmt.Printf("export symbol %v\n", n.Sym())
101         }
102
103         Target.Exports = append(Target.Exports, n)
104 }
105
106 // Redeclared emits a diagnostic about symbol s being redeclared at pos.
107 func Redeclared(pos src.XPos, s *types.Sym, where string) {
108         if !s.Lastlineno.IsKnown() {
109                 var pkgName *ir.PkgName
110                 if s.Def == nil {
111                         for id, pkg := range DotImportRefs {
112                                 if id.Sym().Name == s.Name {
113                                         pkgName = pkg
114                                         break
115                                 }
116                         }
117                 } else {
118                         pkgName = DotImportRefs[s.Def.(*ir.Ident)]
119                 }
120                 base.ErrorfAt(pos, "%v redeclared %s\n"+
121                         "\t%v: previous declaration during import %q", s, where, base.FmtPos(pkgName.Pos()), pkgName.Pkg.Path)
122         } else {
123                 prevPos := s.Lastlineno
124
125                 // When an import and a declaration collide in separate files,
126                 // present the import as the "redeclared", because the declaration
127                 // is visible where the import is, but not vice versa.
128                 // See issue 4510.
129                 if s.Def == nil {
130                         pos, prevPos = prevPos, pos
131                 }
132
133                 base.ErrorfAt(pos, "%v redeclared %s\n"+
134                         "\t%v: previous declaration", s, where, base.FmtPos(prevPos))
135         }
136 }
137
138 // declare the function proper
139 // and declare the arguments.
140 // called in extern-declaration context
141 // returns in auto-declaration context.
142 func StartFuncBody(fn *ir.Func) {
143         // change the declaration context from extern to auto
144         funcStack = append(funcStack, funcStackEnt{ir.CurFunc, DeclContext})
145         ir.CurFunc = fn
146         DeclContext = ir.PAUTO
147
148         types.Markdcl()
149
150         if fn.Nname.Ntype != nil {
151                 funcargs(fn.Nname.Ntype.(*ir.FuncType))
152         } else {
153                 funcargs2(fn.Type())
154         }
155 }
156
157 // finish the body.
158 // called in auto-declaration context.
159 // returns in extern-declaration context.
160 func FinishFuncBody() {
161         // change the declaration context from auto to previous context
162         types.Popdcl()
163         var e funcStackEnt
164         funcStack, e = funcStack[:len(funcStack)-1], funcStack[len(funcStack)-1]
165         ir.CurFunc, DeclContext = e.curfn, e.dclcontext
166 }
167
168 func CheckFuncStack() {
169         if len(funcStack) != 0 {
170                 base.Fatalf("funcStack is non-empty: %v", len(funcStack))
171         }
172 }
173
174 // Add a method, declared as a function.
175 // - msym is the method symbol
176 // - t is function type (with receiver)
177 // Returns a pointer to the existing or added Field; or nil if there's an error.
178 func addmethod(n *ir.Func, msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field {
179         if msym == nil {
180                 base.Fatalf("no method symbol")
181         }
182
183         // get parent type sym
184         rf := t.Recv() // ptr to this structure
185         if rf == nil {
186                 base.Errorf("missing receiver")
187                 return nil
188         }
189
190         mt := types.ReceiverBaseType(rf.Type)
191         if mt == nil || mt.Sym() == nil {
192                 pa := rf.Type
193                 t := pa
194                 if t != nil && t.IsPtr() {
195                         if t.Sym() != nil {
196                                 base.Errorf("invalid receiver type %v (%v is a pointer type)", pa, t)
197                                 return nil
198                         }
199                         t = t.Elem()
200                 }
201
202                 switch {
203                 case t == nil || t.Broke():
204                         // rely on typecheck having complained before
205                 case t.Sym() == nil:
206                         base.Errorf("invalid receiver type %v (%v is not a defined type)", pa, t)
207                 case t.IsPtr():
208                         base.Errorf("invalid receiver type %v (%v is a pointer type)", pa, t)
209                 case t.IsInterface():
210                         base.Errorf("invalid receiver type %v (%v is an interface type)", pa, t)
211                 default:
212                         // Should have picked off all the reasons above,
213                         // but just in case, fall back to generic error.
214                         base.Errorf("invalid receiver type %v (%L / %L)", pa, pa, t)
215                 }
216                 return nil
217         }
218
219         if local && mt.Sym().Pkg != types.LocalPkg {
220                 base.Errorf("cannot define new methods on non-local type %v", mt)
221                 return nil
222         }
223
224         if msym.IsBlank() {
225                 return nil
226         }
227
228         if mt.IsStruct() {
229                 for _, f := range mt.Fields().Slice() {
230                         if f.Sym == msym {
231                                 base.Errorf("type %v has both field and method named %v", mt, msym)
232                                 f.SetBroke(true)
233                                 return nil
234                         }
235                 }
236         }
237
238         for _, f := range mt.Methods().Slice() {
239                 if msym.Name != f.Sym.Name {
240                         continue
241                 }
242                 // types.Identical only checks that incoming and result parameters match,
243                 // so explicitly check that the receiver parameters match too.
244                 if !types.Identical(t, f.Type) || !types.Identical(t.Recv().Type, f.Type.Recv().Type) {
245                         base.Errorf("method redeclared: %v.%v\n\t%v\n\t%v", mt, msym, f.Type, t)
246                 }
247                 return f
248         }
249
250         f := types.NewField(base.Pos, msym, t)
251         f.Nname = n.Nname
252         f.SetNointerface(nointerface)
253
254         mt.Methods().Append(f)
255         return f
256 }
257
258 func autoexport(n *ir.Name, ctxt ir.Class) {
259         if n.Sym().Pkg != types.LocalPkg {
260                 return
261         }
262         if (ctxt != ir.PEXTERN && ctxt != ir.PFUNC) || DeclContext != ir.PEXTERN {
263                 return
264         }
265         if n.Type() != nil && n.Type().IsKind(types.TFUNC) && ir.IsMethod(n) {
266                 return
267         }
268
269         if types.IsExported(n.Sym().Name) || n.Sym().Name == "init" {
270                 Export(n)
271         }
272         if base.Flag.AsmHdr != "" && !n.Sym().Asm() {
273                 n.Sym().SetAsm(true)
274                 Target.Asms = append(Target.Asms, n)
275         }
276 }
277
278 // checkdupfields emits errors for duplicately named fields or methods in
279 // a list of struct or interface types.
280 func checkdupfields(what string, fss ...[]*types.Field) {
281         seen := make(map[*types.Sym]bool)
282         for _, fs := range fss {
283                 for _, f := range fs {
284                         if f.Sym == nil || f.Sym.IsBlank() {
285                                 continue
286                         }
287                         if seen[f.Sym] {
288                                 base.ErrorfAt(f.Pos, "duplicate %s %s", what, f.Sym.Name)
289                                 continue
290                         }
291                         seen[f.Sym] = true
292                 }
293         }
294 }
295
296 // structs, functions, and methods.
297 // they don't belong here, but where do they belong?
298 func checkembeddedtype(t *types.Type) {
299         if t == nil {
300                 return
301         }
302
303         if t.Sym() == nil && t.IsPtr() {
304                 t = t.Elem()
305                 if t.IsInterface() {
306                         base.Errorf("embedded type cannot be a pointer to interface")
307                 }
308         }
309
310         if t.IsPtr() || t.IsUnsafePtr() {
311                 base.Errorf("embedded type cannot be a pointer")
312         } else if t.Kind() == types.TFORW && !t.ForwardType().Embedlineno.IsKnown() {
313                 t.ForwardType().Embedlineno = base.Pos
314         }
315 }
316
317 // TODO(mdempsky): Move to package types.
318 func FakeRecv() *types.Field {
319         return types.NewField(src.NoXPos, nil, types.FakeRecvType())
320 }
321
322 var fakeRecvField = FakeRecv
323
324 var funcStack []funcStackEnt // stack of previous values of ir.CurFunc/DeclContext
325
326 type funcStackEnt struct {
327         curfn      *ir.Func
328         dclcontext ir.Class
329 }
330
331 func funcarg(n *ir.Field, ctxt ir.Class) {
332         if n.Sym == nil {
333                 return
334         }
335
336         name := ir.NewNameAt(n.Pos, n.Sym)
337         n.Decl = name
338         name.Ntype = n.Ntype
339         Declare(name, ctxt)
340 }
341
342 func funcarg2(f *types.Field, ctxt ir.Class) {
343         if f.Sym == nil {
344                 return
345         }
346         n := ir.NewNameAt(f.Pos, f.Sym)
347         f.Nname = n
348         n.SetType(f.Type)
349         Declare(n, ctxt)
350 }
351
352 func funcargs(nt *ir.FuncType) {
353         if nt.Op() != ir.OTFUNC {
354                 base.Fatalf("funcargs %v", nt.Op())
355         }
356
357         // declare the receiver and in arguments.
358         if nt.Recv != nil {
359                 funcarg(nt.Recv, ir.PPARAM)
360         }
361         for _, n := range nt.Params {
362                 funcarg(n, ir.PPARAM)
363         }
364
365         // declare the out arguments.
366         for i, n := range nt.Results {
367                 if n.Sym == nil {
368                         // Name so that escape analysis can track it. ~r stands for 'result'.
369                         n.Sym = LookupNum("~r", i)
370                 }
371                 if n.Sym.IsBlank() {
372                         // Give it a name so we can assign to it during return. ~b stands for 'blank'.
373                         // The name must be different from ~r above because if you have
374                         //      func f() (_ int)
375                         //      func g() int
376                         // f is allowed to use a plain 'return' with no arguments, while g is not.
377                         // So the two cases must be distinguished.
378                         n.Sym = LookupNum("~b", i)
379                 }
380
381                 funcarg(n, ir.PPARAMOUT)
382         }
383 }
384
385 // Same as funcargs, except run over an already constructed TFUNC.
386 // This happens during import, where the hidden_fndcl rule has
387 // used functype directly to parse the function's type.
388 func funcargs2(t *types.Type) {
389         if t.Kind() != types.TFUNC {
390                 base.Fatalf("funcargs2 %v", t)
391         }
392
393         for _, f := range t.Recvs().Fields().Slice() {
394                 funcarg2(f, ir.PPARAM)
395         }
396         for _, f := range t.Params().Fields().Slice() {
397                 funcarg2(f, ir.PPARAM)
398         }
399         for _, f := range t.Results().Fields().Slice() {
400                 funcarg2(f, ir.PPARAMOUT)
401         }
402 }
403
404 func Temp(t *types.Type) *ir.Name {
405         return TempAt(base.Pos, ir.CurFunc, t)
406 }
407
408 // make a new Node off the books
409 func TempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name {
410         if curfn == nil {
411                 base.Fatalf("no curfn for TempAt")
412         }
413         if curfn.Op() == ir.OCLOSURE {
414                 ir.Dump("TempAt", curfn)
415                 base.Fatalf("adding TempAt to wrong closure function")
416         }
417         if t == nil {
418                 base.Fatalf("TempAt called with nil type")
419         }
420         if t.Kind() == types.TFUNC && t.Recv() != nil {
421                 base.Fatalf("misuse of method type: %v", t)
422         }
423
424         s := &types.Sym{
425                 Name: autotmpname(len(curfn.Dcl)),
426                 Pkg:  types.LocalPkg,
427         }
428         n := ir.NewNameAt(pos, s)
429         s.Def = n
430         n.SetType(t)
431         n.SetTypecheck(1)
432         n.Class = ir.PAUTO
433         n.SetEsc(ir.EscNever)
434         n.Curfn = curfn
435         n.SetUsed(true)
436         n.SetAutoTemp(true)
437         curfn.Dcl = append(curfn.Dcl, n)
438
439         types.CalcSize(t)
440
441         return n
442 }
443
444 var (
445         autotmpnamesmu sync.Mutex
446         autotmpnames   []string
447 )
448
449 // autotmpname returns the name for an autotmp variable numbered n.
450 func autotmpname(n int) string {
451         autotmpnamesmu.Lock()
452         defer autotmpnamesmu.Unlock()
453
454         // Grow autotmpnames, if needed.
455         if n >= len(autotmpnames) {
456                 autotmpnames = append(autotmpnames, make([]string, n+1-len(autotmpnames))...)
457                 autotmpnames = autotmpnames[:cap(autotmpnames)]
458         }
459
460         s := autotmpnames[n]
461         if s == "" {
462                 // Give each tmp a different name so that they can be registerized.
463                 // Add a preceding . to avoid clashing with legal names.
464                 prefix := ".autotmp_%d"
465
466                 // In quirks mode, pad out the number to stabilize variable
467                 // sorting. This ensures autotmps 8 and 9 sort the same way even
468                 // if they get renumbered to 9 and 10, respectively.
469                 if base.Debug.UnifiedQuirks != 0 {
470                         prefix = ".autotmp_%06d"
471                 }
472
473                 s = fmt.Sprintf(prefix, n)
474                 autotmpnames[n] = s
475         }
476         return s
477 }
478
479 // f is method type, with receiver.
480 // return function type, receiver as first argument (or not).
481 func NewMethodType(sig *types.Type, recv *types.Type) *types.Type {
482         nrecvs := 0
483         if recv != nil {
484                 nrecvs++
485         }
486
487         // TODO(mdempsky): Move this function to types.
488         // TODO(mdempsky): Preserve positions, names, and package from sig+recv.
489
490         params := make([]*types.Field, nrecvs+sig.Params().Fields().Len())
491         if recv != nil {
492                 params[0] = types.NewField(base.Pos, nil, recv)
493         }
494         for i, param := range sig.Params().Fields().Slice() {
495                 d := types.NewField(base.Pos, nil, param.Type)
496                 d.SetIsDDD(param.IsDDD())
497                 params[nrecvs+i] = d
498         }
499
500         results := make([]*types.Field, sig.Results().Fields().Len())
501         for i, t := range sig.Results().Fields().Slice() {
502                 results[i] = types.NewField(base.Pos, nil, t.Type)
503         }
504
505         return types.NewSignature(types.LocalPkg, nil, nil, params, results)
506 }