Skip to content

Commit

Permalink
cmd/compile: casts from slices to array pointers are known to be non-nil
Browse files Browse the repository at this point in the history
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 <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
Reviewed-by: Cuong Manh Le <[email protected]>
Auto-Submit: Keith Randall <[email protected]>
Reviewed-by: Matthew Dempsky <[email protected]>
  • Loading branch information
randall77 authored and gopherbot committed Mar 29, 2023
1 parent 9c75c4b commit 0d9eb8b
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/cmd/compile/internal/ssagen/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions test/nilptr3.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}

0 comments on commit 0d9eb8b

Please sign in to comment.