1
2
3
4
5 package noder
6
7 import (
8 "fmt"
9 "go/constant"
10 "go/token"
11 "os"
12 "path/filepath"
13 "runtime"
14 "strconv"
15 "strings"
16 "unicode"
17 "unicode/utf8"
18
19 "cmd/compile/internal/base"
20 "cmd/compile/internal/dwarfgen"
21 "cmd/compile/internal/ir"
22 "cmd/compile/internal/syntax"
23 "cmd/compile/internal/typecheck"
24 "cmd/compile/internal/types"
25 "cmd/internal/objabi"
26 "cmd/internal/src"
27 )
28
29 func LoadPackage(filenames []string) {
30 base.Timer.Start("fe", "parse")
31
32 mode := syntax.CheckBranches
33 if base.Flag.G != 0 {
34 mode |= syntax.AllowGenerics
35 }
36
37
38 sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
39
40 noders := make([]*noder, len(filenames))
41 for i, filename := range filenames {
42 p := noder{
43 err: make(chan syntax.Error),
44 trackScopes: base.Flag.Dwarf,
45 }
46 noders[i] = &p
47
48 filename := filename
49 go func() {
50 sem <- struct{}{}
51 defer func() { <-sem }()
52 defer close(p.err)
53 fbase := syntax.NewFileBase(filename)
54
55 f, err := os.Open(filename)
56 if err != nil {
57 p.error(syntax.Error{Msg: err.Error()})
58 return
59 }
60 defer f.Close()
61
62 p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode)
63 }()
64 }
65
66 var lines uint
67 for _, p := range noders {
68 for e := range p.err {
69 p.errorAt(e.Pos, "%s", e.Msg)
70 }
71 if p.file == nil {
72 base.ErrorExit()
73 }
74 lines += p.file.EOF.Line()
75 }
76 base.Timer.AddEvent(int64(lines), "lines")
77
78 if base.Flag.G != 0 {
79
80 check2(noders)
81 return
82 }
83
84 for _, p := range noders {
85 p.node()
86 p.file = nil
87 }
88
89 if base.SyntaxErrors() != 0 {
90 base.ErrorExit()
91 }
92 types.CheckDclstack()
93
94 for _, p := range noders {
95 p.processPragmas()
96 }
97
98
99 types.LocalPkg.Height = myheight
100 typecheck.DeclareUniverse()
101 typecheck.TypecheckAllowed = true
102
103
104
105
106
107
108
109
110
111
112
113
114 base.Timer.Start("fe", "typecheck", "top1")
115 for i := 0; i < len(typecheck.Target.Decls); i++ {
116 n := typecheck.Target.Decls[i]
117 if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.(*ir.Decl).X.Alias()) {
118 typecheck.Target.Decls[i] = typecheck.Stmt(n)
119 }
120 }
121
122
123
124
125
126 base.Timer.Start("fe", "typecheck", "top2")
127 for i := 0; i < len(typecheck.Target.Decls); i++ {
128 n := typecheck.Target.Decls[i]
129 if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).X.Alias() {
130 typecheck.Target.Decls[i] = typecheck.Stmt(n)
131 }
132 }
133
134
135
136 base.Timer.Start("fe", "typecheck", "func")
137 var fcount int64
138 for i := 0; i < len(typecheck.Target.Decls); i++ {
139 n := typecheck.Target.Decls[i]
140 if n.Op() == ir.ODCLFUNC {
141 if base.Flag.W > 1 {
142 s := fmt.Sprintf("\nbefore typecheck %v", n)
143 ir.Dump(s, n)
144 }
145 typecheck.FuncBody(n.(*ir.Func))
146 if base.Flag.W > 1 {
147 s := fmt.Sprintf("\nafter typecheck %v", n)
148 ir.Dump(s, n)
149 }
150 fcount++
151 }
152 }
153
154
155
156
157 base.Timer.Start("fe", "typecheck", "externdcls")
158 for i, n := range typecheck.Target.Externs {
159 if n.Op() == ir.ONAME {
160 typecheck.Target.Externs[i] = typecheck.Expr(typecheck.Target.Externs[i])
161 }
162 }
163
164
165
166 typecheck.CheckMapKeys()
167 CheckDotImports()
168 base.ExitIfErrors()
169 }
170
171 func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
172 base.ErrorfAt(p.makeXPos(pos), format, args...)
173 }
174
175
176 func fileh(name string) string {
177 return objabi.AbsFile("", name, base.Flag.TrimPath)
178 }
179
180 func absFilename(name string) string {
181 return objabi.AbsFile(base.Ctxt.Pathname, name, base.Flag.TrimPath)
182 }
183
184
185 type noder struct {
186 posMap
187
188 file *syntax.File
189 linknames []linkname
190 pragcgobuf [][]string
191 err chan syntax.Error
192 importedUnsafe bool
193 importedEmbed bool
194 trackScopes bool
195
196 funcState *funcState
197 }
198
199
200
201 type funcState struct {
202
203
204 scopeVars []int
205 marker dwarfgen.ScopeMarker
206
207 lastCloseScopePos syntax.Pos
208 }
209
210 func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
211 outerFuncState := p.funcState
212 p.funcState = new(funcState)
213 typecheck.StartFuncBody(fn)
214
215 if block != nil {
216 body := p.stmts(block.List)
217 if body == nil {
218 body = []ir.Node{ir.NewBlockStmt(base.Pos, nil)}
219 }
220 fn.Body = body
221
222 base.Pos = p.makeXPos(block.Rbrace)
223 fn.Endlineno = base.Pos
224 }
225
226 typecheck.FinishFuncBody()
227 p.funcState.marker.WriteTo(fn)
228 p.funcState = outerFuncState
229 }
230
231 func (p *noder) openScope(pos syntax.Pos) {
232 fs := p.funcState
233 types.Markdcl()
234
235 if p.trackScopes {
236 fs.scopeVars = append(fs.scopeVars, len(ir.CurFunc.Dcl))
237 fs.marker.Push(p.makeXPos(pos))
238 }
239 }
240
241 func (p *noder) closeScope(pos syntax.Pos) {
242 fs := p.funcState
243 fs.lastCloseScopePos = pos
244 types.Popdcl()
245
246 if p.trackScopes {
247 scopeVars := fs.scopeVars[len(fs.scopeVars)-1]
248 fs.scopeVars = fs.scopeVars[:len(fs.scopeVars)-1]
249 if scopeVars == len(ir.CurFunc.Dcl) {
250
251 fs.marker.Unpush()
252 } else {
253 fs.marker.Pop(p.makeXPos(pos))
254 }
255 }
256 }
257
258
259
260
261
262 func (p *noder) closeAnotherScope() {
263 p.closeScope(p.funcState.lastCloseScopePos)
264 }
265
266
267 type linkname struct {
268 pos syntax.Pos
269 local string
270 remote string
271 }
272
273 func (p *noder) node() {
274 p.importedUnsafe = false
275 p.importedEmbed = false
276
277 p.setlineno(p.file.PkgName)
278 mkpackage(p.file.PkgName.Value)
279
280 if pragma, ok := p.file.Pragma.(*pragmas); ok {
281 pragma.Flag &^= ir.GoBuildPragma
282 p.checkUnused(pragma)
283 }
284
285 typecheck.Target.Decls = append(typecheck.Target.Decls, p.decls(p.file.DeclList)...)
286
287 base.Pos = src.NoXPos
288 clearImports()
289 }
290
291 func (p *noder) processPragmas() {
292 for _, l := range p.linknames {
293 if !p.importedUnsafe {
294 p.errorAt(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
295 continue
296 }
297 n := ir.AsNode(typecheck.Lookup(l.local).Def)
298 if n == nil || n.Op() != ir.ONAME {
299
300
301 continue
302 }
303 if n.Sym().Linkname != "" {
304 p.errorAt(l.pos, "duplicate //go:linkname for %s", l.local)
305 continue
306 }
307 n.Sym().Linkname = l.remote
308 }
309 typecheck.Target.CgoPragmas = append(typecheck.Target.CgoPragmas, p.pragcgobuf...)
310 }
311
312 func (p *noder) decls(decls []syntax.Decl) (l []ir.Node) {
313 var cs constState
314
315 for _, decl := range decls {
316 p.setlineno(decl)
317 switch decl := decl.(type) {
318 case *syntax.ImportDecl:
319 p.importDecl(decl)
320
321 case *syntax.VarDecl:
322 l = append(l, p.varDecl(decl)...)
323
324 case *syntax.ConstDecl:
325 l = append(l, p.constDecl(decl, &cs)...)
326
327 case *syntax.TypeDecl:
328 l = append(l, p.typeDecl(decl))
329
330 case *syntax.FuncDecl:
331 l = append(l, p.funcDecl(decl))
332
333 default:
334 panic("unhandled Decl")
335 }
336 }
337
338 return
339 }
340
341 func (p *noder) importDecl(imp *syntax.ImportDecl) {
342 if imp.Path == nil || imp.Path.Bad {
343 return
344 }
345
346 if pragma, ok := imp.Pragma.(*pragmas); ok {
347 p.checkUnused(pragma)
348 }
349
350 ipkg := importfile(imp)
351 if ipkg == nil {
352 if base.Errors() == 0 {
353 base.Fatalf("phase error in import")
354 }
355 return
356 }
357
358 if ipkg == ir.Pkgs.Unsafe {
359 p.importedUnsafe = true
360 }
361 if ipkg.Path == "embed" {
362 p.importedEmbed = true
363 }
364
365 var my *types.Sym
366 if imp.LocalPkgName != nil {
367 my = p.name(imp.LocalPkgName)
368 } else {
369 my = typecheck.Lookup(ipkg.Name)
370 }
371
372 pack := ir.NewPkgName(p.pos(imp), my, ipkg)
373
374 switch my.Name {
375 case ".":
376 importDot(pack)
377 return
378 case "init":
379 base.ErrorfAt(pack.Pos(), "cannot import package as init - init must be a func")
380 return
381 case "_":
382 return
383 }
384 if my.Def != nil {
385 typecheck.Redeclared(pack.Pos(), my, "as imported package name")
386 }
387 my.Def = pack
388 my.Lastlineno = pack.Pos()
389 my.Block = 1
390 }
391
392 func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
393 names := p.declNames(ir.ONAME, decl.NameList)
394 typ := p.typeExprOrNil(decl.Type)
395 exprs := p.exprList(decl.Values)
396
397 if pragma, ok := decl.Pragma.(*pragmas); ok {
398 varEmbed(p.makeXPos, names[0], decl, pragma, p.importedEmbed)
399 p.checkUnused(pragma)
400 }
401
402 var init []ir.Node
403 p.setlineno(decl)
404
405 if len(names) > 1 && len(exprs) == 1 {
406 as2 := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, exprs)
407 for _, v := range names {
408 as2.Lhs.Append(v)
409 typecheck.Declare(v, typecheck.DeclContext)
410 v.Ntype = typ
411 v.Defn = as2
412 if ir.CurFunc != nil {
413 init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
414 }
415 }
416
417 return append(init, as2)
418 }
419
420 for i, v := range names {
421 var e ir.Node
422 if i < len(exprs) {
423 e = exprs[i]
424 }
425
426 typecheck.Declare(v, typecheck.DeclContext)
427 v.Ntype = typ
428
429 if ir.CurFunc != nil {
430 init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
431 }
432 as := ir.NewAssignStmt(base.Pos, v, e)
433 init = append(init, as)
434 if e != nil || ir.CurFunc == nil {
435 v.Defn = as
436 }
437 }
438
439 if len(exprs) != 0 && len(names) != len(exprs) {
440 base.Errorf("assignment mismatch: %d variables but %d values", len(names), len(exprs))
441 }
442
443 return init
444 }
445
446
447
448
449 type constState struct {
450 group *syntax.Group
451 typ ir.Ntype
452 values []ir.Node
453 iota int64
454 }
455
456 func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node {
457 if decl.Group == nil || decl.Group != cs.group {
458 *cs = constState{
459 group: decl.Group,
460 }
461 }
462
463 if pragma, ok := decl.Pragma.(*pragmas); ok {
464 p.checkUnused(pragma)
465 }
466
467 names := p.declNames(ir.OLITERAL, decl.NameList)
468 typ := p.typeExprOrNil(decl.Type)
469
470 var values []ir.Node
471 if decl.Values != nil {
472 values = p.exprList(decl.Values)
473 cs.typ, cs.values = typ, values
474 } else {
475 if typ != nil {
476 base.Errorf("const declaration cannot have type without expression")
477 }
478 typ, values = cs.typ, cs.values
479 }
480
481 nn := make([]ir.Node, 0, len(names))
482 for i, n := range names {
483 if i >= len(values) {
484 base.Errorf("missing value in const declaration")
485 break
486 }
487 v := values[i]
488 if decl.Values == nil {
489 v = ir.DeepCopy(n.Pos(), v)
490 }
491 typecheck.Declare(n, typecheck.DeclContext)
492
493 n.Ntype = typ
494 n.Defn = v
495 n.SetIota(cs.iota)
496
497 nn = append(nn, ir.NewDecl(p.pos(decl), ir.ODCLCONST, n))
498 }
499
500 if len(values) > len(names) {
501 base.Errorf("extra expression in const declaration")
502 }
503
504 cs.iota++
505
506 return nn
507 }
508
509 func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
510 n := p.declName(ir.OTYPE, decl.Name)
511 typecheck.Declare(n, typecheck.DeclContext)
512
513
514 typ := p.typeExprOrNil(decl.Type)
515
516 n.Ntype = typ
517 n.SetAlias(decl.Alias)
518 if pragma, ok := decl.Pragma.(*pragmas); ok {
519 if !decl.Alias {
520 n.SetPragma(pragma.Flag & typePragmas)
521 pragma.Flag &^= typePragmas
522 }
523 p.checkUnused(pragma)
524 }
525
526 nod := ir.NewDecl(p.pos(decl), ir.ODCLTYPE, n)
527 if n.Alias() && !types.AllowsGoVersion(types.LocalPkg, 1, 9) {
528 base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
529 }
530 return nod
531 }
532
533 func (p *noder) declNames(op ir.Op, names []*syntax.Name) []*ir.Name {
534 nodes := make([]*ir.Name, 0, len(names))
535 for _, name := range names {
536 nodes = append(nodes, p.declName(op, name))
537 }
538 return nodes
539 }
540
541 func (p *noder) declName(op ir.Op, name *syntax.Name) *ir.Name {
542 return ir.NewDeclNameAt(p.pos(name), op, p.name(name))
543 }
544
545 func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
546 name := p.name(fun.Name)
547 t := p.signature(fun.Recv, fun.Type)
548 f := ir.NewFunc(p.pos(fun))
549
550 if fun.Recv == nil {
551 if name.Name == "init" {
552 name = renameinit()
553 if len(t.Params) > 0 || len(t.Results) > 0 {
554 base.ErrorfAt(f.Pos(), "func init must have no arguments and no return values")
555 }
556 typecheck.Target.Inits = append(typecheck.Target.Inits, f)
557 }
558
559 if types.LocalPkg.Name == "main" && name.Name == "main" {
560 if len(t.Params) > 0 || len(t.Results) > 0 {
561 base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values")
562 }
563 }
564 } else {
565 f.Shortname = name
566 name = ir.BlankNode.Sym()
567 }
568
569 f.Nname = ir.NewNameAt(p.pos(fun.Name), name)
570 f.Nname.Func = f
571 f.Nname.Defn = f
572 f.Nname.Ntype = t
573
574 if pragma, ok := fun.Pragma.(*pragmas); ok {
575 f.Pragma = pragma.Flag & funcPragmas
576 if pragma.Flag&ir.Systemstack != 0 && pragma.Flag&ir.Nosplit != 0 {
577 base.ErrorfAt(f.Pos(), "go:nosplit and go:systemstack cannot be combined")
578 }
579 pragma.Flag &^= funcPragmas
580 p.checkUnused(pragma)
581 }
582
583 if fun.Recv == nil {
584 typecheck.Declare(f.Nname, ir.PFUNC)
585 }
586
587 p.funcBody(f, fun.Body)
588
589 if fun.Body != nil {
590 if f.Pragma&ir.Noescape != 0 {
591 base.ErrorfAt(f.Pos(), "can only use //go:noescape with external func implementations")
592 }
593 } else {
594 if base.Flag.Complete || strings.HasPrefix(ir.FuncName(f), "init.") {
595
596
597 isLinknamed := false
598 for _, n := range p.linknames {
599 if ir.FuncName(f) == n.local {
600 isLinknamed = true
601 break
602 }
603 }
604 if !isLinknamed {
605 base.ErrorfAt(f.Pos(), "missing function body")
606 }
607 }
608 }
609
610 return f
611 }
612
613 func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *ir.FuncType {
614 var rcvr *ir.Field
615 if recv != nil {
616 rcvr = p.param(recv, false, false)
617 }
618 return ir.NewFuncType(p.pos(typ), rcvr,
619 p.params(typ.ParamList, true),
620 p.params(typ.ResultList, false))
621 }
622
623 func (p *noder) params(params []*syntax.Field, dddOk bool) []*ir.Field {
624 nodes := make([]*ir.Field, 0, len(params))
625 for i, param := range params {
626 p.setlineno(param)
627 nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))
628 }
629 return nodes
630 }
631
632 func (p *noder) param(param *syntax.Field, dddOk, final bool) *ir.Field {
633 var name *types.Sym
634 if param.Name != nil {
635 name = p.name(param.Name)
636 }
637
638 typ := p.typeExpr(param.Type)
639 n := ir.NewField(p.pos(param), name, typ, nil)
640
641
642 if typ, ok := typ.(*ir.SliceType); ok && typ.DDD {
643 if !dddOk {
644
645
646 base.Errorf("syntax error: cannot use ... in receiver or result parameter list")
647 } else if !final {
648 if param.Name == nil {
649 base.Errorf("syntax error: cannot use ... with non-final parameter")
650 } else {
651 p.errorAt(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value)
652 }
653 }
654 typ.DDD = false
655 n.IsDDD = true
656 }
657
658 return n
659 }
660
661 func (p *noder) exprList(expr syntax.Expr) []ir.Node {
662 switch expr := expr.(type) {
663 case nil:
664 return nil
665 case *syntax.ListExpr:
666 return p.exprs(expr.ElemList)
667 default:
668 return []ir.Node{p.expr(expr)}
669 }
670 }
671
672 func (p *noder) exprs(exprs []syntax.Expr) []ir.Node {
673 nodes := make([]ir.Node, 0, len(exprs))
674 for _, expr := range exprs {
675 nodes = append(nodes, p.expr(expr))
676 }
677 return nodes
678 }
679
680 func (p *noder) expr(expr syntax.Expr) ir.Node {
681 p.setlineno(expr)
682 switch expr := expr.(type) {
683 case nil, *syntax.BadExpr:
684 return nil
685 case *syntax.Name:
686 return p.mkname(expr)
687 case *syntax.BasicLit:
688 n := ir.NewBasicLit(p.pos(expr), p.basicLit(expr))
689 if expr.Kind == syntax.RuneLit {
690 n.SetType(types.UntypedRune)
691 }
692 n.SetDiag(expr.Bad || n.Val().Kind() == constant.Unknown)
693 return n
694 case *syntax.CompositeLit:
695 n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, p.typeExpr(expr.Type), nil)
696 l := p.exprs(expr.ElemList)
697 for i, e := range l {
698 l[i] = p.wrapname(expr.ElemList[i], e)
699 }
700 n.List = l
701 base.Pos = p.makeXPos(expr.Rbrace)
702 return n
703 case *syntax.KeyValueExpr:
704
705 return ir.NewKeyExpr(p.pos(expr.Key), p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
706 case *syntax.FuncLit:
707 return p.funcLit(expr)
708 case *syntax.ParenExpr:
709 return ir.NewParenExpr(p.pos(expr), p.expr(expr.X))
710 case *syntax.SelectorExpr:
711
712 obj := p.expr(expr.X)
713 if obj.Op() == ir.OPACK {
714 pack := obj.(*ir.PkgName)
715 pack.Used = true
716 return importName(pack.Pkg.Lookup(expr.Sel.Value))
717 }
718 n := ir.NewSelectorExpr(base.Pos, ir.OXDOT, obj, p.name(expr.Sel))
719 n.SetPos(p.pos(expr))
720 return n
721 case *syntax.IndexExpr:
722 return ir.NewIndexExpr(p.pos(expr), p.expr(expr.X), p.expr(expr.Index))
723 case *syntax.SliceExpr:
724 op := ir.OSLICE
725 if expr.Full {
726 op = ir.OSLICE3
727 }
728 x := p.expr(expr.X)
729 var index [3]ir.Node
730 for i, n := range &expr.Index {
731 if n != nil {
732 index[i] = p.expr(n)
733 }
734 }
735 return ir.NewSliceExpr(p.pos(expr), op, x, index[0], index[1], index[2])
736 case *syntax.AssertExpr:
737 return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type))
738 case *syntax.Operation:
739 if expr.Op == syntax.Add && expr.Y != nil {
740 return p.sum(expr)
741 }
742 x := p.expr(expr.X)
743 if expr.Y == nil {
744 pos, op := p.pos(expr), p.unOp(expr.Op)
745 switch op {
746 case ir.OADDR:
747 return typecheck.NodAddrAt(pos, x)
748 case ir.ODEREF:
749 return ir.NewStarExpr(pos, x)
750 }
751 return ir.NewUnaryExpr(pos, op, x)
752 }
753
754 pos, op, y := p.pos(expr), p.binOp(expr.Op), p.expr(expr.Y)
755 switch op {
756 case ir.OANDAND, ir.OOROR:
757 return ir.NewLogicalExpr(pos, op, x, y)
758 }
759 return ir.NewBinaryExpr(pos, op, x, y)
760 case *syntax.CallExpr:
761 n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), p.exprs(expr.ArgList))
762 n.IsDDD = expr.HasDots
763 return n
764
765 case *syntax.ArrayType:
766 var len ir.Node
767 if expr.Len != nil {
768 len = p.expr(expr.Len)
769 }
770 return ir.NewArrayType(p.pos(expr), len, p.typeExpr(expr.Elem))
771 case *syntax.SliceType:
772 return ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
773 case *syntax.DotsType:
774 t := ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
775 t.DDD = true
776 return t
777 case *syntax.StructType:
778 return p.structType(expr)
779 case *syntax.InterfaceType:
780 return p.interfaceType(expr)
781 case *syntax.FuncType:
782 return p.signature(nil, expr)
783 case *syntax.MapType:
784 return ir.NewMapType(p.pos(expr),
785 p.typeExpr(expr.Key), p.typeExpr(expr.Value))
786 case *syntax.ChanType:
787 return ir.NewChanType(p.pos(expr),
788 p.typeExpr(expr.Elem), p.chanDir(expr.Dir))
789
790 case *syntax.TypeSwitchGuard:
791 var tag *ir.Ident
792 if expr.Lhs != nil {
793 tag = ir.NewIdent(p.pos(expr.Lhs), p.name(expr.Lhs))
794 if ir.IsBlank(tag) {
795 base.Errorf("invalid variable name %v in type switch", tag)
796 }
797 }
798 return ir.NewTypeSwitchGuard(p.pos(expr), tag, p.expr(expr.X))
799 }
800 panic("unhandled Expr")
801 }
802
803
804
805
806 func (p *noder) sum(x syntax.Expr) ir.Node {
807
808
809
810
811
812 adds := make([]*syntax.Operation, 0, 2)
813 for {
814 add, ok := x.(*syntax.Operation)
815 if !ok || add.Op != syntax.Add || add.Y == nil {
816 break
817 }
818 adds = append(adds, add)
819 x = add.X
820 }
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841 var nstr ir.Node
842 chunks := make([]string, 0, 1)
843
844 n := p.expr(x)
845 if ir.IsConst(n, constant.String) && n.Sym() == nil {
846 nstr = n
847 chunks = append(chunks, ir.StringVal(nstr))
848 }
849
850 for i := len(adds) - 1; i >= 0; i-- {
851 add := adds[i]
852
853 r := p.expr(add.Y)
854 if ir.IsConst(r, constant.String) && r.Sym() == nil {
855 if nstr != nil {
856
857 chunks = append(chunks, ir.StringVal(r))
858 continue
859 }
860
861 nstr = r
862 chunks = append(chunks, ir.StringVal(nstr))
863 } else {
864 if len(chunks) > 1 {
865 nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
866 }
867 nstr = nil
868 chunks = chunks[:0]
869 }
870 n = ir.NewBinaryExpr(p.pos(add), ir.OADD, n, r)
871 }
872 if len(chunks) > 1 {
873 nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
874 }
875
876 return n
877 }
878
879 func (p *noder) typeExpr(typ syntax.Expr) ir.Ntype {
880
881 n := p.expr(typ)
882 if n == nil {
883 return nil
884 }
885 return n.(ir.Ntype)
886 }
887
888 func (p *noder) typeExprOrNil(typ syntax.Expr) ir.Ntype {
889 if typ != nil {
890 return p.typeExpr(typ)
891 }
892 return nil
893 }
894
895 func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir {
896 switch dir {
897 case 0:
898 return types.Cboth
899 case syntax.SendOnly:
900 return types.Csend
901 case syntax.RecvOnly:
902 return types.Crecv
903 }
904 panic("unhandled ChanDir")
905 }
906
907 func (p *noder) structType(expr *syntax.StructType) ir.Node {
908 l := make([]*ir.Field, 0, len(expr.FieldList))
909 for i, field := range expr.FieldList {
910 p.setlineno(field)
911 var n *ir.Field
912 if field.Name == nil {
913 n = p.embedded(field.Type)
914 } else {
915 n = ir.NewField(p.pos(field), p.name(field.Name), p.typeExpr(field.Type), nil)
916 }
917 if i < len(expr.TagList) && expr.TagList[i] != nil {
918 n.Note = constant.StringVal(p.basicLit(expr.TagList[i]))
919 }
920 l = append(l, n)
921 }
922
923 p.setlineno(expr)
924 return ir.NewStructType(p.pos(expr), l)
925 }
926
927 func (p *noder) interfaceType(expr *syntax.InterfaceType) ir.Node {
928 l := make([]*ir.Field, 0, len(expr.MethodList))
929 for _, method := range expr.MethodList {
930 p.setlineno(method)
931 var n *ir.Field
932 if method.Name == nil {
933 n = ir.NewField(p.pos(method), nil, importName(p.packname(method.Type)).(ir.Ntype), nil)
934 } else {
935 mname := p.name(method.Name)
936 if mname.IsBlank() {
937 base.Errorf("methods must have a unique non-blank name")
938 continue
939 }
940 sig := p.typeExpr(method.Type).(*ir.FuncType)
941 sig.Recv = fakeRecv()
942 n = ir.NewField(p.pos(method), mname, sig, nil)
943 }
944 l = append(l, n)
945 }
946
947 return ir.NewInterfaceType(p.pos(expr), l)
948 }
949
950 func (p *noder) packname(expr syntax.Expr) *types.Sym {
951 switch expr := expr.(type) {
952 case *syntax.Name:
953 name := p.name(expr)
954 if n := oldname(name); n.Name() != nil && n.Name().PkgName != nil {
955 n.Name().PkgName.Used = true
956 }
957 return name
958 case *syntax.SelectorExpr:
959 name := p.name(expr.X.(*syntax.Name))
960 def := ir.AsNode(name.Def)
961 if def == nil {
962 base.Errorf("undefined: %v", name)
963 return name
964 }
965 var pkg *types.Pkg
966 if def.Op() != ir.OPACK {
967 base.Errorf("%v is not a package", name)
968 pkg = types.LocalPkg
969 } else {
970 def := def.(*ir.PkgName)
971 def.Used = true
972 pkg = def.Pkg
973 }
974 return pkg.Lookup(expr.Sel.Value)
975 }
976 panic(fmt.Sprintf("unexpected packname: %#v", expr))
977 }
978
979 func (p *noder) embedded(typ syntax.Expr) *ir.Field {
980 op, isStar := typ.(*syntax.Operation)
981 if isStar {
982 if op.Op != syntax.Mul || op.Y != nil {
983 panic("unexpected Operation")
984 }
985 typ = op.X
986 }
987
988 sym := p.packname(typ)
989 n := ir.NewField(p.pos(typ), typecheck.Lookup(sym.Name), importName(sym).(ir.Ntype), nil)
990 n.Embedded = true
991
992 if isStar {
993 n.Ntype = ir.NewStarExpr(p.pos(op), n.Ntype)
994 }
995 return n
996 }
997
998 func (p *noder) stmts(stmts []syntax.Stmt) []ir.Node {
999 return p.stmtsFall(stmts, false)
1000 }
1001
1002 func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []ir.Node {
1003 var nodes []ir.Node
1004 for i, stmt := range stmts {
1005 s := p.stmtFall(stmt, fallOK && i+1 == len(stmts))
1006 if s == nil {
1007 } else if s.Op() == ir.OBLOCK && len(s.(*ir.BlockStmt).List) > 0 {
1008
1009
1010 nodes = append(nodes, s.(*ir.BlockStmt).List...)
1011 } else {
1012 nodes = append(nodes, s)
1013 }
1014 }
1015 return nodes
1016 }
1017
1018 func (p *noder) stmt(stmt syntax.Stmt) ir.Node {
1019 return p.stmtFall(stmt, false)
1020 }
1021
1022 func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
1023 p.setlineno(stmt)
1024 switch stmt := stmt.(type) {
1025 case nil, *syntax.EmptyStmt:
1026 return nil
1027 case *syntax.LabeledStmt:
1028 return p.labeledStmt(stmt, fallOK)
1029 case *syntax.BlockStmt:
1030 l := p.blockStmt(stmt)
1031 if len(l) == 0 {
1032
1033 return ir.NewBlockStmt(base.Pos, nil)
1034 }
1035 return ir.NewBlockStmt(src.NoXPos, l)
1036 case *syntax.ExprStmt:
1037 return p.wrapname(stmt, p.expr(stmt.X))
1038 case *syntax.SendStmt:
1039 return ir.NewSendStmt(p.pos(stmt), p.expr(stmt.Chan), p.expr(stmt.Value))
1040 case *syntax.DeclStmt:
1041 return ir.NewBlockStmt(src.NoXPos, p.decls(stmt.DeclList))
1042 case *syntax.AssignStmt:
1043 if stmt.Rhs == nil {
1044 pos := p.pos(stmt)
1045 n := ir.NewAssignOpStmt(pos, p.binOp(stmt.Op), p.expr(stmt.Lhs), ir.NewBasicLit(pos, one))
1046 n.IncDec = true
1047 return n
1048 }
1049
1050 if stmt.Op != 0 && stmt.Op != syntax.Def {
1051 n := ir.NewAssignOpStmt(p.pos(stmt), p.binOp(stmt.Op), p.expr(stmt.Lhs), p.expr(stmt.Rhs))
1052 return n
1053 }
1054
1055 rhs := p.exprList(stmt.Rhs)
1056 if list, ok := stmt.Lhs.(*syntax.ListExpr); ok && len(list.ElemList) != 1 || len(rhs) != 1 {
1057 n := ir.NewAssignListStmt(p.pos(stmt), ir.OAS2, nil, nil)
1058 n.Def = stmt.Op == syntax.Def
1059 n.Lhs = p.assignList(stmt.Lhs, n, n.Def)
1060 n.Rhs = rhs
1061 return n
1062 }
1063
1064 n := ir.NewAssignStmt(p.pos(stmt), nil, nil)
1065 n.Def = stmt.Op == syntax.Def
1066 n.X = p.assignList(stmt.Lhs, n, n.Def)[0]
1067 n.Y = rhs[0]
1068 return n
1069
1070 case *syntax.BranchStmt:
1071 var op ir.Op
1072 switch stmt.Tok {
1073 case syntax.Break:
1074 op = ir.OBREAK
1075 case syntax.Continue:
1076 op = ir.OCONTINUE
1077 case syntax.Fallthrough:
1078 if !fallOK {
1079 base.Errorf("fallthrough statement out of place")
1080 }
1081 op = ir.OFALL
1082 case syntax.Goto:
1083 op = ir.OGOTO
1084 default:
1085 panic("unhandled BranchStmt")
1086 }
1087 var sym *types.Sym
1088 if stmt.Label != nil {
1089 sym = p.name(stmt.Label)
1090 }
1091 return ir.NewBranchStmt(p.pos(stmt), op, sym)
1092 case *syntax.CallStmt:
1093 var op ir.Op
1094 switch stmt.Tok {
1095 case syntax.Defer:
1096 op = ir.ODEFER
1097 case syntax.Go:
1098 op = ir.OGO
1099 default:
1100 panic("unhandled CallStmt")
1101 }
1102 return ir.NewGoDeferStmt(p.pos(stmt), op, p.expr(stmt.Call))
1103 case *syntax.ReturnStmt:
1104 n := ir.NewReturnStmt(p.pos(stmt), p.exprList(stmt.Results))
1105 if len(n.Results) == 0 && ir.CurFunc != nil {
1106 for _, ln := range ir.CurFunc.Dcl {
1107 if ln.Class == ir.PPARAM {
1108 continue
1109 }
1110 if ln.Class != ir.PPARAMOUT {
1111 break
1112 }
1113 if ln.Sym().Def != ln {
1114 base.Errorf("%s is shadowed during return", ln.Sym().Name)
1115 }
1116 }
1117 }
1118 return n
1119 case *syntax.IfStmt:
1120 return p.ifStmt(stmt)
1121 case *syntax.ForStmt:
1122 return p.forStmt(stmt)
1123 case *syntax.SwitchStmt:
1124 return p.switchStmt(stmt)
1125 case *syntax.SelectStmt:
1126 return p.selectStmt(stmt)
1127 }
1128 panic("unhandled Stmt")
1129 }
1130
1131 func (p *noder) assignList(expr syntax.Expr, defn ir.InitNode, colas bool) []ir.Node {
1132 if !colas {
1133 return p.exprList(expr)
1134 }
1135
1136 var exprs []syntax.Expr
1137 if list, ok := expr.(*syntax.ListExpr); ok {
1138 exprs = list.ElemList
1139 } else {
1140 exprs = []syntax.Expr{expr}
1141 }
1142
1143 res := make([]ir.Node, len(exprs))
1144 seen := make(map[*types.Sym]bool, len(exprs))
1145
1146 newOrErr := false
1147 for i, expr := range exprs {
1148 p.setlineno(expr)
1149 res[i] = ir.BlankNode
1150
1151 name, ok := expr.(*syntax.Name)
1152 if !ok {
1153 p.errorAt(expr.Pos(), "non-name %v on left side of :=", p.expr(expr))
1154 newOrErr = true
1155 continue
1156 }
1157
1158 sym := p.name(name)
1159 if sym.IsBlank() {
1160 continue
1161 }
1162
1163 if seen[sym] {
1164 p.errorAt(expr.Pos(), "%v repeated on left side of :=", sym)
1165 newOrErr = true
1166 continue
1167 }
1168 seen[sym] = true
1169
1170 if sym.Block == types.Block {
1171 res[i] = oldname(sym)
1172 continue
1173 }
1174
1175 newOrErr = true
1176 n := typecheck.NewName(sym)
1177 typecheck.Declare(n, typecheck.DeclContext)
1178 n.Defn = defn
1179 defn.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, n))
1180 res[i] = n
1181 }
1182
1183 if !newOrErr {
1184 base.ErrorfAt(defn.Pos(), "no new variables on left side of :=")
1185 }
1186 return res
1187 }
1188
1189 func (p *noder) blockStmt(stmt *syntax.BlockStmt) []ir.Node {
1190 p.openScope(stmt.Pos())
1191 nodes := p.stmts(stmt.List)
1192 p.closeScope(stmt.Rbrace)
1193 return nodes
1194 }
1195
1196 func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
1197 p.openScope(stmt.Pos())
1198 init := p.stmt(stmt.Init)
1199 n := ir.NewIfStmt(p.pos(stmt), p.expr(stmt.Cond), p.blockStmt(stmt.Then), nil)
1200 if init != nil {
1201 *n.PtrInit() = []ir.Node{init}
1202 }
1203 if stmt.Else != nil {
1204 e := p.stmt(stmt.Else)
1205 if e.Op() == ir.OBLOCK {
1206 e := e.(*ir.BlockStmt)
1207 n.Else = e.List
1208 } else {
1209 n.Else = []ir.Node{e}
1210 }
1211 }
1212 p.closeAnotherScope()
1213 return n
1214 }
1215
1216 func (p *noder) forStmt(stmt *syntax.ForStmt) ir.Node {
1217 p.openScope(stmt.Pos())
1218 if r, ok := stmt.Init.(*syntax.RangeClause); ok {
1219 if stmt.Cond != nil || stmt.Post != nil {
1220 panic("unexpected RangeClause")
1221 }
1222
1223 n := ir.NewRangeStmt(p.pos(r), nil, nil, p.expr(r.X), nil)
1224 if r.Lhs != nil {
1225 n.Def = r.Def
1226 lhs := p.assignList(r.Lhs, n, n.Def)
1227 n.Key = lhs[0]
1228 if len(lhs) > 1 {
1229 n.Value = lhs[1]
1230 }
1231 }
1232 n.Body = p.blockStmt(stmt.Body)
1233 p.closeAnotherScope()
1234 return n
1235 }
1236
1237 n := ir.NewForStmt(p.pos(stmt), p.stmt(stmt.Init), p.expr(stmt.Cond), p.stmt(stmt.Post), p.blockStmt(stmt.Body))
1238 p.closeAnotherScope()
1239 return n
1240 }
1241
1242 func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
1243 p.openScope(stmt.Pos())
1244
1245 init := p.stmt(stmt.Init)
1246 n := ir.NewSwitchStmt(p.pos(stmt), p.expr(stmt.Tag), nil)
1247 if init != nil {
1248 *n.PtrInit() = []ir.Node{init}
1249 }
1250
1251 var tswitch *ir.TypeSwitchGuard
1252 if l := n.Tag; l != nil && l.Op() == ir.OTYPESW {
1253 tswitch = l.(*ir.TypeSwitchGuard)
1254 }
1255 n.Cases = p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)
1256
1257 p.closeScope(stmt.Rbrace)
1258 return n
1259 }
1260
1261 func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []*ir.CaseClause {
1262 nodes := make([]*ir.CaseClause, 0, len(clauses))
1263 for i, clause := range clauses {
1264 p.setlineno(clause)
1265 if i > 0 {
1266 p.closeScope(clause.Pos())
1267 }
1268 p.openScope(clause.Pos())
1269
1270 n := ir.NewCaseStmt(p.pos(clause), p.exprList(clause.Cases), nil)
1271 if tswitch != nil && tswitch.Tag != nil {
1272 nn := typecheck.NewName(tswitch.Tag.Sym())
1273 typecheck.Declare(nn, typecheck.DeclContext)
1274 n.Var = nn
1275
1276 nn.Defn = tswitch
1277 }
1278
1279
1280
1281
1282 body := clause.Body
1283 for len(body) > 0 {
1284 if _, ok := body[len(body)-1].(*syntax.EmptyStmt); !ok {
1285 break
1286 }
1287 body = body[:len(body)-1]
1288 }
1289
1290 n.Body = p.stmtsFall(body, true)
1291 if l := len(n.Body); l > 0 && n.Body[l-1].Op() == ir.OFALL {
1292 if tswitch != nil {
1293 base.Errorf("cannot fallthrough in type switch")
1294 }
1295 if i+1 == len(clauses) {
1296 base.Errorf("cannot fallthrough final case in switch")
1297 }
1298 }
1299
1300 nodes = append(nodes, n)
1301 }
1302 if len(clauses) > 0 {
1303 p.closeScope(rbrace)
1304 }
1305 return nodes
1306 }
1307
1308 func (p *noder) selectStmt(stmt *syntax.SelectStmt) ir.Node {
1309 return ir.NewSelectStmt(p.pos(stmt), p.commClauses(stmt.Body, stmt.Rbrace))
1310 }
1311
1312 func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*ir.CommClause {
1313 nodes := make([]*ir.CommClause, len(clauses))
1314 for i, clause := range clauses {
1315 p.setlineno(clause)
1316 if i > 0 {
1317 p.closeScope(clause.Pos())
1318 }
1319 p.openScope(clause.Pos())
1320
1321 nodes[i] = ir.NewCommStmt(p.pos(clause), p.stmt(clause.Comm), p.stmts(clause.Body))
1322 }
1323 if len(clauses) > 0 {
1324 p.closeScope(rbrace)
1325 }
1326 return nodes
1327 }
1328
1329 func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) ir.Node {
1330 sym := p.name(label.Label)
1331 lhs := ir.NewLabelStmt(p.pos(label), sym)
1332
1333 var ls ir.Node
1334 if label.Stmt != nil {
1335 ls = p.stmtFall(label.Stmt, fallOK)
1336
1337 if ls != nil {
1338 switch ls.Op() {
1339 case ir.OFOR:
1340 ls := ls.(*ir.ForStmt)
1341 ls.Label = sym
1342 case ir.ORANGE:
1343 ls := ls.(*ir.RangeStmt)
1344 ls.Label = sym
1345 case ir.OSWITCH:
1346 ls := ls.(*ir.SwitchStmt)
1347 ls.Label = sym
1348 case ir.OSELECT:
1349 ls := ls.(*ir.SelectStmt)
1350 ls.Label = sym
1351 }
1352 }
1353 }
1354
1355 l := []ir.Node{lhs}
1356 if ls != nil {
1357 if ls.Op() == ir.OBLOCK {
1358 ls := ls.(*ir.BlockStmt)
1359 l = append(l, ls.List...)
1360 } else {
1361 l = append(l, ls)
1362 }
1363 }
1364 return ir.NewBlockStmt(src.NoXPos, l)
1365 }
1366
1367 var unOps = [...]ir.Op{
1368 syntax.Recv: ir.ORECV,
1369 syntax.Mul: ir.ODEREF,
1370 syntax.And: ir.OADDR,
1371
1372 syntax.Not: ir.ONOT,
1373 syntax.Xor: ir.OBITNOT,
1374 syntax.Add: ir.OPLUS,
1375 syntax.Sub: ir.ONEG,
1376 }
1377
1378 func (p *noder) unOp(op syntax.Operator) ir.Op {
1379 if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 {
1380 panic("invalid Operator")
1381 }
1382 return unOps[op]
1383 }
1384
1385 var binOps = [...]ir.Op{
1386 syntax.OrOr: ir.OOROR,
1387 syntax.AndAnd: ir.OANDAND,
1388
1389 syntax.Eql: ir.OEQ,
1390 syntax.Neq: ir.ONE,
1391 syntax.Lss: ir.OLT,
1392 syntax.Leq: ir.OLE,
1393 syntax.Gtr: ir.OGT,
1394 syntax.Geq: ir.OGE,
1395
1396 syntax.Add: ir.OADD,
1397 syntax.Sub: ir.OSUB,
1398 syntax.Or: ir.OOR,
1399 syntax.Xor: ir.OXOR,
1400
1401 syntax.Mul: ir.OMUL,
1402 syntax.Div: ir.ODIV,
1403 syntax.Rem: ir.OMOD,
1404 syntax.And: ir.OAND,
1405 syntax.AndNot: ir.OANDNOT,
1406 syntax.Shl: ir.OLSH,
1407 syntax.Shr: ir.ORSH,
1408 }
1409
1410 func (p *noder) binOp(op syntax.Operator) ir.Op {
1411 if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 {
1412 panic("invalid Operator")
1413 }
1414 return binOps[op]
1415 }
1416
1417
1418
1419 func checkLangCompat(lit *syntax.BasicLit) {
1420 s := lit.Value
1421 if len(s) <= 2 || types.AllowsGoVersion(types.LocalPkg, 1, 13) {
1422 return
1423 }
1424
1425 if strings.Contains(s, "_") {
1426 base.ErrorfVers("go1.13", "underscores in numeric literals")
1427 return
1428 }
1429 if s[0] != '0' {
1430 return
1431 }
1432 radix := s[1]
1433 if radix == 'b' || radix == 'B' {
1434 base.ErrorfVers("go1.13", "binary literals")
1435 return
1436 }
1437 if radix == 'o' || radix == 'O' {
1438 base.ErrorfVers("go1.13", "0o/0O-style octal literals")
1439 return
1440 }
1441 if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
1442 base.ErrorfVers("go1.13", "hexadecimal floating-point literals")
1443 }
1444 }
1445
1446 func (p *noder) basicLit(lit *syntax.BasicLit) constant.Value {
1447
1448
1449
1450
1451 if lit.Bad {
1452 return constant.MakeUnknown()
1453 }
1454
1455 switch lit.Kind {
1456 case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
1457 checkLangCompat(lit)
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467 const limit = 10000
1468 if len(lit.Value) > limit {
1469 p.errorAt(lit.Pos(), "excessively long constant: %s... (%d chars)", lit.Value[:10], len(lit.Value))
1470 return constant.MakeUnknown()
1471 }
1472 }
1473
1474 v := constant.MakeFromLiteral(lit.Value, tokenForLitKind[lit.Kind], 0)
1475 if v.Kind() == constant.Unknown {
1476
1477 p.errorAt(lit.Pos(), "malformed constant: %s", lit.Value)
1478 }
1479
1480 return v
1481 }
1482
1483 var tokenForLitKind = [...]token.Token{
1484 syntax.IntLit: token.INT,
1485 syntax.RuneLit: token.CHAR,
1486 syntax.FloatLit: token.FLOAT,
1487 syntax.ImagLit: token.IMAG,
1488 syntax.StringLit: token.STRING,
1489 }
1490
1491 func (p *noder) name(name *syntax.Name) *types.Sym {
1492 return typecheck.Lookup(name.Value)
1493 }
1494
1495 func (p *noder) mkname(name *syntax.Name) ir.Node {
1496
1497 return mkname(p.name(name))
1498 }
1499
1500 func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node {
1501
1502
1503 switch x.Op() {
1504 case ir.OTYPE, ir.OLITERAL:
1505 if x.Sym() == nil {
1506 break
1507 }
1508 fallthrough
1509 case ir.ONAME, ir.ONONAME, ir.OPACK:
1510 p := ir.NewParenExpr(p.pos(n), x)
1511 p.SetImplicit(true)
1512 return p
1513 }
1514 return x
1515 }
1516
1517 func (p *noder) setlineno(n syntax.Node) {
1518 if n != nil {
1519 base.Pos = p.pos(n)
1520 }
1521 }
1522
1523
1524 func (p *noder) error(err error) {
1525 p.err <- err.(syntax.Error)
1526 }
1527
1528
1529
1530 var allowedStdPragmas = map[string]bool{
1531 "go:cgo_export_static": true,
1532 "go:cgo_export_dynamic": true,
1533 "go:cgo_import_static": true,
1534 "go:cgo_import_dynamic": true,
1535 "go:cgo_ldflag": true,
1536 "go:cgo_dynamic_linker": true,
1537 "go:embed": true,
1538 "go:generate": true,
1539 }
1540
1541
1542 type pragmas struct {
1543 Flag ir.PragmaFlag
1544 Pos []pragmaPos
1545 Embeds []pragmaEmbed
1546 }
1547
1548 type pragmaPos struct {
1549 Flag ir.PragmaFlag
1550 Pos syntax.Pos
1551 }
1552
1553 type pragmaEmbed struct {
1554 Pos syntax.Pos
1555 Patterns []string
1556 }
1557
1558 func (p *noder) checkUnused(pragma *pragmas) {
1559 for _, pos := range pragma.Pos {
1560 if pos.Flag&pragma.Flag != 0 {
1561 p.errorAt(pos.Pos, "misplaced compiler directive")
1562 }
1563 }
1564 if len(pragma.Embeds) > 0 {
1565 for _, e := range pragma.Embeds {
1566 p.errorAt(e.Pos, "misplaced go:embed directive")
1567 }
1568 }
1569 }
1570
1571 func (p *noder) checkUnusedDuringParse(pragma *pragmas) {
1572 for _, pos := range pragma.Pos {
1573 if pos.Flag&pragma.Flag != 0 {
1574 p.error(syntax.Error{Pos: pos.Pos, Msg: "misplaced compiler directive"})
1575 }
1576 }
1577 if len(pragma.Embeds) > 0 {
1578 for _, e := range pragma.Embeds {
1579 p.error(syntax.Error{Pos: e.Pos, Msg: "misplaced go:embed directive"})
1580 }
1581 }
1582 }
1583
1584
1585 func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.Pragma) syntax.Pragma {
1586 pragma, _ := old.(*pragmas)
1587 if pragma == nil {
1588 pragma = new(pragmas)
1589 }
1590
1591 if text == "" {
1592
1593 p.checkUnusedDuringParse(pragma)
1594 return nil
1595 }
1596
1597 if strings.HasPrefix(text, "line ") {
1598
1599 panic("unreachable")
1600 }
1601
1602 if !blankLine {
1603
1604 p.error(syntax.Error{Pos: pos, Msg: "misplaced compiler directive"})
1605 return pragma
1606 }
1607
1608 switch {
1609 case strings.HasPrefix(text, "go:linkname "):
1610 f := strings.Fields(text)
1611 if !(2 <= len(f) && len(f) <= 3) {
1612 p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname [linkname]"})
1613 break
1614 }
1615
1616
1617
1618
1619
1620 var target string
1621 if len(f) == 3 {
1622 target = f[2]
1623 } else if base.Ctxt.Pkgpath != "" {
1624
1625
1626 target = objabi.PathToPrefix(base.Ctxt.Pkgpath) + "." + f[1]
1627 } else {
1628 p.error(syntax.Error{Pos: pos, Msg: "//go:linkname requires linkname argument or -p compiler flag"})
1629 break
1630 }
1631 p.linknames = append(p.linknames, linkname{pos, f[1], target})
1632
1633 case text == "go:embed", strings.HasPrefix(text, "go:embed "):
1634 args, err := parseGoEmbed(text[len("go:embed"):])
1635 if err != nil {
1636 p.error(syntax.Error{Pos: pos, Msg: err.Error()})
1637 }
1638 if len(args) == 0 {
1639 p.error(syntax.Error{Pos: pos, Msg: "usage: //go:embed pattern..."})
1640 break
1641 }
1642 pragma.Embeds = append(pragma.Embeds, pragmaEmbed{pos, args})
1643
1644 case strings.HasPrefix(text, "go:cgo_import_dynamic "):
1645
1646
1647 fields := pragmaFields(text)
1648 if len(fields) >= 4 {
1649 lib := strings.Trim(fields[3], `"`)
1650 if lib != "" && !safeArg(lib) && !isCgoGeneratedFile(pos) {
1651 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("invalid library name %q in cgo_import_dynamic directive", lib)})
1652 }
1653 p.pragcgo(pos, text)
1654 pragma.Flag |= pragmaFlag("go:cgo_import_dynamic")
1655 break
1656 }
1657 fallthrough
1658 case strings.HasPrefix(text, "go:cgo_"):
1659
1660
1661
1662 if !isCgoGeneratedFile(pos) && !base.Flag.Std {
1663 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
1664 }
1665 p.pragcgo(pos, text)
1666 fallthrough
1667 default:
1668 verb := text
1669 if i := strings.Index(text, " "); i >= 0 {
1670 verb = verb[:i]
1671 }
1672 flag := pragmaFlag(verb)
1673 const runtimePragmas = ir.Systemstack | ir.Nowritebarrier | ir.Nowritebarrierrec | ir.Yeswritebarrierrec
1674 if !base.Flag.CompilingRuntime && flag&runtimePragmas != 0 {
1675 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)})
1676 }
1677 if flag == 0 && !allowedStdPragmas[verb] && base.Flag.Std {
1678 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)})
1679 }
1680 pragma.Flag |= flag
1681 pragma.Pos = append(pragma.Pos, pragmaPos{flag, pos})
1682 }
1683
1684 return pragma
1685 }
1686
1687
1688
1689
1690
1691
1692
1693 func isCgoGeneratedFile(pos syntax.Pos) bool {
1694 return strings.HasPrefix(filepath.Base(filepath.Clean(fileh(pos.Base().Filename()))), "_cgo_")
1695 }
1696
1697
1698
1699
1700
1701 func safeArg(name string) bool {
1702 if name == "" {
1703 return false
1704 }
1705 c := name[0]
1706 return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
1707 }
1708
1709 func mkname(sym *types.Sym) ir.Node {
1710 n := oldname(sym)
1711 if n.Name() != nil && n.Name().PkgName != nil {
1712 n.Name().PkgName.Used = true
1713 }
1714 return n
1715 }
1716
1717
1718
1719
1720 func parseGoEmbed(args string) ([]string, error) {
1721 var list []string
1722 for args = strings.TrimSpace(args); args != ""; args = strings.TrimSpace(args) {
1723 var path string
1724 Switch:
1725 switch args[0] {
1726 default:
1727 i := len(args)
1728 for j, c := range args {
1729 if unicode.IsSpace(c) {
1730 i = j
1731 break
1732 }
1733 }
1734 path = args[:i]
1735 args = args[i:]
1736
1737 case '`':
1738 i := strings.Index(args[1:], "`")
1739 if i < 0 {
1740 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1741 }
1742 path = args[1 : 1+i]
1743 args = args[1+i+1:]
1744
1745 case '"':
1746 i := 1
1747 for ; i < len(args); i++ {
1748 if args[i] == '\\' {
1749 i++
1750 continue
1751 }
1752 if args[i] == '"' {
1753 q, err := strconv.Unquote(args[:i+1])
1754 if err != nil {
1755 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args[:i+1])
1756 }
1757 path = q
1758 args = args[i+1:]
1759 break Switch
1760 }
1761 }
1762 if i >= len(args) {
1763 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1764 }
1765 }
1766
1767 if args != "" {
1768 r, _ := utf8.DecodeRuneInString(args)
1769 if !unicode.IsSpace(r) {
1770 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1771 }
1772 }
1773 list = append(list, path)
1774 }
1775 return list, nil
1776 }
1777
1778 func fakeRecv() *ir.Field {
1779 return ir.NewField(base.Pos, nil, nil, types.FakeRecvType())
1780 }
1781
1782 func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
1783 xtype := p.typeExpr(expr.Type)
1784
1785 fn := ir.NewFunc(p.pos(expr))
1786 fn.SetIsHiddenClosure(ir.CurFunc != nil)
1787
1788 fn.Nname = ir.NewNameAt(p.pos(expr), ir.BlankNode.Sym())
1789 fn.Nname.Func = fn
1790 fn.Nname.Ntype = xtype
1791 fn.Nname.Defn = fn
1792
1793 clo := ir.NewClosureExpr(p.pos(expr), fn)
1794 fn.OClosure = clo
1795
1796 p.funcBody(fn, expr.Body)
1797
1798 ir.FinishCaptureNames(base.Pos, ir.CurFunc, fn)
1799
1800 return clo
1801 }
1802
1803
1804
1805
1806
1807 var renameinitgen int
1808
1809 func renameinit() *types.Sym {
1810 s := typecheck.LookupNum("init.", renameinitgen)
1811 renameinitgen++
1812 return s
1813 }
1814
1815
1816
1817
1818
1819 func oldname(s *types.Sym) ir.Node {
1820 if s.Pkg != types.LocalPkg {
1821 return ir.NewIdent(base.Pos, s)
1822 }
1823
1824 n := ir.AsNode(s.Def)
1825 if n == nil {
1826
1827
1828
1829 return ir.NewIdent(base.Pos, s)
1830 }
1831
1832 if n, ok := n.(*ir.Name); ok {
1833
1834
1835
1836
1837 return ir.CaptureName(base.Pos, ir.CurFunc, n)
1838 }
1839
1840 return n
1841 }
1842
1843 func varEmbed(makeXPos func(syntax.Pos) src.XPos, name *ir.Name, decl *syntax.VarDecl, pragma *pragmas, haveEmbed bool) {
1844 if pragma.Embeds == nil {
1845 return
1846 }
1847
1848 pragmaEmbeds := pragma.Embeds
1849 pragma.Embeds = nil
1850 pos := makeXPos(pragmaEmbeds[0].Pos)
1851
1852 if !haveEmbed {
1853 base.ErrorfAt(pos, "go:embed only allowed in Go files that import \"embed\"")
1854 return
1855 }
1856 if len(decl.NameList) > 1 {
1857 base.ErrorfAt(pos, "go:embed cannot apply to multiple vars")
1858 return
1859 }
1860 if decl.Values != nil {
1861 base.ErrorfAt(pos, "go:embed cannot apply to var with initializer")
1862 return
1863 }
1864 if decl.Type == nil {
1865
1866 base.ErrorfAt(pos, "go:embed cannot apply to var without type")
1867 return
1868 }
1869 if typecheck.DeclContext != ir.PEXTERN {
1870 base.ErrorfAt(pos, "go:embed cannot apply to var inside func")
1871 return
1872 }
1873
1874 var embeds []ir.Embed
1875 for _, e := range pragmaEmbeds {
1876 embeds = append(embeds, ir.Embed{Pos: makeXPos(e.Pos), Patterns: e.Patterns})
1877 }
1878 typecheck.Target.Embeds = append(typecheck.Target.Embeds, name)
1879 name.Embed = &embeds
1880 }
1881
View as plain text