1
2
3
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
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
36
37 func Declare(n *ir.Name, ctxt ir.Class) {
38 if ir.IsBlank(n) {
39 return
40 }
41
42 s := n.Sym()
43
44
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
75
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
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
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
126
127
128
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
139
140
141
142 func StartFuncBody(fn *ir.Func) {
143
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
158
159
160 func FinishFuncBody() {
161
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
175
176
177
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
184 rf := t.Recv()
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
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
213
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
243
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
279
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
297
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 var funcStack []funcStackEnt
318
319 type funcStackEnt struct {
320 curfn *ir.Func
321 dclcontext ir.Class
322 }
323
324 func funcarg(n *ir.Field, ctxt ir.Class) {
325 if n.Sym == nil {
326 return
327 }
328
329 name := ir.NewNameAt(n.Pos, n.Sym)
330 n.Decl = name
331 name.Ntype = n.Ntype
332 Declare(name, ctxt)
333 }
334
335 func funcarg2(f *types.Field, ctxt ir.Class) {
336 if f.Sym == nil {
337 return
338 }
339 n := ir.NewNameAt(f.Pos, f.Sym)
340 f.Nname = n
341 n.SetType(f.Type)
342 Declare(n, ctxt)
343 }
344
345 func funcargs(nt *ir.FuncType) {
346 if nt.Op() != ir.OTFUNC {
347 base.Fatalf("funcargs %v", nt.Op())
348 }
349
350
351 if nt.Recv != nil {
352 funcarg(nt.Recv, ir.PPARAM)
353 }
354 for _, n := range nt.Params {
355 funcarg(n, ir.PPARAM)
356 }
357
358
359 for i, n := range nt.Results {
360 if n.Sym == nil {
361
362 n.Sym = LookupNum("~r", i)
363 } else if n.Sym.IsBlank() {
364
365
366
367
368
369
370 n.Sym = LookupNum("~b", i)
371 }
372
373 funcarg(n, ir.PPARAMOUT)
374 }
375 }
376
377
378
379
380 func funcargs2(t *types.Type) {
381 if t.Kind() != types.TFUNC {
382 base.Fatalf("funcargs2 %v", t)
383 }
384
385 for _, f := range t.Recvs().Fields().Slice() {
386 funcarg2(f, ir.PPARAM)
387 }
388 for _, f := range t.Params().Fields().Slice() {
389 funcarg2(f, ir.PPARAM)
390 }
391 for _, f := range t.Results().Fields().Slice() {
392 funcarg2(f, ir.PPARAMOUT)
393 }
394 }
395
396 func Temp(t *types.Type) *ir.Name {
397 return TempAt(base.Pos, ir.CurFunc, t)
398 }
399
400
401 func TempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name {
402 if curfn == nil {
403 base.Fatalf("no curfn for TempAt")
404 }
405 if curfn.Op() == ir.OCLOSURE {
406 ir.Dump("TempAt", curfn)
407 base.Fatalf("adding TempAt to wrong closure function")
408 }
409 if t == nil {
410 base.Fatalf("TempAt called with nil type")
411 }
412 if t.Kind() == types.TFUNC && t.Recv() != nil {
413 base.Fatalf("misuse of method type: %v", t)
414 }
415
416 s := &types.Sym{
417 Name: autotmpname(len(curfn.Dcl)),
418 Pkg: types.LocalPkg,
419 }
420 n := ir.NewNameAt(pos, s)
421 s.Def = n
422 n.SetType(t)
423 n.SetTypecheck(1)
424 n.Class = ir.PAUTO
425 n.SetEsc(ir.EscNever)
426 n.Curfn = curfn
427 n.SetUsed(true)
428 n.SetAutoTemp(true)
429 curfn.Dcl = append(curfn.Dcl, n)
430
431 types.CalcSize(t)
432
433 return n
434 }
435
436 var (
437 autotmpnamesmu sync.Mutex
438 autotmpnames []string
439 )
440
441
442 func autotmpname(n int) string {
443 autotmpnamesmu.Lock()
444 defer autotmpnamesmu.Unlock()
445
446
447 if n >= len(autotmpnames) {
448 autotmpnames = append(autotmpnames, make([]string, n+1-len(autotmpnames))...)
449 autotmpnames = autotmpnames[:cap(autotmpnames)]
450 }
451
452 s := autotmpnames[n]
453 if s == "" {
454
455
456 prefix := ".autotmp_%d"
457
458
459
460
461 if base.Debug.UnifiedQuirks != 0 {
462 prefix = ".autotmp_%06d"
463 }
464
465 s = fmt.Sprintf(prefix, n)
466 autotmpnames[n] = s
467 }
468 return s
469 }
470
471
472
473 func NewMethodType(sig *types.Type, recv *types.Type) *types.Type {
474 if sig.HasTParam() {
475 base.Fatalf("NewMethodType with type parameters in signature %+v", sig)
476 }
477 if recv != nil && recv.HasTParam() {
478 base.Fatalf("NewMethodType with type parameters in receiver %+v", recv)
479 }
480 nrecvs := 0
481 if recv != nil {
482 nrecvs++
483 }
484
485
486
487
488 params := make([]*types.Field, nrecvs+sig.Params().Fields().Len())
489 if recv != nil {
490 params[0] = types.NewField(base.Pos, nil, recv)
491 }
492 for i, param := range sig.Params().Fields().Slice() {
493 d := types.NewField(base.Pos, nil, param.Type)
494 d.SetIsDDD(param.IsDDD())
495 params[nrecvs+i] = d
496 }
497
498 results := make([]*types.Field, sig.Results().Fields().Len())
499 for i, t := range sig.Results().Fields().Slice() {
500 results[i] = types.NewField(base.Pos, nil, t.Type)
501 }
502
503 return types.NewSignature(types.LocalPkg, nil, nil, params, results)
504 }
505
View as plain text