diff options
| author | Cuong Manh Le <cuong.manhle.vn@gmail.com> | 2026-03-30 13:15:38 +0700 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-03-31 10:58:53 -0700 |
| commit | 9002bd9fa1a3b500ca570844ea563967268a3878 (patch) | |
| tree | efb230d9569af0cfdf1cb58e932d5f7393db631a /src/cmd | |
| parent | d9fbe4c90d956f7835224f4de1afcf799e8cc3ed (diff) | |
| download | go-9002bd9fa1a3b500ca570844ea563967268a3878.tar.xz | |
cmd/compile: ensure map/slice clearing expressions are walked
The order pass ensures that initialization operations for clear(expr)
are scheduled. However, if 'expr' is a conversion that the walk pass
subsequently optimizes away or transforms, the resulting nodes can
be left in an un-walked state.
These un-walked nodes reach the SSA backend, which does not expect
high-level IR, resulting in an ICE.
This change ensures the expression is always walked during the
transformation of the 'clear' builtin.
Fixes #78410
Change-Id: I1997a28af020f39b2d325a58429eff9495048b1f
Reviewed-on: https://go-review.googlesource.com/c/go/+/760981
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/compile/internal/walk/builtin.go | 7 | ||||
| -rw-r--r-- | src/cmd/compile/internal/walk/expr.go | 2 |
2 files changed, 5 insertions, 4 deletions
diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go index 2288df709d..4d056da184 100644 --- a/src/cmd/compile/internal/walk/builtin.go +++ b/src/cmd/compile/internal/walk/builtin.go @@ -136,17 +136,18 @@ func walkGrowslice(slice *ir.Name, init *ir.Nodes, oldPtr, newLen, oldCap, num i } // walkClear walks an OCLEAR node. -func walkClear(n *ir.UnaryExpr) ir.Node { +func walkClear(n *ir.UnaryExpr, init *ir.Nodes) ir.Node { + x := walkExpr(n.X, init) typ := n.X.Type() switch { case typ.IsSlice(): - if n := arrayClear(n.X.Pos(), n.X, nil); n != nil { + if n := arrayClear(x.Pos(), x, nil); n != nil { return n } // If n == nil, we are clearing an array which takes zero memory, do nothing. return ir.NewBlockStmt(n.Pos(), nil) case typ.IsMap(): - return mapClear(n.X, reflectdata.TypePtrAt(n.X.Pos(), n.X.Type())) + return mapClear(x, reflectdata.TypePtrAt(x.Pos(), typ)) } panic("unreachable") } diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 125ffd53b1..1ebf6db7f1 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -293,7 +293,7 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { case ir.OCLEAR: n := n.(*ir.UnaryExpr) - return walkClear(n) + return walkClear(n, init) case ir.OCLOSE: n := n.(*ir.UnaryExpr) |
