Skip to content

Commit

Permalink
fix index and selector addressability
Browse files Browse the repository at this point in the history
  • Loading branch information
deelawn committed Aug 29, 2024
1 parent 9956c26 commit 6940714
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 18 deletions.
17 changes: 11 additions & 6 deletions gnovm/pkg/gnolang/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,22 +420,27 @@ func (x *CallExpr) isAddressable() bool {

type IndexExpr struct { // X[Index]
Attributes
X Expr // expression
Index Expr // index expression
HasOK bool // if true, is form: `value, ok := <X>[<Key>]
NotAddressable bool
X Expr // expression
Index Expr // index expression
HasOK bool // if true, is form: `value, ok := <X>[<Key>]
IsAddressable bool // true if X is an array pointer or slice
XIsString bool // true if X is a string (never addressable)
}

func (x *IndexExpr) isAddressable() bool {
return !x.NotAddressable && x.X.isAddressable()
if x.XIsString {
return false
}

return x.IsAddressable || x.X.isAddressable()
}

type SelectorExpr struct { // X.Sel
Attributes
X Expr // expression
Path ValuePath // set by preprocessor.
Sel Name // field selector
IsAddressable bool
IsAddressable bool // true if X is a pointer
}

func (x *SelectorExpr) isAddressable() bool {
Expand Down
19 changes: 7 additions & 12 deletions gnovm/pkg/gnolang/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -1493,15 +1493,19 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
dt = dt.Elem()
n.X = &StarExpr{X: n.X}
n.X.SetAttribute(ATTR_PREPROCESSED, true)
n.IsAddressable = true
}
switch dt.Kind() {
case StringKind, ArrayKind, SliceKind:
// Replace const index with int *ConstExpr,
// or if not const, assert integer type..
checkOrConvertIntegerKind(store, last, n.Index)
if dt.Kind() == StringKind {
if dt.Kind() == SliceKind {
// A string index is not addressable.
n.NotAddressable = true
n.IsAddressable = true
} else if dt.Kind() == StringKind {
// Special case; string indexes are never addressable.
n.XIsString = true
}
case MapKind:
mt := baseOf(gnoTypeOf(store, dt)).(*MapType)
Expand Down Expand Up @@ -1705,7 +1709,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
// Set selector path based on xt's type.
switch cxt := xt.(type) {
case *PointerType, *DeclaredType, *StructType, *InterfaceType:
tr, _, rcvr, fieldType, aerr := findEmbeddedFieldType(lastpn.PkgPath, cxt, n.Sel, nil)
tr, _, rcvr, _, aerr := findEmbeddedFieldType(lastpn.PkgPath, cxt, n.Sel, nil)
if aerr {
panic(fmt.Sprintf("cannot access %s.%s from %s",
cxt.String(), n.Sel, lastpn.PkgPath))
Expand All @@ -1714,15 +1718,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
n.Sel, cxt.String()))
}

// In the case where n.X is a non-pointer declared type or struct,
// only selectors of pointers or slices are addressable. Strings
// are not included in this check, but will be marked as addressable
// during the TRANS_LEAVE of SliceExpr if this is selecting a string.
switch baseOf(fieldType).(type) {
case *PointerType, *SliceType:
n.IsAddressable = true
}

if len(tr) > 1 {
// (the last vp, tr[len(tr)-1], is for n.Sel)
if debug {
Expand Down
17 changes: 17 additions & 0 deletions gnovm/tests/files/addressable_3c_err.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

type MyStruct struct {
Mp *int
}

func makeT() MyStruct {
x := 10
return MyStruct{Mp: &x}
}

func main() {
_ = &makeT().Mp
}

// Error:
// main/files/addressable_3c_err.gno:13:6: cannot take address of makeT<VPBlock(3,1)>().Mp

0 comments on commit 6940714

Please sign in to comment.