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.
19 "cmd/compile/internal/base"
20 "cmd/compile/internal/dwarfgen"
21 "cmd/compile/internal/ir"
22 "cmd/compile/internal/syntax"
23 "cmd/compile/internal/typecheck"
24 "cmd/compile/internal/types"
29 func LoadPackage(filenames []string) {
30 base.Timer.Start("fe", "parse")
32 mode := syntax.CheckBranches
34 mode |= syntax.AllowGenerics
37 // Limit the number of simultaneously open files.
38 sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
40 noders := make([]*noder, len(filenames))
41 for i, filename := range filenames {
43 err: make(chan syntax.Error),
44 trackScopes: base.Flag.Dwarf,
51 defer func() { <-sem }()
53 fbase := syntax.NewFileBase(filename)
55 f, err := os.Open(filename)
57 p.error(syntax.Error{Msg: err.Error()})
62 p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error
67 for _, p := range noders {
68 for e := range p.err {
69 p.errorAt(e.Pos, "%s", e.Msg)
71 lines += p.file.EOF.Line()
73 base.Timer.AddEvent(int64(lines), "lines")
76 // Use types2 to type-check and possibly generate IR.
81 for _, p := range noders {
83 p.file = nil // release memory
86 if base.SyntaxErrors() != 0 {
91 for _, p := range noders {
96 types.LocalPkg.Height = myheight
97 typecheck.DeclareUniverse()
98 typecheck.TypecheckAllowed = true
100 // Process top-level declarations in phases.
102 // Phase 1: const, type, and names and types of funcs.
103 // This will gather all the information about types
104 // and methods but doesn't depend on any of it.
106 // We also defer type alias declarations until phase 2
107 // to avoid cycles like #18640.
108 // TODO(gri) Remove this again once we have a fix for #25838.
110 // Don't use range--typecheck can add closures to Target.Decls.
111 base.Timer.Start("fe", "typecheck", "top1")
112 for i := 0; i < len(typecheck.Target.Decls); i++ {
113 n := typecheck.Target.Decls[i]
114 if op := n.Op(); op != ir.ODCL && op != ir.OAS && op != ir.OAS2 && (op != ir.ODCLTYPE || !n.(*ir.Decl).X.Alias()) {
115 typecheck.Target.Decls[i] = typecheck.Stmt(n)
119 // Phase 2: Variable assignments.
120 // To check interface assignments, depends on phase 1.
122 // Don't use range--typecheck can add closures to Target.Decls.
123 base.Timer.Start("fe", "typecheck", "top2")
124 for i := 0; i < len(typecheck.Target.Decls); i++ {
125 n := typecheck.Target.Decls[i]
126 if op := n.Op(); op == ir.ODCL || op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).X.Alias() {
127 typecheck.Target.Decls[i] = typecheck.Stmt(n)
131 // Phase 3: Type check function bodies.
132 // Don't use range--typecheck can add closures to Target.Decls.
133 base.Timer.Start("fe", "typecheck", "func")
135 for i := 0; i < len(typecheck.Target.Decls); i++ {
136 n := typecheck.Target.Decls[i]
137 if n.Op() == ir.ODCLFUNC {
139 s := fmt.Sprintf("\nbefore typecheck %v", n)
142 typecheck.FuncBody(n.(*ir.Func))
144 s := fmt.Sprintf("\nafter typecheck %v", n)
151 // Phase 4: Check external declarations.
152 // TODO(mdempsky): This should be handled when type checking their
153 // corresponding ODCL nodes.
154 base.Timer.Start("fe", "typecheck", "externdcls")
155 for i, n := range typecheck.Target.Externs {
156 if n.Op() == ir.ONAME {
157 typecheck.Target.Externs[i] = typecheck.Expr(typecheck.Target.Externs[i])
161 // Phase 5: With all user code type-checked, it's now safe to verify map keys.
162 // With all user code typechecked, it's now safe to verify unused dot imports.
163 typecheck.CheckMapKeys()
168 func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
169 base.ErrorfAt(p.makeXPos(pos), format, args...)
172 // TODO(gri) Can we eliminate fileh in favor of absFilename?
173 func fileh(name string) string {
174 return objabi.AbsFile("", name, base.Flag.TrimPath)
177 func absFilename(name string) string {
178 return objabi.AbsFile(base.Ctxt.Pathname, name, base.Flag.TrimPath)
181 // noder transforms package syntax's AST into a Node tree.
187 pragcgobuf [][]string
188 err chan syntax.Error
196 // funcState tracks all per-function state to make handling nested
198 type funcState struct {
199 // scopeVars is a stack tracking the number of variables declared in
200 // the current function at the moment each open scope was opened.
202 marker dwarfgen.ScopeMarker
204 lastCloseScopePos syntax.Pos
207 func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
208 outerFuncState := p.funcState
209 p.funcState = new(funcState)
210 typecheck.StartFuncBody(fn)
213 body := p.stmts(block.List)
215 body = []ir.Node{ir.NewBlockStmt(base.Pos, nil)}
219 base.Pos = p.makeXPos(block.Rbrace)
220 fn.Endlineno = base.Pos
223 typecheck.FinishFuncBody()
224 p.funcState.marker.WriteTo(fn)
225 p.funcState = outerFuncState
228 func (p *noder) openScope(pos syntax.Pos) {
233 fs.scopeVars = append(fs.scopeVars, len(ir.CurFunc.Dcl))
234 fs.marker.Push(p.makeXPos(pos))
238 func (p *noder) closeScope(pos syntax.Pos) {
240 fs.lastCloseScopePos = pos
244 scopeVars := fs.scopeVars[len(fs.scopeVars)-1]
245 fs.scopeVars = fs.scopeVars[:len(fs.scopeVars)-1]
246 if scopeVars == len(ir.CurFunc.Dcl) {
247 // no variables were declared in this scope, so we can retract it.
250 fs.marker.Pop(p.makeXPos(pos))
255 // closeAnotherScope is like closeScope, but it reuses the same mark
256 // position as the last closeScope call. This is useful for "for" and
257 // "if" statements, as their implicit blocks always end at the same
258 // position as an explicit block.
259 func (p *noder) closeAnotherScope() {
260 p.closeScope(p.funcState.lastCloseScopePos)
263 // linkname records a //go:linkname directive.
264 type linkname struct {
270 func (p *noder) node() {
271 p.importedUnsafe = false
272 p.importedEmbed = false
274 p.setlineno(p.file.PkgName)
275 mkpackage(p.file.PkgName.Value)
277 if pragma, ok := p.file.Pragma.(*pragmas); ok {
278 pragma.Flag &^= ir.GoBuildPragma
279 p.checkUnused(pragma)
282 typecheck.Target.Decls = append(typecheck.Target.Decls, p.decls(p.file.DeclList)...)
284 base.Pos = src.NoXPos
288 func (p *noder) processPragmas() {
289 for _, l := range p.linknames {
290 if !p.importedUnsafe {
291 p.errorAt(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
294 n := ir.AsNode(typecheck.Lookup(l.local).Def)
295 if n == nil || n.Op() != ir.ONAME {
296 // TODO(mdempsky): Change to p.errorAt before Go 1.17 release.
297 // base.WarnfAt(p.makeXPos(l.pos), "//go:linkname must refer to declared function or variable (will be an error in Go 1.17)")
300 if n.Sym().Linkname != "" {
301 p.errorAt(l.pos, "duplicate //go:linkname for %s", l.local)
304 n.Sym().Linkname = l.remote
306 typecheck.Target.CgoPragmas = append(typecheck.Target.CgoPragmas, p.pragcgobuf...)
309 func (p *noder) decls(decls []syntax.Decl) (l []ir.Node) {
312 for _, decl := range decls {
314 switch decl := decl.(type) {
315 case *syntax.ImportDecl:
318 case *syntax.VarDecl:
319 l = append(l, p.varDecl(decl)...)
321 case *syntax.ConstDecl:
322 l = append(l, p.constDecl(decl, &cs)...)
324 case *syntax.TypeDecl:
325 l = append(l, p.typeDecl(decl))
327 case *syntax.FuncDecl:
328 l = append(l, p.funcDecl(decl))
331 panic("unhandled Decl")
338 func (p *noder) importDecl(imp *syntax.ImportDecl) {
339 if imp.Path == nil || imp.Path.Bad {
340 return // avoid follow-on errors if there was a syntax error
343 if pragma, ok := imp.Pragma.(*pragmas); ok {
344 p.checkUnused(pragma)
347 ipkg := importfile(imp)
349 if base.Errors() == 0 {
350 base.Fatalf("phase error in import")
355 if ipkg == ir.Pkgs.Unsafe {
356 p.importedUnsafe = true
358 if ipkg.Path == "embed" {
359 p.importedEmbed = true
363 if imp.LocalPkgName != nil {
364 my = p.name(imp.LocalPkgName)
366 my = typecheck.Lookup(ipkg.Name)
369 pack := ir.NewPkgName(p.pos(imp), my, ipkg)
376 base.ErrorfAt(pack.Pos(), "cannot import package as init - init must be a func")
382 typecheck.Redeclared(pack.Pos(), my, "as imported package name")
385 my.Lastlineno = pack.Pos()
386 my.Block = 1 // at top level
389 func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
390 names := p.declNames(ir.ONAME, decl.NameList)
391 typ := p.typeExprOrNil(decl.Type)
392 exprs := p.exprList(decl.Values)
394 if pragma, ok := decl.Pragma.(*pragmas); ok {
395 varEmbed(p.makeXPos, names[0], decl, pragma, p.importedEmbed)
396 p.checkUnused(pragma)
402 if len(names) > 1 && len(exprs) == 1 {
403 as2 := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, exprs)
404 for _, v := range names {
406 typecheck.Declare(v, typecheck.DeclContext)
409 if ir.CurFunc != nil {
410 init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
414 return append(init, as2)
417 for i, v := range names {
423 typecheck.Declare(v, typecheck.DeclContext)
426 if ir.CurFunc != nil {
427 init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
429 as := ir.NewAssignStmt(base.Pos, v, e)
430 init = append(init, as)
431 if e != nil || ir.CurFunc == nil {
436 if len(exprs) != 0 && len(names) != len(exprs) {
437 base.Errorf("assignment mismatch: %d variables but %d values", len(names), len(exprs))
443 // constState tracks state between constant specifiers within a
444 // declaration group. This state is kept separate from noder so nested
445 // constant declarations are handled correctly (e.g., issue 15550).
446 type constState struct {
453 func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node {
454 if decl.Group == nil || decl.Group != cs.group {
460 if pragma, ok := decl.Pragma.(*pragmas); ok {
461 p.checkUnused(pragma)
464 names := p.declNames(ir.OLITERAL, decl.NameList)
465 typ := p.typeExprOrNil(decl.Type)
468 if decl.Values != nil {
469 values = p.exprList(decl.Values)
470 cs.typ, cs.values = typ, values
473 base.Errorf("const declaration cannot have type without expression")
475 typ, values = cs.typ, cs.values
478 nn := make([]ir.Node, 0, len(names))
479 for i, n := range names {
480 if i >= len(values) {
481 base.Errorf("missing value in const declaration")
485 if decl.Values == nil {
486 v = ir.DeepCopy(n.Pos(), v)
488 typecheck.Declare(n, typecheck.DeclContext)
494 nn = append(nn, ir.NewDecl(p.pos(decl), ir.ODCLCONST, n))
497 if len(values) > len(names) {
498 base.Errorf("extra expression in const declaration")
506 func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
507 n := p.declName(ir.OTYPE, decl.Name)
508 typecheck.Declare(n, typecheck.DeclContext)
510 // decl.Type may be nil but in that case we got a syntax error during parsing
511 typ := p.typeExprOrNil(decl.Type)
514 n.SetAlias(decl.Alias)
515 if pragma, ok := decl.Pragma.(*pragmas); ok {
517 n.SetPragma(pragma.Flag & typePragmas)
518 pragma.Flag &^= typePragmas
520 p.checkUnused(pragma)
523 nod := ir.NewDecl(p.pos(decl), ir.ODCLTYPE, n)
524 if n.Alias() && !types.AllowsGoVersion(types.LocalPkg, 1, 9) {
525 base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
530 func (p *noder) declNames(op ir.Op, names []*syntax.Name) []*ir.Name {
531 nodes := make([]*ir.Name, 0, len(names))
532 for _, name := range names {
533 nodes = append(nodes, p.declName(op, name))
538 func (p *noder) declName(op ir.Op, name *syntax.Name) *ir.Name {
539 return ir.NewDeclNameAt(p.pos(name), op, p.name(name))
542 func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
543 name := p.name(fun.Name)
544 t := p.signature(fun.Recv, fun.Type)
545 f := ir.NewFunc(p.pos(fun))
548 if name.Name == "init" {
550 if len(t.Params) > 0 || len(t.Results) > 0 {
551 base.ErrorfAt(f.Pos(), "func init must have no arguments and no return values")
553 typecheck.Target.Inits = append(typecheck.Target.Inits, f)
556 if types.LocalPkg.Name == "main" && name.Name == "main" {
557 if len(t.Params) > 0 || len(t.Results) > 0 {
558 base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values")
563 name = ir.BlankNode.Sym() // filled in by tcFunc
566 f.Nname = ir.NewNameAt(p.pos(fun.Name), name)
571 if pragma, ok := fun.Pragma.(*pragmas); ok {
572 f.Pragma = pragma.Flag & funcPragmas
573 if pragma.Flag&ir.Systemstack != 0 && pragma.Flag&ir.Nosplit != 0 {
574 base.ErrorfAt(f.Pos(), "go:nosplit and go:systemstack cannot be combined")
576 pragma.Flag &^= funcPragmas
577 p.checkUnused(pragma)
581 typecheck.Declare(f.Nname, ir.PFUNC)
584 p.funcBody(f, fun.Body)
587 if f.Pragma&ir.Noescape != 0 {
588 base.ErrorfAt(f.Pos(), "can only use //go:noescape with external func implementations")
591 if base.Flag.Complete || strings.HasPrefix(ir.FuncName(f), "init.") {
592 // Linknamed functions are allowed to have no body. Hopefully
593 // the linkname target has a body. See issue 23311.
595 for _, n := range p.linknames {
596 if ir.FuncName(f) == n.local {
602 base.ErrorfAt(f.Pos(), "missing function body")
610 func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *ir.FuncType {
613 rcvr = p.param(recv, false, false)
615 return ir.NewFuncType(p.pos(typ), rcvr,
616 p.params(typ.ParamList, true),
617 p.params(typ.ResultList, false))
620 func (p *noder) params(params []*syntax.Field, dddOk bool) []*ir.Field {
621 nodes := make([]*ir.Field, 0, len(params))
622 for i, param := range params {
624 nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))
629 func (p *noder) param(param *syntax.Field, dddOk, final bool) *ir.Field {
631 if param.Name != nil {
632 name = p.name(param.Name)
635 typ := p.typeExpr(param.Type)
636 n := ir.NewField(p.pos(param), name, typ, nil)
638 // rewrite ...T parameter
639 if typ, ok := typ.(*ir.SliceType); ok && typ.DDD {
641 // We mark these as syntax errors to get automatic elimination
642 // of multiple such errors per line (see ErrorfAt in subr.go).
643 base.Errorf("syntax error: cannot use ... in receiver or result parameter list")
645 if param.Name == nil {
646 base.Errorf("syntax error: cannot use ... with non-final parameter")
648 p.errorAt(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value)
658 func (p *noder) exprList(expr syntax.Expr) []ir.Node {
659 switch expr := expr.(type) {
662 case *syntax.ListExpr:
663 return p.exprs(expr.ElemList)
665 return []ir.Node{p.expr(expr)}
669 func (p *noder) exprs(exprs []syntax.Expr) []ir.Node {
670 nodes := make([]ir.Node, 0, len(exprs))
671 for _, expr := range exprs {
672 nodes = append(nodes, p.expr(expr))
677 func (p *noder) expr(expr syntax.Expr) ir.Node {
679 switch expr := expr.(type) {
680 case nil, *syntax.BadExpr:
683 return p.mkname(expr)
684 case *syntax.BasicLit:
685 n := ir.NewBasicLit(p.pos(expr), p.basicLit(expr))
686 if expr.Kind == syntax.RuneLit {
687 n.SetType(types.UntypedRune)
689 n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error
691 case *syntax.CompositeLit:
692 n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, p.typeExpr(expr.Type), nil)
693 l := p.exprs(expr.ElemList)
694 for i, e := range l {
695 l[i] = p.wrapname(expr.ElemList[i], e)
698 base.Pos = p.makeXPos(expr.Rbrace)
700 case *syntax.KeyValueExpr:
701 // use position of expr.Key rather than of expr (which has position of ':')
702 return ir.NewKeyExpr(p.pos(expr.Key), p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
703 case *syntax.FuncLit:
704 return p.funcLit(expr)
705 case *syntax.ParenExpr:
706 return ir.NewParenExpr(p.pos(expr), p.expr(expr.X))
707 case *syntax.SelectorExpr:
708 // parser.new_dotname
709 obj := p.expr(expr.X)
710 if obj.Op() == ir.OPACK {
711 pack := obj.(*ir.PkgName)
713 return importName(pack.Pkg.Lookup(expr.Sel.Value))
715 n := ir.NewSelectorExpr(base.Pos, ir.OXDOT, obj, p.name(expr.Sel))
716 n.SetPos(p.pos(expr)) // lineno may have been changed by p.expr(expr.X)
718 case *syntax.IndexExpr:
719 return ir.NewIndexExpr(p.pos(expr), p.expr(expr.X), p.expr(expr.Index))
720 case *syntax.SliceExpr:
727 for i, n := range &expr.Index {
732 return ir.NewSliceExpr(p.pos(expr), op, x, index[0], index[1], index[2])
733 case *syntax.AssertExpr:
734 return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type))
735 case *syntax.Operation:
736 if expr.Op == syntax.Add && expr.Y != nil {
741 pos, op := p.pos(expr), p.unOp(expr.Op)
744 return typecheck.NodAddrAt(pos, x)
746 return ir.NewStarExpr(pos, x)
748 return ir.NewUnaryExpr(pos, op, x)
751 pos, op, y := p.pos(expr), p.binOp(expr.Op), p.expr(expr.Y)
753 case ir.OANDAND, ir.OOROR:
754 return ir.NewLogicalExpr(pos, op, x, y)
756 return ir.NewBinaryExpr(pos, op, x, y)
757 case *syntax.CallExpr:
758 n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), p.exprs(expr.ArgList))
759 n.IsDDD = expr.HasDots
762 case *syntax.ArrayType:
765 len = p.expr(expr.Len)
767 return ir.NewArrayType(p.pos(expr), len, p.typeExpr(expr.Elem))
768 case *syntax.SliceType:
769 return ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
770 case *syntax.DotsType:
771 t := ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
774 case *syntax.StructType:
775 return p.structType(expr)
776 case *syntax.InterfaceType:
777 return p.interfaceType(expr)
778 case *syntax.FuncType:
779 return p.signature(nil, expr)
780 case *syntax.MapType:
781 return ir.NewMapType(p.pos(expr),
782 p.typeExpr(expr.Key), p.typeExpr(expr.Value))
783 case *syntax.ChanType:
784 return ir.NewChanType(p.pos(expr),
785 p.typeExpr(expr.Elem), p.chanDir(expr.Dir))
787 case *syntax.TypeSwitchGuard:
790 tag = ir.NewIdent(p.pos(expr.Lhs), p.name(expr.Lhs))
792 base.Errorf("invalid variable name %v in type switch", tag)
795 return ir.NewTypeSwitchGuard(p.pos(expr), tag, p.expr(expr.X))
797 panic("unhandled Expr")
800 // sum efficiently handles very large summation expressions (such as
801 // in issue #16394). In particular, it avoids left recursion and
802 // collapses string literals.
803 func (p *noder) sum(x syntax.Expr) ir.Node {
804 // While we need to handle long sums with asymptotic
805 // efficiency, the vast majority of sums are very small: ~95%
806 // have only 2 or 3 operands, and ~99% of string literals are
807 // never concatenated.
809 adds := make([]*syntax.Operation, 0, 2)
811 add, ok := x.(*syntax.Operation)
812 if !ok || add.Op != syntax.Add || add.Y == nil {
815 adds = append(adds, add)
819 // nstr is the current rightmost string literal in the
820 // summation (if any), and chunks holds its accumulated
823 // Consider the expression x + "a" + "b" + "c" + y. When we
824 // reach the string literal "a", we assign nstr to point to
825 // its corresponding Node and initialize chunks to {"a"}.
826 // Visiting the subsequent string literals "b" and "c", we
827 // simply append their values to chunks. Finally, when we
828 // reach the non-constant operand y, we'll join chunks to form
829 // "abc" and reassign the "a" string literal's value.
831 // N.B., we need to be careful about named string constants
832 // (indicated by Sym != nil) because 1) we can't modify their
833 // value, as doing so would affect other uses of the string
834 // constant, and 2) they may have types, which we need to
835 // handle correctly. For now, we avoid these problems by
836 // treating named string constants the same as non-constant
839 chunks := make([]string, 0, 1)
842 if ir.IsConst(n, constant.String) && n.Sym() == nil {
844 chunks = append(chunks, ir.StringVal(nstr))
847 for i := len(adds) - 1; i >= 0; i-- {
851 if ir.IsConst(r, constant.String) && r.Sym() == nil {
853 // Collapse r into nstr instead of adding to n.
854 chunks = append(chunks, ir.StringVal(r))
859 chunks = append(chunks, ir.StringVal(nstr))
862 nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
867 n = ir.NewBinaryExpr(p.pos(add), ir.OADD, n, r)
870 nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
876 func (p *noder) typeExpr(typ syntax.Expr) ir.Ntype {
877 // TODO(mdempsky): Be stricter? typecheck should handle errors anyway.
882 if _, ok := n.(ir.Ntype); !ok {
883 ir.Dump("NOT NTYPE", n)
888 func (p *noder) typeExprOrNil(typ syntax.Expr) ir.Ntype {
890 return p.typeExpr(typ)
895 func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir {
899 case syntax.SendOnly:
901 case syntax.RecvOnly:
904 panic("unhandled ChanDir")
907 func (p *noder) structType(expr *syntax.StructType) ir.Node {
908 l := make([]*ir.Field, 0, len(expr.FieldList))
909 for i, field := range expr.FieldList {
912 if field.Name == nil {
913 n = p.embedded(field.Type)
915 n = ir.NewField(p.pos(field), p.name(field.Name), p.typeExpr(field.Type), nil)
917 if i < len(expr.TagList) && expr.TagList[i] != nil {
918 n.Note = constant.StringVal(p.basicLit(expr.TagList[i]))
924 return ir.NewStructType(p.pos(expr), l)
927 func (p *noder) interfaceType(expr *syntax.InterfaceType) ir.Node {
928 l := make([]*ir.Field, 0, len(expr.MethodList))
929 for _, method := range expr.MethodList {
932 if method.Name == nil {
933 n = ir.NewField(p.pos(method), nil, importName(p.packname(method.Type)).(ir.Ntype), nil)
935 mname := p.name(method.Name)
937 base.Errorf("methods must have a unique non-blank name")
940 sig := p.typeExpr(method.Type).(*ir.FuncType)
941 sig.Recv = fakeRecv()
942 n = ir.NewField(p.pos(method), mname, sig, nil)
947 return ir.NewInterfaceType(p.pos(expr), l)
950 func (p *noder) packname(expr syntax.Expr) *types.Sym {
951 switch expr := expr.(type) {
954 if n := oldname(name); n.Name() != nil && n.Name().PkgName != nil {
955 n.Name().PkgName.Used = true
958 case *syntax.SelectorExpr:
959 name := p.name(expr.X.(*syntax.Name))
960 def := ir.AsNode(name.Def)
962 base.Errorf("undefined: %v", name)
966 if def.Op() != ir.OPACK {
967 base.Errorf("%v is not a package", name)
970 def := def.(*ir.PkgName)
974 return pkg.Lookup(expr.Sel.Value)
976 panic(fmt.Sprintf("unexpected packname: %#v", expr))
979 func (p *noder) embedded(typ syntax.Expr) *ir.Field {
980 op, isStar := typ.(*syntax.Operation)
982 if op.Op != syntax.Mul || op.Y != nil {
983 panic("unexpected Operation")
988 sym := p.packname(typ)
989 n := ir.NewField(p.pos(typ), typecheck.Lookup(sym.Name), importName(sym).(ir.Ntype), nil)
993 n.Ntype = ir.NewStarExpr(p.pos(op), n.Ntype)
998 func (p *noder) stmts(stmts []syntax.Stmt) []ir.Node {
999 return p.stmtsFall(stmts, false)
1002 func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []ir.Node {
1004 for i, stmt := range stmts {
1005 s := p.stmtFall(stmt, fallOK && i+1 == len(stmts))
1007 } else if s.Op() == ir.OBLOCK && len(s.(*ir.BlockStmt).List) > 0 {
1008 // Inline non-empty block.
1009 // Empty blocks must be preserved for CheckReturn.
1010 nodes = append(nodes, s.(*ir.BlockStmt).List...)
1012 nodes = append(nodes, s)
1018 func (p *noder) stmt(stmt syntax.Stmt) ir.Node {
1019 return p.stmtFall(stmt, false)
1022 func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
1024 switch stmt := stmt.(type) {
1025 case nil, *syntax.EmptyStmt:
1027 case *syntax.LabeledStmt:
1028 return p.labeledStmt(stmt, fallOK)
1029 case *syntax.BlockStmt:
1030 l := p.blockStmt(stmt)
1032 // TODO(mdempsky): Line number?
1033 return ir.NewBlockStmt(base.Pos, nil)
1035 return ir.NewBlockStmt(src.NoXPos, l)
1036 case *syntax.ExprStmt:
1037 return p.wrapname(stmt, p.expr(stmt.X))
1038 case *syntax.SendStmt:
1039 return ir.NewSendStmt(p.pos(stmt), p.expr(stmt.Chan), p.expr(stmt.Value))
1040 case *syntax.DeclStmt:
1041 return ir.NewBlockStmt(src.NoXPos, p.decls(stmt.DeclList))
1042 case *syntax.AssignStmt:
1043 if stmt.Rhs == nil {
1045 n := ir.NewAssignOpStmt(pos, p.binOp(stmt.Op), p.expr(stmt.Lhs), ir.NewBasicLit(pos, one))
1050 if stmt.Op != 0 && stmt.Op != syntax.Def {
1051 n := ir.NewAssignOpStmt(p.pos(stmt), p.binOp(stmt.Op), p.expr(stmt.Lhs), p.expr(stmt.Rhs))
1055 rhs := p.exprList(stmt.Rhs)
1056 if list, ok := stmt.Lhs.(*syntax.ListExpr); ok && len(list.ElemList) != 1 || len(rhs) != 1 {
1057 n := ir.NewAssignListStmt(p.pos(stmt), ir.OAS2, nil, nil)
1058 n.Def = stmt.Op == syntax.Def
1059 n.Lhs = p.assignList(stmt.Lhs, n, n.Def)
1064 n := ir.NewAssignStmt(p.pos(stmt), nil, nil)
1065 n.Def = stmt.Op == syntax.Def
1066 n.X = p.assignList(stmt.Lhs, n, n.Def)[0]
1070 case *syntax.BranchStmt:
1075 case syntax.Continue:
1077 case syntax.Fallthrough:
1079 base.Errorf("fallthrough statement out of place")
1085 panic("unhandled BranchStmt")
1088 if stmt.Label != nil {
1089 sym = p.name(stmt.Label)
1091 return ir.NewBranchStmt(p.pos(stmt), op, sym)
1092 case *syntax.CallStmt:
1100 panic("unhandled CallStmt")
1102 return ir.NewGoDeferStmt(p.pos(stmt), op, p.expr(stmt.Call))
1103 case *syntax.ReturnStmt:
1104 n := ir.NewReturnStmt(p.pos(stmt), p.exprList(stmt.Results))
1105 if len(n.Results) == 0 && ir.CurFunc != nil {
1106 for _, ln := range ir.CurFunc.Dcl {
1107 if ln.Class == ir.PPARAM {
1110 if ln.Class != ir.PPARAMOUT {
1113 if ln.Sym().Def != ln {
1114 base.Errorf("%s is shadowed during return", ln.Sym().Name)
1119 case *syntax.IfStmt:
1120 return p.ifStmt(stmt)
1121 case *syntax.ForStmt:
1122 return p.forStmt(stmt)
1123 case *syntax.SwitchStmt:
1124 return p.switchStmt(stmt)
1125 case *syntax.SelectStmt:
1126 return p.selectStmt(stmt)
1128 panic("unhandled Stmt")
1131 func (p *noder) assignList(expr syntax.Expr, defn ir.InitNode, colas bool) []ir.Node {
1133 return p.exprList(expr)
1136 var exprs []syntax.Expr
1137 if list, ok := expr.(*syntax.ListExpr); ok {
1138 exprs = list.ElemList
1140 exprs = []syntax.Expr{expr}
1143 res := make([]ir.Node, len(exprs))
1144 seen := make(map[*types.Sym]bool, len(exprs))
1147 for i, expr := range exprs {
1149 res[i] = ir.BlankNode
1151 name, ok := expr.(*syntax.Name)
1153 p.errorAt(expr.Pos(), "non-name %v on left side of :=", p.expr(expr))
1164 p.errorAt(expr.Pos(), "%v repeated on left side of :=", sym)
1170 if sym.Block == types.Block {
1171 res[i] = oldname(sym)
1176 n := typecheck.NewName(sym)
1177 typecheck.Declare(n, typecheck.DeclContext)
1179 defn.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, n))
1184 base.ErrorfAt(defn.Pos(), "no new variables on left side of :=")
1189 func (p *noder) blockStmt(stmt *syntax.BlockStmt) []ir.Node {
1190 p.openScope(stmt.Pos())
1191 nodes := p.stmts(stmt.List)
1192 p.closeScope(stmt.Rbrace)
1196 func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
1197 p.openScope(stmt.Pos())
1198 init := p.stmt(stmt.Init)
1199 n := ir.NewIfStmt(p.pos(stmt), p.expr(stmt.Cond), p.blockStmt(stmt.Then), nil)
1201 *n.PtrInit() = []ir.Node{init}
1203 if stmt.Else != nil {
1204 e := p.stmt(stmt.Else)
1205 if e.Op() == ir.OBLOCK {
1206 e := e.(*ir.BlockStmt)
1209 n.Else = []ir.Node{e}
1212 p.closeAnotherScope()
1216 func (p *noder) forStmt(stmt *syntax.ForStmt) ir.Node {
1217 p.openScope(stmt.Pos())
1218 if r, ok := stmt.Init.(*syntax.RangeClause); ok {
1219 if stmt.Cond != nil || stmt.Post != nil {
1220 panic("unexpected RangeClause")
1223 n := ir.NewRangeStmt(p.pos(r), nil, nil, p.expr(r.X), nil)
1226 lhs := p.assignList(r.Lhs, n, n.Def)
1232 n.Body = p.blockStmt(stmt.Body)
1233 p.closeAnotherScope()
1237 n := ir.NewForStmt(p.pos(stmt), p.stmt(stmt.Init), p.expr(stmt.Cond), p.stmt(stmt.Post), p.blockStmt(stmt.Body))
1238 p.closeAnotherScope()
1242 func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
1243 p.openScope(stmt.Pos())
1245 init := p.stmt(stmt.Init)
1246 n := ir.NewSwitchStmt(p.pos(stmt), p.expr(stmt.Tag), nil)
1248 *n.PtrInit() = []ir.Node{init}
1251 var tswitch *ir.TypeSwitchGuard
1252 if l := n.Tag; l != nil && l.Op() == ir.OTYPESW {
1253 tswitch = l.(*ir.TypeSwitchGuard)
1255 n.Cases = p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)
1257 p.closeScope(stmt.Rbrace)
1261 func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []*ir.CaseClause {
1262 nodes := make([]*ir.CaseClause, 0, len(clauses))
1263 for i, clause := range clauses {
1266 p.closeScope(clause.Pos())
1268 p.openScope(clause.Pos())
1270 n := ir.NewCaseStmt(p.pos(clause), p.exprList(clause.Cases), nil)
1271 if tswitch != nil && tswitch.Tag != nil {
1272 nn := typecheck.NewName(tswitch.Tag.Sym())
1273 typecheck.Declare(nn, typecheck.DeclContext)
1275 // keep track of the instances for reporting unused
1279 // Trim trailing empty statements. We omit them from
1280 // the Node AST anyway, and it's easier to identify
1281 // out-of-place fallthrough statements without them.
1284 if _, ok := body[len(body)-1].(*syntax.EmptyStmt); !ok {
1287 body = body[:len(body)-1]
1290 n.Body = p.stmtsFall(body, true)
1291 if l := len(n.Body); l > 0 && n.Body[l-1].Op() == ir.OFALL {
1293 base.Errorf("cannot fallthrough in type switch")
1295 if i+1 == len(clauses) {
1296 base.Errorf("cannot fallthrough final case in switch")
1300 nodes = append(nodes, n)
1302 if len(clauses) > 0 {
1303 p.closeScope(rbrace)
1308 func (p *noder) selectStmt(stmt *syntax.SelectStmt) ir.Node {
1309 return ir.NewSelectStmt(p.pos(stmt), p.commClauses(stmt.Body, stmt.Rbrace))
1312 func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*ir.CommClause {
1313 nodes := make([]*ir.CommClause, len(clauses))
1314 for i, clause := range clauses {
1317 p.closeScope(clause.Pos())
1319 p.openScope(clause.Pos())
1321 nodes[i] = ir.NewCommStmt(p.pos(clause), p.stmt(clause.Comm), p.stmts(clause.Body))
1323 if len(clauses) > 0 {
1324 p.closeScope(rbrace)
1329 func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) ir.Node {
1330 sym := p.name(label.Label)
1331 lhs := ir.NewLabelStmt(p.pos(label), sym)
1334 if label.Stmt != nil { // TODO(mdempsky): Should always be present.
1335 ls = p.stmtFall(label.Stmt, fallOK)
1336 // Attach label directly to control statement too.
1340 ls := ls.(*ir.ForStmt)
1343 ls := ls.(*ir.RangeStmt)
1346 ls := ls.(*ir.SwitchStmt)
1349 ls := ls.(*ir.SelectStmt)
1357 if ls.Op() == ir.OBLOCK {
1358 ls := ls.(*ir.BlockStmt)
1359 l = append(l, ls.List...)
1364 return ir.NewBlockStmt(src.NoXPos, l)
1367 var unOps = [...]ir.Op{
1368 syntax.Recv: ir.ORECV,
1369 syntax.Mul: ir.ODEREF,
1370 syntax.And: ir.OADDR,
1372 syntax.Not: ir.ONOT,
1373 syntax.Xor: ir.OBITNOT,
1374 syntax.Add: ir.OPLUS,
1375 syntax.Sub: ir.ONEG,
1378 func (p *noder) unOp(op syntax.Operator) ir.Op {
1379 if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 {
1380 panic("invalid Operator")
1385 var binOps = [...]ir.Op{
1386 syntax.OrOr: ir.OOROR,
1387 syntax.AndAnd: ir.OANDAND,
1396 syntax.Add: ir.OADD,
1397 syntax.Sub: ir.OSUB,
1399 syntax.Xor: ir.OXOR,
1401 syntax.Mul: ir.OMUL,
1402 syntax.Div: ir.ODIV,
1403 syntax.Rem: ir.OMOD,
1404 syntax.And: ir.OAND,
1405 syntax.AndNot: ir.OANDNOT,
1406 syntax.Shl: ir.OLSH,
1407 syntax.Shr: ir.ORSH,
1410 func (p *noder) binOp(op syntax.Operator) ir.Op {
1411 if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 {
1412 panic("invalid Operator")
1417 // checkLangCompat reports an error if the representation of a numeric
1418 // literal is not compatible with the current language version.
1419 func checkLangCompat(lit *syntax.BasicLit) {
1421 if len(s) <= 2 || types.AllowsGoVersion(types.LocalPkg, 1, 13) {
1425 if strings.Contains(s, "_") {
1426 base.ErrorfVers("go1.13", "underscores in numeric literals")
1433 if radix == 'b' || radix == 'B' {
1434 base.ErrorfVers("go1.13", "binary literals")
1437 if radix == 'o' || radix == 'O' {
1438 base.ErrorfVers("go1.13", "0o/0O-style octal literals")
1441 if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
1442 base.ErrorfVers("go1.13", "hexadecimal floating-point literals")
1446 func (p *noder) basicLit(lit *syntax.BasicLit) constant.Value {
1447 // We don't use the errors of the conversion routines to determine
1448 // if a literal string is valid because the conversion routines may
1449 // accept a wider syntax than the language permits. Rely on lit.Bad
1452 return constant.MakeUnknown()
1456 case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
1457 checkLangCompat(lit)
1460 v := constant.MakeFromLiteral(lit.Value, tokenForLitKind[lit.Kind], 0)
1461 if v.Kind() == constant.Unknown {
1462 // TODO(mdempsky): Better error message?
1463 p.errorAt(lit.Pos(), "malformed constant: %s", lit.Value)
1466 // go/constant uses big.Rat by default, which is more precise, but
1467 // causes toolstash -cmp and some tests to fail. For now, convert
1468 // to big.Float to match cmd/compile's historical precision.
1469 // TODO(mdempsky): Remove.
1470 if v.Kind() == constant.Float {
1471 v = constant.Make(ir.BigFloat(v))
1477 var tokenForLitKind = [...]token.Token{
1478 syntax.IntLit: token.INT,
1479 syntax.RuneLit: token.CHAR,
1480 syntax.FloatLit: token.FLOAT,
1481 syntax.ImagLit: token.IMAG,
1482 syntax.StringLit: token.STRING,
1485 func (p *noder) name(name *syntax.Name) *types.Sym {
1486 return typecheck.Lookup(name.Value)
1489 func (p *noder) mkname(name *syntax.Name) ir.Node {
1490 // TODO(mdempsky): Set line number?
1491 return mkname(p.name(name))
1494 func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node {
1495 // These nodes do not carry line numbers.
1496 // Introduce a wrapper node to give them the correct line.
1498 case ir.OTYPE, ir.OLITERAL:
1503 case ir.ONAME, ir.ONONAME, ir.OPACK:
1504 p := ir.NewParenExpr(p.pos(n), x)
1511 func (p *noder) setlineno(n syntax.Node) {
1517 // error is called concurrently if files are parsed concurrently.
1518 func (p *noder) error(err error) {
1519 p.err <- err.(syntax.Error)
1522 // pragmas that are allowed in the std lib, but don't have
1523 // a syntax.Pragma value (see lex.go) associated with them.
1524 var allowedStdPragmas = map[string]bool{
1525 "go:cgo_export_static": true,
1526 "go:cgo_export_dynamic": true,
1527 "go:cgo_import_static": true,
1528 "go:cgo_import_dynamic": true,
1529 "go:cgo_ldflag": true,
1530 "go:cgo_dynamic_linker": true,
1532 "go:generate": true,
1535 // *pragmas is the value stored in a syntax.pragmas during parsing.
1536 type pragmas struct {
1537 Flag ir.PragmaFlag // collected bits
1538 Pos []pragmaPos // position of each individual flag
1539 Embeds []pragmaEmbed
1542 type pragmaPos struct {
1547 type pragmaEmbed struct {
1552 func (p *noder) checkUnused(pragma *pragmas) {
1553 for _, pos := range pragma.Pos {
1554 if pos.Flag&pragma.Flag != 0 {
1555 p.errorAt(pos.Pos, "misplaced compiler directive")
1558 if len(pragma.Embeds) > 0 {
1559 for _, e := range pragma.Embeds {
1560 p.errorAt(e.Pos, "misplaced go:embed directive")
1565 func (p *noder) checkUnusedDuringParse(pragma *pragmas) {
1566 for _, pos := range pragma.Pos {
1567 if pos.Flag&pragma.Flag != 0 {
1568 p.error(syntax.Error{Pos: pos.Pos, Msg: "misplaced compiler directive"})
1571 if len(pragma.Embeds) > 0 {
1572 for _, e := range pragma.Embeds {
1573 p.error(syntax.Error{Pos: e.Pos, Msg: "misplaced go:embed directive"})
1578 // pragma is called concurrently if files are parsed concurrently.
1579 func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.Pragma) syntax.Pragma {
1580 pragma, _ := old.(*pragmas)
1582 pragma = new(pragmas)
1586 // unused pragma; only called with old != nil.
1587 p.checkUnusedDuringParse(pragma)
1591 if strings.HasPrefix(text, "line ") {
1592 // line directives are handled by syntax package
1593 panic("unreachable")
1597 // directive must be on line by itself
1598 p.error(syntax.Error{Pos: pos, Msg: "misplaced compiler directive"})
1603 case strings.HasPrefix(text, "go:linkname "):
1604 f := strings.Fields(text)
1605 if !(2 <= len(f) && len(f) <= 3) {
1606 p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname [linkname]"})
1609 // The second argument is optional. If omitted, we use
1610 // the default object symbol name for this and
1611 // linkname only serves to mark this symbol as
1612 // something that may be referenced via the object
1613 // symbol name from another package.
1617 } else if base.Ctxt.Pkgpath != "" {
1618 // Use the default object symbol name if the
1619 // user didn't provide one.
1620 target = objabi.PathToPrefix(base.Ctxt.Pkgpath) + "." + f[1]
1622 p.error(syntax.Error{Pos: pos, Msg: "//go:linkname requires linkname argument or -p compiler flag"})
1625 p.linknames = append(p.linknames, linkname{pos, f[1], target})
1627 case text == "go:embed", strings.HasPrefix(text, "go:embed "):
1628 args, err := parseGoEmbed(text[len("go:embed"):])
1630 p.error(syntax.Error{Pos: pos, Msg: err.Error()})
1633 p.error(syntax.Error{Pos: pos, Msg: "usage: //go:embed pattern..."})
1636 pragma.Embeds = append(pragma.Embeds, pragmaEmbed{pos, args})
1638 case strings.HasPrefix(text, "go:cgo_import_dynamic "):
1639 // This is permitted for general use because Solaris
1640 // code relies on it in golang.org/x/sys/unix and others.
1641 fields := pragmaFields(text)
1642 if len(fields) >= 4 {
1643 lib := strings.Trim(fields[3], `"`)
1644 if lib != "" && !safeArg(lib) && !isCgoGeneratedFile(pos) {
1645 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("invalid library name %q in cgo_import_dynamic directive", lib)})
1647 p.pragcgo(pos, text)
1648 pragma.Flag |= pragmaFlag("go:cgo_import_dynamic")
1652 case strings.HasPrefix(text, "go:cgo_"):
1653 // For security, we disallow //go:cgo_* directives other
1654 // than cgo_import_dynamic outside cgo-generated files.
1655 // Exception: they are allowed in the standard library, for runtime and syscall.
1656 if !isCgoGeneratedFile(pos) && !base.Flag.Std {
1657 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
1659 p.pragcgo(pos, text)
1660 fallthrough // because of //go:cgo_unsafe_args
1663 if i := strings.Index(text, " "); i >= 0 {
1666 flag := pragmaFlag(verb)
1667 const runtimePragmas = ir.Systemstack | ir.Nowritebarrier | ir.Nowritebarrierrec | ir.Yeswritebarrierrec
1668 if !base.Flag.CompilingRuntime && flag&runtimePragmas != 0 {
1669 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)})
1671 if flag == 0 && !allowedStdPragmas[verb] && base.Flag.Std {
1672 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)})
1675 pragma.Pos = append(pragma.Pos, pragmaPos{flag, pos})
1681 // isCgoGeneratedFile reports whether pos is in a file
1682 // generated by cgo, which is to say a file with name
1683 // beginning with "_cgo_". Such files are allowed to
1684 // contain cgo directives, and for security reasons
1685 // (primarily misuse of linker flags), other files are not.
1686 // See golang.org/issue/23672.
1687 func isCgoGeneratedFile(pos syntax.Pos) bool {
1688 return strings.HasPrefix(filepath.Base(filepath.Clean(fileh(pos.Base().Filename()))), "_cgo_")
1691 // safeArg reports whether arg is a "safe" command-line argument,
1692 // meaning that when it appears in a command-line, it probably
1693 // doesn't have some special meaning other than its own name.
1694 // This is copied from SafeArg in cmd/go/internal/load/pkg.go.
1695 func safeArg(name string) bool {
1700 return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
1703 func mkname(sym *types.Sym) ir.Node {
1705 if n.Name() != nil && n.Name().PkgName != nil {
1706 n.Name().PkgName.Used = true
1711 // parseGoEmbed parses the text following "//go:embed" to extract the glob patterns.
1712 // It accepts unquoted space-separated patterns as well as double-quoted and back-quoted Go strings.
1713 // go/build/read.go also processes these strings and contains similar logic.
1714 func parseGoEmbed(args string) ([]string, error) {
1716 for args = strings.TrimSpace(args); args != ""; args = strings.TrimSpace(args) {
1722 for j, c := range args {
1723 if unicode.IsSpace(c) {
1732 i := strings.Index(args[1:], "`")
1734 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1736 path = args[1 : 1+i]
1741 for ; i < len(args); i++ {
1742 if args[i] == '\\' {
1747 q, err := strconv.Unquote(args[:i+1])
1749 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args[:i+1])
1757 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1762 r, _ := utf8.DecodeRuneInString(args)
1763 if !unicode.IsSpace(r) {
1764 return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
1767 list = append(list, path)
1772 func fakeRecv() *ir.Field {
1773 return ir.NewField(base.Pos, nil, nil, types.FakeRecvType())
1776 func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
1777 xtype := p.typeExpr(expr.Type)
1779 fn := ir.NewFunc(p.pos(expr))
1780 fn.SetIsHiddenClosure(ir.CurFunc != nil)
1782 fn.Nname = ir.NewNameAt(p.pos(expr), ir.BlankNode.Sym()) // filled in by tcClosure
1784 fn.Nname.Ntype = xtype
1787 clo := ir.NewClosureExpr(p.pos(expr), fn)
1790 p.funcBody(fn, expr.Body)
1792 ir.FinishCaptureNames(base.Pos, ir.CurFunc, fn)
1797 // A function named init is a special case.
1798 // It is called by the initialization before main is run.
1799 // To make it unique within a package and also uncallable,
1800 // the name, normally "pkg.init", is altered to "pkg.init.0".
1801 var renameinitgen int
1803 func renameinit() *types.Sym {
1804 s := typecheck.LookupNum("init.", renameinitgen)
1809 // oldname returns the Node that declares symbol s in the current scope.
1810 // If no such Node currently exists, an ONONAME Node is returned instead.
1811 // Automatically creates a new closure variable if the referenced symbol was
1812 // declared in a different (containing) function.
1813 func oldname(s *types.Sym) ir.Node {
1814 if s.Pkg != types.LocalPkg {
1815 return ir.NewIdent(base.Pos, s)
1818 n := ir.AsNode(s.Def)
1820 // Maybe a top-level declaration will come along later to
1821 // define s. resolve will check s.Def again once all input
1822 // source has been processed.
1823 return ir.NewIdent(base.Pos, s)
1826 if n, ok := n.(*ir.Name); ok {
1827 // TODO(rsc): If there is an outer variable x and we
1828 // are parsing x := 5 inside the closure, until we get to
1829 // the := it looks like a reference to the outer x so we'll
1830 // make x a closure variable unnecessarily.
1831 return ir.CaptureName(base.Pos, ir.CurFunc, n)
1837 func varEmbed(makeXPos func(syntax.Pos) src.XPos, name *ir.Name, decl *syntax.VarDecl, pragma *pragmas, haveEmbed bool) {
1838 if pragma.Embeds == nil {
1842 pragmaEmbeds := pragma.Embeds
1844 pos := makeXPos(pragmaEmbeds[0].Pos)
1847 base.ErrorfAt(pos, "go:embed only allowed in Go files that import \"embed\"")
1850 if len(decl.NameList) > 1 {
1851 base.ErrorfAt(pos, "go:embed cannot apply to multiple vars")
1854 if decl.Values != nil {
1855 base.ErrorfAt(pos, "go:embed cannot apply to var with initializer")
1858 if decl.Type == nil {
1859 // Should not happen, since Values == nil now.
1860 base.ErrorfAt(pos, "go:embed cannot apply to var without type")
1863 if typecheck.DeclContext != ir.PEXTERN {
1864 base.ErrorfAt(pos, "go:embed cannot apply to var inside func")
1868 var embeds []ir.Embed
1869 for _, e := range pragmaEmbeds {
1870 embeds = append(embeds, ir.Embed{Pos: makeXPos(e.Pos), Patterns: e.Patterns})
1872 typecheck.Target.Embeds = append(typecheck.Target.Embeds, name)
1873 name.Embed = &embeds