return n.Val().U.(string)
}
+// TODO(gri) smallintconst is only used in one place - can we used indexconst?
func smallintconst(n *Node) bool {
if n.Op == OLITERAL && Isconst(n, CTINT) && n.Type != nil {
switch simtype[n.Type.Etype] {
case TIDEAL, TINT64, TUINT64, TPTR:
v, ok := n.Val().U.(*Mpint)
- if ok && v.Cmp(minintval[TINT32]) > 0 && v.Cmp(maxintval[TINT32]) < 0 {
+ if ok && v.Cmp(minintval[TINT32]) >= 0 && v.Cmp(maxintval[TINT32]) <= 0 {
return true
}
}
return false
}
-// nonnegintconst checks if Node n contains a constant expression
-// representable as a non-negative small integer, and returns its
-// (integer) value if that's the case. Otherwise, it returns -1.
-func nonnegintconst(n *Node) int64 {
+// indexconst checks if Node n contains a constant expression
+// representable as a non-negative int and returns its value.
+// If n is not a constant expression, not representable as an
+// integer, or negative, it returns -1. If n is too large, it
+// returns -2.
+func indexconst(n *Node) int64 {
if n.Op != OLITERAL {
return -1
}
- // toint will leave n.Val unchanged if it's not castable to an
- // Mpint, so we still have to guard the conversion.
- v := toint(n.Val())
+ v := toint(n.Val()) // toint returns argument unchanged if not representable as an *Mpint
vi, ok := v.U.(*Mpint)
- if !ok || vi.CmpInt64(0) < 0 || vi.Cmp(maxintval[TINT32]) > 0 {
+ if !ok || vi.CmpInt64(0) < 0 {
return -1
}
+ if vi.Cmp(maxintval[TINT]) > 0 {
+ return -2
+ }
return vi.Int64()
}
var k int64
splitnode = func(r *Node) (*Node, *Node) {
if r.Op == OKEY {
- k = nonnegintconst(r.Left)
+ k = indexconst(r.Left)
+ if k < 0 {
+ Fatalf("fixedlit: invalid index %v", r.Left)
+ }
r = r.Right
}
a := nod(OINDEX, var_, nodintconst(k))
var index int64
for _, value := range n.List.Slice() {
if value.Op == OKEY {
- index = nonnegintconst(value.Left)
+ index = indexconst(value.Left)
+ if index < 0 {
+ Fatalf("slicelit: invalid index %v", value.Left)
+ }
value = value.Right
}
a := nod(OINDEX, vauto, nodintconst(index))
var k int64
for _, a := range n.List.Slice() {
if a.Op == OKEY {
- k = nonnegintconst(a.Left)
+ k = indexconst(a.Left)
+ if k < 0 {
+ Fatalf("initplan arraylit: invalid index %v", a.Left)
+ }
a = a.Right
}
addvalue(p, k*n.Type.Elem().Width, a)
case OSTRUCTLIT:
for _, a := range n.List.Slice() {
if a.Op != OSTRUCTKEY {
- Fatalf("initplan fixedlit")
+ Fatalf("initplan structlit")
}
addvalue(p, a.Xoffset, a.Left)
}
if l.Op == OKEY {
l.Left = typecheck(l.Left, ctxExpr)
evconst(l.Left)
- i = nonnegintconst(l.Left)
- if i < 0 && !l.Left.Diag() {
- yyerror("index must be non-negative integer constant")
- l.Left.SetDiag(true)
+ i = indexconst(l.Left)
+ if i < 0 {
+ if !l.Left.Diag() {
+ if i == -2 {
+ yyerror("index too large")
+ } else {
+ yyerror("index must be non-negative integer constant")
+ }
+ l.Left.SetDiag(true)
+ }
i = -(1 << 30) // stay negative for a while
}
vp = &l.Right
}
// var arr [r]T
// n = arr[:l]
- t = types.NewArray(t.Elem(), nonnegintconst(r)) // [r]T
+ i := indexconst(r)
+ if i < 0 {
+ Fatalf("walkexpr: invalid index %v", r)
+ }
+ t = types.NewArray(t.Elem(), i) // [r]T
var_ := temp(t)
a := nod(OAS, var_, nil) // zero temp
a = typecheck(a, ctxStmt)
--- /dev/null
+// +build amd64
+// compile
+
+// Copyright 2009 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 p
+
+var _ = []int{1 << 31: 1} // ok on machines with 64bit int