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 {
|
func tcLenCap(n *ir.UnaryExpr) ir.Node {
|
||||||
n.X = Expr(n.X)
|
n.X = Expr(n.X)
|
||||||
n.X = DefaultLit(n.X, nil)
|
n.X = DefaultLit(n.X, nil)
|
||||||
n.X = implicitstar(n.X)
|
|
||||||
l := n.X
|
l := n.X
|
||||||
t := l.Type()
|
t := l.Type()
|
||||||
if t == nil {
|
if t == nil {
|
||||||
n.SetType(nil)
|
n.SetType(nil)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
var ok bool
|
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()]
|
ok = okforlen[t.Kind()]
|
||||||
} else {
|
} else {
|
||||||
ok = okforcap[t.Kind()]
|
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