// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package noder

import (
	"errors"
	"fmt"
	"go/constant"
	"go/token"
	"internal/buildcfg"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"

	"cmd/compile/internal/base"
	"cmd/compile/internal/dwarfgen"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/syntax"
	"cmd/compile/internal/typecheck"
	"cmd/compile/internal/types"
	"cmd/internal/objabi"
	"cmd/internal/src"
)

func LoadPackage(filenames []string) {
	base.Timer.Start("fe", "parse")

	// -G=3 and unified expect generics syntax, but -G=0 does not.
	supportsGenerics := base.Flag.G != 0 || buildcfg.Experiment.Unified

	mode := syntax.CheckBranches
	if supportsGenerics {
		mode |= syntax.AllowGenerics
	}

	// Limit the number of simultaneously open files.
	sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)

	noders := make([]*noder, len(filenames))
	for i, filename := range filenames {
		p := noder{
			err:         make(chan syntax.Error),
			trackScopes: base.Flag.Dwarf,
		}
		noders[i] = &p

		filename := filename
		go func() {
			sem <- struct{}{}
			defer func() { <-sem }()
			defer close(p.err)
			fbase := syntax.NewFileBase(filename)

			f, err := os.Open(filename)
			if err != nil {
				p.error(syntax.Error{Msg: err.Error()})
				return
			}
			defer f.Close()

			p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error
		}()
	}

	var lines uint
	for _, p := range noders {
		for e := range p.err {
			p.errorAt(e.Pos, "%s", e.Msg)
		}
		if p.file == nil {
			base.ErrorExit()
		}
		lines += p.file.EOF.Line()
	}
	base.Timer.AddEvent(int64(lines), "lines")

	if base.Debug.Unified != 0 {
		unified(noders)
		return
	}

	if base.Flag.G != 0 {
		// Use types2 to type-check and possibly generate IR.
		check2(noders)
		return
	}

	for _, p := range noders {
		p.node()
		p.file = nil // release memory
	}

	if base.SyntaxErrors() != 0 {
		base.ErrorExit()
	}
	types.CheckDclstack()

	for _, p := range noders {
		p.processPragmas()
	}

	// Typecheck.
	types.LocalPkg.Height = myheight
	typecheck.DeclareUniverse()
	typecheck.TypecheckAllowed = true

	// Process top-level declarations in phases.

	// Phase 1: const, type, and names and types of funcs.
	//   This will gather all the information about types
	//   and methods but doesn't depend on any of it.
	//
	//   We also defer type alias declarations until phase 2
	//   to avoid cycles like #18640.
	//   TODO(gri) Remove this again once we have a fix for #25838.
	//
	// Phase 2: Variable assignments.
	//   To check interface assignments, depends on phase 1.

	// Don't use range--typecheck can add closures to Target.Decls.
	for phase, name := range []string{"top1", "top2"} {
		base.Timer.Start("fe", "typecheck", name)
		for i := 0; i < len(typecheck.Target.Decls); i++ {
			n := typecheck.Target.Decls[i]
			op := n.Op()

			// Closure function declarations are typechecked as part of the
			// closure expression.
			if fn, ok := n.(*ir.Func); ok && fn.OClosure != nil {
				continue
			}

			// We don't actually add ir.ODCL nodes to Target.Decls. Make sure of that.
			if op == ir.ODCL {
				base.FatalfAt(n.Pos(), "unexpected top declaration: %v", op)
			}

			// Identify declarations that should be deferred to the second
			// iteration.
			late := op == ir.OAS || op == ir.OAS2 || op == ir.ODCLTYPE && n.(*ir.Decl).X.Alias()

			if late == (phase == 1) {
				typecheck.Target.Decls[i] = typecheck.Stmt(n)
			}
		}
	}

	// Phase 3: Type check function bodies.
	// Don't use range--typecheck can add closures to Target.Decls.
	base.Timer.Start("fe", "typecheck", "func")
	var fcount int64
	for i := 0; i < len(typecheck.Target.Decls); i++ {
		if fn, ok := typecheck.Target.Decls[i].(*ir.Func); ok {
			if base.Flag.W > 1 {
				s := fmt.Sprintf("\nbefore typecheck %v", fn)
				ir.Dump(s, fn)
			}
			typecheck.FuncBody(fn)
			if base.Flag.W > 1 {
				s := fmt.Sprintf("\nafter typecheck %v", fn)
				ir.Dump(s, fn)
			}
			fcount++
		}
	}

	// Phase 4: Check external declarations.
	// TODO(mdempsky): This should be handled when type checking their
	// corresponding ODCL nodes.
	base.Timer.Start("fe", "typecheck", "externdcls")
	for i, n := range typecheck.Target.Externs {
		if n.Op() == ir.ONAME {
			typecheck.Target.Externs[i] = typecheck.Expr(typecheck.Target.Externs[i])
		}
	}

	// Phase 5: With all user code type-checked, it's now safe to verify map keys.
	// With all user code typechecked, it's now safe to verify unused dot imports.
	typecheck.CheckMapKeys()
	CheckDotImports()
	base.ExitIfErrors()
}

func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
	base.ErrorfAt(p.makeXPos(pos), format, args...)
}

// trimFilename returns the "trimmed" filename of b, which is the
// absolute filename after applying -trimpath processing. This
// filename form is suitable for use in object files and export data.
//
// If b's filename has already been trimmed (i.e., because it was read
// in from an imported package's export data), then the filename is
// returned unchanged.
func trimFilename(b *syntax.PosBase) string {
	filename := b.Filename()
	if !b.Trimmed() {
		dir := ""
		if b.IsFileBase() {
			dir = base.Ctxt.Pathname
		}
		filename = objabi.AbsFile(dir, filename, base.Flag.TrimPath)
	}
	return filename
}

// noder transforms package syntax's AST into a Node tree.
type noder struct {
	posMap

	file           *syntax.File
	linknames      []linkname
	pragcgobuf     [][]string
	err            chan syntax.Error
	importedUnsafe bool
	importedEmbed  bool
	trackScopes    bool

	funcState *funcState
}

// funcState tracks all per-function state to make handling nested
// functions easier.
type funcState struct {
	// scopeVars is a stack tracking the number of variables declared in
	// the current function at the moment each open scope was opened.
	scopeVars []int
	marker    dwarfgen.ScopeMarker

	lastCloseScopePos syntax.Pos
}

func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
	outerFuncState := p.funcState
	p.funcState = new(funcState)
	typecheck.StartFuncBody(fn)

	if block != nil {
		body := p.stmts(block.List)
		if body == nil {
			body = []ir.Node{ir.NewBlockStmt(base.Pos, nil)}
		}
		fn.Body = body

		base.Pos = p.makeXPos(block.Rbrace)
		fn.Endlineno = base.Pos
	}

	typecheck.FinishFuncBody()
	p.funcState.marker.WriteTo(fn)
	p.funcState = outerFuncState
}

func (p *noder) openScope(pos syntax.Pos) {
	fs := p.funcState
	types.Markdcl()

	if p.trackScopes {
		fs.scopeVars = append(fs.scopeVars, len(ir.CurFunc.Dcl))
		fs.marker.Push(p.makeXPos(pos))
	}
}

