Normally we don't SSA-ify variables with types that have more than
4 fields. But we really do want to SSA-ify them if they are pointer
shaped.
An odd case, but the compiler shouldn't barf on them.
Failure probably started with CL 714421.
Fixes #77536
Change-Id: I51ef87676cc31df1e51e164bbd58d58c0ab72436
Reviewed-on: https://go-review.googlesource.com/c/go/+/744280
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
(cherry picked from commit
6435bf46c17dccb2eb5f7bab7dd8aa4972252b21)
Reviewed-on: https://go-review.googlesource.com/c/go/+/749421
Reviewed-by: Mark Freeman <markfreeman@google.com>
func decomposeStructPhi(v *Value) {
t := v.Type
n := t.NumFields()
- var fields [MaxStruct]*Value
+ fields := make([]*Value, 0, MaxStruct)
for i := 0; i < n; i++ {
- fields[i] = v.Block.NewValue0(v.Pos, OpPhi, t.FieldType(i))
+ fields = append(fields, v.Block.NewValue0(v.Pos, OpPhi, t.FieldType(i)))
}
for _, a := range v.Args {
for i := 0; i < n; i++ {
}
}
v.reset(OpStructMake)
- v.AddArgs(fields[:n]...)
+ v.AddArgs(fields...)
// Recursively decompose phis for each field.
- for _, f := range fields[:n] {
+ for _, f := range fields {
decomposeUserPhi(f)
}
}
addArg(e)
pos = pos.WithNotStmt()
}
- if at.NumFields() > 4 {
+ if at.NumFields() > MaxStruct && !types.IsDirectIface(at) {
panic(fmt.Errorf("Too many fields (%d, %d bytes), container=%s", at.NumFields(), at.Size(), container.LongString()))
}
a = makeOf(a, OpStructMake, args)
}
return false
case types.TSTRUCT:
+ if types.IsDirectIface(t) {
+ // Note: even if t.NumFields()>MaxStruct! See issue 77534.
+ return true
+ }
if t.NumFields() > MaxStruct {
return false
}
--- /dev/null
+// compile
+
+// Copyright 2026 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.
+
+// Issue 77534: compiler crash when >4 fields, but only one nonempty pointer field.
+
+package p
+
+type T struct {
+ a, b, c, d struct{}
+ e *byte
+}
+
+func f1(p *any, t T) {
+ *p = t
+}
+
+func f2(p *any, t *T) {
+ *p = *t
+}
+
+func f3(p, x, y *T, b bool) {
+ var z T
+ if b {
+ z = *x
+ } else {
+ z = *y
+ }
+ *p = z
+}
+
+func f4(i any) T {
+ return i.(T)
+}