]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: casts from slices to array pointers are known to be non-nil
authorKeith Randall <khr@golang.org>
Fri, 24 Mar 2023 21:31:29 +0000 (14:31 -0700)
committerGopher Robot <gobot@golang.org>
Wed, 29 Mar 2023 21:55:11 +0000 (21:55 +0000)
The cast is proceeded by a bounds check. If the bounds check passes
then we know the pointer in the slice is non-nil.

... except casts to pointers of 0-sized arrays. They are strange, as
the bounds check can pass for a nil input.

Change-Id: Ic01cf4a82d59fbe3071d4b271c94efca9cafaec1
Reviewed-on: https://go-review.googlesource.com/c/go/+/479335
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Auto-Submit: Keith Randall <khr@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/ssagen/ssa.go
test/nilptr3.go

index a37604963fe96c42af134b072b862b081cfc74c6..e67241004ef6643bd0577837ef40cf14958eb1f3 100644 (file)
@@ -3277,10 +3277,15 @@ func (s *state) exprCheckPtr(n ir.Node, checkPtrOK bool) *ssa.Value {
                // slice.ptr
                n := n.(*ir.ConvExpr)
                v := s.expr(n.X)
-               arrlen := s.constInt(types.Types[types.TINT], n.Type().Elem().NumElem())
+               nelem := n.Type().Elem().NumElem()
+               arrlen := s.constInt(types.Types[types.TINT], nelem)
                cap := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], v)
                s.boundsCheck(arrlen, cap, ssa.BoundsConvert, false)
-               return s.newValue1(ssa.OpSlicePtrUnchecked, n.Type(), v)
+               op := ssa.OpSlicePtr
+               if nelem == 0 {
+                       op = ssa.OpSlicePtrUnchecked
+               }
+               return s.newValue1(op, n.Type(), v)
 
        case ir.OCALLFUNC:
                n := n.(*ir.CallExpr)
index 0e818ebf66b7fdba8faee377083166635e1ee362..5f08a5b20c20191437894e7b8d3f279a6a92b466 100644 (file)
@@ -248,3 +248,10 @@ func f10(p **int) int {
        /* */
        *p // ERROR "removed nil check"
 }
+
+func f11(x []byte) {
+       p := (*[0]byte)(x)
+       _ = *p // ERROR "generated nil check"
+       q := (*[4]byte)(x)
+       _ = *q // ERROR "removed nil check"
+}