func (p *noder) closeScope(pos syntax.Pos) {
	fs := p.funcState
	fs.lastCloseScopePos = pos
	types.Popdcl()

	if p.trackScopes {
		scopeVars := fs.scopeVars[len(fs.scopeVars)-1]
		fs.scopeVars = fs.scopeVars[:len(fs.scopeVars)-1]
		if scopeVars == len(ir.CurFunc.Dcl) {
			// no variables were declared in this scope, so we can retract it.
			fs.marker.Unpush()
		} else {
			fs.marker.Pop(p.makeXPos(pos))
		}
	}
}

// closeAnotherScope is like closeScope, but it reuses the same mark
// position as the last closeScope call. This is useful for "for" and
// "if" statements, as their implicit blocks always end at the same
// position as an explicit block.
func (p *noder) closeAnotherScope() {
	p.closeScope(p.funcState.lastCloseScopePos)
}

// linkname records a //go:linkname directive.
type linkname struct {
	pos    syntax.Pos
	local  string
	remote string
}

func (p *noder) node() {
	p.importedUnsafe = false
	p.importedEmbed = false

	p.setlineno(p.file.PkgName)
	mkpackage(p.file.PkgName.Value)

	if pragma, ok := p.file.Pragma.(*pragmas); ok {
		pragma.Flag &^= ir.GoBuildPragma
		p.checkUnused(pragma)
	}

	typecheck.Target.Decls = append(typecheck.Target.Decls, p.decls(p.file.DeclList)...)

	base.Pos = src.NoXPos
	clearImports()
}

func (p *noder) processPragmas() {
	for _, l := range p.linknames {
		if !p.importedUnsafe {
			p.errorAt(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
			continue
		}
		n := ir.AsNode(typecheck.Lookup(l.local).Def)
		if n == nil || n.Op() != ir.ONAME {
			// TODO(mdempsky): Change to p.errorAt before Go 1.17 release.
			// base.WarnfAt(p.makeXPos(l.pos), "//go:linkname must refer to declared function or variable (will be an error in Go 1.17)")
			continue
		}
		if n.Sym().Linkname != "" {
			p.errorAt(l.pos, "duplicate //go:linkname for %s", l.local)
			continue
		}
		n.Sym().Linkname = l.remote
	}
	typecheck.Target.CgoPragmas = append(typecheck.Target.CgoPragmas, p.pragcgobuf...)
}

func (p *noder) decls(decls []syntax.Decl) (l []ir.Node) {
	var cs constState

	for _, decl := range decls {
		p.setlineno(decl)
		switch decl := decl.(type) {
		case *syntax.ImportDecl:
			p.importDecl(decl)

		case *syntax.VarDecl:
			l = append(l, p.varDecl(decl)...)

		case *syntax.ConstDecl:
			l = append(l, p.constDecl(decl, &cs)...)

		case *syntax.TypeDecl:
			l = append(l, p.typeDecl(decl))

		case *syntax.FuncDecl:
			l = append(l, p.funcDecl(decl))

		default:
			panic("unhandled Decl")
		}
	}

	return
}

func (p *noder) importDecl(imp *syntax.ImportDecl) {
	if imp.Path == nil || imp.Path.Bad {
		return // avoid follow-on errors if there was a syntax error
	}

	if pragma, ok := imp.Pragma.(*pragmas); ok {
		p.checkUnused(pragma)
	}

	ipkg := importfile(imp)
	if ipkg == nil {
		if base.Errors() == 0 {
			base.Fatalf("phase error in import")
		}
		return
	}

	if ipkg == types.UnsafePkg {
		p.importedUnsafe = true
	}
	if ipkg.Path == "embed" {
		p.importedEmbed = true
	}

	var my *types.Sym
	if imp.LocalPkgName != nil {
		my = p.name(imp.LocalPkgName)
	} else {
		my = typecheck.Lookup(ipkg.Name)
	}

	pack := ir.NewPkgName(p.pos(imp), my, ipkg)

	switch my.Name {
	case ".":
		importDot(pack)
		return
	case "init":
		base.ErrorfAt(pack.Pos(), "cannot import package as init - init must be a func")
		return
	case "_":
		return
	}
	if my.Def != nil {
		typecheck.Redeclared(pack.Pos(), my, "as imported package name")
	}
	my.Def = pack
	my.Lastlineno = pack.Pos()
	my.Block = 1 // at top level
}

func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
	names := p.declNames(ir.ONAME, decl.NameList)
	typ := p.typeExprOrNil(decl.Type)
	exprs := p.exprList(decl.Values)

	if pragma, ok := decl.Pragma.(*pragmas); ok {
		varEmbed(p.makeXPos, names[0], decl, pragma, p.importedEmbed)
		p.checkUnused(pragma)
	}

	var init []ir.Node
	p.setlineno(decl)

	if len(names) > 1 && len(exprs) == 1 {
		as2 := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, exprs)
		for _, v := range names {
			as2.Lhs.Append(v)
			typecheck.Declare(v, typecheck.DeclContext)
			v.Ntype = typ
			v.Defn = as2
			if ir.CurFunc != nil {
				init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
			}
		}

		return append(init, as2)
	}

	for i, v := range names {
		var e ir.Node
		if i < len(exprs) {
			e = exprs[i]
		}

		typecheck.Declare(v, typecheck.DeclContext)
		v.Ntype = typ

		if ir.CurFunc != nil {
			init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
		}
		as := ir.NewAssignStmt(base.Pos, v, e)
		init = append(init, as)
		if e != nil || ir.CurFunc == nil {
			v.Defn = as
		}
	}

	if len(exprs) != 0 && len(names) != len(exprs) {
		base.Errorf("assignment mismatch: %d variables but %d values", len(names), len(exprs))
	}

	return init
}

// constState tracks state between constant specifiers within a
// declaration group. This state is kept separate from noder so nested
// constant declarations are handled correctly (e.g., issue 15550).
type constState struct {
	group  *syntax.Group
	typ    ir.Ntype
	values syntax.Expr
	iota   int64
}

func (p *noder) constDecl(decl *syntax.ConstDecl, cs *constState) []ir.Node {
	if decl.Group == nil || decl.Group != cs.group {
		*cs = constState{
			group: decl.Group,
		}
	}

	if pragma, ok := decl.Pragma.(*pragmas); ok {
		p.checkUnused(pragma)
	}

	names := p.declNames(ir.OLITERAL, decl.NameList)
	typ := p.typeExprOrNil(decl.Type)

	if decl.Values != nil {
		cs.typ, cs.values = typ, decl.Values
	} else {
		if typ != nil {
			base.Errorf("const declaration cannot have type without expression")
		}
		typ = cs.typ
	}
	values := p.exprList(cs.values)

	nn := make([]ir.Node, 0, len(names))
	for i, n := range names {
		if i >= len(values) {
			base.Errorf("missing value in const declaration")
			break
		}

		v := values[i]
		if decl.Values == nil {
			ir.Visit(v, func(v ir.Node) {
				if ir.HasUniquePos(v) {
					v.SetPos(n.Pos())
				}
			})
		}

		typecheck.Declare(n, typecheck.DeclContext)

		n.Ntype = typ
		n.Defn = v
		n.SetIota(cs.iota)

		nn = append(nn, ir.NewDecl(p.pos(decl), ir.ODCLCONST, n))
	}

	if len(values) > len(names) {
		base.Errorf("extra expression in const declaration")
	}

	cs.iota++

	return nn
}

