]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: first start towards using Ident
authorMatthew Dempsky <mdempsky@google.com>
Tue, 8 Dec 2020 05:56:58 +0000 (21:56 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 9 Dec 2020 17:17:53 +0000 (17:17 +0000)
This CL adds Ident, which will eventually replace *Name and *PkgName
within the AST for representing uses of declared names. (Originally, I
intended to call it "IdentExpr", but neither go/ast nor
cmd/compile/internal/syntax include the "Expr" suffix for their
respective types.)

To start, this CL converts two uses of *Name to *Ident: the tag
identifier in a TypeSwitchGuard (which doesn't actually declare a
variable by itself), and the not-yet-known placeholder ONONAME
returned by oldname to stand-in for identifiers that might be declared
later in the package.

The TypeSwitchGuard's Name's Used flag was previously used for
detecting whether none of the per-clause variables were used. To avoid
bloating all Idents for this rare use, a "Used" bool is added to
TypeSwitchGuard instead. Eventually it could maybe be packed into
miniNode.bits, but for now this is good enough.

Passes buildall w/ toolstash -cmp.

Change-Id: I393284d86757cbbebd26e1320c7354e2bdcb30b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/276113
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/iimport.go
src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/walk.go
src/cmd/compile/internal/ir/mknode.go
src/cmd/compile/internal/ir/name.go
src/cmd/compile/internal/ir/node.go
src/cmd/compile/internal/ir/node_gen.go
src/cmd/compile/internal/ir/stmt.go

index 1c23c5a92f635efa0523728b7a5347784adbcb55..1ebadd92137258186a333b66c35eb773bfccc84a 100644 (file)
@@ -215,7 +215,7 @@ func oldname(s *types.Sym) ir.Node {
                // 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.NewDeclNameAt(base.Pos, s)
+               return ir.NewIdent(base.Pos, s)
        }
 
        if Curfn != nil && n.Op() == ir.ONAME && n.Name().Curfn != nil && n.Name().Curfn != Curfn {
index 1f75393b3e1e5f94e0fd2a7a809a0ab84f43b321..3c9693e5fce054880c7be99f0b7f27b33f880867 100644 (file)
@@ -833,13 +833,13 @@ func (r *importReader) node() ir.Node {
                return ir.TypeNode(r.typ())
 
        case ir.OTYPESW:
-               n := ir.NodAt(r.pos(), ir.OTYPESW, nil, nil)
+               pos := r.pos()
+               var tag *ir.Ident
                if s := r.ident(); s != nil {
-                       n.SetLeft(ir.NewDeclNameAt(n.Pos(), s))
+                       tag = ir.NewIdent(pos, s)
                }
-               right, _ := r.exprsOrNil()
-               n.SetRight(right)
-               return n
+               expr, _ := r.exprsOrNil()
+               return ir.NewTypeSwitchGuard(pos, tag, expr)
 
        // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
        //      unreachable - should have been resolved by typechecking
index f39bf2ff3c4764d87445b1b485625d895648af37..8c765f9dfc25fbe6628cae388cbf97839867f323 100644 (file)
@@ -751,14 +751,14 @@ func (p *noder) expr(expr syntax.Expr) ir.Node {
                        p.typeExpr(expr.Elem), p.chanDir(expr.Dir))
 
        case *syntax.TypeSwitchGuard:
-               n := p.nod(expr, ir.OTYPESW, nil, p.expr(expr.X))
+               var tag *ir.Ident
                if expr.Lhs != nil {
-                       n.SetLeft(p.declName(expr.Lhs))
-                       if ir.IsBlank(n.Left()) {
-                               base.Errorf("invalid variable name %v in type switch", n.Left())
+                       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 n
+               return ir.NewTypeSwitchGuard(p.pos(expr), tag, p.expr(expr.X))
        }
        panic("unhandled Expr")
 }
index 36526d4c2d6e7ce6d2c71355124b106717ae08e0..d88989f83c8357c8addafe2046e70884f7f26622 100644 (file)
@@ -90,12 +90,16 @@ func resolve(n ir.Node) (res ir.Node) {
                defer tracePrint("resolve", n)(&res)
        }
 
-       if n.Sym().Pkg != types.LocalPkg {
+       // Stub ir.Name left for us by iimport.
+       if n, ok := n.(*ir.Name); ok {
+               if n.Sym().Pkg == types.LocalPkg {
+                       base.Fatalf("unexpected Name: %+v", n)
+               }
                if inimport {
                        base.Fatalf("recursive inimport")
                }
                inimport = true
-               expandDecl(n.(*ir.Name))
+               expandDecl(n)
                inimport = false
                return n
        }
index f35e9d768bd491527ce60612ada9573c1b56fae6..390719e441a84d725aa4992dd7d04c7fe0195013 100644 (file)
@@ -44,7 +44,7 @@ func walk(fn *ir.Func) {
        // Propagate the used flag for typeswitch variables up to the NONAME in its definition.
        for _, ln := range fn.Dcl {
                if ln.Op() == ir.ONAME && (ln.Class() == ir.PAUTO || ln.Class() == ir.PAUTOHEAP) && ln.Defn != nil && ln.Defn.Op() == ir.OTYPESW && ln.Used() {
-                       ln.Defn.Left().Name().SetUsed(true)
+                       ln.Defn.(*ir.TypeSwitchGuard).Used = true
                }
        }
 
@@ -52,12 +52,12 @@ func walk(fn *ir.Func) {
                if ln.Op() != ir.ONAME || (ln.Class() != ir.PAUTO && ln.Class() != ir.PAUTOHEAP) || ln.Sym().Name[0] == '&' || ln.Used() {
                        continue
                }
-               if defn := ln.Defn; defn != nil && defn.Op() == ir.OTYPESW {
-                       if defn.Left().Name().Used() {
+               if defn, ok := ln.Defn.(*ir.TypeSwitchGuard); ok {
+                       if defn.Used {
                                continue
                        }
-                       base.ErrorfAt(defn.Left().Pos(), "%v declared but not used", ln.Sym())
-                       defn.Left().Name().SetUsed(true) // suppress repeats
+                       base.ErrorfAt(defn.Tag.Pos(), "%v declared but not used", ln.Sym())
+                       defn.Used = true // suppress repeats
                } else {
                        base.ErrorfAt(ln.Pos(), "%v declared but not used", ln.Sym())
                }
index 72034022cbdf65511a9bc514071b609dab1d38df..18d768ceb1bac8e19c8a0bf9a50e6cfa474565f9 100644 (file)
@@ -39,7 +39,7 @@ func main() {
        nodesType := lookup("Nodes")
        ptrFieldType := types.NewPointer(lookup("Field"))
        slicePtrFieldType := types.NewSlice(ptrFieldType)
-       ptrNameType := types.NewPointer(lookup("Name"))
+       ptrIdentType := types.NewPointer(lookup("Ident"))
 
        var buf bytes.Buffer
        fmt.Fprintln(&buf, "// Code generated by mknode.go. DO NOT EDIT.")
@@ -84,7 +84,7 @@ func main() {
                fmt.Fprintf(&buf, "func (n *%s) doChildren(do func(Node) error) error { var err error\n", name)
                forNodeFields(typName, typ, func(name string, is func(types.Type) bool) {
                        switch {
-                       case is(ptrNameType):
+                       case is(ptrIdentType):
                                fmt.Fprintf(&buf, "if n.%s != nil { err = maybeDo(n.%s, err, do) }\n", name, name)
                        case is(nodeType), is(ntypeType):
                                fmt.Fprintf(&buf, "err = maybeDo(n.%s, err, do)\n", name)
@@ -101,8 +101,8 @@ func main() {
                fmt.Fprintf(&buf, "func (n *%s) editChildren(edit func(Node) Node) {\n", name)
                forNodeFields(typName, typ, func(name string, is func(types.Type) bool) {
                        switch {
-                       case is(ptrNameType):
-                               fmt.Fprintf(&buf, "if n.%s != nil { n.%s = edit(n.%s).(*Name) }\n", name, name, name)
+                       case is(ptrIdentType):
+                               fmt.Fprintf(&buf, "if n.%s != nil { n.%s = edit(n.%s).(*Ident) }\n", name, name, name)
                        case is(nodeType):
                                fmt.Fprintf(&buf, "n.%s = maybeEdit(n.%s, edit)\n", name, name)
                        case is(ntypeType):
index 4cf12f2c5d7f9efee201317dc7ff15450f4bd084..2330838f1c548240a87ada0b7073de78dea277ed 100644 (file)
@@ -13,6 +13,25 @@ import (
        "go/constant"
 )
 
+// An Ident is an identifier, possibly qualified.
+type Ident struct {
+       miniExpr
+       sym  *types.Sym
+       Used bool
+}
+
+func NewIdent(pos src.XPos, sym *types.Sym) *Ident {
+       n := new(Ident)
+       n.op = ONONAME
+       n.pos = pos
+       n.sym = sym
+       return n
+}
+
+func (n *Ident) Sym() *types.Sym { return n.sym }
+
+func (*Ident) CanBeNtype() {}
+
 // Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL).
 type Name struct {
        miniExpr
index 0191014133c2af89e1eab41366c57855d36d147d..598659a3db34563934f55944d083ab11487b475a 100644 (file)
@@ -794,8 +794,6 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
                return NewSliceHeaderExpr(pos, nil, nleft, nil, nil)
        case OSWITCH:
                return NewSwitchStmt(pos, nleft, nil)
-       case OTYPESW:
-               return NewTypeSwitchGuard(pos, nleft, nright)
        case OINLCALL:
                return NewInlinedCallExpr(pos, nil, nil)
        }
index 4eedcfdd29bc8f4a77eed1e41204a85a48d8a1a2..264171e797cf297c470fab3180f9df46bf22cbfd 100644 (file)
@@ -450,6 +450,22 @@ func (n *GoDeferStmt) editChildren(edit func(Node) Node) {
        n.Call = maybeEdit(n.Call, edit)
 }
 
+func (n *Ident) String() string                { return fmt.Sprint(n) }
+func (n *Ident) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *Ident) copy() Node {
+       c := *n
+       c.init = c.init.Copy()
+       return &c
+}
+func (n *Ident) doChildren(do func(Node) error) error {
+       var err error
+       err = maybeDoList(n.init, err, do)
+       return err
+}
+func (n *Ident) editChildren(edit func(Node) Node) {
+       editList(n.init, edit)
+}
+
 func (n *IfStmt) String() string                { return fmt.Sprint(n) }
 func (n *IfStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
 func (n *IfStmt) copy() Node {
@@ -1004,15 +1020,15 @@ func (n *TypeSwitchGuard) copy() Node {
 }
 func (n *TypeSwitchGuard) doChildren(do func(Node) error) error {
        var err error
-       if n.Name_ != nil {
-               err = maybeDo(n.Name_, err, do)
+       if n.Tag != nil {
+               err = maybeDo(n.Tag, err, do)
        }
        err = maybeDo(n.X, err, do)
        return err
 }
 func (n *TypeSwitchGuard) editChildren(edit func(Node) Node) {
-       if n.Name_ != nil {
-               n.Name_ = edit(n.Name_).(*Name)
+       if n.Tag != nil {
+               n.Tag = edit(n.Tag).(*Ident)
        }
        n.X = maybeEdit(n.X, edit)
 }
index 28c40c07813579d52dd9688937f5a5b3771e1d82..f41c50c92b1920db4339e131c4b593c7d0c5c40e 100644 (file)
@@ -512,32 +512,30 @@ func (n *SwitchStmt) SetHasBreak(x bool)  { n.HasBreak_ = x }
 // A TypeSwitchGuard is the [Name :=] X.(type) in a type switch.
 type TypeSwitchGuard struct {
        miniNode
-       Name_ *Name
-       X     Node
+       Tag  *Ident
+       X    Node
+       Used bool
 }
 
-func NewTypeSwitchGuard(pos src.XPos, name, x Node) *TypeSwitchGuard {
-       n := &TypeSwitchGuard{X: x}
-       if name != nil {
-               n.Name_ = name.(*Name)
-       }
+func NewTypeSwitchGuard(pos src.XPos, tag *Ident, x Node) *TypeSwitchGuard {
+       n := &TypeSwitchGuard{Tag: tag, X: x}
        n.pos = pos
        n.op = OTYPESW
        return n
 }
 
 func (n *TypeSwitchGuard) Left() Node {
-       if n.Name_ == nil {
+       if n.Tag == nil {
                return nil
        }
-       return n.Name_
+       return n.Tag
 }
 func (n *TypeSwitchGuard) SetLeft(x Node) {
        if x == nil {
-               n.Name_ = nil
+               n.Tag = nil
                return
        }
-       n.Name_ = x.(*Name)
+       n.Tag = x.(*Ident)
 }
 func (n *TypeSwitchGuard) Right() Node     { return n.X }
 func (n *TypeSwitchGuard) SetRight(x Node) { n.X = x }