mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
cmd/compile: remove implicit deref from len(p) where p is ptr-to-array
func f() *[4]int { return nil } _ = len(f()) should not panic. We evaluate f, but there isn't a dereference according to the spec (just "arg is evaluated"). Update #72844 Change-Id: Ia32cefc1b7aa091cd1c13016e015842b4d12d5b4 Reviewed-on: https://go-review.googlesource.com/c/go/+/658096 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Griesemer <gri@google.com> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
56e5476e10
commit
deb6790fcf
@ -634,16 +634,16 @@ func tcIndex(n *ir.IndexExpr) ir.Node {
|
||||
func tcLenCap(n *ir.UnaryExpr) ir.Node {
|
||||
n.X = Expr(n.X)
|
||||
n.X = DefaultLit(n.X, nil)
|
||||
n.X = implicitstar(n.X)
|
||||
l := n.X
|
||||
t := l.Type()
|
||||
if t == nil {
|
||||
n.SetType(nil)
|
||||
return n
|
||||
}
|
||||
|
||||
var ok bool
|
||||
if n.Op() == ir.OLEN {
|
||||
if t.IsPtr() && t.Elem().IsArray() {
|
||||
ok = true
|
||||
} else if n.Op() == ir.OLEN {
|
||||
ok = okforlen[t.Kind()]
|
||||
} else {
|
||||
ok = okforcap[t.Kind()]
|
||||
|
70
test/fixedbugs/issue72844.go
Normal file
70
test/fixedbugs/issue72844.go
Normal file
@ -0,0 +1,70 @@
|
||||
// run
|
||||
|
||||
// Copyright 2025 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 main
|
||||
|
||||
//go:noinline
|
||||
func nilPtrFunc() *[4]int {
|
||||
return nil
|
||||
}
|
||||
|
||||
var nilPtrVar *[4]int
|
||||
|
||||
func testLen1() {
|
||||
_ = len(*nilPtrFunc())
|
||||
}
|
||||
|
||||
func testLen2() {
|
||||
_ = len(nilPtrFunc())
|
||||
}
|
||||
|
||||
func testLen3() {
|
||||
_ = len(*nilPtrVar)
|
||||
}
|
||||
|
||||
func testLen4() {
|
||||
_ = len(nilPtrVar)
|
||||
}
|
||||
|
||||
func testRange1() {
|
||||
for range *nilPtrFunc() {
|
||||
}
|
||||
}
|
||||
func testRange2() {
|
||||
for range nilPtrFunc() {
|
||||
}
|
||||
}
|
||||
func testRange3() {
|
||||
for range *nilPtrVar {
|
||||
}
|
||||
}
|
||||
func testRange4() {
|
||||
for range nilPtrVar {
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
//shouldPanic(testLen1)
|
||||
shouldNotPanic(testLen2)
|
||||
shouldNotPanic(testLen3)
|
||||
shouldNotPanic(testLen4)
|
||||
//shouldPanic(testRange1)
|
||||
shouldNotPanic(testRange2)
|
||||
shouldNotPanic(testRange3)
|
||||
shouldNotPanic(testRange4)
|
||||
}
|
||||
|
||||
func shouldPanic(f func()) {
|
||||
defer func() {
|
||||
if e := recover(); e == nil {
|
||||
panic("should have panicked")
|
||||
}
|
||||
}()
|
||||
f()
|
||||
}
|
||||
func shouldNotPanic(f func()) {
|
||||
f()
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user