func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
	n := p.declName(ir.OTYPE, decl.Name)
	typecheck.Declare(n, typecheck.DeclContext)

	// decl.Type may be nil but in that case we got a syntax error during parsing
	typ := p.typeExprOrNil(decl.Type)

	n.Ntype = typ
	n.SetAlias(decl.Alias)
	if pragma, ok := decl.Pragma.(*pragmas); ok {
		if !decl.Alias {
			n.SetPragma(pragma.Flag & typePragmas)
			pragma.Flag &^= typePragmas
		}
		p.checkUnused(pragma)
	}

	nod := ir.NewDecl(p.pos(decl), ir.ODCLTYPE, n)
	if n.Alias() && !types.AllowsGoVersion(types.LocalPkg, 1, 9) {
		base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
	}
	return nod
}

func (p *noder) declNames(op ir.Op, names []*syntax.Name) []*ir.Name {
	nodes := make([]*ir.Name, 0, len(names))
	for _, name := range names {
		nodes = append(nodes, p.declName(op, name))
	}
	return nodes
}

func (p *noder) declName(op ir.Op, name *syntax.Name) *ir.Name {
	return ir.NewDeclNameAt(p.pos(name), op, p.name(name))
}

func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
	name := p.name(fun.Name)
	t := p.signature(fun.Recv, fun.Type)
	f := ir.NewFunc(p.pos(fun))

	if fun.Recv == nil {
		if name.Name == "init" {
			name = renameinit()
			if len(t.Params) > 0 || len(t.Results) > 0 {
				base.ErrorfAt(f.Pos(), "func init must have no arguments and no return values")
			}
			typecheck.Target.Inits = append(typecheck.Target.Inits, f)
		}

		if types.LocalPkg.Name == "main" && name.Name == "main" {
			if len(t.Params) > 0 || len(t.Results) > 0 {
				base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values")
			}
		}
	} else {
		f.Shortname = name
		name = ir.BlankNode.Sym() // filled in by tcFunc
	}

	f.Nname = ir.NewNameAt(p.pos(fun.Name), name)
	f.Nname.Func = f
	f.Nname.Defn = f
	f.Nname.Ntype = t

	if pragma, ok := fun.Pragma.(*pragmas); ok {
		f.Pragma = pragma.Flag & funcPragmas
		if pragma.Flag&ir.Systemstack != 0 && pragma.Flag&ir.Nosplit != 0 {
			base.ErrorfAt(f.Pos(), "go:nosplit and go:systemstack cannot be combined")
		}
		pragma.Flag &^= funcPragmas
		p.checkUnused(pragma)
	}

	if fun.Recv == nil {
		typecheck.Declare(f.Nname, ir.PFUNC)
	}

	p.funcBody(f, fun.Body)

	if fun.Body != nil {
		if f.Pragma&ir.Noescape != 0 {
			base.ErrorfAt(f.Pos(), "can only use //go:noescape with external func implementations")
		}
	} else {
		if base.Flag.Complete || strings.HasPrefix(ir.FuncName(f), "init.") {
			// Linknamed functions are allowed to have no body. Hopefully
			// the linkname target has a body. See issue 23311.
			isLinknamed := false
			for _, n := range p.linknames {
				if ir.FuncName(f) == n.local {
					isLinknamed = true
					break
				}
			}
			if !isLinknamed {
				base.ErrorfAt(f.Pos(), "missing function body")
			}
		}
	}

	return f
}

func (p *noder) signature(recv *syntax.Field, typ *syntax.FuncType) *ir.FuncType {
	var rcvr *ir.Field
	if recv != nil {
		rcvr = p.param(recv, false, false)
	}
	return ir.NewFuncType(p.pos(typ), rcvr,
		p.params(typ.ParamList, true),
		p.params(typ.ResultList, false))
}

func (p *noder) params(params []*syntax.Field, dddOk bool) []*ir.Field {
	nodes := make([]*ir.Field, 0, len(params))
	for i, param := range params {
		p.setlineno(param)
		nodes = append(nodes, p.param(param, dddOk, i+1 == len(params)))
		if i > 0 && params[i].Type == params[i-1].Type {
			nodes[i].Ntype = nodes[i-1].Ntype
		}
	}
	return nodes
}

func (p *noder) param(param *syntax.Field, dddOk, final bool) *ir.Field {
	var name *types.Sym
	if param.Name != nil {
		name = p.name(param.Name)
	}

	typ := p.typeExpr(param.Type)
	n := ir.NewField(p.pos(param), name, typ, nil)

	// rewrite ...T parameter
	if typ, ok := typ.(*ir.SliceType); ok && typ.DDD {
		if !dddOk {
			// We mark these as syntax errors to get automatic elimination
			// of multiple such errors per line (see ErrorfAt in subr.go).
			base.Errorf("syntax error: cannot use ... in receiver or result parameter list")
		} else if !final {
			if param.Name == nil {
				base.Errorf("syntax error: cannot use ... with non-final parameter")
			} else {
				p.errorAt(param.Name.Pos(), "syntax error: cannot use ... with non-final parameter %s", param.Name.Value)
			}
		}
		typ.DDD = false
		n.IsDDD = true
	}

	return n
}

func (p *noder) exprList(expr syntax.Expr) []ir.Node {
	switch expr := expr.(type) {
	case nil:
		return nil
	case *syntax.ListExpr:
		return p.exprs(expr.ElemList)
	default:
		return []ir.Node{p.expr(expr)}
	}
}

func (p *noder) exprs(exprs []syntax.Expr) []ir.Node {
	nodes := make([]ir.Node, 0, len(exprs))
	for _, expr := range exprs {
		nodes = append(nodes, p.expr(expr))
	}
	return nodes
}

