]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/gc/noder.go
[dev.typeparams] all: merge dev.regabi (6d03cde) into dev.typeparams
[gostls13.git] / src / cmd / compile / internal / gc / noder.go
1 // Copyright 2016 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 gc
6
7 import (
8         "fmt"
9         "go/constant"
10         "go/token"
11         "io"
12         "os"
13         "path/filepath"
14         "runtime"
15         "strconv"
16         "strings"
17         "unicode"
18         "unicode/utf8"
19
20         "cmd/compile/internal/base"
21         "cmd/compile/internal/importer"
22         "cmd/compile/internal/ir"
23         "cmd/compile/internal/syntax"
24         "cmd/compile/internal/types"
25         "cmd/compile/internal/types2"
26         "cmd/internal/objabi"
27         "cmd/internal/src"
28 )
29
30 // parseFiles concurrently parses files into *syntax.File structures.
31 // Each declaration in every *syntax.File is converted to a syntax tree
32 // and its root represented by *Node is appended to Target.Decls.
33 // Returns the total count of parsed lines.
34 func parseFiles(filenames []string) (lines uint) {
35         noders := make([]*noder, 0, len(filenames))
36         // Limit the number of simultaneously open files.
37         sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
38
39         for _, filename := range filenames {
40                 p := &noder{
41                         basemap:     make(map[*syntax.PosBase]*src.PosBase),
42                         err:         make(chan syntax.Error),
43                         trackScopes: base.Flag.Dwarf,
44                 }
45                 noders = append(noders, p)
46
47                 go func(filename string) {
48                         sem <- struct{}{}
49                         defer func() { <-sem }()
50                         defer close(p.err)
51                         fbase := syntax.NewFileBase(filename)
52
53                         f, err := os.Open(filename)
54                         if err != nil {
55                                 p.error(syntax.Error{Msg: err.Error()})
56                                 return
57                         }
58                         defer f.Close()
59
60                         mode := syntax.CheckBranches
61                         if base.Flag.G != 0 {
62                                 mode |= syntax.AllowGenerics
63                         }
64                         p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error
65                 }(filename)
66         }
67
68         // generic noding phase (using new typechecker)
69         if base.Flag.G != 0 {
70                 // setup and syntax error reporting
71                 nodersmap := make(map[string]*noder)
72                 var files []*syntax.File
73                 for _, p := range noders {
74                         for e := range p.err {
75                                 p.errorAt(e.Pos, "%s", e.Msg)
76                         }
77
78                         nodersmap[p.file.Pos().RelFilename()] = p
79                         files = append(files, p.file)
80                         lines += p.file.EOF.Line()
81
82                 }
83                 if base.SyntaxErrors() != 0 {
84                         base.ErrorExit()
85                 }
86
87                 // typechecking
88                 conf := types2.Config{
89                         InferFromConstraints:  true,
90                         IgnoreBranches:        true, // parser already checked via syntax.CheckBranches mode
91                         CompilerErrorMessages: true, // use error strings matching existing compiler errors
92                         Error: func(err error) {
93                                 terr := err.(types2.Error)
94                                 if len(terr.Msg) > 0 && terr.Msg[0] == '\t' {
95                                         // types2 reports error clarifications via separate
96                                         // error messages which are indented with a tab.
97                                         // Ignore them to satisfy tools and tests that expect
98                                         // only one error in such cases.
99                                         // TODO(gri) Need to adjust error reporting in types2.
100                                         return
101                                 }
102                                 p := nodersmap[terr.Pos.RelFilename()]
103                                 base.ErrorfAt(p.makeXPos(terr.Pos), "%s", terr.Msg)
104                         },
105                         Importer: &gcimports{
106                                 packages: make(map[string]*types2.Package),
107                                 lookup: func(path string) (io.ReadCloser, error) {
108                                         file, ok := findpkg(path)
109                                         if !ok {
110                                                 return nil, fmt.Errorf("can't find import: %q", path)
111                                         }
112                                         return os.Open(file)
113                                 },
114                         },
115                 }
116                 info := types2.Info{
117                         Types:      make(map[syntax.Expr]types2.TypeAndValue),
118                         Defs:       make(map[*syntax.Name]types2.Object),
119                         Uses:       make(map[*syntax.Name]types2.Object),
120                         Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
121                         // expand as needed
122                 }
123                 conf.Check(base.Ctxt.Pkgpath, files, &info)
124                 base.ExitIfErrors()
125                 if base.Flag.G < 2 {
126                         return
127                 }
128
129                 // noding
130                 for _, p := range noders {
131                         // errors have already been reported
132
133                         p.typeInfo = &info
134                         p.node()
135                         lines += p.file.EOF.Line()
136                         p.file = nil // release memory
137                         base.ExitIfErrors()
138
139                         // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
140                         testdclstack()
141                 }
142
143                 types.LocalPkg.Height = myheight
144                 return
145         }
146
147         // traditional (non-generic) noding phase
148         for _, p := range noders {
149                 for e := range p.err {
150                         p.errorAt(e.Pos, "%s", e.Msg)
151                 }
152
153                 p.node()
154                 lines += p.file.EOF.Line()
155                 p.file = nil // release memory
156                 if base.SyntaxErrors() != 0 {
157                         base.ErrorExit()
158                 }
159
160                 // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
161                 testdclstack()
162         }
163
164         for _, p := range noders {
165                 p.processPragmas()
166         }
167
168         types.LocalPkg.Height = myheight
169         return
170 }
171
172 // Temporary import helper to get type2-based type-checking going.
173 type gcimports struct {
174         packages map[string]*types2.Package
175         lookup   func(path string) (io.ReadCloser, error)
176 }
177
178 func (m *gcimports) Import(path string) (*types2.Package, error) {
179         return m.ImportFrom(path, "" /* no vendoring */, 0)
180 }
181
182 func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*types2.Package, error) {
183         if mode != 0 {
184                 panic("mode must be 0")
185         }
186         return importer.Import(m.packages, path, srcDir, m.lookup)
187 }
188
189 // makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase.
190 func (p *noder) makeSrcPosBase(b0 *syntax.PosBase) *src.PosBase {
191         // fast path: most likely PosBase hasn't changed
192         if p.basecache.last == b0 {
193                 return p.basecache.base
194         }
195
196         b1, ok := p.basemap[b0]
197         if !ok {
198                 fn := b0.Filename()
199                 if b0.IsFileBase() {
200                         b1 = src.NewFileBase(fn, absFilename(fn))
201                 } else {
202                         // line directive base
203                         p0 := b0.Pos()
204                         p0b := p0.Base()
205                         if p0b == b0 {
206                                 panic("infinite recursion in makeSrcPosBase")
207                         }
208                         p1 := src.MakePos(p.makeSrcPosBase(p0b), p0.Line(), p0.Col())
209                         b1 = src.NewLinePragmaBase(p1, fn, fileh(fn), b0.Line(), b0.Col())
210                 }
211                 p.basemap[b0] = b1
212         }
213
214         // update cache
215         p.basecache.last = b0
216         p.basecache.base = b1
217
218         return b1
219 }
220
221 func (p *noder) makeXPos(pos syntax.Pos) (_ src.XPos) {
222         return base.Ctxt.PosTable.XPos(src.MakePos(p.makeSrcPosBase(pos.Base()), pos.Line(), pos.Col()))
223 }
224
225 func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
226         base.ErrorfAt(p.makeXPos(pos), format, args...)
227 }
228
229 // TODO(gri) Can we eliminate fileh in favor of absFilename?
230 func fileh(name string) string {
231         return objabi.AbsFile("", name, base.Flag.TrimPath)
232 }
233
234 func absFilename(name string) string {
235         return objabi.AbsFile(base.Ctxt.Pathname, name, base.Flag.TrimPath)
236 }
237
238 // noder transforms package syntax's AST into a Node tree.
239 type noder struct {
240         basemap   map[*syntax.PosBase]*src.PosBase
241         basecache struct {
242                 last *syntax.PosBase
243                 base *src.PosBase
244         }
245
246         file           *syntax.File
247         linknames      []linkname
248         pragcgobuf     [][]string
249         err            chan syntax.Error
250         scope          ir.ScopeID
251         importedUnsafe bool
252         importedEmbed  bool
253
254         // scopeVars is a stack tracking the number of variables declared in the
255         // current function at the moment each open scope was opened.
256         trackScopes bool
257         scopeVars   []int
258
259         // typeInfo provides access to the type information computed by the new
260         // typechecker. It is only present if -G is set, and all noders point to
261         // the same types.Info. For now this is a local field, if need be we can
262         // make it global.
263         typeInfo *types2.Info
264
265         lastCloseScopePos syntax.Pos
266 }
267
268 // For now we provide these basic accessors to get to type and object
269 // information of expression nodes during noding. Eventually we will
270 // attach this information directly to the syntax tree which should
271 // simplify access and make it more efficient as well.
272
273 // typ returns the type and value information for the given expression.
274 func (p *noder) typ(x syntax.Expr) types2.TypeAndValue {
275         return p.typeInfo.Types[x]
276 }
277
278 // def returns the object for the given name in its declaration.
279 func (p *noder) def(x *syntax.Name) types2.Object {
280         return p.typeInfo.Defs[x]
281 }
282
283 // use returns the object for the given name outside its declaration.
284 func (p *noder) use(x *syntax.Name) types2.Object {
285         return p.typeInfo.Uses[x]
286 }
287
288 // sel returns the selection information for the given selector expression.
289 func (p *noder) sel(x *syntax.SelectorExpr) *types2.Selection {
290         return p.typeInfo.Selections[x]
291 }
292
293 func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
294         oldScope := p.scope
295         p.scope = 0
296         funchdr(fn)
297
298         if block != nil {
299                 body := p.stmts(block.List)
300                 if body == nil {
301                         body = []ir.Node{ir.Nod(ir.OBLOCK, nil, nil)}
302                 }
303                 fn.PtrBody().Set(body)
304
305                 base.Pos = p.makeXPos(block.Rbrace)
306                 fn.Endlineno = base.Pos
307         }
308
309         funcbody()
310         p.scope = oldScope
311 }
312
313 func (p *noder) openScope(pos syntax.Pos) {
314         types.Markdcl()
315
316         if p.trackScopes {
317                 Curfn.Parents = append(Curfn.Parents, p.scope)
318                 p.scopeVars = append(p.scopeVars, len(Curfn.Dcl))
319                 p.scope = ir.ScopeID(len(Curfn.Parents))
320
321                 p.markScope(pos)
322         }
323 }
324
325 func (p *noder) closeScope(pos syntax.Pos) {
326         p.lastCloseScopePos = pos
327         types.Popdcl()
328
329         if p.trackScopes {
330                 scopeVars := p.scopeVars[len(p.scopeVars)-1]
331                 p.scopeVars = p.scopeVars[:len(p.scopeVars)-1]
332                 if scopeVars == len(Curfn.Dcl) {
333                         // no variables were declared in this scope, so we can retract it.
334
335                         if int(p.scope) != len(Curfn.Parents) {
336                                 base.Fatalf("scope tracking inconsistency, no variables declared but scopes were not retracted")
337                         }
338
339                         p.scope = Curfn.Parents[p.scope-1]
340                         Curfn.Parents = Curfn.Parents[:len(Curfn.Parents)-1]
341
342                         nmarks := len(Curfn.Marks)
343                         Curfn.Marks[nmarks-1].Scope = p.scope
344                         prevScope := ir.ScopeID(0)
345                         if nmarks >= 2 {
346                                 prevScope = Curfn.Marks[nmarks-2].Scope
347                         }
348                         if Curfn.Marks[nmarks-1].Scope == prevScope {
349                                 Curfn.Marks = Curfn.Marks[:nmarks-1]
350                         }
351                         return
352                 }
353
354                 p.scope = Curfn.Parents[p.scope-1]
355
356                 p.markScope(pos)
357         }
358 }
359
360 func (p *noder) markScope(pos syntax.Pos) {
361         xpos := p.makeXPos(pos)
362         if i := len(Curfn.Marks); i > 0 && Curfn.Marks[i-1].Pos == xpos {
363                 Curfn.Marks[i-1].Scope = p.scope
364         } else {
365                 Curfn.Marks = append(Curfn.Marks, ir.Mark{Pos: xpos, Scope: p.scope})
366         }
367 }
368
369 // closeAnotherScope is like closeScope, but it reuses the same mark
370 // position as the last closeScope call. This is useful for "for" and
371 // "if" statements, as their implicit blocks always end at the same
372 // position as an explicit block.
373 func (p *noder) closeAnotherScope() {
374         p.closeScope(p.lastCloseScopePos)
375 }
376
377 // linkname records a //go:linkname directive.
378 type linkname struct {
379         pos    syntax.Pos
380         local  string
381         remote string
382 }
383
384 func (p *noder) node() {
385         types.Block = 1
386         p.importedUnsafe = false
387         p.importedEmbed = false
388
389         p.setlineno(p.file.PkgName)
390         mkpackage(p.file.PkgName.Value)
391
392         if pragma, ok := p.file.Pragma.(*Pragma); ok {
393                 pragma.Flag &^= ir.GoBuildPragma
394                 p.checkUnused(pragma)
395         }
396
397         Target.Decls = append(Target.Decls, p.decls(p.file.DeclList)...)
398
399         base.Pos = src.NoXPos
400         clearImports()
401 }
402
403 func (p *noder) processPragmas() {
404         for _, l := range p.linknames {
405                 if !p.importedUnsafe {
406                         p.errorAt(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
407                         continue
408                 }
409                 n := ir.AsNode(lookup(l.local).Def)
410                 if n == nil || n.Op() != ir.ONAME {
411                         // TODO(mdempsky): Change to p.errorAt before Go 1.17 release.
412                         // base.WarnfAt(p.makeXPos(l.pos), "//go:linkname must refer to declared function or variable (will be an error in Go 1.17)")
413                         continue
414                 }
415                 if n.Sym().Linkname != "" {
416                         p.errorAt(l.pos, "duplicate //go:linkname for %s", l.local)
417                         continue
418                 }
419                 n.Sym().Linkname = l.remote
420         }
421         Target.CgoPragmas = append(Target.CgoPragmas, p.pragcgobuf...)
422 }
423
424 func (p *noder) decls(decls []syntax.Decl) (l []ir.Node) {
425         var cs constState
426
427         for _, decl := range decls {
428                 p.setlineno(decl)
429                 switch decl := decl.(type) {
430                 case *syntax.ImportDecl:
431                         p.importDecl(decl)
432
433                 case *syntax.VarDecl:
434                         l = append(l, p.varDecl(decl)...)
435
436                 case *syntax.ConstDecl:
437                         l = append(l, p.constDecl(decl, &cs)...)
438
439                 case *syntax.TypeDecl:
440                         l = append(l, p.typeDecl(decl))
441
442                 case *syntax.FuncDecl:
443                         l = append(l, p.funcDecl(decl))
444
445                 default:
446                         panic("unhandled Decl")
447                 }
448         }
449
450         return
451 }
452
453 func (p *noder) importDecl(imp *syntax.ImportDecl) {
454         if imp.Path == nil || imp.Path.Bad {
455                 return // avoid follow-on errors if there was a syntax error
456         }
457
458         if pragma, ok := imp.Pragma.(*Pragma); ok {
459                 p.checkUnused(pragma)
460         }
461
462         ipkg := importfile(p.basicLit(imp.Path))
463         if ipkg == nil {
464                 if base.Errors() == 0 {
465                         base.Fatalf("phase error in import")
466                 }
467                 return
468         }
469
470         if ipkg == unsafepkg {
471                 p.importedUnsafe = true
472         }
473         if ipkg.Path == "embed" {
474                 p.importedEmbed = true
475         }
476
477         if !ipkg.Direct {
478                 Target.Imports = append(Target.Imports, ipkg)
479         }
480         ipkg.Direct = true
481
482         var my *types.Sym
483         if imp.LocalPkgName != nil {
484                 my = p.name(imp.LocalPkgName)
485         } else {
486                 my = lookup(ipkg.Name)
487         }
488
489         pack := ir.NewPkgName(p.pos(imp), my, ipkg)
490
491         switch my.Name {
492         case ".":
493                 importDot(pack)
494                 return
495         case "init":
496                 base.ErrorfAt(pack.Pos(), "cannot import package as init - init must be a func")
497                 return
498         case "_":
499                 return
500         }
501         if my.Def != nil {
502                 redeclare(pack.Pos(), my, "as imported package name")
503         }
504         my.Def = pack
505         my.Lastlineno = pack.Pos()
506         my.Block = 1 // at top level
507 }
508
509 func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
510         names := p.declNames(ir.ONAME, decl.NameList)
511         typ := p.typeExprOrNil(decl.Type)
512
513         var exprs []ir.Node
514         if decl.Values != nil {
515                 exprs = p.exprList(decl.Values)
516         }
517
518         if pragma, ok := decl.Pragma.(*Pragma); ok {
519                 if len(pragma.Embeds) > 0 {
520                         if !p.importedEmbed {
521                                 // This check can't be done when building the list pragma.Embeds
522                                 // because that list is created before the noder starts walking over the file,
523                                 // so at that point it hasn't seen the imports.
524                                 // We're left to check now, just before applying the //go:embed lines.
525                                 for _, e := range pragma.Embeds {
526                                         p.errorAt(e.Pos, "//go:embed only allowed in Go files that import \"embed\"")
527                                 }
528                         } else {
529                                 exprs = varEmbed(p, names, typ, exprs, pragma.Embeds)
530                         }
531                         pragma.Embeds = nil
532                 }
533                 p.checkUnused(pragma)
534         }
535
536         p.setlineno(decl)
537         return variter(names, typ, exprs)
538 }
539
540 // constState tracks state between constant specifiers within a
541 // declaration group. This state is kept separate from noder so nested
542 // constant declarations are handled correctly (e.g., issue 15550).
543 type constState struct {
544         group  *syntax.Group
545         typ    ir.Ntype
546         values []ir.Node
547         iota   int64
548 }
549
550 func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node {
551         if decl.Group == nil || decl.Group != cs.group {
552                 *cs = constState{
553                         group: decl.Group,
554                 }
555         }
556
557         if pragma, ok := decl.Pragma.(*Pragma); ok {
558                 p.checkUnused(pragma)
559         }
560
561         names := p.declNames(ir.OLITERAL, decl.NameList)
562         typ := p.typeExprOrNil(decl.Type)
563
564         var values []ir.Node
565         if decl.Values != nil {
566                 values = p.exprList(decl.Values)
567                 cs.typ, cs.values = typ, values
568         } else {
569                 if typ != nil {
570                         base.Errorf("const declaration cannot have type without expression")
571                 }
572                 typ, values = cs.typ, cs.values
573         }
574
575         nn := make([]ir.Node, 0, len(names))
576         for i, n := range names {
577                 if i >= len(values) {
578                         base.Errorf("missing value in const declaration")
579                         break
580                 }
581                 v := values[i]
582                 if decl.Values == nil {
583                         v = ir.DeepCopy(n.Pos(), v)
584                 }
585                 declare(n, dclcontext)
586
587                 n.Ntype = typ
588                 n.Defn = v
589                 n.SetIota(cs.iota)
590
591                 nn = append(nn, p.nod(decl, ir.ODCLCONST, n, nil))
592         }
593
594         if len(values) > len(names) {
595                 base.Errorf("extra expression in const declaration")
596         }
597
598         cs.iota++
599
600         return nn
601 }
602
603 func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
604         n := p.declName(ir.OTYPE, decl.Name)
605         declare(n, dclcontext)
606
607         // decl.Type may be nil but in that case we got a syntax error during parsing
608         typ := p.typeExprOrNil(decl.Type)
609
610         n.Ntype = typ
611         n.SetAlias(decl.Alias)
612         if pragma, ok := decl.Pragma.(*Pragma); ok {
613                 if !decl.Alias {
614                         n.SetPragma(pragma.Flag & TypePragmas)
615                         pragma.Flag &^= TypePragmas
616                 }
617                 p.checkUnused(pragma)
618         }
619
620         nod := p.nod(decl, ir.ODCLTYPE, n, nil)
621         if n.Alias() && !langSupported(1, 9, types.LocalPkg) {
622                 base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
623         }
624         return nod
625 }
626
627 func (p *noder) declNames(op ir.Op, names []*syntax.Name) []*ir.Name {
628         nodes := make([]*ir.Name, 0, len(names))
629         for _, name := range names {
630                 nodes = append(nodes, p.declName(op, name))
631         }
632         return nodes
633 }
634
635 func (p *noder) declName(op ir.Op, name *syntax.Name) *ir.Name {
636         return ir.NewDeclNameAt(p.pos(name), op, p.name(name))
637 }
638
639 func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
640         name := p.name(fun.Name)
641         t := p.signature(fun.Recv, fun.Type)
642         f := ir.NewFunc(p.pos(fun))
643
644         if fun.Recv == nil {
645                 if name.Name == "init" {
646                         name = renameinit()
647                         if len(t.Params) > 0 || len(t.Results) > 0 {
648                                 base.ErrorfAt(f.Pos(), "func init must have no arguments and no return values")
649                         }
650                         Target.Inits = append(Target.Inits, f)
651                 }
652
653                 if types.LocalPkg.Name == "main" && name.Name == "main" {
654                         if len(t.Params) > 0 || len(t.Results) > 0 {
655                                 base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values")
656                         }
657                 }
658         } else {
659                 f.Shortname = name
660                 name = ir.BlankNode.Sym() // filled in by typecheckfunc
661         }
662
663         f.Nname = newFuncNameAt(p.pos(fun.Name), name, f)
664         f.Nname.Defn = f
665         f.Nname.Ntype = t
666
667         if pragma, ok := fun.Pragma.(*Pragma); ok {
668                 f.Pragma = pragma.Flag & FuncPragmas
669                 if pragma.Flag&ir.Systemstack != 0 && pragma.Flag&ir.Nosplit != 0 {
670                         base.ErrorfAt(f.Pos(), "go:nosplit and go:systemstack cannot be combined")
671                 }
672                 pragma.Flag &^= FuncPragmas
673                 p.checkUnused(pragma)
674         }
675
676         if fun.Recv == nil {
677                 declare(f.Nname, ir.PFUNC)
678         }
679
680         p.funcBody(f, fun.Body)
681
682         if fun.Body != nil {
683                 if f.Pragma&ir.Noescape != 0 {
684                         base.ErrorfAt(f.Pos(), "can only use //go:noescape with external func implementations")
685                 }
686         } else {
687                 if base.Flag.Complete || strings.HasPrefix(ir.FuncName(f), "init.") {
688                         // Linknamed functions are allowed to have no body. Hopefully
689                         // the linkname target has a body. See issue 23311.
690                         isLinknamed := false
691                         for _, n := range p.linknames {
692                                 if ir.FuncName(f) == n.local {
693                                         isLinknamed = true
694                                         break
695                                 }
696                         }
697                         if !isLinknamed {
698                                 base.ErrorfAt(f.Pos(), "missing function body")
699                         }
700                 }
701         }
702
703         return f
704 }
705
706 func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *ir.FuncType {
707         var rcvr *ir.Field
708         if recv != nil {
709                 rcvr = p.param(recv, false, false)
710         }
711         return ir.NewFuncType(p.pos(typ), rcvr,
712                 p.params(typ.ParamList, true),
713                 p.params(typ.ResultList, false))
714 }
715
716 func (p *noder) params(params []*syntax.Field, dddOk bool) []*ir.Field {
717         nodes := make([]*ir.Field, 0, len(params))
718         for i, param := range params {
719                 p.setlineno(param)
720                 nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))
721         }
722         return nodes
723 }
724
725 func (p *noder) param(param *syntax.Field, dddOk, final bool) *ir.Field {
726         var name *types.Sym
727         if param.Name != nil {
728                 name = p.name(param.Name)
729         }
730
731         typ := p.typeExpr(param.Type)
732         n := ir.NewField(p.pos(param), name, typ, nil)
733
734         // rewrite ...T parameter
735         if typ, ok := typ.(*ir.SliceType); ok && typ.DDD {
736                 if !dddOk {
737                         // We mark these as syntax errors to get automatic elimination
738                         // of multiple such errors per line (see ErrorfAt in subr.go).
739                         base.Errorf("syntax error: cannot use ... in receiver or result parameter list")
740                 } else if !final {
741                         if param.Name == nil {
742                                 base.Errorf("syntax error: cannot use ... with non-final parameter")
743                         } else {
744                                 p.errorAt(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value)
745                         }
746                 }
747                 typ.DDD = false
748                 n.IsDDD = true
749         }
750
751         return n
752 }
753
754 func (p *noder) exprList(expr syntax.Expr) []ir.Node {
755         if list, ok := expr.(*syntax.ListExpr); ok {
756                 return p.exprs(list.ElemList)
757         }
758         return []ir.Node{p.expr(expr)}
759 }
760
761 func (p *noder) exprs(exprs []syntax.Expr) []ir.Node {
762         nodes := make([]ir.Node, 0, len(exprs))
763         for _, expr := range exprs {
764                 nodes = append(nodes, p.expr(expr))
765         }
766         return nodes
767 }
768
769 func (p *noder) expr(expr syntax.Expr) ir.Node {
770         p.setlineno(expr)
771         switch expr := expr.(type) {
772         case nil, *syntax.BadExpr:
773                 return nil
774         case *syntax.Name:
775                 return p.mkname(expr)
776         case *syntax.BasicLit:
777                 n := ir.NewLiteral(p.basicLit(expr))
778                 if expr.Kind == syntax.RuneLit {
779                         n.SetType(types.UntypedRune)
780                 }
781                 n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error
782                 return n
783         case *syntax.CompositeLit:
784                 n := p.nod(expr, ir.OCOMPLIT, nil, nil)
785                 if expr.Type != nil {
786                         n.SetRight(p.expr(expr.Type))
787                 }
788                 l := p.exprs(expr.ElemList)
789                 for i, e := range l {
790                         l[i] = p.wrapname(expr.ElemList[i], e)
791                 }
792                 n.PtrList().Set(l)
793                 base.Pos = p.makeXPos(expr.Rbrace)
794                 return n
795         case *syntax.KeyValueExpr:
796                 // use position of expr.Key rather than of expr (which has position of ':')
797                 return p.nod(expr.Key, ir.OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
798         case *syntax.FuncLit:
799                 return p.funcLit(expr)
800         case *syntax.ParenExpr:
801                 return p.nod(expr, ir.OPAREN, p.expr(expr.X), nil)
802         case *syntax.SelectorExpr:
803                 // parser.new_dotname
804                 obj := p.expr(expr.X)
805                 if obj.Op() == ir.OPACK {
806                         pack := obj.(*ir.PkgName)
807                         pack.Used = true
808                         return importName(pack.Pkg.Lookup(expr.Sel.Value))
809                 }
810                 n := nodSym(ir.OXDOT, obj, p.name(expr.Sel))
811                 n.SetPos(p.pos(expr)) // lineno may have been changed by p.expr(expr.X)
812                 return n
813         case *syntax.IndexExpr:
814                 return p.nod(expr, ir.OINDEX, p.expr(expr.X), p.expr(expr.Index))
815         case *syntax.SliceExpr:
816                 op := ir.OSLICE
817                 if expr.Full {
818                         op = ir.OSLICE3
819                 }
820                 n := ir.NewSliceExpr(p.pos(expr), op, p.expr(expr.X))
821                 var index [3]ir.Node
822                 for i, x := range &expr.Index {
823                         if x != nil {
824                                 index[i] = p.expr(x)
825                         }
826                 }
827                 n.SetSliceBounds(index[0], index[1], index[2])
828                 return n
829         case *syntax.AssertExpr:
830                 return p.nod(expr, ir.ODOTTYPE, p.expr(expr.X), p.typeExpr(expr.Type))
831         case *syntax.Operation:
832                 if expr.Op == syntax.Add && expr.Y != nil {
833                         return p.sum(expr)
834                 }
835                 x := p.expr(expr.X)
836                 if expr.Y == nil {
837                         pos, op := p.pos(expr), p.unOp(expr.Op)
838                         switch op {
839                         case ir.OADDR:
840                                 return nodAddrAt(pos, x)
841                         case ir.ODEREF:
842                                 return ir.NewStarExpr(pos, x)
843                         }
844                         return ir.NewUnaryExpr(pos, op, x)
845                 }
846
847                 pos, op, y := p.pos(expr), p.binOp(expr.Op), p.expr(expr.Y)
848                 switch op {
849                 case ir.OANDAND, ir.OOROR:
850                         return ir.NewLogicalExpr(pos, op, x, y)
851                 }
852                 return ir.NewBinaryExpr(pos, op, x, y)
853         case *syntax.CallExpr:
854                 n := p.nod(expr, ir.OCALL, p.expr(expr.Fun), nil)
855                 n.PtrList().Set(p.exprs(expr.ArgList))
856                 n.SetIsDDD(expr.HasDots)
857                 return n
858
859         case *syntax.ArrayType:
860                 var len ir.Node
861                 if expr.Len != nil {
862                         len = p.expr(expr.Len)
863                 }
864                 return ir.NewArrayType(p.pos(expr), len, p.typeExpr(expr.Elem))
865         case *syntax.SliceType:
866                 return ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
867         case *syntax.DotsType:
868                 t := ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
869                 t.DDD = true
870                 return t
871         case *syntax.StructType:
872                 return p.structType(expr)
873         case *syntax.InterfaceType:
874                 return p.interfaceType(expr)
875         case *syntax.FuncType:
876                 return p.signature(nil, expr)
877         case *syntax.MapType:
878                 return ir.NewMapType(p.pos(expr),
879                         p.typeExpr(expr.Key), p.typeExpr(expr.Value))
880         case *syntax.ChanType:
881                 return ir.NewChanType(p.pos(expr),
882                         p.typeExpr(expr.Elem), p.chanDir(expr.Dir))
883
884         case *syntax.TypeSwitchGuard:
885                 var tag *ir.Ident
886                 if expr.Lhs != nil {
887                         tag = ir.NewIdent(p.pos(expr.Lhs), p.name(expr.Lhs))
888                         if ir.IsBlank(tag) {
889                                 base.Errorf("invalid variable name %v in type switch", tag)
890                         }
891                 }
892                 return ir.NewTypeSwitchGuard(p.pos(expr), tag, p.expr(expr.X))
893         }
894         panic("unhandled Expr")
895 }
896
897 // sum efficiently handles very large summation expressions (such as
898 // in issue #16394). In particular, it avoids left recursion and
899 // collapses string literals.
900 func (p *noder) sum(x syntax.Expr) ir.Node {
901         // While we need to handle long sums with asymptotic
902         // efficiency, the vast majority of sums are very small: ~95%
903         // have only 2 or 3 operands, and ~99% of string literals are
904         // never concatenated.
905
906         adds := make([]*syntax.Operation, 0, 2)
907         for {
908                 add, ok := x.(*syntax.Operation)
909                 if !ok || add.Op != syntax.Add || add.Y == nil {
910                         break
911                 }
912                 adds = append(adds, add)
913                 x = add.X
914         }
915
916         // nstr is the current rightmost string literal in the
917         // summation (if any), and chunks holds its accumulated
918         // substrings.
919         //
920         // Consider the expression x + "a" + "b" + "c" + y. When we
921         // reach the string literal "a", we assign nstr to point to
922         // its corresponding Node and initialize chunks to {"a"}.
923         // Visiting the subsequent string literals "b" and "c", we
924         // simply append their values to chunks. Finally, when we
925         // reach the non-constant operand y, we'll join chunks to form
926         // "abc" and reassign the "a" string literal's value.
927         //
928         // N.B., we need to be careful about named string constants
929         // (indicated by Sym != nil) because 1) we can't modify their
930         // value, as doing so would affect other uses of the string
931         // constant, and 2) they may have types, which we need to
932         // handle correctly. For now, we avoid these problems by
933         // treating named string constants the same as non-constant
934         // operands.
935         var nstr ir.Node
936         chunks := make([]string, 0, 1)
937
938         n := p.expr(x)
939         if ir.IsConst(n, constant.String) && n.Sym() == nil {
940                 nstr = n
941                 chunks = append(chunks, ir.StringVal(nstr))
942         }
943
944         for i := len(adds) - 1; i >= 0; i-- {
945                 add := adds[i]
946
947                 r := p.expr(add.Y)
948                 if ir.IsConst(r, constant.String) && r.Sym() == nil {
949                         if nstr != nil {
950                                 // Collapse r into nstr instead of adding to n.
951                                 chunks = append(chunks, ir.StringVal(r))
952                                 continue
953                         }
954
955                         nstr = r
956                         chunks = append(chunks, ir.StringVal(nstr))
957                 } else {
958                         if len(chunks) > 1 {
959                                 nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
960                         }
961                         nstr = nil
962                         chunks = chunks[:0]
963                 }
964                 n = p.nod(add, ir.OADD, n, r)
965         }
966         if len(chunks) > 1 {
967                 nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
968         }
969
970         return n
971 }
972
973 func (p *noder) typeExpr(typ syntax.Expr) ir.Ntype {
974         // TODO(mdempsky): Be stricter? typecheck should handle errors anyway.
975         n := p.expr(typ)
976         if n == nil {
977                 return nil
978         }
979         if _, ok := n.(ir.Ntype); !ok {
980                 ir.Dump("NOT NTYPE", n)
981         }
982         return n.(ir.Ntype)
983 }
984
985 func (p *noder) typeExprOrNil(typ syntax.Expr) ir.Ntype {
986         if typ != nil {
987                 return p.typeExpr(typ)
988         }
989         return nil
990 }
991
992 func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir {
993         switch dir {
994         case 0:
995                 return types.Cboth
996         case syntax.SendOnly:
997                 return types.Csend
998         case syntax.RecvOnly:
999                 return types.Crecv
1000         }
1001         panic("unhandled ChanDir")
1002 }
1003
1004 func (p *noder) structType(expr *syntax.StructType) ir.Node {
1005         l := make([]*ir.Field, 0, len(expr.FieldList))
1006         for i, field := range expr.FieldList {
1007                 p.setlineno(field)
1008                 var n *ir.Field
1009                 if field.Name == nil {
1010                         n = p.embedded(field.Type)
1011                 } else {
1012                         n = ir.NewField(p.pos(field), p.name(field.Name), p.typeExpr(field.Type), nil)
1013                 }
1014                 if i < len(expr.TagList) && expr.TagList[i] != nil {
1015                         n.Note = constant.StringVal(p.basicLit(expr.TagList[i]))
1016                 }
1017                 l = append(l, n)
1018         }
1019
1020         p.setlineno(expr)
1021         return ir.NewStructType(p.pos(expr), l)
1022 }
1023
1024 func (p *noder) interfaceType(expr *syntax.InterfaceType) ir.Node {
1025         l := make([]*ir.Field, 0, len(expr.MethodList))
1026         for _, method := range expr.MethodList {
1027                 p.setlineno(method)
1028                 var n *ir.Field
1029                 if method.Name == nil {
1030                         n = ir.NewField(p.pos(method), nil, importName(p.packname(method.Type)).(ir.Ntype), nil)
1031                 } else {
1032                         mname := p.name(method.Name)
1033                         if mname.IsBlank() {
1034                                 base.Errorf("methods must have a unique non-blank name")
1035                                 continue
1036                         }
1037                         sig := p.typeExpr(method.Type).(*ir.FuncType)
1038                         sig.Recv = fakeRecv()
1039                         n = ir.NewField(p.pos(method), mname, sig, nil)
1040                 }
1041                 l = append(l, n)
1042         }
1043
1044         return ir.NewInterfaceType(p.pos(expr), l)
1045 }
1046
1047 func (p *noder) packname(expr syntax.Expr) *types.Sym {
1048         switch expr := expr.(type) {
1049         case *syntax.Name:
1050                 name := p.name(expr)
1051                 if n := oldname(name); n.Name() != nil && n.Name().PkgName != nil {
1052                         n.Name().PkgName.Used = true
1053                 }
1054                 return name
1055         case *syntax.SelectorExpr:
1056                 name := p.name(expr.X.(*syntax.Name))
1057                 def := ir.AsNode(name.Def)
1058                 if def == nil {
1059                         base.Errorf("undefined: %v", name)
1060                         return name
1061                 }
1062                 var pkg *types.Pkg
1063                 if def.Op() != ir.OPACK {
1064                         base.Errorf("%v is not a package", name)
1065                         pkg = types.LocalPkg
1066                 } else {
1067                         def := def.(*ir.PkgName)
1068                         def.Used = true
1069                         pkg = def.Pkg
1070                 }
1071                 return pkg.Lookup(expr.Sel.Value)
1072         }
1073         panic(fmt.Sprintf("unexpected packname: %#v", expr))
1074 }
1075
1076 func (p *noder) embedded(typ syntax.Expr) *ir.Field {
1077         op, isStar := typ.(*syntax.Operation)
1078         if isStar {
1079                 if op.Op != syntax.Mul || op.Y != nil {
1080                         panic("unexpected Operation")
1081                 }
1082                 typ = op.X
1083         }
1084
1085         sym := p.packname(typ)
1086         n := ir.NewField(p.pos(typ), lookup(sym.Name), importName(sym).(ir.Ntype), nil)
1087         n.Embedded = true
1088
1089         if isStar {
1090                 n.Ntype = ir.NewStarExpr(p.pos(op), n.Ntype)
1091         }
1092         return n
1093 }
1094
1095 func (p *noder) stmts(stmts []syntax.Stmt) []ir.Node {
1096         return p.stmtsFall(stmts, false)
1097 }
1098
1099 func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []ir.Node {
1100         var nodes []ir.Node
1101         for i, stmt := range stmts {
1102                 s := p.stmtFall(stmt, fallOK && i+1 == len(stmts))
1103                 if s == nil {
1104                 } else if s.Op() == ir.OBLOCK && s.(*ir.BlockStmt).List().Len() > 0 {
1105                         // Inline non-empty block.
1106                         // Empty blocks must be preserved for checkreturn.
1107                         nodes = append(nodes, s.(*ir.BlockStmt).List().Slice()...)
1108                 } else {
1109                         nodes = append(nodes, s)
1110                 }
1111         }
1112         return nodes
1113 }
1114
1115 func (p *noder) stmt(stmt syntax.Stmt) ir.Node {
1116         return p.stmtFall(stmt, false)
1117 }
1118
1119 func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
1120         p.setlineno(stmt)
1121         switch stmt := stmt.(type) {
1122         case *syntax.EmptyStmt:
1123                 return nil
1124         case *syntax.LabeledStmt:
1125                 return p.labeledStmt(stmt, fallOK)
1126         case *syntax.BlockStmt:
1127                 l := p.blockStmt(stmt)
1128                 if len(l) == 0 {
1129                         // TODO(mdempsky): Line number?
1130                         return ir.Nod(ir.OBLOCK, nil, nil)
1131                 }
1132                 return liststmt(l)
1133         case *syntax.ExprStmt:
1134                 return p.wrapname(stmt, p.expr(stmt.X))
1135         case *syntax.SendStmt:
1136                 return p.nod(stmt, ir.OSEND, p.expr(stmt.Chan), p.expr(stmt.Value))
1137         case *syntax.DeclStmt:
1138                 return liststmt(p.decls(stmt.DeclList))
1139         case *syntax.AssignStmt:
1140                 if stmt.Op != 0 && stmt.Op != syntax.Def {
1141                         n := ir.NewAssignOpStmt(p.pos(stmt), p.binOp(stmt.Op), p.expr(stmt.Lhs), p.expr(stmt.Rhs))
1142                         n.SetImplicit(stmt.Rhs == syntax.ImplicitOne)
1143                         return n
1144                 }
1145
1146                 rhs := p.exprList(stmt.Rhs)
1147                 if list, ok := stmt.Lhs.(*syntax.ListExpr); ok && len(list.ElemList) != 1 || len(rhs) != 1 {
1148                         n := p.nod(stmt, ir.OAS2, nil, nil)
1149                         n.SetColas(stmt.Op == syntax.Def)
1150                         n.PtrList().Set(p.assignList(stmt.Lhs, n, n.Colas()))
1151                         n.PtrRlist().Set(rhs)
1152                         return n
1153                 }
1154
1155                 n := p.nod(stmt, ir.OAS, nil, nil)
1156                 n.SetColas(stmt.Op == syntax.Def)
1157                 n.SetLeft(p.assignList(stmt.Lhs, n, n.Colas())[0])
1158                 n.SetRight(rhs[0])
1159                 return n
1160
1161         case *syntax.BranchStmt:
1162                 var op ir.Op
1163                 switch stmt.Tok {
1164                 case syntax.Break:
1165                         op = ir.OBREAK
1166                 case syntax.Continue:
1167                         op = ir.OCONTINUE
1168                 case syntax.Fallthrough:
1169                         if !fallOK {
1170                                 base.Errorf("fallthrough statement out of place")
1171                         }
1172                         op = ir.OFALL
1173                 case syntax.Goto:
1174                         op = ir.OGOTO
1175                 default:
1176                         panic("unhandled BranchStmt")
1177                 }
1178                 var sym *types.Sym
1179                 if stmt.Label != nil {
1180                         sym = p.name(stmt.Label)
1181                 }
1182                 return ir.NewBranchStmt(p.pos(stmt), op, sym)
1183         case *syntax.CallStmt:
1184                 var op ir.Op
1185                 switch stmt.Tok {
1186                 case syntax.Defer:
1187                         op = ir.ODEFER
1188                 case syntax.Go:
1189                         op = ir.OGO
1190                 default:
1191                         panic("unhandled CallStmt")
1192                 }
1193                 return ir.NewGoDeferStmt(p.pos(stmt), op, p.expr(stmt.Call))
1194         case *syntax.ReturnStmt:
1195                 var results []ir.Node
1196                 if stmt.Results != nil {
1197                         results = p.exprList(stmt.Results)
1198                 }
1199                 n := p.nod(stmt, ir.ORETURN, nil, nil)
1200                 n.PtrList().Set(results)
1201                 if n.List().Len() == 0 && Curfn != nil {
1202                         for _, ln := range Curfn.Dcl {
1203                                 if ln.Class() == ir.PPARAM {
1204                                         continue
1205                                 }
1206                                 if ln.Class() != ir.PPARAMOUT {
1207                                         break
1208                                 }
1209                                 if ln.Sym().Def != ln {
1210                                         base.Errorf("%s is shadowed during return", ln.Sym().Name)
1211                                 }
1212                         }
1213                 }
1214                 return n
1215         case *syntax.IfStmt:
1216                 return p.ifStmt(stmt)
1217         case *syntax.ForStmt:
1218                 return p.forStmt(stmt)
1219         case *syntax.SwitchStmt:
1220                 return p.switchStmt(stmt)
1221         case *syntax.SelectStmt:
1222                 return p.selectStmt(stmt)
1223         }
1224         panic("unhandled Stmt")
1225 }
1226
1227 func (p *noder) assignList(expr syntax.Expr, defn ir.Node, colas bool) []ir.Node {
1228         if !colas {
1229                 return p.exprList(expr)
1230         }
1231
1232         var exprs []syntax.Expr
1233         if list, ok := expr.(*syntax.ListExpr); ok {
1234                 exprs = list.ElemList
1235         } else {
1236                 exprs = []syntax.Expr{expr}
1237         }
1238
1239         res := make([]ir.Node, len(exprs))
1240         seen := make(map[*types.Sym]bool, len(exprs))
1241
1242         newOrErr := false
1243         for i, expr := range exprs {
1244                 p.setlineno(expr)
1245                 res[i] = ir.BlankNode
1246
1247                 name, ok := expr.(*syntax.Name)
1248                 if !ok {
1249                         p.errorAt(expr.Pos(), "non-name %v on left side of :=", p.expr(expr))
1250                         newOrErr = true
1251                         continue
1252                 }
1253
1254                 sym := p.name(name)
1255                 if sym.IsBlank() {
1256                         continue
1257                 }
1258
1259                 if seen[sym] {
1260                         p.errorAt(expr.Pos(), "%v repeated on left side of :=", sym)
1261                         newOrErr = true
1262                         continue
1263                 }
1264                 seen[sym] = true
1265
1266                 if sym.Block == types.Block {
1267                         res[i] = oldname(sym)
1268                         continue
1269                 }
1270
1271                 newOrErr = true
1272                 n := NewName(sym)
1273                 declare(n, dclcontext)
1274                 n.Defn = defn
1275                 defn.PtrInit().Append(ir.Nod(ir.ODCL, n, nil))
1276                 res[i] = n
1277         }
1278
1279         if !newOrErr {
1280                 base.ErrorfAt(defn.Pos(), "no new variables on left side of :=")
1281         }
1282         return res
1283 }
1284
1285 func (p *noder) blockStmt(stmt *syntax.BlockStmt) []ir.Node {
1286         p.openScope(stmt.Pos())
1287         nodes := p.stmts(stmt.List)
1288         p.closeScope(stmt.Rbrace)
1289         return nodes
1290 }
1291
1292 func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
1293         p.openScope(stmt.Pos())
1294         n := p.nod(stmt, ir.OIF, nil, nil)
1295         if stmt.Init != nil {
1296                 n.PtrInit().Set1(p.stmt(stmt.Init))
1297         }
1298         if stmt.Cond != nil {
1299                 n.SetLeft(p.expr(stmt.Cond))
1300         }
1301         n.PtrBody().Set(p.blockStmt(stmt.Then))
1302         if stmt.Else != nil {
1303                 e := p.stmt(stmt.Else)
1304                 if e.Op() == ir.OBLOCK {
1305                         n.PtrRlist().Set(e.List().Slice())
1306                 } else {
1307                         n.PtrRlist().Set1(e)
1308                 }
1309         }
1310         p.closeAnotherScope()
1311         return n
1312 }
1313
1314 func (p *noder) forStmt(stmt *syntax.ForStmt) ir.Node {
1315         p.openScope(stmt.Pos())
1316         if r, ok := stmt.Init.(*syntax.RangeClause); ok {
1317                 if stmt.Cond != nil || stmt.Post != nil {
1318                         panic("unexpected RangeClause")
1319                 }
1320
1321                 n := p.nod(r, ir.ORANGE, nil, p.expr(r.X))
1322                 if r.Lhs != nil {
1323                         n.SetColas(r.Def)
1324                         n.PtrList().Set(p.assignList(r.Lhs, n, n.Colas()))
1325                 }
1326                 n.PtrBody().Set(p.blockStmt(stmt.Body))
1327                 p.closeAnotherScope()
1328                 return n
1329         }
1330
1331         n := p.nod(stmt, ir.OFOR, nil, nil)
1332         if stmt.Init != nil {
1333                 n.PtrInit().Set1(p.stmt(stmt.Init))
1334         }
1335         if stmt.Cond != nil {
1336                 n.SetLeft(p.expr(stmt.Cond))
1337         }
1338         if stmt.Post != nil {
1339                 n.SetRight(p.stmt(stmt.Post))
1340         }
1341         n.PtrBody().Set(p.blockStmt(stmt.Body))
1342         p.closeAnotherScope()
1343         return n
1344 }
1345
1346 func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
1347         p.openScope(stmt.Pos())
1348         n := p.nod(stmt, ir.OSWITCH, nil, nil)
1349         if stmt.Init != nil {
1350                 n.PtrInit().Set1(p.stmt(stmt.Init))
1351         }
1352         if stmt.Tag != nil {
1353                 n.SetLeft(p.expr(stmt.Tag))
1354         }
1355
1356         var tswitch *ir.TypeSwitchGuard
1357         if l := n.Left(); l != nil && l.Op() == ir.OTYPESW {
1358                 tswitch = l.(*ir.TypeSwitchGuard)
1359         }
1360         n.PtrList().Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace))
1361
1362         p.closeScope(stmt.Rbrace)
1363         return n
1364 }
1365
1366 func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []ir.Node {
1367         nodes := make([]ir.Node, 0, len(clauses))
1368         for i, clause := range clauses {
1369                 p.setlineno(clause)
1370                 if i > 0 {
1371                         p.closeScope(clause.Pos())
1372                 }
1373                 p.openScope(clause.Pos())
1374
1375                 n := p.nod(clause, ir.OCASE, nil, nil)
1376                 if clause.Cases != nil {
1377                         n.PtrList().Set(p.exprList(clause.Cases))
1378                 }
1379                 if tswitch != nil && tswitch.Left() != nil {
1380                         nn := NewName(tswitch.Left().Sym())
1381                         declare(nn, dclcontext)
1382                         n.PtrRlist().Set1(nn)
1383                         // keep track of the instances for reporting unused
1384                         nn.Defn = tswitch
1385                 }
1386
1387                 // Trim trailing empty statements. We omit them from
1388                 // the Node AST anyway, and it's easier to identify
1389                 // out-of-place fallthrough statements without them.
1390                 body := clause.Body
1391                 for len(body) > 0 {
1392                         if _, ok := body[len(body)-1].(*syntax.EmptyStmt); !ok {
1393                                 break
1394                         }
1395                         body = body[:len(body)-1]
1396                 }
1397
1398                 n.PtrBody().Set(p.stmtsFall(body, true))
1399                 if l := n.Body().Len(); l > 0 && n.Body().Index(l-1).Op() == ir.OFALL {
1400                         if tswitch != nil {
1401                                 base.Errorf("cannot fallthrough in type switch")
1402                         }
1403                         if i+1 == len(clauses) {
1404                                 base.Errorf("cannot fallthrough final case in switch")
1405                         }
1406                 }
1407
1408                 nodes = append(nodes, n)
1409         }
1410         if len(clauses) > 0 {
1411                 p.closeScope(rbrace)
1412         }
1413         return nodes
1414 }
1415
1416 func (p *noder) selectStmt(stmt *syntax.SelectStmt) ir.Node {
1417         n := p.nod(stmt, ir.OSELECT, nil, nil)
1418         n.PtrList().Set(p.commClauses(stmt.Body, stmt.Rbrace))
1419         return n
1420 }
1421
1422 func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []ir.Node {
1423         nodes := make([]ir.Node, 0, len(clauses))
1424         for i, clause := range clauses {
1425                 p.setlineno(clause)
1426                 if i > 0 {
1427                         p.closeScope(clause.Pos())
1428                 }
1429                 p.openScope(clause.Pos())
1430
1431                 n := p.nod(clause, ir.OCASE, nil, nil)
1432                 if clause.Comm != nil {
1433                         n.PtrList().Set1(p.stmt(clause.Comm))
1434                 }
1435                 n.PtrBody().Set(p.stmts(clause.Body))
1436                 nodes = append(nodes, n)
1437         }
1438         if len(clauses) > 0 {
1439                 p.closeScope(rbrace)
1440         }
1441         return nodes
1442 }
1443
1444 func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) ir.Node {
1445         sym := p.name(label.Label)
1446         lhs := p.nodSym(label, ir.OLABEL, nil, sym)
1447
1448         var ls ir.Node
1449         if label.Stmt != nil { // TODO(mdempsky): Should always be present.
1450                 ls = p.stmtFall(label.Stmt, fallOK)
1451                 // Attach label directly to control statement too.
1452                 if ls != nil {
1453                         switch ls.Op() {
1454                         case ir.OFOR:
1455                                 ls.SetSym(sym)
1456                         case ir.ORANGE:
1457                                 ls.SetSym(sym)
1458                         case ir.OSWITCH:
1459                                 ls.SetSym(sym)
1460                         case ir.OSELECT:
1461                                 ls.SetSym(sym)
1462                         }
1463                 }
1464         }
1465
1466         l := []ir.Node{lhs}
1467         if ls != nil {
1468                 if ls.Op() == ir.OBLOCK {
1469                         l = append(l, ls.List().Slice()...)
1470                 } else {
1471                         l = append(l, ls)
1472                 }
1473         }
1474         return liststmt(l)
1475 }
1476
1477 var unOps = [...]ir.Op{
1478         syntax.Recv: ir.ORECV,
1479         syntax.Mul:  ir.ODEREF,
1480         syntax.And:  ir.OADDR,
1481
1482         syntax.Not: ir.ONOT,
1483         syntax.Xor: ir.OBITNOT,
1484         syntax.Add: ir.OPLUS,
1485         syntax.Sub: ir.ONEG,
1486 }
1487
1488 func (p *noder) unOp(op syntax.Operator) ir.Op {
1489         if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 {
1490                 panic("invalid Operator")
1491         }
1492         return unOps[op]
1493 }
1494
1495 var binOps = [...]ir.Op{
1496         syntax.OrOr:   ir.OOROR,
1497         syntax.AndAnd: ir.OANDAND,
1498
1499         syntax.Eql: ir.OEQ,
1500         syntax.Neq: ir.ONE,
1501         syntax.Lss: ir.OLT,
1502         syntax.Leq: ir.OLE,
1503         syntax.Gtr: ir.OGT,
1504         syntax.Geq: ir.OGE,
1505
1506         syntax.Add: ir.OADD,
1507         syntax.Sub: ir.OSUB,
1508         syntax.Or:  ir.OOR,
1509         syntax.Xor: ir.OXOR,
1510
1511         syntax.Mul:    ir.OMUL,
1512         syntax.Div:    ir.ODIV,
1513         syntax.Rem:    ir.OMOD,
1514         syntax.And:    ir.OAND,
1515         syntax.AndNot: ir.OANDNOT,
1516         syntax.Shl:    ir.OLSH,
1517         syntax.Shr:    ir.ORSH,
1518 }
1519
1520 func (p *noder) binOp(op syntax.Operator) ir.Op {
1521         if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 {
1522                 panic("invalid Operator")
1523         }
1524         return binOps[op]
1525 }
1526
1527 // checkLangCompat reports an error if the representation of a numeric
1528 // literal is not compatible with the current language version.
1529 func checkLangCompat(lit *syntax.BasicLit) {
1530         s := lit.Value
1531         if len(s) <= 2 || langSupported(1, 13, types.LocalPkg) {
1532                 return
1533         }
1534         // len(s) > 2
1535         if strings.Contains(s, "_") {
1536                 base.ErrorfVers("go1.13", "underscores in numeric literals")
1537                 return
1538         }
1539         if s[0] != '0' {
1540                 return
1541         }
1542         radix := s[1]
1543         if radix == 'b' || radix == 'B' {
1544                 base.ErrorfVers("go1.13", "binary literals")
1545                 return
1546         }
1547         if radix == 'o' || radix == 'O' {
1548                 base.ErrorfVers("go1.13", "0o/0O-style octal literals")
1549                 return
1550         }
1551         if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
1552                 base.ErrorfVers("go1.13", "hexadecimal floating-point literals")
1553         }
1554 }
1555
1556 func (p *noder) basicLit(lit *syntax.BasicLit) constant.Value {
1557         // We don't use the errors of the conversion routines to determine
1558         // if a literal string is valid because the conversion routines may
1559         // accept a wider syntax than the language permits. Rely on lit.Bad
1560         // instead.
1561         if lit.Bad {
1562                 return constant.MakeUnknown()
1563         }
1564
1565         switch lit.Kind {
1566         case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
1567                 checkLangCompat(lit)
1568         }
1569
1570         v := constant.MakeFromLiteral(lit.Value, tokenForLitKind[lit.Kind], 0)
1571         if v.Kind() == constant.Unknown {
1572                 // TODO(mdempsky): Better error message?
1573                 p.errorAt(lit.Pos(), "malformed constant: %s", lit.Value)
1574         }
1575
1576         // go/constant uses big.Rat by default, which is more precise, but
1577         // causes toolstash -cmp and some tests to fail. For now, convert
1578         // to big.Float to match cmd/compile's historical precision.
1579         // TODO(mdempsky): Remove.
1580         if v.Kind() == constant.Float {
1581                 v = constant.Make(bigFloatVal(v))
1582         }
1583
1584         return v
1585 }
1586
1587 var tokenForLitKind = [...]token.Token{
1588         syntax.IntLit:    token.INT,
1589         syntax.RuneLit:   token.CHAR,
1590         syntax.FloatLit:  token.FLOAT,
1591         syntax.ImagLit:   token.IMAG,
1592         syntax.StringLit: token.STRING,
1593 }
1594
1595 func (p *noder) name(name *syntax.Name) *types.Sym {
1596         return lookup(name.Value)
1597 }
1598
1599 func (p *noder) mkname(name *syntax.Name) ir.Node {
1600         // TODO(mdempsky): Set line number?
1601         return mkname(p.name(name))
1602 }
1603
1604 func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node {
1605         // These nodes do not carry line numbers.
1606         // Introduce a wrapper node to give them the correct line.
1607         switch x.Op() {
1608         case ir.OTYPE, ir.OLITERAL:
1609                 if x.Sym() == nil {
1610                         break
1611                 }
1612                 fallthrough
1613         case ir.ONAME, ir.ONONAME, ir.OPACK:
1614                 p := p.nod(n, ir.OPAREN, x, nil)
1615                 p.SetImplicit(true)
1616                 return p
1617         }
1618         return x
1619 }
1620
1621 func (p *noder) nod(orig syntax.Node, op ir.Op, left, right ir.Node) ir.Node {
1622         return ir.NodAt(p.pos(orig), op, left, right)
1623 }
1624
1625 func (p *noder) nodSym(orig syntax.Node, op ir.Op, left ir.Node, sym *types.Sym) ir.Node {
1626         n := nodSym(op, left, sym)
1627         n.SetPos(p.pos(orig))
1628         return n
1629 }
1630
1631 func (p *noder) pos(n syntax.Node) src.XPos {
1632         // TODO(gri): orig.Pos() should always be known - fix package syntax
1633         xpos := base.Pos
1634         if pos := n.Pos(); pos.IsKnown() {
1635                 xpos = p.makeXPos(pos)
1636         }
1637         return xpos
1638 }
1639
1640 func (p *noder) setlineno(n syntax.Node) {
1641         if n != nil {
1642                 base.Pos = p.pos(n)
1643         }
1644 }
1645
1646 // error is called concurrently if files are parsed concurrently.
1647 func (p *noder) error(err error) {
1648         p.err <- err.(syntax.Error)
1649 }
1650
1651 // pragmas that are allowed in the std lib, but don't have
1652 // a syntax.Pragma value (see lex.go) associated with them.
1653 var allowedStdPragmas = map[string]bool{
1654         "go:cgo_export_static":  true,
1655         "go:cgo_export_dynamic": true,
1656         "go:cgo_import_static":  true,
1657         "go:cgo_import_dynamic": true,
1658         "go:cgo_ldflag":         true,
1659         "go:cgo_dynamic_linker": true,
1660         "go:embed":              true,
1661         "go:generate":           true,
1662 }
1663
1664 // *Pragma is the value stored in a syntax.Pragma during parsing.
1665 type Pragma struct {
1666         Flag   ir.PragmaFlag // collected bits
1667         Pos    []PragmaPos   // position of each individual flag
1668         Embeds []PragmaEmbed
1669 }
1670
1671 type PragmaPos struct {
1672         Flag ir.PragmaFlag
1673         Pos  syntax.Pos
1674 }
1675
1676 type PragmaEmbed struct {
1677         Pos      syntax.Pos
1678         Patterns []string
1679 }
1680
1681 func (p *noder) checkUnused(pragma *Pragma) {
1682         for _, pos := range pragma.Pos {
1683                 if pos.Flag&pragma.Flag != 0 {
1684                         p.errorAt(pos.Pos, "misplaced compiler directive")
1685                 }
1686         }
1687         if len(pragma.Embeds) > 0 {
1688                 for _, e := range pragma.Embeds {
1689                         p.errorAt(e.Pos, "misplaced go:embed directive")
1690                 }
1691         }
1692 }
1693
1694 func (p *noder) checkUnusedDuringParse(pragma *Pragma) {
1695         for _, pos := range pragma.Pos {
1696                 if pos.Flag&pragma.Flag != 0 {
1697                         p.error(syntax.Error{Pos: pos.Pos, Msg: "misplaced compiler directive"})
1698                 }
1699         }
1700         if len(pragma.Embeds) > 0 {
1701                 for _, e := range pragma.Embeds {
1702                         p.error(syntax.Error{Pos: e.Pos, Msg: "misplaced go:embed directive"})
1703                 }
1704         }
1705 }
1706
1707 // pragma is called concurrently if files are parsed concurrently.
1708 func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.Pragma) syntax.Pragma {
1709         pragma, _ := old.(*Pragma)
1710         if pragma == nil {
1711                 pragma = new(Pragma)
1712         }
1713
1714         if text == "" {
1715                 // unused pragma; only called with old != nil.
1716                 p.checkUnusedDuringParse(pragma)
1717                 return nil
1718         }
1719
1720         if strings.HasPrefix(text, "line ") {
1721                 // line directives are handled by syntax package
1722                 panic("unreachable")
1723         }
1724
1725         if !blankLine {
1726                 // directive must be on line by itself
1727                 p.error(syntax.Error{Pos: pos, Msg: "misplaced compiler directive"})
1728                 return pragma
1729         }
1730
1731         switch {
1732         case strings.HasPrefix(text, "go:linkname "):
1733                 f := strings.Fields(text)
1734                 if !(2 <= len(f) && len(f) <= 3) {
1735                         p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname [linkname]"})
1736                         break
1737                 }
1738                 // The second argument is optional. If omitted, we use
1739                 // the default object symbol name for this and
1740                 // linkname only serves to mark this symbol as
1741                 // something that may be referenced via the object
1742                 // symbol name from another package.
1743                 var target string
1744                 if len(f) == 3 {
1745                         target = f[2]
1746                 } else if base.Ctxt.Pkgpath != "" {
1747                         // Use the default object symbol name if the
1748                         // user didn't provide one.
1749                         target = objabi.PathToPrefix(base.Ctxt.Pkgpath) + "." + f[1]
1750                 } else {
1751                         p.error(syntax.Error{Pos: pos, Msg: "//go:linkname requires linkname argument or -p compiler flag"})
1752                         break
1753                 }
1754                 p.linknames = append(p.linknames, linkname{pos, f[1], target})
1755
1756         case text == "go:embed", strings.HasPrefix(text, "go:embed "):
1757                 args, err := parseGoEmbed(text[len("go:embed"):])
1758                 if err != nil {
1759                         p.error(syntax.Error{Pos: pos, Msg: err.Error()})
1760                 }
1761                 if len(args) == 0 {
1762                         p.error(syntax.Error{Pos: pos, Msg: "usage: //go:embed pattern..."})
1763                         break
1764                 }
1765                 pragma.Embeds = append(pragma.Embeds, PragmaEmbed{pos, args})
1766
1767         case strings.HasPrefix(text, "go:cgo_import_dynamic "):
1768                 // This is permitted for general use because Solaris
1769                 // code relies on it in golang.org/x/sys/unix and others.
1770                 fields := pragmaFields(text)
1771                 if len(fields) >= 4 {
1772                         lib := strings.Trim(fields[3], `"`)
1773                         if lib != "" && !safeArg(lib) && !isCgoGeneratedFile(pos) {
1774                                 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("invalid library name %q in cgo_import_dynamic directive", lib)})
1775                         }
1776                         p.pragcgo(pos, text)
1777                         pragma.Flag |= pragmaFlag("go:cgo_import_dynamic")
1778                         break
1779                 }
1780                 fallthrough
1781         case strings.HasPrefix(text, "go:cgo_"):
1782                 // For security, we disallow //go:cgo_* directives other
1783                 // than cgo_import_dynamic outside cgo-generated files.
1784                 // Exception: they are allowed in the standard library, for runtime and syscall.
1785                 if !isCgoGeneratedFile(pos) && !base.Flag.Std {
1786                         p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
1787                 }
1788                 p.pragcgo(pos, text)
1789                 fallthrough // because of //go:cgo_unsafe_args
1790         default:
1791                 verb := text
1792                 if i := strings.Index(text, " "); i >= 0 {
1793                         verb = verb[:i]
1794                 }
1795                 flag := pragmaFlag(verb)
1796                 const runtimePragmas = ir.Systemstack | ir.Nowritebarrier | ir.Nowritebarrierrec | ir.Yeswritebarrierrec
1797                 if !base.Flag.CompilingRuntime && flag&runtimePragmas != 0 {
1798                         p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)})
1799                 }
1800                 if flag == 0 && !allowedStdPragmas[verb] && base.Flag.Std {
1801                         p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)})
1802                 }
1803                 pragma.Flag |= flag
1804                 pragma.Pos = append(pragma.Pos, PragmaPos{flag, pos})
1805         }
1806
1807         return pragma
1808 }
1809
1810 // isCgoGeneratedFile reports whether pos is in a file
1811 // generated by cgo, which is to say a file with name
1812 // beginning with "_cgo_". Such files are allowed to
1813 // contain cgo directives, and for security reasons
1814 // (primarily misuse of linker flags), other files are not.
1815 // See golang.org/issue/23672.
1816 func isCgoGeneratedFile(pos syntax.Pos) bool {
1817         return strings.HasPrefix(filepath.Base(filepath.Clean(fileh(pos.Base().Filename()))), "_cgo_")
1818 }
1819
1820 // safeArg reports whether arg is a "safe" command-line argument,
1821 // meaning that when it appears in a command-line, it probably
1822 // doesn't have some special meaning other than its own name.
1823 // This is copied from SafeArg in cmd/go/internal/load/pkg.go.
1824 func safeArg(name string) bool {
1825         if name == "" {
1826                 return false
1827         }
1828         c := name[0]
1829         return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
1830 }
1831
1832 func mkname(sym *types.Sym) ir.Node {
1833         n := oldname(sym)
1834         if n.Name() != nil && n.Name().PkgName != nil {
1835                 n.Name().PkgName.Used = true
1836         }
1837         return n
1838 }
1839
1840 // parseGoEmbed parses the text following "//go:embed" to extract the glob patterns.
1841 // It accepts unquoted space-separated patterns as well as double-quoted and back-quoted Go strings.
1842 // go/build/read.go also processes these strings and contains similar logic.
1843 func parseGoEmbed(args string) ([]string, error) {
1844         var list []string
1845         for args = strings.TrimSpace(args); args != ""; args = strings.TrimSpace(args) {
1846                 var path string
1847         Switch:
1848                 switch args[0] {
1849                 default:
1850                         i := len(args)
1851                         for j, c := range args {
1852                                 if unicode.IsSpace(c) {
1853                                         i = j
1854                                         break
1855                                 }
1856                         }
1857                         path = args[:i]
1858                         args = args[i:]
1859
1860                 case '`':
1861                         i := strings.Index(args[1:], "`")
1862                         if i < 0 {
1863                                 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1864                         }
1865                         path = args[1 : 1+i]
1866                         args = args[1+i+1:]
1867
1868                 case '"':
1869                         i := 1
1870                         for ; i < len(args); i++ {
1871                                 if args[i] == '\\' {
1872                                         i++
1873                                         continue
1874                                 }
1875                                 if args[i] == '"' {
1876                                         q, err := strconv.Unquote(args[:i+1])
1877                                         if err != nil {
1878                                                 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args[:i+1])
1879                                         }
1880                                         path = q
1881                                         args = args[i+1:]
1882                                         break Switch
1883                                 }
1884                         }
1885                         if i >= len(args) {
1886                                 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1887                         }
1888                 }
1889
1890                 if args != "" {
1891                         r, _ := utf8.DecodeRuneInString(args)
1892                         if !unicode.IsSpace(r) {
1893                                 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1894                         }
1895                 }
1896                 list = append(list, path)
1897         }
1898         return list, nil
1899 }