// declare constants from grammar
// new_name_list [[type] = expr_list]
-func constiter(vl []*Node, t *Node, cl []*Node) []*Node {
+func constiter(vl []*Node, t *Node, cl []*Node, iotaVal int64) []*Node {
var lno src.XPos // default is to leave line number alone in listtreecopy
if len(cl) == 0 {
if t != nil {
lastconst = cl
lasttype = t
}
- clcopy := listtreecopy(cl, lno)
var vv []*Node
- for _, v := range vl {
- if len(clcopy) == 0 {
+ for i, v := range vl {
+ if i >= len(cl) {
yyerror("missing value in const declaration")
break
}
- c := clcopy[0]
- clcopy = clcopy[1:]
+ c := treecopy(cl[i], lno)
v.Op = OLITERAL
declare(v, dclcontext)
v.Name.Param.Ntype = t
v.Name.Defn = c
+ v.SetIota(iotaVal)
vv = append(vv, nod(ODCLCONST, v, nil))
}
- if len(clcopy) != 0 {
+ if len(cl) > len(vl) {
yyerror("extra expression in const declaration")
}
- iota_ += 1
return vv
}
// 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.
- n = newnoname(s)
- n.SetIota(iota_) // save current iota value in const declarations
- return n
+ return newnoname(s)
}
if Curfn != nil && n.Op == ONAME && n.Name.Funcdepth > 0 && n.Name.Funcdepth != funcdepth {
var statuniqgen int // name generator for static temps
-var iota_ int64
-
var lastconst []*Node
var lasttype *Node
// but does not make them visible to user code.
func loadsys() {
block = 1
- iota_ = -1000000
importpkg = Runtimepkg
typecheckok = true
func (p *noder) node() {
block = 1
- iota_ = -1000000
imported_unsafe = false
p.lineno(p.file.PkgName)
case *syntax.ConstDecl:
// Tricky to handle golang.org/issue/15550 correctly.
- prevIota := iota_
-
if decl.Group == nil || decl.Group != lastConstGroup {
iotaVal = 0
lastConstRHS = nil
}
- iota_ = iotaVal
lastconst = lastConstRHS
- l = append(l, p.constDecl(decl)...)
+ l = append(l, p.constDecl(decl, iotaVal)...)
lastConstRHS = lastconst
lastconst = nil
- iota_ = prevIota
iotaVal++
lastConstGroup = decl.Group
return variter(names, typ, exprs)
}
-func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
+func (p *noder) constDecl(decl *syntax.ConstDecl, iotaVal int64) []*Node {
names := p.declNames(decl.NameList)
typ := p.typeExprOrNil(decl.Type)
exprs = p.exprList(decl.Values)
}
- return constiter(names, typ, exprs)
+ return constiter(names, typ, exprs, iotaVal)
}
func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
}
return &m
- case ONONAME:
- if n.Sym == lookup("iota") {
- // Not sure yet whether this is the real iota,
- // but make a copy of the Node* just in case,
- // so that all the copies of this const definition
- // don't have the same iota value.
- m := *n
- if pos.IsKnown() {
- m.Pos = pos
- }
- m.SetIota(iota_)
- return &m
- }
- return n
-
case OPACK:
// OPACK nodes are never valid in const value declarations,
// but allow them like any other declared symbol to avoid
// crashing (golang.org/issue/11361).
fallthrough
- case ONAME, OLITERAL, OTYPE:
+ case ONAME, ONONAME, OLITERAL, OTYPE:
return n
}
// - ODOT, ODOTPTR, and OINDREGSP use it to indicate offset relative to their base address.
// - OSTRUCTKEY uses it to store the named field's offset.
// - OXCASE and OXFALL use it to validate the use of fallthrough.
- // - ONONAME uses it to store the current value of iota, see Node.Iota
+ // - Named OLITERALs use it to to store their ambient iota value.
// Possibly still more uses. If you find any, document them.
Xoffset int64
if r != nil {
if r.Op != OIOTA {
n = r
- } else if n.Iota() >= 0 {
- n = nodintconst(n.Iota())
+ } else if len(typecheckdefstack) > 0 {
+ x := typecheckdefstack[len(typecheckdefstack)-1]
+ if x.Op == OLITERAL {
+ n = nodintconst(x.Iota())
+ }
}
}
}