func (p *noder) expr(expr syntax.Expr) ir.Node {
	p.setlineno(expr)
	switch expr := expr.(type) {
	case nil, *syntax.BadExpr:
		return nil
	case *syntax.Name:
		return p.mkname(expr)
	case *syntax.BasicLit:
		n := ir.NewBasicLit(p.pos(expr), p.basicLit(expr))
		if expr.Kind == syntax.RuneLit {
			n.SetType(types.UntypedRune)
		}
		n.SetDiag(expr.Bad || n.Val().Kind() == constant.Unknown) // avoid follow-on errors if there was a syntax error
		return n
	case *syntax.CompositeLit:
		n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, p.typeExpr(expr.Type), nil)
		l := p.exprs(expr.ElemList)
		for i, e := range l {
			l[i] = p.wrapname(expr.ElemList[i], e)
		}
		n.List = l
		base.Pos = p.makeXPos(expr.Rbrace)
		return n
	case *syntax.KeyValueExpr:
		// use position of expr.Key rather than of expr (which has position of ':')
		return ir.NewKeyExpr(p.pos(expr.Key), p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
	case *syntax.FuncLit:
		return p.funcLit(expr)
	case *syntax.ParenExpr:
		return ir.NewParenExpr(p.pos(expr), p.expr(expr.X))
	case *syntax.SelectorExpr:
		// parser.new_dotname
		obj := p.expr(expr.X)
		if obj.Op() == ir.OPACK {
			pack := obj.(*ir.PkgName)
			pack.Used = true
			return importName(pack.Pkg.Lookup(expr.Sel.Value))
		}
		n := ir.NewSelectorExpr(base.Pos, ir.OXDOT, obj, p.name(expr.Sel))
		n.SetPos(p.pos(expr)) // lineno may have been changed by p.expr(expr.X)
		return n
	case *syntax.IndexExpr:
		return ir.NewIndexExpr(p.pos(expr), p.expr(expr.X), p.expr(expr.Index))
	case *syntax.SliceExpr:
		op := ir.OSLICE
		if expr.Full {
			op = ir.OSLICE3
		}
		x := p.expr(expr.X)
		var index [3]ir.Node
		for i, n := range &expr.Index {
			if n != nil {
				index[i] = p.expr(n)
			}
		}
		return ir.NewSliceExpr(p.pos(expr), op, x, index[0], index[1], index[2])
	case *syntax.AssertExpr:
		return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type))
	case *syntax.Operation:
		if expr.Op == syntax.Add && expr.Y != nil {
			return p.sum(expr)
		}
		x := p.expr(expr.X)
		if expr.Y == nil {
			pos, op := p.pos(expr), p.unOp(expr.Op)
			switch op {
			case ir.OADDR:
				return typecheck.NodAddrAt(pos, x)
			case ir.ODEREF:
				return ir.NewStarExpr(pos, x)
			}
			return ir.NewUnaryExpr(pos, op, x)
		}

		pos, op, y := p.pos(expr), p.binOp(expr.Op), p.expr(expr.Y)
		switch op {
		case ir.OANDAND, ir.OOROR:
			return ir.NewLogicalExpr(pos, op, x, y)
		}
		return ir.NewBinaryExpr(pos, op, x, y)
	case *syntax.CallExpr:
		n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), p.exprs(expr.ArgList))
		n.IsDDD = expr.HasDots
		return n

	case *syntax.ArrayType:
		var len ir.Node
		if expr.Len != nil {
			len = p.expr(expr.Len)
		}
		return ir.NewArrayType(p.pos(expr), len, p.typeExpr(expr.Elem))
	case *syntax.SliceType:
		return ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
	case *syntax.DotsType:
		t := ir.NewSliceType(p.pos(expr), p.typeExpr(expr.Elem))
		t.DDD = true
		return t
	case *syntax.StructType:
		return p.structType(expr)
	case *syntax.InterfaceType:
		return p.interfaceType(expr)
	case *syntax.FuncType:
		return p.signature(nil, expr)
	case *syntax.MapType:
		return ir.NewMapType(p.pos(expr),
			p.typeExpr(expr.Key), p.typeExpr(expr.Value))
	case *syntax.ChanType:
		return ir.NewChanType(p.pos(expr),
			p.typeExpr(expr.Elem), p.chanDir(expr.Dir))

	case *syntax.TypeSwitchGuard:
		var tag *ir.Ident
		if expr.Lhs != nil {
			tag = ir.NewIdent(p.pos(expr.Lhs), p.name(expr.Lhs))
			if ir.IsBlank(tag) {
				base.Errorf("invalid variable name %v in type switch", tag)
			}
		}
		return ir.NewTypeSwitchGuard(p.pos(expr), tag, p.expr(expr.X))
	}
	panic("unhandled Expr")
}

// sum efficiently handles very large summation expressions (such as
// in issue #16394). In particular, it avoids left recursion and
// collapses string literals.
func (p *noder) sum(x syntax.Expr) ir.Node {
	// While we need to handle long sums with asymptotic
	// efficiency, the vast majority of sums are very small: ~95%
	// have only 2 or 3 operands, and ~99% of string literals are
	// never concatenated.

	adds := make([]*syntax.Operation, 0, 2)
	for {
		add, ok := x.(*syntax.Operation)
		if !ok || add.Op != syntax.Add || add.Y == nil {
			break
		}
		adds = append(adds, add)
		x = add.X
	}

	// nstr is the current rightmost string literal in the
	// summation (if any), and chunks holds its accumulated
	// substrings.
	//
	// Consider the expression x + "a" + "b" + "c" + y. When we
	// reach the string literal "a", we assign nstr to point to
	// its corresponding Node and initialize chunks to {"a"}.
	// Visiting the subsequent string literals "b" and "c", we
	// simply append their values to chunks. Finally, when we
	// reach the non-constant operand y, we'll join chunks to form
	// "abc" and reassign the "a" string literal's value.
	//
	// N.B., we need to be careful about named string constants
	// (indicated by Sym != nil) because 1) we can't modify their
	// value, as doing so would affect other uses of the string
	// constant, and 2) they may have types, which we need to
	// handle correctly. For now, we avoid these problems by
	// treating named string constants the same as non-constant
	// operands.
	var nstr ir.Node
	chunks := make([]string, 0, 1)

	n := p.expr(x)
	if ir.IsConst(n, constant.String) && n.Sym() == nil {
		nstr = n
		chunks = append(chunks, ir.StringVal(nstr))
	}

	for i := len(adds) - 1; i >= 0; i-- {
		add := adds[i]

		r := p.expr(add.Y)
		if ir.IsConst(r, constant.String) && r.Sym() == nil {
			if nstr != nil {
				// Collapse r into nstr instead of adding to n.
				chunks = append(chunks, ir.StringVal(r))
				continue
			}

			nstr = r
			chunks = append(chunks, ir.StringVal(nstr))
		} else {
			if len(chunks) > 1 {
				nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
			}
			nstr = nil
			chunks = chunks[:0]
		}
		n = ir.NewBinaryExpr(p.pos(add), ir.OADD, n, r)
	}
	if len(chunks) > 1 {
		nstr.SetVal(constant.MakeString(strings.Join(chunks, "")))
	}

	return n
}

func (p *noder) typeExpr(typ syntax.Expr) ir.Ntype {
	// TODO(mdempsky): Be stricter? typecheck should handle errors anyway.
	n := p.expr(typ)
	if n == nil {
		return nil
	}
	return n.(ir.Ntype)
}

func (p *noder) typeExprOrNil(typ syntax.Expr) ir.Ntype {
	if typ != nil {
		return p.typeExpr(typ)
	}
	return nil
}

func (p *noder) chanDir(dir syntax.ChanDir) types.ChanDir {
	switch dir {
	case 0:
		return types.Cboth
	case syntax.SendOnly:
		return types.Csend
	case syntax.RecvOnly:
		return types.Crecv
	}
	panic("unhandled ChanDir")
}

func (p *noder) structType(expr *syntax.StructType) ir.Node {
	l := make([]*ir.Field, 0, len(expr.FieldList))
	for i, field := range expr.FieldList {
		p.setlineno(field)
		var n *ir.Field
		if field.Name == nil {
			n = p.embedded(field.Type)
		} else {
			n = ir.NewField(p.pos(field), p.name(field.Name), p.typeExpr(field.Type), nil)
		}
		if i > 0 && expr.FieldList[i].Type == expr.FieldList[i-1].Type {
			n.Ntype = l[i-1].Ntype
		}
		if i < len(expr.TagList) && expr.TagList[i] != nil {
			n.Note = constant.StringVal(p.basicLit(expr.TagList[i]))
		}
		l = append(l, n)
	}

	p.setlineno(expr)
	return ir.NewStructType(p.pos(expr), l)
}

