autoexport(n, ctxt)
 }
 
-func addvar(n *ir.Name, t *types.Type, ctxt ir.Class) {
-       if n == nil || n.Sym() == nil || (n.Op() != ir.ONAME && n.Op() != ir.ONONAME) || t == nil {
-               base.Fatalf("addvar: n=%v t=%v nil", n, t)
-       }
-
-       n.SetOp(ir.ONAME)
-       declare(n, ctxt)
-       n.SetType(t)
-}
-
 // declare variables from grammar
 // new_name_list (type | [type] = expr_list)
 func variter(vl []ir.Node, t ir.Ntype, el []ir.Node) []ir.Node {
        return init
 }
 
-// newnoname returns a new ONONAME Node associated with symbol s.
-func newnoname(s *types.Sym) ir.Node {
-       if s == nil {
-               base.Fatalf("newnoname nil")
-       }
-       n := ir.NewNameAt(base.Pos, s)
-       n.SetOp(ir.ONONAME)
-       return n
-}
-
 // newFuncNameAt generates a new name node for a function or method.
 func newFuncNameAt(pos src.XPos, s *types.Sym, fn *ir.Func) *ir.Name {
        if fn.Nname != nil {
        return n
 }
 
-// this generates a new name node for a name
-// being declared.
-func dclname(s *types.Sym) *ir.Name {
-       n := NewName(s)
-       n.SetOp(ir.ONONAME) // caller will correct it
-       return n
-}
-
 func anonfield(typ *types.Type) *ir.Field {
        return symfield(nil, typ)
 }
                // 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 newnoname(s)
+               return ir.NewDeclNameAt(base.Pos, s)
        }
 
        if Curfn != nil && n.Op() == ir.ONAME && n.Name().Curfn != nil && n.Name().Curfn != Curfn {
 
                        base.Fatalf("missing ONONAME for %v\n", s)
                }
 
-               n = dclname(s)
+               n = ir.NewDeclNameAt(src.NoXPos, s)
                s.SetPkgDef(n)
                s.Importdef = ipkg
        }
 
                        if s.Def != nil {
                                base.Fatalf("unexpected definition for %v: %v", s, ir.AsNode(s.Def))
                        }
-                       s.Def = npos(src.NoXPos, dclname(s))
+                       s.Def = ir.NewDeclNameAt(src.NoXPos, s)
                }
        }
 
        case ir.OTYPESW:
                n := ir.NodAt(r.pos(), ir.OTYPESW, nil, nil)
                if s := r.ident(); s != nil {
-                       n.SetLeft(npos(n.Pos(), newnoname(s)))
+                       n.SetLeft(ir.NewDeclNameAt(n.Pos(), s))
                }
                right, _ := r.exprsOrNil()
                n.SetRight(right)
        // statements
        case ir.ODCL:
                pos := r.pos()
-               lhs := npos(pos, dclname(r.ident()))
+               lhs := ir.NewDeclNameAt(pos, r.ident())
                typ := ir.TypeNode(r.typ())
                return npos(pos, liststmt(variter([]ir.Node{lhs}, typ, nil))) // TODO(gri) avoid list creation
 
 
 }
 
 func (p *noder) declName(name *syntax.Name) *ir.Name {
-       n := dclname(p.name(name))
-       n.SetPos(p.pos(name))
-       return n
+       return ir.NewDeclNameAt(p.pos(name), p.name(name))
 }
 
 func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
 
        // Don't use lookupN; it interns the resulting string, but these are all unique.
        n := NewName(lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen)))
        statuniqgen++
-       addvar(n, t, ir.PEXTERN)
+       declare(n, ir.PEXTERN)
+       n.SetType(t)
        n.Sym().Linksym().Set(obj.AttrLocal, true)
        return n
 }
 
 
        defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type {
                sym := pkg.Lookup(name)
-               n := ir.NewNameAt(src.NoXPos, sym)
+               n := ir.NewDeclNameAt(src.NoXPos, sym)
                n.SetOp(ir.OTYPE)
                t := types.NewBasic(kind, n)
                n.SetType(t)
 
        // error type
        s := ir.BuiltinPkg.Lookup("error")
-       n := ir.NewNameAt(src.NoXPos, s)
+       n := ir.NewDeclNameAt(src.NoXPos, s)
        n.SetOp(ir.OTYPE)
        types.ErrorType = types.NewNamed(n)
        types.ErrorType.SetUnderlying(makeErrorInterface())
 
 }
 
 // NewNameAt returns a new ONAME Node associated with symbol s at position pos.
-// The caller is responsible for setting n.Name.Curfn.
+// The caller is responsible for setting Curfn.
 func NewNameAt(pos src.XPos, sym *types.Sym) *Name {
        if sym == nil {
                base.Fatalf("NewNameAt nil")
        }
-       return newNameAt(pos, sym)
+       return newNameAt(pos, ONAME, sym)
+}
+
+// NewDeclNameAt returns a new ONONAME Node associated with symbol s at position pos.
+// The caller is responsible for setting Curfn.
+func NewDeclNameAt(pos src.XPos, sym *types.Sym) *Name {
+       if sym == nil {
+               base.Fatalf("NewDeclNameAt nil")
+       }
+       return newNameAt(pos, ONONAME, sym)
 }
 
 // newNameAt is like NewNameAt but allows sym == nil.
-func newNameAt(pos src.XPos, sym *types.Sym) *Name {
+func newNameAt(pos src.XPos, op Op, sym *types.Sym) *Name {
        n := new(Name)
-       n.op = ONAME
+       n.op = op
        n.pos = pos
        n.orig = n
        n.sym = sym
 func (*Name) CanBeNtype() {}
 
 func (n *Name) SetOp(op Op) {
+       if n.op != ONONAME {
+               base.Fatalf("%v already has Op %v", n, n.op)
+       }
        switch op {
        default:
                panic(n.no("SetOp " + op.String()))
-       case OLITERAL, ONONAME, ONAME, OTYPE, OIOTA:
+       case OLITERAL, ONAME, OTYPE, OIOTA:
                n.op = op
        }
 }
 
        case OLABEL:
                return NewLabelStmt(pos, nil)
        case OLITERAL, OTYPE, OIOTA:
-               n := newNameAt(pos, nil)
-               n.SetOp(op)
-               return n
+               return newNameAt(pos, op, nil)
        case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY:
                return NewMakeExpr(pos, op, nleft, nright)
        case OMETHEXPR: