"*cmd/compile/internal/ssa.Value %s": "",
"*cmd/compile/internal/ssa.Value %v": "",
"*cmd/compile/internal/ssa.sparseTreeMapEntry %v": "",
+ "*cmd/compile/internal/syntax.CallExpr %s": "",
+ "*cmd/compile/internal/syntax.CallExpr %v": "",
+ "*cmd/compile/internal/syntax.FuncLit %s": "",
+ "*cmd/compile/internal/syntax.IndexExpr %s": "",
"*cmd/compile/internal/types.Field %p": "",
"*cmd/compile/internal/types.Field %v": "",
"*cmd/compile/internal/types.Sym %0S": "",
"*cmd/compile/internal/types.Type %p": "",
"*cmd/compile/internal/types.Type %s": "",
"*cmd/compile/internal/types.Type %v": "",
+ "*cmd/compile/internal/types2.Basic %s": "",
+ "*cmd/compile/internal/types2.Chan %s": "",
+ "*cmd/compile/internal/types2.Func %s": "",
+ "*cmd/compile/internal/types2.Initializer %s": "",
+ "*cmd/compile/internal/types2.Interface %s": "",
+ "*cmd/compile/internal/types2.MethodSet %s": "",
+ "*cmd/compile/internal/types2.Named %s": "",
+ "*cmd/compile/internal/types2.Named %v": "",
+ "*cmd/compile/internal/types2.Package %s": "",
+ "*cmd/compile/internal/types2.Package %v": "",
+ "*cmd/compile/internal/types2.Scope %p": "",
+ "*cmd/compile/internal/types2.Selection %s": "",
+ "*cmd/compile/internal/types2.Signature %s": "",
+ "*cmd/compile/internal/types2.TypeName %s": "",
+ "*cmd/compile/internal/types2.TypeName %v": "",
+ "*cmd/compile/internal/types2.TypeParam %s": "",
+ "*cmd/compile/internal/types2.Var %s": "",
+ "*cmd/compile/internal/types2.operand %s": "",
+ "*cmd/compile/internal/types2.substMap %s": "",
"*cmd/internal/obj.Addr %v": "",
"*cmd/internal/obj.LSym %v": "",
"*math/big.Float %f": "",
"[16]byte %x": "",
"[]*cmd/compile/internal/ssa.Block %v": "",
"[]*cmd/compile/internal/ssa.Value %v": "",
+ "[]*cmd/compile/internal/types2.Func %v": "",
+ "[]*cmd/compile/internal/types2.TypeName %s": "",
"[][]string %q": "",
"[]byte %s": "",
"[]byte %x": "",
"[]cmd/compile/internal/ssa.posetNode %v": "",
"[]cmd/compile/internal/ssa.posetUndo %v": "",
"[]cmd/compile/internal/syntax.token %s": "",
+ "[]cmd/compile/internal/types2.Type %s": "",
+ "[]int %v": "",
"[]string %v": "",
"[]uint32 %v": "",
"bool %v": "",
"cmd/compile/internal/gc.fmtMode %d": "",
"cmd/compile/internal/gc.initKind %d": "",
"cmd/compile/internal/gc.itag %v": "",
+ "cmd/compile/internal/importer.itag %v": "",
"cmd/compile/internal/ssa.BranchPrediction %d": "",
"cmd/compile/internal/ssa.Edge %v": "",
"cmd/compile/internal/ssa.GCNode %v": "",
"cmd/compile/internal/ssa.ID %d": "",
"cmd/compile/internal/ssa.ID %v": "",
- "cmd/compile/internal/ssa.LocPair %s": "",
"cmd/compile/internal/ssa.LocalSlot %s": "",
"cmd/compile/internal/ssa.LocalSlot %v": "",
- "cmd/compile/internal/ssa.Location %T": "",
"cmd/compile/internal/ssa.Location %s": "",
"cmd/compile/internal/ssa.Op %s": "",
"cmd/compile/internal/ssa.Op %v": "",
"cmd/compile/internal/ssa.regMask %d": "",
"cmd/compile/internal/ssa.register %d": "",
"cmd/compile/internal/ssa.relation %s": "",
+ "cmd/compile/internal/syntax.ChanDir %d": "",
+ "cmd/compile/internal/syntax.Decl %T": "",
"cmd/compile/internal/syntax.Error %q": "",
+ "cmd/compile/internal/syntax.Error %v": "",
"cmd/compile/internal/syntax.Expr %#v": "",
+ "cmd/compile/internal/syntax.Expr %T": "",
+ "cmd/compile/internal/syntax.Expr %s": "",
"cmd/compile/internal/syntax.LitKind %d": "",
"cmd/compile/internal/syntax.Node %T": "",
"cmd/compile/internal/syntax.Operator %s": "",
"cmd/compile/internal/types.EType %d": "",
"cmd/compile/internal/types.EType %s": "",
"cmd/compile/internal/types.EType %v": "",
+ "cmd/compile/internal/types2.Object %T": "",
+ "cmd/compile/internal/types2.Object %p": "",
+ "cmd/compile/internal/types2.Object %s": "",
+ "cmd/compile/internal/types2.Object %v": "",
+ "cmd/compile/internal/types2.Type %T": "",
+ "cmd/compile/internal/types2.Type %s": "",
+ "cmd/compile/internal/types2.Type %v": "",
+ "cmd/compile/internal/types2.color %s": "",
"cmd/internal/obj.ABI %v": "",
+ "error %s": "",
"error %v": "",
"float64 %.2f": "",
"float64 %.3f": "",
"float64 %.6g": "",
"float64 %g": "",
+ "go/constant.Value %s": "",
"int %#x": "",
"int %-12d": "",
"int %-6d": "",
"interface{} %q": "",
"interface{} %s": "",
"interface{} %v": "",
- "map[*cmd/compile/internal/gc.Node]*cmd/compile/internal/ssa.Value %v": "",
- "map[*cmd/compile/internal/gc.Node][]*cmd/compile/internal/gc.Node %v": "",
- "map[cmd/compile/internal/ssa.ID]uint32 %v": "",
+ "map[*cmd/compile/internal/gc.Node]*cmd/compile/internal/ssa.Value %v": "",
+ "map[*cmd/compile/internal/gc.Node][]*cmd/compile/internal/gc.Node %v": "",
+ "map[*cmd/compile/internal/types2.TypeParam]cmd/compile/internal/types2.Type %s": "",
+ "map[cmd/compile/internal/ssa.ID]uint32 %v": "",
"map[int64]uint32 %v": "",
"math/big.Accuracy %s": "",
"reflect.Type %s": "",
"string %-*s": "",
"string %-16s": "",
"string %-6s": "",
+ "string %T": "",
"string %q": "",
"string %s": "",
"string %v": "",
"uint64 %08x": "",
"uint64 %b": "",
"uint64 %d": "",
+ "uint64 %v": "",
"uint64 %x": "",
"uint8 %#x": "",
"uint8 %d": "",
"strings"
)
- var imported_unsafe bool
-
var (
buildid string
spectre string
objabi.Flagcount("B", "disable bounds checking", &Debug.B)
objabi.Flagcount("C", "disable printing of columns in error messages", &Debug.C)
objabi.Flagcount("E", "debug symbol export", &Debug.E)
+ objabi.Flagcount("G", "accept generic code", &Debug.G)
objabi.Flagcount("K", "debug missing line numbers", &Debug.K)
objabi.Flagcount("L", "show full file names in error messages", &Debug.L)
objabi.Flagcount("N", "disable optimizations", &Debug.N)
flag.BoolVar(&flagDWARF, "dwarf", !Wasm, "generate DWARF symbols")
flag.BoolVar(&Ctxt.Flag_locationlists, "dwarflocationlists", true, "add location lists to DWARF in optimized mode")
flag.IntVar(&genDwarfInline, "gendwarfinl", 2, "generate DWARF inline info records")
+ objabi.Flagfn1("embedcfg", "read go:embed configuration from `file`", readEmbedCfg)
objabi.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
objabi.Flagfn1("importcfg", "read import configuration from `file`", readImportCfg)
flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
loadsys()
timings.Start("fe", "parse")
- lines := parseFiles(flag.Args())
+ lines := parseFiles(flag.Args(), Debug.G != 0)
timings.Stop()
timings.AddEvent(int64(lines), "lines")
+ if Debug.G != 0 {
+ // can only parse generic code for now
+ if nerrors+nsavederrors != 0 {
+ errorexit()
+ }
+ return
+ }
finishUniverse()
timings.Start("fe", "typecheck", "top1")
for i := 0; i < len(xtop); i++ {
n := xtop[i]
- if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
+ if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias()) {
xtop[i] = typecheck(n, ctxStmt)
}
}
timings.Start("fe", "typecheck", "top2")
for i := 0; i < len(xtop); i++ {
n := xtop[i]
- if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
+ if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias() {
xtop[i] = typecheck(n, ctxStmt)
}
}
})
}
+ for _, n := range xtop {
+ if n.Op == ODCLFUNC {
+ devirtualize(n)
+ }
+ }
+ Curfn = nil
+
// Phase 6: Escape analysis.
// Required for moving heap allocations onto stack,
// which in turn is required by the closure implementation,
}
if path_ == "unsafe" {
- imported_unsafe = true
return unsafepkg
}
import (
"fmt"
+ "io"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
+ "unicode"
"unicode/utf8"
+ "cmd/compile/internal/importer"
"cmd/compile/internal/syntax"
"cmd/compile/internal/types"
+ "cmd/compile/internal/types2"
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/src"
// Each declaration in every *syntax.File is converted to a syntax tree
// and its root represented by *Node is appended to xtop.
// Returns the total count of parsed lines.
-func parseFiles(filenames []string) uint {
+func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
noders := make([]*noder, 0, len(filenames))
// Limit the number of simultaneously open files.
sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
}
defer f.Close()
- p.file, _ = syntax.Parse(base, f, p.error, p.pragma, syntax.CheckBranches) // errors are tracked via p.error
+ mode := syntax.CheckBranches
+ if allowGenerics {
+ mode |= syntax.AllowGenerics
+ }
+ p.file, _ = syntax.Parse(base, f, p.error, p.pragma, mode) // errors are tracked via p.error
}(filename)
}
- var lines uint
+ if allowGenerics {
+ nodersmap := make(map[string]*noder)
+ var files []*syntax.File
+ for _, p := range noders {
+ for e := range p.err {
+ p.yyerrorpos(e.Pos, "%s", e.Msg)
+ }
+
+ nodersmap[p.file.Pos().RelFilename()] = p
+ files = append(files, p.file)
+ lines += p.file.EOF.Line()
+
+ if nsyntaxerrors != 0 {
+ errorexit()
+ }
+ }
+
+ conf := types2.Config{
+ InferFromConstraints: true,
+ Error: func(err error) {
+ terr := err.(types2.Error)
+ if len(terr.Msg) > 0 && terr.Msg[0] == '\t' {
+ // types2 reports error clarifications via separate
+ // error messages which are indented with a tab.
+ // Ignore them to satisfy tools and tests that expect
+ // only one error in such cases.
+ // TODO(gri) Need to adjust error reporting in types2.
+ return
+ }
+ p := nodersmap[terr.Pos.RelFilename()]
+ yyerrorl(p.makeXPos(terr.Pos), "%s", terr.Msg)
+ },
+ Importer: &gcimports{
+ packages: make(map[string]*types2.Package),
+ },
+ }
+ conf.Check(Ctxt.Pkgpath, files, nil)
+ return
+ }
+
for _, p := range noders {
for e := range p.err {
p.yyerrorpos(e.Pos, "%s", e.Msg)
}
p.node()
- lines += p.file.Lines
+ lines += p.file.EOF.Line()
p.file = nil // release memory
if nsyntaxerrors != 0 {
}
localpkg.Height = myheight
+ return
+}
+
+// Temporary import helper to get type2-based type-checking going.
+type gcimports struct {
+ packages map[string]*types2.Package
+ lookup func(path string) (io.ReadCloser, error)
+}
+
+func (m *gcimports) Import(path string) (*types2.Package, error) {
+ return m.ImportFrom(path, "" /* no vendoring */, 0)
+}
- return lines
+func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*types2.Package, error) {
+ if mode != 0 {
+ panic("mode must be 0")
+ }
+ return importer.Import(m.packages, path, srcDir, m.lookup)
}
// makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase.
} else {
// line directive base
p0 := b0.Pos()
- p1 := src.MakePos(p.makeSrcPosBase(p0.Base()), p0.Line(), p0.Col())
+ p0b := p0.Base()
+ if p0b == b0 {
+ panic("infinite recursion in makeSrcPosBase")
+ }
+ p1 := src.MakePos(p.makeSrcPosBase(p0b), p0.Line(), p0.Col())
b1 = src.NewLinePragmaBase(p1, fn, fileh(fn), b0.Line(), b0.Col())
}
p.basemap[b0] = b1
base *src.PosBase
}
- file *syntax.File
- linknames []linkname
- pragcgobuf [][]string
- err chan syntax.Error
- scope ScopeID
+ file *syntax.File
+ linknames []linkname
+ pragcgobuf [][]string
+ err chan syntax.Error
+ scope ScopeID
+ importedUnsafe bool
+ importedEmbed bool
// scopeVars is a stack tracking the number of variables declared in the
// current function at the moment each open scope was opened.
func (p *noder) node() {
types.Block = 1
- imported_unsafe = false
+ p.importedUnsafe = false
+ p.importedEmbed = false
p.setlineno(p.file.PkgName)
mkpackage(p.file.PkgName.Value)
xtop = append(xtop, p.decls(p.file.DeclList)...)
for _, n := range p.linknames {
- if !imported_unsafe {
+ if !p.importedUnsafe {
p.yyerrorpos(n.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
continue
}
val := p.basicLit(imp.Path)
ipkg := importfile(&val)
-
if ipkg == nil {
if nerrors == 0 {
Fatalf("phase error in import")
return
}
+ if ipkg == unsafepkg {
+ p.importedUnsafe = true
+ }
+ if ipkg.Path == "embed" {
+ p.importedEmbed = true
+ }
+
ipkg.Direct = true
var my *types.Sym
}
if pragma, ok := decl.Pragma.(*Pragma); ok {
+ if len(pragma.Embeds) > 0 {
+ if !p.importedEmbed {
+ // This check can't be done when building the list pragma.Embeds
+ // because that list is created before the noder starts walking over the file,
+ // so at that point it hasn't seen the imports.
+ // We're left to check now, just before applying the //go:embed lines.
+ for _, e := range pragma.Embeds {
+ p.yyerrorpos(e.Pos, "//go:embed only allowed in Go files that import \"embed\"")
+ }
+ } else {
+ exprs = varEmbed(p, names, typ, exprs, pragma.Embeds)
+ }
+ pragma.Embeds = nil
+ }
p.checkUnused(pragma)
}
param := n.Name.Param
param.Ntype = typ
- param.Alias = decl.Alias
+ param.SetAlias(decl.Alias)
if pragma, ok := decl.Pragma.(*Pragma); ok {
if !decl.Alias {
- param.Pragma = pragma.Flag & TypePragmas
+ param.SetPragma(pragma.Flag & TypePragmas)
pragma.Flag &^= TypePragmas
}
p.checkUnused(pragma)
}
nod := p.nod(decl, ODCLTYPE, n, nil)
- if param.Alias && !langSupported(1, 9, localpkg) {
+ if param.Alias() && !langSupported(1, 9, localpkg) {
yyerrorl(nod.Pos, "type aliases only supported as of -lang=go1.9")
}
return nod
"go:cgo_import_dynamic": true,
"go:cgo_ldflag": true,
"go:cgo_dynamic_linker": true,
+ "go:embed": true,
"go:generate": true,
}
// *Pragma is the value stored in a syntax.Pragma during parsing.
type Pragma struct {
- Flag PragmaFlag // collected bits
- Pos []PragmaPos // position of each individual flag
+ Flag PragmaFlag // collected bits
+ Pos []PragmaPos // position of each individual flag
+ Embeds []PragmaEmbed
}
type PragmaPos struct {
Pos syntax.Pos
}
+ type PragmaEmbed struct {
+ Pos syntax.Pos
+ Patterns []string
+ }
+
func (p *noder) checkUnused(pragma *Pragma) {
for _, pos := range pragma.Pos {
if pos.Flag&pragma.Flag != 0 {
p.yyerrorpos(pos.Pos, "misplaced compiler directive")
}
}
+ if len(pragma.Embeds) > 0 {
+ for _, e := range pragma.Embeds {
+ p.yyerrorpos(e.Pos, "misplaced go:embed directive")
+ }
+ }
}
func (p *noder) checkUnusedDuringParse(pragma *Pragma) {
p.error(syntax.Error{Pos: pos.Pos, Msg: "misplaced compiler directive"})
}
}
+ if len(pragma.Embeds) > 0 {
+ for _, e := range pragma.Embeds {
+ p.error(syntax.Error{Pos: e.Pos, Msg: "misplaced go:embed directive"})
+ }
+ }
}
// pragma is called concurrently if files are parsed concurrently.
}
p.linknames = append(p.linknames, linkname{pos, f[1], target})
+ case text == "go:embed", strings.HasPrefix(text, "go:embed "):
+ args, err := parseGoEmbed(text[len("go:embed"):])
+ if err != nil {
+ p.error(syntax.Error{Pos: pos, Msg: err.Error()})
+ }
+ if len(args) == 0 {
+ p.error(syntax.Error{Pos: pos, Msg: "usage: //go:embed pattern..."})
+ break
+ }
+ pragma.Embeds = append(pragma.Embeds, PragmaEmbed{pos, args})
+
case strings.HasPrefix(text, "go:cgo_import_dynamic "):
// This is permitted for general use because Solaris
// code relies on it in golang.org/x/sys/unix and others.
}
return n
}
+
+ // parseGoEmbed parses the text following "//go:embed" to extract the glob patterns.
+ // It accepts unquoted space-separated patterns as well as double-quoted and back-quoted Go strings.
+ // go/build/read.go also processes these strings and contains similar logic.
+ func parseGoEmbed(args string) ([]string, error) {
+ var list []string
+ for args = strings.TrimSpace(args); args != ""; args = strings.TrimSpace(args) {
+ var path string
+ Switch:
+ switch args[0] {
+ default:
+ i := len(args)
+ for j, c := range args {
+ if unicode.IsSpace(c) {
+ i = j
+ break
+ }
+ }
+ path = args[:i]
+ args = args[i:]
+
+ case '`':
+ i := strings.Index(args[1:], "`")
+ if i < 0 {
+ return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
+ }
+ path = args[1 : 1+i]
+ args = args[1+i+1:]
+
+ case '"':
+ i := 1
+ for ; i < len(args); i++ {
+ if args[i] == '\\' {
+ i++
+ continue
+ }
+ if args[i] == '"' {
+ q, err := strconv.Unquote(args[:i+1])
+ if err != nil {
+ return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args[:i+1])
+ }
+ path = q
+ args = args[i+1:]
+ break Switch
+ }
+ }
+ if i >= len(args) {
+ return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
+ }
+ }
+
+ if args != "" {
+ r, _ := utf8.DecodeRuneInString(args)
+ if !unicode.IsSpace(r) {
+ return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
+ }
+ }
+ list = append(list, path)
+ }
+ return list, nil
+ }