func (p *noder) interfaceType(expr *syntax.InterfaceType) ir.Node {
	l := make([]*ir.Field, 0, len(expr.MethodList))
	for _, method := range expr.MethodList {
		p.setlineno(method)
		var n *ir.Field
		if method.Name == nil {
			n = ir.NewField(p.pos(method), nil, importName(p.packname(method.Type)).(ir.Ntype), nil)
		} else {
			mname := p.name(method.Name)
			if mname.IsBlank() {
				base.Errorf("methods must have a unique non-blank name")
				continue
			}
			sig := p.typeExpr(method.Type).(*ir.FuncType)
			sig.Recv = fakeRecv()
			n = ir.NewField(p.pos(method), mname, sig, nil)
		}
		l = append(l, n)
	}

	return ir.NewInterfaceType(p.pos(expr), l)
}

func (p *noder) packname(expr syntax.Expr) *types.Sym {
	switch expr := expr.(type) {
	case *syntax.Name:
		name := p.name(expr)
		if n := oldname(name); n.Name() != nil && n.Name().PkgName != nil {
			n.Name().PkgName.Used = true
		}
		return name
	case *syntax.SelectorExpr:
		name := p.name(expr.X.(*syntax.Name))
		def := ir.AsNode(name.Def)
		if def == nil {
			base.Errorf("undefined: %v", name)
			return name
		}
		var pkg *types.Pkg
		if def.Op() != ir.OPACK {
			base.Errorf("%v is not a package", name)
			pkg = types.LocalPkg
		} else {
			def := def.(*ir.PkgName)
			def.Used = true
			pkg = def.Pkg
		}
		return pkg.Lookup(expr.Sel.Value)
	}
	panic(fmt.Sprintf("unexpected packname: %#v", expr))
}

func (p *noder) embedded(typ syntax.Expr) *ir.Field {
	pos := p.pos(syntax.StartPos(typ))

	op, isStar := typ.(*syntax.Operation)
	if isStar {
		if op.Op != syntax.Mul || op.Y != nil {
			panic("unexpected Operation")
		}
		typ = op.X
	}

	sym := p.packname(typ)
	n := ir.NewField(pos, typecheck.Lookup(sym.Name), importName(sym).(ir.Ntype), nil)
	n.Embedded = true

	if isStar {
		n.Ntype = ir.NewStarExpr(pos, n.Ntype)
	}
	return n
}

func (p *noder) stmts(stmts []syntax.Stmt) []ir.Node {
	return p.stmtsFall(stmts, false)
}

func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []ir.Node {
	var nodes []ir.Node
	for i, stmt := range stmts {
		s := p.stmtFall(stmt, fallOK && i+1 == len(stmts))
		if s == nil {
		} else if s.Op() == ir.OBLOCK && len(s.(*ir.BlockStmt).List) > 0 {
			// Inline non-empty block.
			// Empty blocks must be preserved for CheckReturn.
			nodes = append(nodes, s.(*ir.BlockStmt).List...)
		} else {
			nodes = append(nodes, s)
		}
	}
	return nodes
}

func (p *noder) stmt(stmt syntax.Stmt) ir.Node {
	return p.stmtFall(stmt, false)
}

func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
	p.setlineno(stmt)
	switch stmt := stmt.(type) {
	case nil, *syntax.EmptyStmt:
		return nil
	case *syntax.LabeledStmt:
		return p.labeledStmt(stmt, fallOK)
	case *syntax.BlockStmt:
		l := p.blockStmt(stmt)
		if len(l) == 0 {
			// TODO(mdempsky): Line number?
			return ir.NewBlockStmt(base.Pos, nil)
		}
		return ir.NewBlockStmt(src.NoXPos, l)
	case *syntax.ExprStmt:
		return p.wrapname(stmt, p.expr(stmt.X))
	case *syntax.SendStmt:
		return ir.NewSendStmt(p.pos(stmt), p.expr(stmt.Chan), p.expr(stmt.Value))
	case *syntax.DeclStmt:
		return ir.NewBlockStmt(src.NoXPos, p.decls(stmt.DeclList))
	case *syntax.AssignStmt:
		if stmt.Rhs == nil {
			pos := p.pos(stmt)
			n := ir.NewAssignOpStmt(pos, p.binOp(stmt.Op), p.expr(stmt.Lhs), ir.NewBasicLit(pos, one))
			n.IncDec = true
			return n
		}

		if stmt.Op != 0 && stmt.Op != syntax.Def {
			n := ir.NewAssignOpStmt(p.pos(stmt), p.binOp(stmt.Op), p.expr(stmt.Lhs), p.expr(stmt.Rhs))
			return n
		}

		rhs := p.exprList(stmt.Rhs)
		if list, ok := stmt.Lhs.(*syntax.ListExpr); ok && len(list.ElemList) != 1 || len(rhs) != 1 {
			n := ir.NewAssignListStmt(p.pos(stmt), ir.OAS2, nil, nil)
			n.Def = stmt.Op == syntax.Def
			n.Lhs = p.assignList(stmt.Lhs, n, n.Def)
			n.Rhs = rhs
			return n
		}

		n := ir.NewAssignStmt(p.pos(stmt), nil, nil)
		n.Def = stmt.Op == syntax.Def
		n.X = p.assignList(stmt.Lhs, n, n.Def)[0]
		n.Y = rhs[0]
		return n

	case *syntax.BranchStmt:
		var op ir.Op
		switch stmt.Tok {
		case syntax.Break:
			op = ir.OBREAK
		case syntax.Continue:
			op = ir.OCONTINUE
		case syntax.Fallthrough:
			if !fallOK {
				base.Errorf("fallthrough statement out of place")
			}
			op = ir.OFALL
		case syntax.Goto:
			op = ir.OGOTO
		default:
			panic("unhandled BranchStmt")
		}
		var sym *types.Sym
		if stmt.Label != nil {
			sym = p.name(stmt.Label)
		}
		return ir.NewBranchStmt(p.pos(stmt), op, sym)
	case *syntax.CallStmt:
		var op ir.Op
		switch stmt.Tok {
		case syntax.Defer:
			op = ir.ODEFER
		case syntax.Go:
			op = ir.OGO
		default:
			panic("unhandled CallStmt")
		}
		return ir.NewGoDeferStmt(p.pos(stmt), op, p.expr(stmt.Call))
	case *syntax.ReturnStmt:
		n := ir.NewReturnStmt(p.pos(stmt), p.exprList(stmt.Results))
		if len(n.Results) == 0 && ir.CurFunc != nil {
			for _, ln := range ir.CurFunc.Dcl {
				if ln.Class == ir.PPARAM {
					continue
				}
				if ln.Class != ir.PPARAMOUT {
					break
				}
				if ln.Sym().Def != ln {
					base.Errorf("%s is shadowed during return", ln.Sym().Name)
				}
			}
		}
		return n
	case *syntax.IfStmt:
		return p.ifStmt(stmt)
	case *syntax.ForStmt:
		return p.forStmt(stmt)
	case *syntax.SwitchStmt:
		return p.switchStmt(stmt)
	case *syntax.SelectStmt:
		return p.selectStmt(stmt)
	}
	panic("unhandled Stmt")
}

