mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
- set correct position for closure capture variable in (*irgen).use() (issue20250.go) Also, evaluate rhs, lhs in that order in assignment statements to match noder1 (affects ordering of closure variables). - make sure to set Assign flag properly in (*irgen).forStmt() for range variables which are map accesses (issue9691.go) - make sure CheckSize() is call on the base type for top-level types converted by (*irgen).typ() that are pointer types (issue20174.go and issue37837.go) - deal with parentheses properly in validation function (*irgen).validate() (issue17270.go) - avoid HasNil call on type TTYPEPARAM - types2 typechecker will have already checked validity of the typeparam having nil value (new test issue39755.go) Change-Id: Ie68004d964698aea047e19e7dcd79b297e9d47ca Reviewed-on: https://go-review.googlesource.com/c/go/+/334733 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
191 lines
5.1 KiB
Go
191 lines
5.1 KiB
Go
// Copyright 2021 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 (
|
|
"cmd/compile/internal/base"
|
|
"cmd/compile/internal/ir"
|
|
"cmd/compile/internal/syntax"
|
|
"cmd/compile/internal/typecheck"
|
|
"cmd/compile/internal/types"
|
|
"cmd/compile/internal/types2"
|
|
"cmd/internal/src"
|
|
)
|
|
|
|
func (g *irgen) def(name *syntax.Name) (*ir.Name, types2.Object) {
|
|
obj, ok := g.info.Defs[name]
|
|
if !ok {
|
|
base.FatalfAt(g.pos(name), "unknown name %v", name)
|
|
}
|
|
return g.obj(obj), obj
|
|
}
|
|
|
|
// use returns the Name node associated with the use of name. The returned node
|
|
// will have the correct type and be marked as typechecked.
|
|
func (g *irgen) use(name *syntax.Name) *ir.Name {
|
|
obj2, ok := g.info.Uses[name]
|
|
if !ok {
|
|
base.FatalfAt(g.pos(name), "unknown name %v", name)
|
|
}
|
|
obj := ir.CaptureName(g.pos(name), ir.CurFunc, g.obj(obj2))
|
|
if obj.Defn != nil && obj.Defn.Op() == ir.ONAME {
|
|
// If CaptureName created a closure variable, then transfer the
|
|
// type of the captured name to the new closure variable.
|
|
obj.SetTypecheck(1)
|
|
obj.SetType(obj.Defn.Type())
|
|
}
|
|
return obj
|
|
}
|
|
|
|
// obj returns the Name that represents the given object. If no such Name exists
|
|
// yet, it will be implicitly created. The returned node will have the correct
|
|
// type and be marked as typechecked.
|
|
//
|
|
// For objects declared at function scope, ir.CurFunc must already be
|
|
// set to the respective function when the Name is created.
|
|
func (g *irgen) obj(obj types2.Object) *ir.Name {
|
|
// For imported objects, we use iimport directly instead of mapping
|
|
// the types2 representation.
|
|
if obj.Pkg() != g.self {
|
|
if sig, ok := obj.Type().(*types2.Signature); ok && sig.Recv() != nil {
|
|
// We can't import a method by name - must import the type
|
|
// and access the method from it.
|
|
base.FatalfAt(g.pos(obj), "tried to import a method directly")
|
|
}
|
|
sym := g.sym(obj)
|
|
if sym.Def != nil {
|
|
return sym.Def.(*ir.Name)
|
|
}
|
|
n := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
|
|
if n, ok := n.(*ir.Name); ok {
|
|
n.SetTypecheck(1)
|
|
return n
|
|
}
|
|
base.FatalfAt(g.pos(obj), "failed to resolve %v", obj)
|
|
}
|
|
|
|
if name, ok := g.objs[obj]; ok {
|
|
return name // previously mapped
|
|
}
|
|
|
|
var name *ir.Name
|
|
pos := g.pos(obj)
|
|
|
|
class := typecheck.DeclContext
|
|
if obj.Parent() == g.self.Scope() {
|
|
class = ir.PEXTERN // forward reference to package-block declaration
|
|
}
|
|
|
|
// "You are in a maze of twisting little passages, all different."
|
|
switch obj := obj.(type) {
|
|
case *types2.Const:
|
|
name = g.objCommon(pos, ir.OLITERAL, g.sym(obj), class, g.typ(obj.Type()))
|
|
|
|
case *types2.Func:
|
|
sig := obj.Type().(*types2.Signature)
|
|
var sym *types.Sym
|
|
var typ *types.Type
|
|
if recv := sig.Recv(); recv == nil {
|
|
if obj.Name() == "init" {
|
|
sym = renameinit()
|
|
} else {
|
|
sym = g.sym(obj)
|
|
}
|
|
typ = g.typ(sig)
|
|
} else {
|
|
sym = g.selector(obj)
|
|
if !sym.IsBlank() {
|
|
sym = ir.MethodSym(g.typ(recv.Type()), sym)
|
|
}
|
|
typ = g.signature(g.param(recv), sig)
|
|
}
|
|
name = g.objCommon(pos, ir.ONAME, sym, ir.PFUNC, typ)
|
|
|
|
case *types2.TypeName:
|
|
if obj.IsAlias() {
|
|
name = g.objCommon(pos, ir.OTYPE, g.sym(obj), class, g.typ(obj.Type()))
|
|
name.SetAlias(true)
|
|
} else {
|
|
name = ir.NewDeclNameAt(pos, ir.OTYPE, g.sym(obj))
|
|
g.objFinish(name, class, types.NewNamed(name))
|
|
}
|
|
|
|
case *types2.Var:
|
|
sym := g.sym(obj)
|
|
if class == ir.PPARAMOUT && (sym == nil || sym.IsBlank()) {
|
|
// Backend needs names for result parameters,
|
|
// even if they're anonymous or blank.
|
|
nresults := 0
|
|
for _, n := range ir.CurFunc.Dcl {
|
|
if n.Class == ir.PPARAMOUT {
|
|
nresults++
|
|
}
|
|
}
|
|
if sym == nil {
|
|
sym = typecheck.LookupNum("~r", nresults) // 'r' for "result"
|
|
} else {
|
|
sym = typecheck.LookupNum("~b", nresults) // 'b' for "blank"
|
|
}
|
|
}
|
|
name = g.objCommon(pos, ir.ONAME, sym, class, g.typ(obj.Type()))
|
|
|
|
default:
|
|
g.unhandled("object", obj)
|
|
}
|
|
|
|
g.objs[obj] = name
|
|
name.SetTypecheck(1)
|
|
return name
|
|
}
|
|
|
|
func (g *irgen) objCommon(pos src.XPos, op ir.Op, sym *types.Sym, class ir.Class, typ *types.Type) *ir.Name {
|
|
name := ir.NewDeclNameAt(pos, op, sym)
|
|
g.objFinish(name, class, typ)
|
|
return name
|
|
}
|
|
|
|
func (g *irgen) objFinish(name *ir.Name, class ir.Class, typ *types.Type) {
|
|
sym := name.Sym()
|
|
|
|
name.SetType(typ)
|
|
name.Class = class
|
|
if name.Class == ir.PFUNC {
|
|
sym.SetFunc(true)
|
|
}
|
|
|
|
name.SetTypecheck(1)
|
|
name.SetWalkdef(1)
|
|
|
|
if ir.IsBlank(name) {
|
|
return
|
|
}
|
|
|
|
switch class {
|
|
case ir.PEXTERN:
|
|
g.target.Externs = append(g.target.Externs, name)
|
|
fallthrough
|
|
case ir.PFUNC:
|
|
sym.Def = name
|
|
if name.Class == ir.PFUNC && name.Type().Recv() != nil {
|
|
break // methods are exported with their receiver type
|
|
}
|
|
if types.IsExported(sym.Name) {
|
|
// Generic functions can be marked for export here, even
|
|
// though they will not be compiled until instantiated.
|
|
typecheck.Export(name)
|
|
}
|
|
if base.Flag.AsmHdr != "" && !name.Sym().Asm() {
|
|
name.Sym().SetAsm(true)
|
|
g.target.Asms = append(g.target.Asms, name)
|
|
}
|
|
|
|
default:
|
|
// Function-scoped declaration.
|
|
name.Curfn = ir.CurFunc
|
|
if name.Op() == ir.ONAME {
|
|
ir.CurFunc.Dcl = append(ir.CurFunc.Dcl, name)
|
|
}
|
|
}
|
|
}
|