Skip to content

Commit 961818e

Browse files
thepuddsgopherbot
authored andcommitted
cmd/compile/internal/walk: use original type for composite literals in addrTemp
When creating a new *ir.Name or *ir.LinksymOffsetExpr to represent a composite literal stored in the read-only data section, we should use the original type of the expression that was found via ir.ReassignOracle.StaticValue. (This is needed because the StaticValue method can traverse through OCONVNOP operations to find its final result.) Otherwise, the compilation may succeed, but the linker might erroneously conclude that a type is not used and prune an itab when it should not, leading to a call at execution-time to runtime.unreachableMethod, which throws "fatal error: unreachable method called. linker bug?". The tests exercise both the case of a zero value struct literal that can be represented by the read-only runtime.zeroVal, which was the case of the simplified example from #73888, and also modifies that example to test the non zero value struct literal case. This CL makes two similar changes for those two cases. We can get either of the tests we are adding to fail independently if we only make a single corresponding change. Fixes #73888 Updates #71359 Change-Id: Ifd91f445cc168ab895cc27f7964a6557d5cc32e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/676517 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> Auto-Submit: Keith Randall <khr@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
1 parent c8c3d66 commit 961818e

File tree

4 files changed

+74
-2
lines changed

4 files changed

+74
-2
lines changed

src/cmd/compile/internal/ir/expr.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,10 @@ func IsAddressable(n Node) bool {
853853
//
854854
// calling StaticValue on the "int(y)" expression returns the outer
855855
// "g()" expression.
856+
//
857+
// NOTE: StaticValue can return a result with a different type than
858+
// n's type because it can traverse through OCONVNOP operations.
859+
// TODO: consider reapplying OCONVNOP operations to the result. See https://go.dev/cl/676517.
856860
func StaticValue(n Node) Node {
857861
for {
858862
switch n1 := n.(type) {

src/cmd/compile/internal/walk/order.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,14 +249,14 @@ func (o *orderState) addrTemp(n ir.Node) ir.Node {
249249
if (v.Op() == ir.OSTRUCTLIT || v.Op() == ir.OARRAYLIT) && !base.Ctxt.IsFIPS() {
250250
if ir.IsZero(v) && 0 < v.Type().Size() && v.Type().Size() <= abi.ZeroValSize {
251251
// This zero value can be represented by the read-only zeroVal.
252-
zeroVal := ir.NewLinksymExpr(v.Pos(), ir.Syms.ZeroVal, v.Type())
252+
zeroVal := ir.NewLinksymExpr(v.Pos(), ir.Syms.ZeroVal, n.Type())
253253
vstat := typecheck.Expr(zeroVal).(*ir.LinksymOffsetExpr)
254254
return vstat
255255
}
256256
if isStaticCompositeLiteral(v) {
257257
// v can be directly represented in the read-only data section.
258258
lit := v.(*ir.CompLitExpr)
259-
vstat := readonlystaticname(lit.Type())
259+
vstat := readonlystaticname(n.Type())
260260
fixedlit(inInitFunction, initKindStatic, lit, vstat, nil) // nil init
261261
vstat = typecheck.Expr(vstat).(*ir.Name)
262262
return vstat

test/fixedbugs/issue73888.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// run
2+
3+
// Copyright 2025 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package main
8+
9+
type SourceRange struct {
10+
x, y int
11+
}
12+
13+
func (r *SourceRange) String() string {
14+
return "hello"
15+
}
16+
17+
type SourceNode interface {
18+
SourceRange()
19+
}
20+
21+
type testNode SourceRange
22+
23+
func (tn testNode) SourceRange() {
24+
}
25+
26+
func main() {
27+
n := testNode(SourceRange{}) // zero value
28+
Errorf(n)
29+
}
30+
31+
//go:noinline
32+
func Errorf(n SourceNode) {
33+
n.SourceRange()
34+
}

test/fixedbugs/issue73888b.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// run
2+
3+
// Copyright 2025 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package main
8+
9+
type SourceRange struct {
10+
x, y int
11+
}
12+
13+
func (r *SourceRange) String() string {
14+
return "hello"
15+
}
16+
17+
type SourceNode interface {
18+
SourceRange()
19+
}
20+
21+
type testNode SourceRange
22+
23+
func (tn testNode) SourceRange() {
24+
}
25+
26+
func main() {
27+
n := testNode(SourceRange{1, 1}) // not zero value
28+
Errorf(n)
29+
}
30+
31+
//go:noinline
32+
func Errorf(n SourceNode) {
33+
n.SourceRange()
34+
}

0 commit comments

Comments
 (0)