func (p *noder) assignList(expr syntax.Expr, defn ir.InitNode, colas bool) []ir.Node {
	if !colas {
		return p.exprList(expr)
	}

	var exprs []syntax.Expr
	if list, ok := expr.(*syntax.ListExpr); ok {
		exprs = list.ElemList
	} else {
		exprs = []syntax.Expr{expr}
	}

	res := make([]ir.Node, len(exprs))
	seen := make(map[*types.Sym]bool, len(exprs))

	newOrErr := false
	for i, expr := range exprs {
		p.setlineno(expr)
		res[i] = ir.BlankNode

		name, ok := expr.(*syntax.Name)
		if !ok {
			p.errorAt(expr.Pos(), "non-name %v on left side of :=", p.expr(expr))
			newOrErr = true
			continue
		}

		sym := p.name(name)
		if sym.IsBlank() {
			continue
		}

		if seen[sym] {
			p.errorAt(expr.Pos(), "%v repeated on left side of :=", sym)
			newOrErr = true
			continue
		}
		seen[sym] = true

		if sym.Block == types.Block {
			res[i] = oldname(sym)
			continue
		}

		newOrErr = true
		n := typecheck.NewName(sym)
		typecheck.Declare(n, typecheck.DeclContext)
		n.Defn = defn
		defn.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, n))
		res[i] = n
	}

	if !newOrErr {
		base.ErrorfAt(defn.Pos(), "no new variables on left side of :=")
	}
	return res
}

func (p *noder) blockStmt(stmt *syntax.BlockStmt) []ir.Node {
	p.openScope(stmt.Pos())
	nodes := p.stmts(stmt.List)
	p.closeScope(stmt.Rbrace)
	return nodes
}

func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
	p.openScope(stmt.Pos())
	init := p.stmt(stmt.Init)
	n := ir.NewIfStmt(p.pos(stmt), p.expr(stmt.Cond), p.blockStmt(stmt.Then), nil)
	if init != nil {
		*n.PtrInit() = []ir.Node{init}
	}
	if stmt.Else != nil {
		e := p.stmt(stmt.Else)
		if e.Op() == ir.OBLOCK {
			e := e.(*ir.BlockStmt)
			n.Else = e.List
		} else {
			n.Else = []ir.Node{e}
		}
	}
	p.closeAnotherScope()
	return n
}

func (p *noder) forStmt(stmt *syntax.ForStmt) ir.Node {
	p.openScope(stmt.Pos())
	if r, ok := stmt.Init.(*syntax.RangeClause); ok {
		if stmt.Cond != nil || stmt.Post != nil {
			panic("unexpected RangeClause")
		}

		n := ir.NewRangeStmt(p.pos(r), nil, nil, p.expr(r.X), nil)
		if r.Lhs != nil {
			n.Def = r.Def
			lhs := p.assignList(r.Lhs, n, n.Def)
			n.Key = lhs[0]
			if len(lhs) > 1 {
				n.Value = lhs[1]
			}
		}
		n.Body = p.blockStmt(stmt.Body)
		p.closeAnotherScope()
		return n
	}

	n := ir.NewForStmt(p.pos(stmt), p.stmt(stmt.Init), p.expr(stmt.Cond), p.stmt(stmt.Post), p.blockStmt(stmt.Body))
	p.closeAnotherScope()
	return n
}

func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
	p.openScope(stmt.Pos())

	init := p.stmt(stmt.Init)
	n := ir.NewSwitchStmt(p.pos(stmt), p.expr(stmt.Tag), nil)
	if init != nil {
		*n.PtrInit() = []ir.Node{init}
	}

	var tswitch *ir.TypeSwitchGuard
	if l := n.Tag; l != nil && l.Op() == ir.OTYPESW {
		tswitch = l.(*ir.TypeSwitchGuard)
	}
	n.Cases = p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)

	p.closeScope(stmt.Rbrace)
	return n
}

func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []*ir.CaseClause {
	nodes := make([]*ir.CaseClause, 0, len(clauses))
	for i, clause := range clauses {
		p.setlineno(clause)
		if i > 0 {
			p.closeScope(clause.Pos())
		}
		p.openScope(clause.Pos())

		n := ir.NewCaseStmt(p.pos(clause), p.exprList(clause.Cases), nil)
		if tswitch != nil && tswitch.Tag != nil {
			nn := typecheck.NewName(tswitch.Tag.Sym())
			typecheck.Declare(nn, typecheck.DeclContext)
			n.Var = nn
			// keep track of the instances for reporting unused
			nn.Defn = tswitch
		}

		// Trim trailing empty statements. We omit them from
		// the Node AST anyway, and it's easier to identify
		// out-of-place fallthrough statements without them.
		body := clause.Body
		for len(body) > 0 {
			if _, ok := body[len(body)-1].(*syntax.EmptyStmt); !ok {
				break
			}
			body = body[:len(body)-1]
		}

		n.Body = p.stmtsFall(body, true)
		if l := len(n.Body); l > 0 && n.Body[l-1].Op() == ir.OFALL {
			if tswitch != nil {
				base.Errorf("cannot fallthrough in type switch")
			}
			if i+1 == len(clauses) {
				base.Errorf("cannot fallthrough final case in switch")
			}
		}

		nodes = append(nodes, n)
	}
	if len(clauses) > 0 {
		p.closeScope(rbrace)
	}
	return nodes
}

func (p *noder) selectStmt(stmt *syntax.SelectStmt) ir.Node {
	return ir.NewSelectStmt(p.pos(stmt), p.commClauses(stmt.Body, stmt.Rbrace))
}

func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*ir.CommClause {
	nodes := make([]*ir.CommClause, len(clauses))
	for i, clause := range clauses {
		p.setlineno(clause)
		if i > 0 {
			p.closeScope(clause.Pos())
		}
		p.openScope(clause.Pos())

		nodes[i] = ir.NewCommStmt(p.pos(clause), p.stmt(clause.Comm), p.stmts(clause.Body))
	}
	if len(clauses) > 0 {
		p.closeScope(rbrace)
	}
	return nodes
}

func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) ir.Node {
	sym := p.name(label.Label)
	lhs := ir.NewLabelStmt(p.pos(label), sym)

	var ls ir.Node
	if label.Stmt != nil { // TODO(mdempsky): Should always be present.
		ls = p.stmtFall(label.Stmt, fallOK)
		// Attach label directly to control statement too.
		if ls != nil {
			switch ls.Op() {
			case ir.OFOR:
				ls := ls.(*ir.ForStmt)
				ls.Label = sym
			case ir.ORANGE:
				ls := ls.(*ir.RangeStmt)
				ls.Label = sym
			case ir.OSWITCH:
				ls := ls.(*ir.SwitchStmt)
				ls.Label = sym
			case ir.OSELECT:
				ls := ls.(*ir.SelectStmt)
				ls.Label = sym
			}
		}
	}

	l := []ir.Node{lhs}
	if ls != nil {
		if ls.Op() == ir.OBLOCK {
			ls := ls.(*ir.BlockStmt)
			l = append(l, ls.List...)
		} else {
			l = append(l, ls)
		}
	}
	return ir.NewBlockStmt(src.NoXPos, l)
}

