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.
20 "cmd/compile/internal/base"
21 "cmd/compile/internal/dwarfgen"
22 "cmd/compile/internal/ir"
23 "cmd/compile/internal/syntax"
24 "cmd/compile/internal/typecheck"
25 "cmd/compile/internal/types"
26 "cmd/compile/internal/types2"
31 func LoadPackage(filenames []string) {
32 base.Timer.Start("fe", "parse")
33 lines := ParseFiles(filenames)
35 base.Timer.AddEvent(int64(lines), "lines")
37 if base.Flag.G != 0 && base.Flag.G < 3 {
38 // can only parse generic code for now
46 // With all user code typechecked, it's now safe to verify unused dot imports.
51 // ParseFiles concurrently parses files into *syntax.File structures.
52 // Each declaration in every *syntax.File is converted to a syntax tree
53 // and its root represented by *Node is appended to Target.Decls.
54 // Returns the total count of parsed lines.
55 func ParseFiles(filenames []string) (lines uint) {
56 noders := make([]*noder, 0, len(filenames))
57 // Limit the number of simultaneously open files.
58 sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
60 for _, filename := range filenames {
62 err: make(chan syntax.Error),
63 trackScopes: base.Flag.Dwarf,
65 noders = append(noders, p)
67 go func(filename string) {
69 defer func() { <-sem }()
71 fbase := syntax.NewFileBase(filename)
73 f, err := os.Open(filename)
75 p.error(syntax.Error{Msg: err.Error()})
80 mode := syntax.CheckBranches
82 mode |= syntax.AllowGenerics
84 p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error
88 // generic noding phase (using new typechecker)
90 // setup and syntax error reporting
91 nodersmap := make(map[string]*noder)
92 var files []*syntax.File
93 for _, p := range noders {
94 for e := range p.err {
95 p.errorAt(e.Pos, "%s", e.Msg)
98 nodersmap[p.file.Pos().RelFilename()] = p
99 files = append(files, p.file)
100 lines += p.file.EOF.Line()
103 if base.SyntaxErrors() != 0 {
108 conf := types2.Config{
109 InferFromConstraints: true,
110 IgnoreBranches: true, // parser already checked via syntax.CheckBranches mode
111 CompilerErrorMessages: true, // use error strings matching existing compiler errors
112 Error: func(err error) {
113 terr := err.(types2.Error)
114 if len(terr.Msg) > 0 && terr.Msg[0] == '\t' {
115 // types2 reports error clarifications via separate
116 // error messages which are indented with a tab.
117 // Ignore them to satisfy tools and tests that expect
118 // only one error in such cases.
119 // TODO(gri) Need to adjust error reporting in types2.
122 p := nodersmap[terr.Pos.RelFilename()]
123 base.ErrorfAt(p.makeXPos(terr.Pos), "%s", terr.Msg)
125 Importer: &gcimports{
126 packages: make(map[string]*types2.Package),
131 Types: make(map[syntax.Expr]types2.TypeAndValue),
132 Defs: make(map[*syntax.Name]types2.Object),
133 Uses: make(map[*syntax.Name]types2.Object),
134 Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
137 conf.Check(base.Ctxt.Pkgpath, files, &info)
144 for _, p := range noders {
145 // errors have already been reported
149 lines += p.file.EOF.Line()
150 p.file = nil // release memory
153 // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
154 types.CheckDclstack()
157 types.LocalPkg.Height = myheight
161 // traditional (non-generic) noding phase
162 for _, p := range noders {
163 for e := range p.err {
164 p.errorAt(e.Pos, "%s", e.Msg)
168 lines += p.file.EOF.Line()
169 p.file = nil // release memory
170 if base.SyntaxErrors() != 0 {
174 // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
175 types.CheckDclstack()
178 for _, p := range noders {
182 types.LocalPkg.Height = myheight
187 typecheck.DeclareUniverse()
189 typecheck.TypecheckAllowed = true
191 // Process top-level declarations in phases.
193 // Phase 1: const, type, and names and types of funcs.
194 // This will gather all the information about types
195 // and methods but doesn't depend on any of it.
197 // We also defer type alias declarations until phase 2
198 // to avoid cycles like #18640.
199 // TODO(gri) Remove this again once we have a fix for #25838.
201 // Don't use range--typecheck can add closures to Target.Decls.
202 base.Timer.Start("fe", "typecheck", "top1")
203 for i := 0; i < len(typecheck.Target.Decls); i++ {
204 n := typecheck.Target.Decls[i]
205 if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.(*ir.Decl).X.Alias()) {
206 typecheck.Target.Decls[i] = typecheck.Stmt(n)
210 // Phase 2: Variable assignments.
211 // To check interface assignments, depends on phase 1.
213 // Don't use range--typecheck can add closures to Target.Decls.
214 base.Timer.Start("fe", "typecheck", "top2")
215 for i := 0; i < len(typecheck.Target.Decls); i++ {
216 n := typecheck.Target.Decls[i]
217 if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).X.Alias() {
218 typecheck.Target.Decls[i] = typecheck.Stmt(n)
222 // Phase 3: Type check function bodies.
223 // Don't use range--typecheck can add closures to Target.Decls.
224 base.Timer.Start("fe", "typecheck", "func")
226 for i := 0; i < len(typecheck.Target.Decls); i++ {
227 n := typecheck.Target.Decls[i]
228 if n.Op() == ir.ODCLFUNC {
229 typecheck.FuncBody(n.(*ir.Func))
234 // Phase 4: Check external declarations.
235 // TODO(mdempsky): This should be handled when type checking their
236 // corresponding ODCL nodes.
237 base.Timer.Start("fe", "typecheck", "externdcls")
238 for i, n := range typecheck.Target.Externs {
239 if n.Op() == ir.ONAME {
240 typecheck.Target.Externs[i] = typecheck.Expr(typecheck.Target.Externs[i])
244 // Phase 5: With all user code type-checked, it's now safe to verify map keys.
245 typecheck.CheckMapKeys()
249 func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
250 base.ErrorfAt(p.makeXPos(pos), format, args...)
253 // TODO(gri) Can we eliminate fileh in favor of absFilename?
254 func fileh(name string) string {
255 return objabi.AbsFile("", name, base.Flag.TrimPath)
258 func absFilename(name string) string {
259 return objabi.AbsFile(base.Ctxt.Pathname, name, base.Flag.TrimPath)
262 // noder transforms package syntax's AST into a Node tree.
268 pragcgobuf [][]string
269 err chan syntax.Error
276 // typeInfo provides access to the type information computed by the new
277 // typechecker. It is only present if -G is set, and all noders point to
278 // the same types.Info. For now this is a local field, if need be we can
280 typeInfo *types2.Info
283 // For now we provide these basic accessors to get to type and object
284 // information of expression nodes during noding. Eventually we will
285 // attach this information directly to the syntax tree which should
286 // simplify access and make it more efficient as well.
288 // typ returns the type and value information for the given expression.
289 func (p *noder) typ(x syntax.Expr) types2.TypeAndValue {
290 return p.typeInfo.Types[x]
293 // def returns the object for the given name in its declaration.
294 func (p *noder) def(x *syntax.Name) types2.Object {
295 return p.typeInfo.Defs[x]
298 // use returns the object for the given name outside its declaration.
299 func (p *noder) use(x *syntax.Name) types2.Object {
300 return p.typeInfo.Uses[x]
303 // sel returns the selection information for the given selector expression.
304 func (p *noder) sel(x *syntax.SelectorExpr) *types2.Selection {
305 return p.typeInfo.Selections[x]
308 // funcState tracks all per-function state to make handling nested
310 type funcState struct {
311 // scopeVars is a stack tracking the number of variables declared in
312 // the current function at the moment each open scope was opened.
314 marker dwarfgen.ScopeMarker
316 lastCloseScopePos syntax.Pos
319 func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
320 outerFuncState := p.funcState
321 p.funcState = new(funcState)
322 typecheck.StartFuncBody(fn)
325 body := p.stmts(block.List)
327 body = []ir.Node{ir.NewBlockStmt(base.Pos, nil)}
331 base.Pos = p.makeXPos(block.Rbrace)
332 fn.Endlineno = base.Pos
335 typecheck.FinishFuncBody()
336 p.funcState.marker.WriteTo(fn)
337 p.funcState = outerFuncState
340 func (p *noder) openScope(pos syntax.Pos) {
345 fs.scopeVars = append(fs.scopeVars, len(ir.CurFunc.Dcl))
346 fs.marker.Push(p.makeXPos(pos))
350 func (p *noder) closeScope(pos syntax.Pos) {
352 fs.lastCloseScopePos = pos
356 scopeVars := fs.scopeVars[len(fs.scopeVars)-1]
357 fs.scopeVars = fs.scopeVars[:len(fs.scopeVars)-1]
358 if scopeVars == len(ir.CurFunc.Dcl) {
359 // no variables were declared in this scope, so we can retract it.
362 fs.marker.Pop(p.makeXPos(pos))
367 // closeAnotherScope is like closeScope, but it reuses the same mark
368 // position as the last closeScope call. This is useful for "for" and
369 // "if" statements, as their implicit blocks always end at the same
370 // position as an explicit block.
371 func (p *noder) closeAnotherScope() {
372 p.closeScope(p.funcState.lastCloseScopePos)
375 // linkname records a //go:linkname directive.
376 type linkname struct {
382 func (p *noder) node() {
384 p.importedUnsafe = false
385 p.importedEmbed = false
387 p.setlineno(p.file.PkgName)
388 mkpackage(p.file.PkgName.Value)
390 if pragma, ok := p.file.Pragma.(*pragmas); ok {
391 pragma.Flag &^= ir.GoBuildPragma
392 p.checkUnused(pragma)
395 typecheck.Target.Decls = append(typecheck.Target.Decls, p.decls(p.file.DeclList)...)
397 base.Pos = src.NoXPos
401 func (p *noder) processPragmas() {
402 for _, l := range p.linknames {
403 if !p.importedUnsafe {
404 p.errorAt(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
407 n := ir.AsNode(typecheck.Lookup(l.local).Def)
408 if n == nil || n.Op() != ir.ONAME {
409 // TODO(mdempsky): Change to p.errorAt before Go 1.17 release.
410 // base.WarnfAt(p.makeXPos(l.pos), "//go:linkname must refer to declared function or variable (will be an error in Go 1.17)")
413 if n.Sym().Linkname != "" {
414 p.errorAt(l.pos, "duplicate //go:linkname for %s", l.local)
417 n.Sym().Linkname = l.remote
419 typecheck.Target.CgoPragmas = append(typecheck.Target.CgoPragmas, p.pragcgobuf...)
422 func (p *noder) decls(decls []syntax.Decl) (l []ir.Node) {
425 for _, decl := range decls {
427 switch decl := decl.(type) {
428 case *syntax.ImportDecl:
431 case *syntax.VarDecl:
432 l = append(l, p.varDecl(decl)...)
434 case *syntax.ConstDecl:
435 l = append(l, p.constDecl(decl, &cs)...)
437 case *syntax.TypeDecl:
438 l = append(l, p.typeDecl(decl))
440 case *syntax.FuncDecl:
441 l = append(l, p.funcDecl(decl))
444 panic("unhandled Decl")
451 func (p *noder) importDecl(imp *syntax.ImportDecl) {
452 if imp.Path == nil || imp.Path.Bad {
453 return // avoid follow-on errors if there was a syntax error
456 if pragma, ok := imp.Pragma.(*pragmas); ok {
457 p.checkUnused(pragma)
460 ipkg := importfile(imp)
462 if base.Errors() == 0 {
463 base.Fatalf("phase error in import")
468 if ipkg == ir.Pkgs.Unsafe {
469 p.importedUnsafe = true
471 if ipkg.Path == "embed" {
472 p.importedEmbed = true
476 if imp.LocalPkgName != nil {
477 my = p.name(imp.LocalPkgName)
479 my = typecheck.Lookup(ipkg.Name)
482 pack := ir.NewPkgName(p.pos(imp), my, ipkg)
489 base.ErrorfAt(pack.Pos(), "cannot import package as init - init must be a func")
495 typecheck.Redeclared(pack.Pos(), my, "as imported package name")
498 my.Lastlineno = pack.Pos()
499 my.Block = 1 // at top level
502 func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
503 names := p.declNames(ir.ONAME, decl.NameList)
504 typ := p.typeExprOrNil(decl.Type)
505 exprs := p.exprList(decl.Values)
507 if pragma, ok := decl.Pragma.(*pragmas); ok {
508 if err := varEmbed(p.makeXPos, names[0], decl, pragma); err != nil {
509 p.errorAt(decl.Pos(), "%s", err.Error())
511 p.checkUnused(pragma)
517 if len(names) > 1 && len(exprs) == 1 {
518 as2 := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, exprs)
519 for _, v := range names {
521 typecheck.Declare(v, typecheck.DeclContext)
524 if ir.CurFunc != nil {
525 init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
529 return append(init, as2)
532 for i, v := range names {
538 typecheck.Declare(v, typecheck.DeclContext)
541 if ir.CurFunc != nil {
542 init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
544 as := ir.NewAssignStmt(base.Pos, v, e)
545 init = append(init, as)
546 if e != nil || ir.CurFunc == nil {
551 if len(exprs) != 0 && len(names) != len(exprs) {
552 base.Errorf("assignment mismatch: %d variables but %d values", len(names), len(exprs))
558 // constState tracks state between constant specifiers within a
559 // declaration group. This state is kept separate from noder so nested
560 // constant declarations are handled correctly (e.g., issue 15550).
561 type constState struct {
568 func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node {
569 if decl.Group == nil || decl.Group != cs.group {
575 if pragma, ok := decl.Pragma.(*pragmas); ok {
576 p.checkUnused(pragma)
579 names := p.declNames(ir.OLITERAL, decl.NameList)
580 typ := p.typeExprOrNil(decl.Type)
583 if decl.Values != nil {
584 values = p.exprList(decl.Values)
585 cs.typ, cs.values = typ, values
588 base.Errorf("const declaration cannot have type without expression")
590 typ, values = cs.typ, cs.values
593 nn := make([]ir.Node, 0, len(names))
594 for i, n := range names {
595 if i >= len(values) {
596 base.Errorf("missing value in const declaration")
600 if decl.Values == nil {
601 v = ir.DeepCopy(n.Pos(), v)
603 typecheck.Declare(n, typecheck.DeclContext)
609 nn = append(nn, ir.NewDecl(p.pos(decl), ir.ODCLCONST, n))
612 if len(values) > len(names) {
613 base.Errorf("extra expression in const declaration")
621 func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
622 n := p.declName(ir.OTYPE, decl.Name)
623 typecheck.Declare(n, typecheck.DeclContext)
625 // decl.Type may be nil but in that case we got a syntax error during parsing
626 typ := p.typeExprOrNil(decl.Type)
629 n.SetAlias(decl.Alias)
630 if pragma, ok := decl.Pragma.(*pragmas); ok {
632 n.SetPragma(pragma.Flag & typePragmas)
633 pragma.Flag &^= typePragmas
635 p.checkUnused(pragma)
638 nod := ir.NewDecl(p.pos(decl), ir.ODCLTYPE, n)
639 if n.Alias() && !types.AllowsGoVersion(types.LocalPkg, 1, 9) {
640 base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
645 func (p *noder) declNames(op ir.Op, names []*syntax.Name) []*ir.Name {
646 nodes := make([]*ir.Name, 0, len(names))
647 for _, name := range names {
648 nodes = append(nodes, p.declName(op, name))
653 func (p *noder) declName(op ir.Op, name *syntax.Name) *ir.Name {
654 return ir.NewDeclNameAt(p.pos(name), op, p.name(name))
657 func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
658 name := p.name(fun.Name)
659 t := p.signature(fun.Recv, fun.Type)
660 f := ir.NewFunc(p.pos(fun))
663 if name.Name == "init" {
665 if len(t.Params) > 0 || len(t.Results) > 0 {
666 base.ErrorfAt(f.Pos(), "func init must have no arguments and no return values")
668 typecheck.Target.Inits = append(typecheck.Target.Inits, f)
671 if types.LocalPkg.Name == "main" && name.Name == "main" {
672 if len(t.Params) > 0 || len(t.Results) > 0 {
673 base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values")
678 name = ir.BlankNode.Sym() // filled in by typecheckfunc
681 f.Nname = ir.NewNameAt(p.pos(fun.Name), name)
686 if pragma, ok := fun.Pragma.(*pragmas); ok {
687 f.Pragma = pragma.Flag & funcPragmas
688 if pragma.Flag&ir.Systemstack != 0 && pragma.Flag&ir.Nosplit != 0 {
689 base.ErrorfAt(f.Pos(), "go:nosplit and go:systemstack cannot be combined")
691 pragma.Flag &^= funcPragmas
692 p.checkUnused(pragma)
696 typecheck.Declare(f.Nname, ir.PFUNC)
699 p.funcBody(f, fun.Body)
702 if f.Pragma&ir.Noescape != 0 {
703 base.ErrorfAt(f.Pos(), "can only use //go:noescape with external func implementations")
706 if base.Flag.Complete || strings.HasPrefix(ir.FuncName(f), "init.") {
707 // Linknamed functions are allowed to have no body. Hopefully
708 // the linkname target has a body. See issue 23311.
710 for _, n := range p.linknames {
711 if ir.FuncName(f) == n.local {
717 base.ErrorfAt(f.Pos(), "missing function body")
725 func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *ir.FuncType {
728 rcvr = p.param(recv, false, false)
730 return ir.NewFuncType(p.pos(typ), rcvr,
731 p.params(typ.ParamList, true),
732 p.params(typ.ResultList, false))
735 func (p *noder) params(params []*syntax.Field, dddOk bool) []*ir.Field {
736 nodes := make([]*ir.Field, 0, len(params))
737 for i, param := range params {
739 nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))
744 func (p *noder) param(param *syntax.Field, dddOk, final bool) *ir.Field {
746 if param.Name != nil {
747 name = p.name(param.Name)
750 typ := p.typeExpr(param.Type)
751 n := ir.NewField(p.pos(param), name, typ, nil)
753 // rewrite ...T parameter
754 if typ, ok := typ.(*ir.SliceType); ok && typ.DDD {
756 // We mark these as syntax errors to get automatic elimination
757 // of multiple such errors per line (see ErrorfAt in subr.go).
758 base.Errorf("syntax error: cannot use ... in receiver or result parameter list")
760 if param.Name == nil {
761 base.Errorf("syntax error: cannot use ... with non-final parameter")
763 p.errorAt(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value)
773 func (p *noder) exprList(expr syntax.Expr) []ir.Node {
774 switch expr := expr.(type) {
777 case *syntax.ListExpr:
778 return p.exprs(expr.ElemList)
780 return []ir.Node{p.expr(expr)}
784 func (p *noder) exprs(exprs []syntax.Expr) []ir.Node {
785 nodes := make([]ir.Node, 0, len(exprs))
786 for _, expr := range exprs {
787 nodes = append(nodes, p.expr(expr))
792 func (p *noder) expr(expr syntax.Expr) ir.Node {
794 switch expr := expr.(type) {
795 case nil, *syntax.BadExpr:
798 return p.mkname(expr)
799 case *syntax.BasicLit:
801 if expr != syntax.ImplicitOne { // ImplicitOne doesn't have a unique position
804 n := ir.NewBasicLit(pos, p.basicLit(expr))
805 if expr.Kind == syntax.RuneLit {
806 n.SetType(types.UntypedRune)
808 n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error
810 case *syntax.CompositeLit:
811 n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, p.typeExpr(expr.Type), nil)
812 l := p.exprs(expr.ElemList)
813 for i, e := range l {
814 l[i] = p.wrapname(expr.ElemList[i], e)
817 base.Pos = p.makeXPos(expr.Rbrace)
819 case *syntax.KeyValueExpr:
820 // use position of expr.Key rather than of expr (which has position of ':')
821 return ir.NewKeyExpr(p.pos(expr.Key), p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
822 case *syntax.FuncLit:
823 return p.funcLit(expr)
824 case *syntax.ParenExpr:
825 return ir.NewParenExpr(p.pos(expr), p.expr(expr.X))
826 case *syntax.SelectorExpr:
827 // parser.new_dotname
828 obj := p.expr(expr.X)
829 if obj.Op() == ir.OPACK {
830 pack := obj.(*ir.PkgName)
832 return importName(pack.Pkg.Lookup(expr.Sel.Value))
834 n := ir.NewSelectorExpr(base.Pos, ir.OXDOT, obj, p.name(expr.Sel))
835 n.SetPos(p.pos(expr)) // lineno may have been changed by p.expr(expr.X)
837 case *syntax.IndexExpr:
838 return ir.NewIndexExpr(p.pos(expr), p.expr(expr.X), p.expr(expr.Index))
839 case *syntax.SliceExpr:
846 for i, n := range &expr.Index {
851 return ir.NewSliceExpr(p.pos(expr), op, x, index[0], index[1], index[2])
852 case *syntax.AssertExpr:
853 return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type))
854 case *syntax.Operation:
855 if expr.Op == syntax.Add && expr.Y != nil {
860 pos, op := p.pos(expr), p.unOp(expr.Op)
863 return typecheck.NodAddrAt(pos, x)
865 return ir.NewStarExpr(pos, x)
867 return ir.NewUnaryExpr(pos, op, x)
870 pos, op, y := p.pos(expr), p.binOp(expr.Op), p.expr(expr.Y)
872 case ir.OANDAND, ir.OOROR:
873 return ir.NewLogicalExpr(pos, op, x, y)
875 return ir.NewBinaryExpr(pos, op, x, y)
876 case *syntax.CallExpr:
877 n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), p.exprs(expr.ArgList))
878 n.IsDDD = expr.HasDots
881 case *syntax.ArrayType:
884 len = p.expr(expr.Len)
886 return ir.NewArrayType(p.pos(expr), len, p.typeExpr(expr.Elem))
887 case *syntax.SliceType:
888 return ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
889 case *syntax.DotsType:
890 t := ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
893 case *syntax.StructType:
894 return p.structType(expr)
895 case *syntax.InterfaceType:
896 return p.interfaceType(expr)
897 case *syntax.FuncType:
898 return p.signature(nil, expr)
899 case *syntax.MapType:
900 return ir.NewMapType(p.pos(expr),
901 p.typeExpr(expr.Key), p.typeExpr(expr.Value))
902 case *syntax.ChanType:
903 return ir.NewChanType(p.pos(expr),
904 p.typeExpr(expr.Elem), p.chanDir(expr.Dir))
906 case *syntax.TypeSwitchGuard:
909 tag = ir.NewIdent(p.pos(expr.Lhs), p.name(expr.Lhs))
911 base.Errorf("invalid variable name %v in type switch", tag)
914 return ir.NewTypeSwitchGuard(p.pos(expr), tag, p.expr(expr.X))
916 panic("unhandled Expr")
919 // sum efficiently handles very large summation expressions (such as
920 // in issue #16394). In particular, it avoids left recursion and
921 // collapses string literals.
922 func (p *noder) sum(x syntax.Expr) ir.Node {
923 // While we need to handle long sums with asymptotic
924 // efficiency, the vast majority of sums are very small: ~95%
925 // have only 2 or 3 operands, and ~99% of string literals are
926 // never concatenated.
928 adds := make([]*syntax.Operation, 0, 2)
930 add, ok := x.(*syntax.Operation)
931 if !ok || add.Op != syntax.Add || add.Y == nil {
934 adds = append(adds, add)
938 // nstr is the current rightmost string literal in the
939 // summation (if any), and chunks holds its accumulated
942 // Consider the expression x + "a" + "b" + "c" + y. When we
943 // reach the string literal "a", we assign nstr to point to
944 // its corresponding Node and initialize chunks to {"a"}.
945 // Visiting the subsequent string literals "b" and "c", we
946 // simply append their values to chunks. Finally, when we
947 // reach the non-constant operand y, we'll join chunks to form
948 // "abc" and reassign the "a" string literal's value.
950 // N.B., we need to be careful about named string constants
951 // (indicated by Sym != nil) because 1) we can't modify their
952 // value, as doing so would affect other uses of the string
953 // constant, and 2) they may have types, which we need to
954 // handle correctly. For now, we avoid these problems by
955 // treating named string constants the same as non-constant
958 chunks := make([]string, 0, 1)
961 if ir.IsConst(n, constant.String) && n.Sym() == nil {
963 chunks = append(chunks, ir.StringVal(nstr))
966 for i := len(adds) - 1; i >= 0; i-- {
970 if ir.IsConst(r, constant.String) && r.Sym() == nil {
972 // Collapse r into nstr instead of adding to n.
973 chunks = append(chunks, ir.StringVal(r))
978 chunks = append(chunks, ir.StringVal(nstr))
981 nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
986 n = ir.NewBinaryExpr(p.pos(add), ir.OADD, n, r)
989 nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
995 func (p *noder) typeExpr(typ syntax.Expr) ir.Ntype {
996 // TODO(mdempsky): Be stricter? typecheck should handle errors anyway.
1001 if _, ok := n.(ir.Ntype); !ok {
1002 ir.Dump("NOT NTYPE", n)
1007 func (p *noder) typeExprOrNil(typ syntax.Expr) ir.Ntype {
1009 return p.typeExpr(typ)
1014 func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir {
1018 case syntax.SendOnly:
1020 case syntax.RecvOnly:
1023 panic("unhandled ChanDir")
1026 func (p *noder) structType(expr *syntax.StructType) ir.Node {
1027 l := make([]*ir.Field, 0, len(expr.FieldList))
1028 for i, field := range expr.FieldList {
1031 if field.Name == nil {
1032 n = p.embedded(field.Type)
1034 n = ir.NewField(p.pos(field), p.name(field.Name), p.typeExpr(field.Type), nil)
1036 if i < len(expr.TagList) && expr.TagList[i] != nil {
1037 n.Note = constant.StringVal(p.basicLit(expr.TagList[i]))
1043 return ir.NewStructType(p.pos(expr), l)
1046 func (p *noder) interfaceType(expr *syntax.InterfaceType) ir.Node {
1047 l := make([]*ir.Field, 0, len(expr.MethodList))
1048 for _, method := range expr.MethodList {
1051 if method.Name == nil {
1052 n = ir.NewField(p.pos(method), nil, importName(p.packname(method.Type)).(ir.Ntype), nil)
1054 mname := p.name(method.Name)
1055 if mname.IsBlank() {
1056 base.Errorf("methods must have a unique non-blank name")
1059 sig := p.typeExpr(method.Type).(*ir.FuncType)
1060 sig.Recv = fakeRecv()
1061 n = ir.NewField(p.pos(method), mname, sig, nil)
1066 return ir.NewInterfaceType(p.pos(expr), l)
1069 func (p *noder) packname(expr syntax.Expr) *types.Sym {
1070 switch expr := expr.(type) {
1072 name := p.name(expr)
1073 if n := oldname(name); n.Name() != nil && n.Name().PkgName != nil {
1074 n.Name().PkgName.Used = true
1077 case *syntax.SelectorExpr:
1078 name := p.name(expr.X.(*syntax.Name))
1079 def := ir.AsNode(name.Def)
1081 base.Errorf("undefined: %v", name)
1085 if def.Op() != ir.OPACK {
1086 base.Errorf("%v is not a package", name)
1087 pkg = types.LocalPkg
1089 def := def.(*ir.PkgName)
1093 return pkg.Lookup(expr.Sel.Value)
1095 panic(fmt.Sprintf("unexpected packname: %#v", expr))
1098 func (p *noder) embedded(typ syntax.Expr) *ir.Field {
1099 op, isStar := typ.(*syntax.Operation)
1101 if op.Op != syntax.Mul || op.Y != nil {
1102 panic("unexpected Operation")
1107 sym := p.packname(typ)
1108 n := ir.NewField(p.pos(typ), typecheck.Lookup(sym.Name), importName(sym).(ir.Ntype), nil)
1112 n.Ntype = ir.NewStarExpr(p.pos(op), n.Ntype)
1117 func (p *noder) stmts(stmts []syntax.Stmt) []ir.Node {
1118 return p.stmtsFall(stmts, false)
1121 func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []ir.Node {
1123 for i, stmt := range stmts {
1124 s := p.stmtFall(stmt, fallOK && i+1 == len(stmts))
1126 } else if s.Op() == ir.OBLOCK && len(s.(*ir.BlockStmt).List) > 0 {
1127 // Inline non-empty block.
1128 // Empty blocks must be preserved for checkreturn.
1129 nodes = append(nodes, s.(*ir.BlockStmt).List...)
1131 nodes = append(nodes, s)
1137 func (p *noder) stmt(stmt syntax.Stmt) ir.Node {
1138 return p.stmtFall(stmt, false)
1141 func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
1143 switch stmt := stmt.(type) {
1144 case nil, *syntax.EmptyStmt:
1146 case *syntax.LabeledStmt:
1147 return p.labeledStmt(stmt, fallOK)
1148 case *syntax.BlockStmt:
1149 l := p.blockStmt(stmt)
1151 // TODO(mdempsky): Line number?
1152 return ir.NewBlockStmt(base.Pos, nil)
1154 return ir.NewBlockStmt(src.NoXPos, l)
1155 case *syntax.ExprStmt:
1156 return p.wrapname(stmt, p.expr(stmt.X))
1157 case *syntax.SendStmt:
1158 return ir.NewSendStmt(p.pos(stmt), p.expr(stmt.Chan), p.expr(stmt.Value))
1159 case *syntax.DeclStmt:
1160 return ir.NewBlockStmt(src.NoXPos, p.decls(stmt.DeclList))
1161 case *syntax.AssignStmt:
1162 if stmt.Op != 0 && stmt.Op != syntax.Def {
1163 n := ir.NewAssignOpStmt(p.pos(stmt), p.binOp(stmt.Op), p.expr(stmt.Lhs), p.expr(stmt.Rhs))
1164 n.IncDec = stmt.Rhs == syntax.ImplicitOne
1168 rhs := p.exprList(stmt.Rhs)
1169 if list, ok := stmt.Lhs.(*syntax.ListExpr); ok && len(list.ElemList) != 1 || len(rhs) != 1 {
1170 n := ir.NewAssignListStmt(p.pos(stmt), ir.OAS2, nil, nil)
1171 n.Def = stmt.Op == syntax.Def
1172 n.Lhs = p.assignList(stmt.Lhs, n, n.Def)
1177 n := ir.NewAssignStmt(p.pos(stmt), nil, nil)
1178 n.Def = stmt.Op == syntax.Def
1179 n.X = p.assignList(stmt.Lhs, n, n.Def)[0]
1183 case *syntax.BranchStmt:
1188 case syntax.Continue:
1190 case syntax.Fallthrough:
1192 base.Errorf("fallthrough statement out of place")
1198 panic("unhandled BranchStmt")
1201 if stmt.Label != nil {
1202 sym = p.name(stmt.Label)
1204 return ir.NewBranchStmt(p.pos(stmt), op, sym)
1205 case *syntax.CallStmt:
1213 panic("unhandled CallStmt")
1215 return ir.NewGoDeferStmt(p.pos(stmt), op, p.expr(stmt.Call))
1216 case *syntax.ReturnStmt:
1217 n := ir.NewReturnStmt(p.pos(stmt), p.exprList(stmt.Results))
1218 if len(n.Results) == 0 && ir.CurFunc != nil {
1219 for _, ln := range ir.CurFunc.Dcl {
1220 if ln.Class == ir.PPARAM {
1223 if ln.Class != ir.PPARAMOUT {
1226 if ln.Sym().Def != ln {
1227 base.Errorf("%s is shadowed during return", ln.Sym().Name)
1232 case *syntax.IfStmt:
1233 return p.ifStmt(stmt)
1234 case *syntax.ForStmt:
1235 return p.forStmt(stmt)
1236 case *syntax.SwitchStmt:
1237 return p.switchStmt(stmt)
1238 case *syntax.SelectStmt:
1239 return p.selectStmt(stmt)
1241 panic("unhandled Stmt")
1244 func (p *noder) assignList(expr syntax.Expr, defn ir.InitNode, colas bool) []ir.Node {
1246 return p.exprList(expr)
1249 var exprs []syntax.Expr
1250 if list, ok := expr.(*syntax.ListExpr); ok {
1251 exprs = list.ElemList
1253 exprs = []syntax.Expr{expr}
1256 res := make([]ir.Node, len(exprs))
1257 seen := make(map[*types.Sym]bool, len(exprs))
1260 for i, expr := range exprs {
1262 res[i] = ir.BlankNode
1264 name, ok := expr.(*syntax.Name)
1266 p.errorAt(expr.Pos(), "non-name %v on left side of :=", p.expr(expr))
1277 p.errorAt(expr.Pos(), "%v repeated on left side of :=", sym)
1283 if sym.Block == types.Block {
1284 res[i] = oldname(sym)
1289 n := typecheck.NewName(sym)
1290 typecheck.Declare(n, typecheck.DeclContext)
1292 defn.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, n))
1297 base.ErrorfAt(defn.Pos(), "no new variables on left side of :=")
1302 func (p *noder) blockStmt(stmt *syntax.BlockStmt) []ir.Node {
1303 p.openScope(stmt.Pos())
1304 nodes := p.stmts(stmt.List)
1305 p.closeScope(stmt.Rbrace)
1309 func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
1310 p.openScope(stmt.Pos())
1311 init := p.stmt(stmt.Init)
1312 n := ir.NewIfStmt(p.pos(stmt), p.expr(stmt.Cond), p.blockStmt(stmt.Then), nil)
1314 *n.PtrInit() = []ir.Node{init}
1316 if stmt.Else != nil {
1317 e := p.stmt(stmt.Else)
1318 if e.Op() == ir.OBLOCK {
1319 e := e.(*ir.BlockStmt)
1322 n.Else = []ir.Node{e}
1325 p.closeAnotherScope()
1329 func (p *noder) forStmt(stmt *syntax.ForStmt) ir.Node {
1330 p.openScope(stmt.Pos())
1331 if r, ok := stmt.Init.(*syntax.RangeClause); ok {
1332 if stmt.Cond != nil || stmt.Post != nil {
1333 panic("unexpected RangeClause")
1336 n := ir.NewRangeStmt(p.pos(r), nil, nil, p.expr(r.X), nil)
1339 lhs := p.assignList(r.Lhs, n, n.Def)
1345 n.Body = p.blockStmt(stmt.Body)
1346 p.closeAnotherScope()
1350 n := ir.NewForStmt(p.pos(stmt), p.stmt(stmt.Init), p.expr(stmt.Cond), p.stmt(stmt.Post), p.blockStmt(stmt.Body))
1351 p.closeAnotherScope()
1355 func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
1356 p.openScope(stmt.Pos())
1358 init := p.stmt(stmt.Init)
1359 n := ir.NewSwitchStmt(p.pos(stmt), p.expr(stmt.Tag), nil)
1361 *n.PtrInit() = []ir.Node{init}
1364 var tswitch *ir.TypeSwitchGuard
1365 if l := n.Tag; l != nil && l.Op() == ir.OTYPESW {
1366 tswitch = l.(*ir.TypeSwitchGuard)
1368 n.Cases = p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)
1370 p.closeScope(stmt.Rbrace)
1374 func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []*ir.CaseClause {
1375 nodes := make([]*ir.CaseClause, 0, len(clauses))
1376 for i, clause := range clauses {
1379 p.closeScope(clause.Pos())
1381 p.openScope(clause.Pos())
1383 n := ir.NewCaseStmt(p.pos(clause), p.exprList(clause.Cases), nil)
1384 if tswitch != nil && tswitch.Tag != nil {
1385 nn := typecheck.NewName(tswitch.Tag.Sym())
1386 typecheck.Declare(nn, typecheck.DeclContext)
1388 // keep track of the instances for reporting unused
1392 // Trim trailing empty statements. We omit them from
1393 // the Node AST anyway, and it's easier to identify
1394 // out-of-place fallthrough statements without them.
1397 if _, ok := body[len(body)-1].(*syntax.EmptyStmt); !ok {
1400 body = body[:len(body)-1]
1403 n.Body = p.stmtsFall(body, true)
1404 if l := len(n.Body); l > 0 && n.Body[l-1].Op() == ir.OFALL {
1406 base.Errorf("cannot fallthrough in type switch")
1408 if i+1 == len(clauses) {
1409 base.Errorf("cannot fallthrough final case in switch")
1413 nodes = append(nodes, n)
1415 if len(clauses) > 0 {
1416 p.closeScope(rbrace)
1421 func (p *noder) selectStmt(stmt *syntax.SelectStmt) ir.Node {
1422 return ir.NewSelectStmt(p.pos(stmt), p.commClauses(stmt.Body, stmt.Rbrace))
1425 func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*ir.CommClause {
1426 nodes := make([]*ir.CommClause, len(clauses))
1427 for i, clause := range clauses {
1430 p.closeScope(clause.Pos())
1432 p.openScope(clause.Pos())
1434 nodes[i] = ir.NewCommStmt(p.pos(clause), p.stmt(clause.Comm), p.stmts(clause.Body))
1436 if len(clauses) > 0 {
1437 p.closeScope(rbrace)
1442 func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) ir.Node {
1443 sym := p.name(label.Label)
1444 lhs := ir.NewLabelStmt(p.pos(label), sym)
1447 if label.Stmt != nil { // TODO(mdempsky): Should always be present.
1448 ls = p.stmtFall(label.Stmt, fallOK)
1449 // Attach label directly to control statement too.
1453 ls := ls.(*ir.ForStmt)
1456 ls := ls.(*ir.RangeStmt)
1459 ls := ls.(*ir.SwitchStmt)
1462 ls := ls.(*ir.SelectStmt)
1470 if ls.Op() == ir.OBLOCK {
1471 ls := ls.(*ir.BlockStmt)
1472 l = append(l, ls.List...)
1477 return ir.NewBlockStmt(src.NoXPos, l)
1480 var unOps = [...]ir.Op{
1481 syntax.Recv: ir.ORECV,
1482 syntax.Mul: ir.ODEREF,
1483 syntax.And: ir.OADDR,
1485 syntax.Not: ir.ONOT,
1486 syntax.Xor: ir.OBITNOT,
1487 syntax.Add: ir.OPLUS,
1488 syntax.Sub: ir.ONEG,
1491 func (p *noder) unOp(op syntax.Operator) ir.Op {
1492 if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 {
1493 panic("invalid Operator")
1498 var binOps = [...]ir.Op{
1499 syntax.OrOr: ir.OOROR,
1500 syntax.AndAnd: ir.OANDAND,
1509 syntax.Add: ir.OADD,
1510 syntax.Sub: ir.OSUB,
1512 syntax.Xor: ir.OXOR,
1514 syntax.Mul: ir.OMUL,
1515 syntax.Div: ir.ODIV,
1516 syntax.Rem: ir.OMOD,
1517 syntax.And: ir.OAND,
1518 syntax.AndNot: ir.OANDNOT,
1519 syntax.Shl: ir.OLSH,
1520 syntax.Shr: ir.ORSH,
1523 func (p *noder) binOp(op syntax.Operator) ir.Op {
1524 if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 {
1525 panic("invalid Operator")
1530 // checkLangCompat reports an error if the representation of a numeric
1531 // literal is not compatible with the current language version.
1532 func checkLangCompat(lit *syntax.BasicLit) {
1534 if len(s) <= 2 || types.AllowsGoVersion(types.LocalPkg, 1, 13) {
1538 if strings.Contains(s, "_") {
1539 base.ErrorfVers("go1.13", "underscores in numeric literals")
1546 if radix == 'b' || radix == 'B' {
1547 base.ErrorfVers("go1.13", "binary literals")
1550 if radix == 'o' || radix == 'O' {
1551 base.ErrorfVers("go1.13", "0o/0O-style octal literals")
1554 if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
1555 base.ErrorfVers("go1.13", "hexadecimal floating-point literals")
1559 func (p *noder) basicLit(lit *syntax.BasicLit) constant.Value {
1560 // We don't use the errors of the conversion routines to determine
1561 // if a literal string is valid because the conversion routines may
1562 // accept a wider syntax than the language permits. Rely on lit.Bad
1565 return constant.MakeUnknown()
1569 case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
1570 checkLangCompat(lit)
1573 v := constant.MakeFromLiteral(lit.Value, tokenForLitKind[lit.Kind], 0)
1574 if v.Kind() == constant.Unknown {
1575 // TODO(mdempsky): Better error message?
1576 p.errorAt(lit.Pos(), "malformed constant: %s", lit.Value)
1579 // go/constant uses big.Rat by default, which is more precise, but
1580 // causes toolstash -cmp and some tests to fail. For now, convert
1581 // to big.Float to match cmd/compile's historical precision.
1582 // TODO(mdempsky): Remove.
1583 if v.Kind() == constant.Float {
1584 v = constant.Make(ir.BigFloat(v))
1590 var tokenForLitKind = [...]token.Token{
1591 syntax.IntLit: token.INT,
1592 syntax.RuneLit: token.CHAR,
1593 syntax.FloatLit: token.FLOAT,
1594 syntax.ImagLit: token.IMAG,
1595 syntax.StringLit: token.STRING,
1598 func (p *noder) name(name *syntax.Name) *types.Sym {
1599 return typecheck.Lookup(name.Value)
1602 func (p *noder) mkname(name *syntax.Name) ir.Node {
1603 // TODO(mdempsky): Set line number?
1604 return mkname(p.name(name))
1607 func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node {
1608 // These nodes do not carry line numbers.
1609 // Introduce a wrapper node to give them the correct line.
1611 case ir.OTYPE, ir.OLITERAL:
1616 case ir.ONAME, ir.ONONAME, ir.OPACK:
1617 p := ir.NewParenExpr(p.pos(n), x)
1624 func (p *noder) setlineno(n syntax.Node) {
1625 if n != nil && n != syntax.ImplicitOne {
1630 // error is called concurrently if files are parsed concurrently.
1631 func (p *noder) error(err error) {
1632 p.err <- err.(syntax.Error)
1635 // pragmas that are allowed in the std lib, but don't have
1636 // a syntax.Pragma value (see lex.go) associated with them.
1637 var allowedStdPragmas = map[string]bool{
1638 "go:cgo_export_static": true,
1639 "go:cgo_export_dynamic": true,
1640 "go:cgo_import_static": true,
1641 "go:cgo_import_dynamic": true,
1642 "go:cgo_ldflag": true,
1643 "go:cgo_dynamic_linker": true,
1645 "go:generate": true,
1648 // *pragmas is the value stored in a syntax.pragmas during parsing.
1649 type pragmas struct {
1650 Flag ir.PragmaFlag // collected bits
1651 Pos []pragmaPos // position of each individual flag
1652 Embeds []pragmaEmbed
1655 type pragmaPos struct {
1660 type pragmaEmbed struct {
1665 func (p *noder) checkUnused(pragma *pragmas) {
1666 for _, pos := range pragma.Pos {
1667 if pos.Flag&pragma.Flag != 0 {
1668 p.errorAt(pos.Pos, "misplaced compiler directive")
1671 if len(pragma.Embeds) > 0 {
1672 for _, e := range pragma.Embeds {
1673 p.errorAt(e.Pos, "misplaced go:embed directive")
1678 func (p *noder) checkUnusedDuringParse(pragma *pragmas) {
1679 for _, pos := range pragma.Pos {
1680 if pos.Flag&pragma.Flag != 0 {
1681 p.error(syntax.Error{Pos: pos.Pos, Msg: "misplaced compiler directive"})
1684 if len(pragma.Embeds) > 0 {
1685 for _, e := range pragma.Embeds {
1686 p.error(syntax.Error{Pos: e.Pos, Msg: "misplaced go:embed directive"})
1691 // pragma is called concurrently if files are parsed concurrently.
1692 func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.Pragma) syntax.Pragma {
1693 pragma, _ := old.(*pragmas)
1695 pragma = new(pragmas)
1699 // unused pragma; only called with old != nil.
1700 p.checkUnusedDuringParse(pragma)
1704 if strings.HasPrefix(text, "line ") {
1705 // line directives are handled by syntax package
1706 panic("unreachable")
1710 // directive must be on line by itself
1711 p.error(syntax.Error{Pos: pos, Msg: "misplaced compiler directive"})
1716 case strings.HasPrefix(text, "go:linkname "):
1717 f := strings.Fields(text)
1718 if !(2 <= len(f) && len(f) <= 3) {
1719 p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname [linkname]"})
1722 // The second argument is optional. If omitted, we use
1723 // the default object symbol name for this and
1724 // linkname only serves to mark this symbol as
1725 // something that may be referenced via the object
1726 // symbol name from another package.
1730 } else if base.Ctxt.Pkgpath != "" {
1731 // Use the default object symbol name if the
1732 // user didn't provide one.
1733 target = objabi.PathToPrefix(base.Ctxt.Pkgpath) + "." + f[1]
1735 p.error(syntax.Error{Pos: pos, Msg: "//go:linkname requires linkname argument or -p compiler flag"})
1738 p.linknames = append(p.linknames, linkname{pos, f[1], target})
1740 case text == "go:embed", strings.HasPrefix(text, "go:embed "):
1741 args, err := parseGoEmbed(text[len("go:embed"):])
1743 p.error(syntax.Error{Pos: pos, Msg: err.Error()})
1746 p.error(syntax.Error{Pos: pos, Msg: "usage: //go:embed pattern..."})
1749 pragma.Embeds = append(pragma.Embeds, pragmaEmbed{pos, args})
1751 case strings.HasPrefix(text, "go:cgo_import_dynamic "):
1752 // This is permitted for general use because Solaris
1753 // code relies on it in golang.org/x/sys/unix and others.
1754 fields := pragmaFields(text)
1755 if len(fields) >= 4 {
1756 lib := strings.Trim(fields[3], `"`)
1757 if lib != "" && !safeArg(lib) && !isCgoGeneratedFile(pos) {
1758 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("invalid library name %q in cgo_import_dynamic directive", lib)})
1760 p.pragcgo(pos, text)
1761 pragma.Flag |= pragmaFlag("go:cgo_import_dynamic")
1765 case strings.HasPrefix(text, "go:cgo_"):
1766 // For security, we disallow //go:cgo_* directives other
1767 // than cgo_import_dynamic outside cgo-generated files.
1768 // Exception: they are allowed in the standard library, for runtime and syscall.
1769 if !isCgoGeneratedFile(pos) && !base.Flag.Std {
1770 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
1772 p.pragcgo(pos, text)
1773 fallthrough // because of //go:cgo_unsafe_args
1776 if i := strings.Index(text, " "); i >= 0 {
1779 flag := pragmaFlag(verb)
1780 const runtimePragmas = ir.Systemstack | ir.Nowritebarrier | ir.Nowritebarrierrec | ir.Yeswritebarrierrec
1781 if !base.Flag.CompilingRuntime && flag&runtimePragmas != 0 {
1782 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)})
1784 if flag == 0 && !allowedStdPragmas[verb] && base.Flag.Std {
1785 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)})
1788 pragma.Pos = append(pragma.Pos, pragmaPos{flag, pos})
1794 // isCgoGeneratedFile reports whether pos is in a file
1795 // generated by cgo, which is to say a file with name
1796 // beginning with "_cgo_". Such files are allowed to
1797 // contain cgo directives, and for security reasons
1798 // (primarily misuse of linker flags), other files are not.
1799 // See golang.org/issue/23672.
1800 func isCgoGeneratedFile(pos syntax.Pos) bool {
1801 return strings.HasPrefix(filepath.Base(filepath.Clean(fileh(pos.Base().Filename()))), "_cgo_")
1804 // safeArg reports whether arg is a "safe" command-line argument,
1805 // meaning that when it appears in a command-line, it probably
1806 // doesn't have some special meaning other than its own name.
1807 // This is copied from SafeArg in cmd/go/internal/load/pkg.go.
1808 func safeArg(name string) bool {
1813 return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
1816 func mkname(sym *types.Sym) ir.Node {
1818 if n.Name() != nil && n.Name().PkgName != nil {
1819 n.Name().PkgName.Used = true
1824 // parseGoEmbed parses the text following "//go:embed" to extract the glob patterns.
1825 // It accepts unquoted space-separated patterns as well as double-quoted and back-quoted Go strings.
1826 // go/build/read.go also processes these strings and contains similar logic.
1827 func parseGoEmbed(args string) ([]string, error) {
1829 for args = strings.TrimSpace(args); args != ""; args = strings.TrimSpace(args) {
1835 for j, c := range args {
1836 if unicode.IsSpace(c) {
1845 i := strings.Index(args[1:], "`")
1847 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1849 path = args[1 : 1+i]
1854 for ; i < len(args); i++ {
1855 if args[i] == '\\' {
1860 q, err := strconv.Unquote(args[:i+1])
1862 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args[:i+1])
1870 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1875 r, _ := utf8.DecodeRuneInString(args)
1876 if !unicode.IsSpace(r) {
1877 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1880 list = append(list, path)
1885 func fakeRecv() *ir.Field {
1886 return ir.NewField(base.Pos, nil, nil, types.FakeRecvType())
1889 func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
1890 xtype := p.typeExpr(expr.Type)
1892 fn := ir.NewFunc(p.pos(expr))
1893 fn.SetIsHiddenClosure(ir.CurFunc != nil)
1895 fn.Nname = ir.NewNameAt(p.pos(expr), ir.BlankNode.Sym()) // filled in by typecheckclosure
1897 fn.Nname.Ntype = xtype
1900 clo := ir.NewClosureExpr(p.pos(expr), fn)
1903 p.funcBody(fn, expr.Body)
1905 ir.FinishCaptureNames(base.Pos, ir.CurFunc, fn)
1910 // A function named init is a special case.
1911 // It is called by the initialization before main is run.
1912 // To make it unique within a package and also uncallable,
1913 // the name, normally "pkg.init", is altered to "pkg.init.0".
1914 var renameinitgen int
1916 func renameinit() *types.Sym {
1917 s := typecheck.LookupNum("init.", renameinitgen)
1922 // oldname returns the Node that declares symbol s in the current scope.
1923 // If no such Node currently exists, an ONONAME Node is returned instead.
1924 // Automatically creates a new closure variable if the referenced symbol was
1925 // declared in a different (containing) function.
1926 func oldname(s *types.Sym) ir.Node {
1927 if s.Pkg != types.LocalPkg {
1928 return ir.NewIdent(base.Pos, s)
1931 n := ir.AsNode(s.Def)
1933 // Maybe a top-level declaration will come along later to
1934 // define s. resolve will check s.Def again once all input
1935 // source has been processed.
1936 return ir.NewIdent(base.Pos, s)
1939 if n, ok := n.(*ir.Name); ok {
1940 // TODO(rsc): If there is an outer variable x and we
1941 // are parsing x := 5 inside the closure, until we get to
1942 // the := it looks like a reference to the outer x so we'll
1943 // make x a closure variable unnecessarily.
1944 return ir.CaptureName(base.Pos, ir.CurFunc, n)
1950 func varEmbed(makeXPos func(syntax.Pos) src.XPos, name *ir.Name, decl *syntax.VarDecl, pragma *pragmas) error {
1951 if pragma.Embeds == nil {
1955 pragmaEmbeds := pragma.Embeds
1958 if base.Flag.Cfg.Embed.Patterns == nil {
1959 return errors.New("invalid go:embed: build system did not supply embed configuration")
1961 if len(decl.NameList) > 1 {
1962 return errors.New("go:embed cannot apply to multiple vars")
1964 if decl.Values != nil {
1965 return errors.New("go:embed cannot apply to var with initializer")
1967 if decl.Type == nil {
1968 // Should not happen, since Values == nil now.
1969 return errors.New("go:embed cannot apply to var without type")
1971 if typecheck.DeclContext != ir.PEXTERN {
1972 return errors.New("go:embed cannot apply to var inside func")
1975 var embeds []ir.Embed
1976 for _, e := range pragmaEmbeds {
1977 embeds = append(embeds, ir.Embed{Pos: makeXPos(e.Pos), Patterns: e.Patterns})
1979 typecheck.Target.Embeds = append(typecheck.Target.Embeds, name)
1980 name.Embed = &embeds