mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
cmd/compile: ensure we evaluate side effects of len() arg
For any len() which requires the evaluation of its arg (according to the spec). Update #72844 Change-Id: Id2b0bcc78073a6d5051abd000131dafdf65e7f26 Reviewed-on: https://go-review.googlesource.com/c/go/+/658097 Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
8af32240c6
commit
336626bac4
@ -3469,19 +3469,28 @@ func (s *state) exprCheckPtr(n ir.Node, checkPtrOK bool) *ssa.Value {
|
|||||||
|
|
||||||
case ir.OLEN, ir.OCAP:
|
case ir.OLEN, ir.OCAP:
|
||||||
n := n.(*ir.UnaryExpr)
|
n := n.(*ir.UnaryExpr)
|
||||||
|
// Note: all constant cases are handled by the frontend. If len or cap
|
||||||
|
// makes it here, we want the side effects of the argument. See issue 72844.
|
||||||
|
a := s.expr(n.X)
|
||||||
|
t := n.X.Type()
|
||||||
switch {
|
switch {
|
||||||
case n.X.Type().IsSlice():
|
case t.IsSlice():
|
||||||
op := ssa.OpSliceLen
|
op := ssa.OpSliceLen
|
||||||
if n.Op() == ir.OCAP {
|
if n.Op() == ir.OCAP {
|
||||||
op = ssa.OpSliceCap
|
op = ssa.OpSliceCap
|
||||||
}
|
}
|
||||||
return s.newValue1(op, types.Types[types.TINT], s.expr(n.X))
|
return s.newValue1(op, types.Types[types.TINT], a)
|
||||||
case n.X.Type().IsString(): // string; not reachable for OCAP
|
case t.IsString(): // string; not reachable for OCAP
|
||||||
return s.newValue1(ssa.OpStringLen, types.Types[types.TINT], s.expr(n.X))
|
return s.newValue1(ssa.OpStringLen, types.Types[types.TINT], a)
|
||||||
case n.X.Type().IsMap(), n.X.Type().IsChan():
|
case t.IsMap(), t.IsChan():
|
||||||
return s.referenceTypeBuiltin(n, s.expr(n.X))
|
return s.referenceTypeBuiltin(n, a)
|
||||||
default: // array
|
case t.IsArray():
|
||||||
return s.constInt(types.Types[types.TINT], n.X.Type().NumElem())
|
return s.constInt(types.Types[types.TINT], t.NumElem())
|
||||||
|
case t.IsPtr() && t.Elem().IsArray():
|
||||||
|
return s.constInt(types.Types[types.TINT], t.Elem().NumElem())
|
||||||
|
default:
|
||||||
|
s.Fatalf("bad type in len/cap: %v", t)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
case ir.OSPTR:
|
case ir.OSPTR:
|
||||||
|
@ -278,12 +278,13 @@ func walkLenCap(n *ir.UnaryExpr, init *ir.Nodes) ir.Node {
|
|||||||
// replace len(*[10]int) with 10.
|
// replace len(*[10]int) with 10.
|
||||||
// delayed until now to preserve side effects.
|
// delayed until now to preserve side effects.
|
||||||
t := n.X.Type()
|
t := n.X.Type()
|
||||||
|
|
||||||
if t.IsPtr() {
|
if t.IsPtr() {
|
||||||
t = t.Elem()
|
t = t.Elem()
|
||||||
}
|
}
|
||||||
if t.IsArray() {
|
if t.IsArray() {
|
||||||
safeExpr(n.X, init)
|
// evaluate any side effects in n.X. See issue 72844.
|
||||||
|
appendWalkStmt(init, ir.NewAssignStmt(base.Pos, ir.BlankNode, n.X))
|
||||||
|
|
||||||
con := ir.NewConstExpr(constant.MakeInt64(t.NumElem()), n)
|
con := ir.NewConstExpr(constant.MakeInt64(t.NumElem()), n)
|
||||||
con.SetTypecheck(1)
|
con.SetTypecheck(1)
|
||||||
return con
|
return con
|
||||||
|
@ -47,11 +47,11 @@ func testRange4() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
//shouldPanic(testLen1)
|
shouldPanic(testLen1)
|
||||||
shouldNotPanic(testLen2)
|
shouldNotPanic(testLen2)
|
||||||
shouldNotPanic(testLen3)
|
shouldNotPanic(testLen3)
|
||||||
shouldNotPanic(testLen4)
|
shouldNotPanic(testLen4)
|
||||||
//shouldPanic(testRange1)
|
shouldPanic(testRange1)
|
||||||
shouldNotPanic(testRange2)
|
shouldNotPanic(testRange2)
|
||||||
shouldNotPanic(testRange3)
|
shouldNotPanic(testRange3)
|
||||||
shouldNotPanic(testRange4)
|
shouldNotPanic(testRange4)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user