var unOps = [...]ir.Op{
	syntax.Recv: ir.ORECV,
	syntax.Mul:  ir.ODEREF,
	syntax.And:  ir.OADDR,

	syntax.Not: ir.ONOT,
	syntax.Xor: ir.OBITNOT,
	syntax.Add: ir.OPLUS,
	syntax.Sub: ir.ONEG,
}

func (p *noder) unOp(op syntax.Operator) ir.Op {
	if uint64(op) >= uint64(len(unOps)) || unOps[op] == 0 {
		panic("invalid Operator")
	}
	return unOps[op]
}

var binOps = [...]ir.Op{
	syntax.OrOr:   ir.OOROR,
	syntax.AndAnd: ir.OANDAND,

	syntax.Eql: ir.OEQ,
	syntax.Neq: ir.ONE,
	syntax.Lss: ir.OLT,
	syntax.Leq: ir.OLE,
	syntax.Gtr: ir.OGT,
	syntax.Geq: ir.OGE,

	syntax.Add: ir.OADD,
	syntax.Sub: ir.OSUB,
	syntax.Or:  ir.OOR,
	syntax.Xor: ir.OXOR,

	syntax.Mul:    ir.OMUL,
	syntax.Div:    ir.ODIV,
	syntax.Rem:    ir.OMOD,
	syntax.And:    ir.OAND,
	syntax.AndNot: ir.OANDNOT,
	syntax.Shl:    ir.OLSH,
	syntax.Shr:    ir.ORSH,
}

func (p *noder) binOp(op syntax.Operator) ir.Op {
	if uint64(op) >= uint64(len(binOps)) || binOps[op] == 0 {
		panic("invalid Operator")
	}
	return binOps[op]
}

// checkLangCompat reports an error if the representation of a numeric
// literal is not compatible with the current language version.
func checkLangCompat(lit *syntax.BasicLit) {
	s := lit.Value
	if len(s) <= 2 || types.AllowsGoVersion(types.LocalPkg, 1, 13) {
		return
	}
	// len(s) > 2
	if strings.Contains(s, "_") {
		base.ErrorfVers("go1.13", "underscores in numeric literals")
		return
	}
	if s[0] != '0' {
		return
	}
	radix := s[1]
	if radix == 'b' || radix == 'B' {
		base.ErrorfVers("go1.13", "binary literals")
		return
	}
	if radix == 'o' || radix == 'O' {
		base.ErrorfVers("go1.13", "0o/0O-style octal literals")
		return
	}
	if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
		base.ErrorfVers("go1.13", "hexadecimal floating-point literals")
	}
}

func (p *noder) basicLit(lit *syntax.BasicLit) constant.Value {
	// We don't use the errors of the conversion routines to determine
	// if a literal string is valid because the conversion routines may
	// accept a wider syntax than the language permits. Rely on lit.Bad
	// instead.
	if lit.Bad {
		return constant.MakeUnknown()
	}

	switch lit.Kind {
	case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
		checkLangCompat(lit)
		// The max. mantissa precision for untyped numeric values
		// is 512 bits, or 4048 bits for each of the two integer
		// parts of a fraction for floating-point numbers that are
		// represented accurately in the go/constant package.
		// Constant literals that are longer than this many bits
		// are not meaningful; and excessively long constants may
		// consume a lot of space and time for a useless conversion.
		// Cap constant length with a generous upper limit that also
		// allows for separators between all digits.
		const limit = 10000
		if len(lit.Value) > limit {
			p.errorAt(lit.Pos(), "excessively long constant: %s... (%d chars)", lit.Value[:10], len(lit.Value))
			return constant.MakeUnknown()
		}
	}

	v := constant.MakeFromLiteral(lit.Value, tokenForLitKind[lit.Kind], 0)
	if v.Kind() == constant.Unknown {
		// TODO(mdempsky): Better error message?
		p.errorAt(lit.Pos(), "malformed constant: %s", lit.Value)
	}

	return v
}

var tokenForLitKind = [...]token.Token{
	syntax.IntLit:    token.INT,
	syntax.RuneLit:   token.CHAR,
	syntax.FloatLit:  token.FLOAT,
	syntax.ImagLit:   token.IMAG,
	syntax.StringLit: token.STRING,
}

func (p *noder) name(name *syntax.Name) *types.Sym {
	return typecheck.Lookup(name.Value)
}

func (p *noder) mkname(name *syntax.Name) ir.Node {
	// TODO(mdempsky): Set line number?
	return mkname(p.name(name))
}

func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node {
	// These nodes do not carry line numbers.
	// Introduce a wrapper node to give them the correct line.
	switch x.Op() {
	case ir.OTYPE, ir.OLITERAL:
		if x.Sym() == nil {
			break
		}
		fallthrough
	case ir.ONAME, ir.ONONAME, ir.OPACK:
		p := ir.NewParenExpr(p.pos(n), x)
		p.SetImplicit(true)
		return p
	}
	return x
}

func (p *noder) setlineno(n syntax.Node) {
	if n != nil {
		base.Pos = p.pos(n)
	}
}

// error is called concurrently if files are parsed concurrently.
func (p *noder) error(err error) {
	p.err <- err.(syntax.Error)
}

// pragmas that are allowed in the std lib, but don't have
// a syntax.Pragma value (see lex.go) associated with them.
var allowedStdPragmas = map[string]bool{
	"go:cgo_export_static":  true,
	"go:cgo_export_dynamic": true,
	"go:cgo_import_static":  true,
	"go:cgo_import_dynamic": true,
	"go:cgo_ldflag":         true,
	"go:cgo_dynamic_linker": true,
	"go:embed":              true,
	"go:generate":           true,
}

// *pragmas is the value stored in a syntax.pragmas during parsing.
type pragmas struct {
	Flag   ir.PragmaFlag // collected bits
	Pos    []pragmaPos   // position of each individual flag
	Embeds []pragmaEmbed
}

type pragmaPos struct {
	Flag ir.PragmaFlag
	Pos  syntax.Pos
}

type pragmaEmbed struct {
	Pos      syntax.Pos
	Patterns []string
}

func (p *noder) checkUnused(pragma *pragmas) {
	for _, pos := range pragma.Pos {
		if pos.Flag&pragma.Flag != 0 {
			p.errorAt(pos.Pos, "misplaced compiler directive")
		}
	}
	if len(pragma.Embeds) > 0 {
		for _, e := range pragma.Embeds {
			p.errorAt(e.Pos, "misplaced go:embed directive")
		}
	}
}

func (p *noder) checkUnusedDuringParse(pragma *pragmas) {
	for _, pos := range pragma.Pos {
		if pos.Flag&pragma.Flag != 0 {
			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.
func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.Pragma) syntax.Pragma {
	pragma, _ := old.(*pragmas)
	if pragma == nil {
		pragma = new(pragmas)
	}

	if text == "" {
		// unused pragma; only called with old != nil.
		p.checkUnusedDuringParse(pragma)
		return nil
	}

	if strings.HasPrefix(text, "line ") {
		// line directives are handled by syntax package
		panic("unreachable")
	}

	if !blankLine {
		// directive must be on line by itself
		p.error(syntax.Error{Pos: pos, Msg: "misplaced compiler directive"})
		return pragma
	}

	switch {
	case strings.HasPrefix(text, "go:linkname "):
		f := strings.Fields(text)
		if !(2 <= len(f) && len(f) <= 3) {
			p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname [linkname]"})
			break
		}
		// The second argument is optional. If omitted, we use
		// the default object symbol name for this and
		// linkname only serves to mark this symbol as
		// something that may be referenced via the object
		// symbol name from another package.
		var target string
		if len(f) == 3 {
			target = f[2]
		} else if base.Ctxt.Pkgpath != "" {
			// Use the default object symbol name if the
			// user didn't provide one.
			target = objabi.PathToPrefix(base.Ctxt.Pkgpath) + "." + f[1]
		} else {
			p.error(syntax.Error{Pos: pos, Msg: "//go:linkname requires linkname argument or -p compiler flag"})
			break
		}
		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.
		fields := pragmaFields(text)
		if len(fields) >= 4 {
			lib := strings.Trim(fields[3], `"`)
			if lib != "" && !safeArg(lib) && !isCgoGeneratedFile(pos) {
				p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("invalid library name %q in cgo_import_dynamic directive", lib)})
			}
			p.pragcgo(pos, text)
			pragma.Flag |= pragmaFlag("go:cgo_import_dynamic")
			break
		}
		fallthrough
	case strings.HasPrefix(text, "go:cgo_"):
		// For security, we disallow //go:cgo_* directives other
		// than cgo_import_dynamic outside cgo-generated files.
		// Exception: they are allowed in the standard library, for runtime and syscall.
		if !isCgoGeneratedFile(pos) && !base.Flag.Std {
			p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
		}
		p.pragcgo(pos, text)
		fallthrough // because of //go:cgo_unsafe_args
	default:
		verb := text
		if i := strings.Index(text, " "); i >= 0 {
			verb = verb[:i]
		}
		flag := pragmaFlag(verb)
		const runtimePragmas = ir.Systemstack | ir.Nowritebarrier | ir.Nowritebarrierrec | ir.Yeswritebarrierrec
		if !base.Flag.CompilingRuntime && flag&runtimePragmas != 0 {
			p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in runtime", verb)})
		}
		if flag == 0 && !allowedStdPragmas[verb] && base.Flag.Std {
			p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s is not allowed in the standard library", verb)})
		}
		pragma.Flag |= flag
		pragma.Pos = append(pragma.Pos, pragmaPos{flag, pos})
	}

	return pragma
}

// isCgoGeneratedFile reports whether pos is in a file
// generated by cgo, which is to say a file with name
// beginning with "_cgo_". Such files are allowed to
// contain cgo directives, and for security reasons
// (primarily misuse of linker flags), other files are not.
// See golang.org/issue/23672.
func isCgoGeneratedFile(pos syntax.Pos) bool {
	return strings.HasPrefix(filepath.Base(trimFilename(pos.Base())), "_cgo_")
}

// safeArg reports whether arg is a "safe" command-line argument,
// meaning that when it appears in a command-line, it probably
// doesn't have some special meaning other than its own name.
// This is copied from SafeArg in cmd/go/internal/load/pkg.go.
func safeArg(name string) bool {
	if name == "" {
		return false
	}
	c := name[0]
	return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
}

func mkname(sym *types.Sym) ir.Node {
	n := oldname(sym)
	if n.Name() != nil && n.Name().PkgName != nil {
		n.Name().PkgName.Used = true
	}
	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
}

func fakeRecv() *ir.Field {
	return ir.NewField(base.Pos, nil, nil, types.FakeRecvType())
}

func (p *noder) funcLit(expr *syntax.FuncLit) ir.Node {
	fn := ir.NewClosureFunc(p.pos(expr), ir.CurFunc != nil)
	fn.Nname.Ntype = p.typeExpr(expr.Type)

	p.funcBody(fn, expr.Body)

	ir.FinishCaptureNames(base.Pos, ir.CurFunc, fn)

	return fn.OClosure
}

// A function named init is a special case.
// It is called by the initialization before main is run.
// To make it unique within a package and also uncallable,
// the name, normally "pkg.init", is altered to "pkg.init.0".
var renameinitgen int

func renameinit() *types.Sym {
	s := typecheck.LookupNum("init.", renameinitgen)
	renameinitgen++
	return s
}

// oldname returns the Node that declares symbol s in the current scope.
// If no such Node currently exists, an ONONAME Node is returned instead.
// Automatically creates a new closure variable if the referenced symbol was
// declared in a different (containing) function.
func oldname(s *types.Sym) ir.Node {
	if s.Pkg != types.LocalPkg {
		return ir.NewIdent(base.Pos, s)
	}

	n := ir.AsNode(s.Def)
	if n == nil {
		// Maybe a top-level declaration will come along later to
		// define s. resolve will check s.Def again once all input
		// source has been processed.
		return ir.NewIdent(base.Pos, s)
	}

	if n, ok := n.(*ir.Name); ok {
		// TODO(rsc): If there is an outer variable x and we
		// are parsing x := 5 inside the closure, until we get to
		// the := it looks like a reference to the outer x so we'll
		// make x a closure variable unnecessarily.
		return ir.CaptureName(base.Pos, ir.CurFunc, n)
	}

	return n
}

func varEmbed(makeXPos func(syntax.Pos) src.XPos, name *ir.Name, decl *syntax.VarDecl, pragma *pragmas, haveEmbed bool) {
	pragmaEmbeds := pragma.Embeds
	pragma.Embeds = nil
	if len(pragmaEmbeds) == 0 {
		return
	}

	if err := checkEmbed(decl, haveEmbed, typecheck.DeclContext != ir.PEXTERN); err != nil {
		base.ErrorfAt(makeXPos(pragmaEmbeds[0].Pos), "%s", err)
		return
	}

	var embeds []ir.Embed
	for _, e := range pragmaEmbeds {
		embeds = append(embeds, ir.Embed{Pos: makeXPos(e.Pos), Patterns: e.Patterns})
	}
	typecheck.Target.Embeds = append(typecheck.Target.Embeds, name)
	name.Embed = &embeds
}

func checkEmbed(decl *syntax.VarDecl, haveEmbed, withinFunc bool) error {
	switch {
	case !haveEmbed:
		return errors.New("go:embed only allowed in Go files that import \"embed\"")
	case len(decl.NameList) > 1:
		return errors.New("go:embed cannot apply to multiple vars")
	case decl.Values != nil:
		return errors.New("go:embed cannot apply to var with initializer")
	case decl.Type == nil:
		// Should not happen, since Values == nil now.
		return errors.New("go:embed cannot apply to var without type")
	case withinFunc:
		return errors.New("go:embed cannot apply to var inside func")
	case !types.AllowsGoVersion(types.LocalPkg, 1, 16):
		return fmt.Errorf("go:embed requires go1.16 or later (-lang was set to %s; check go.mod)", base.Flag.Lang)

	default:
		return nil
	}
}
