diff options
Diffstat (limited to 'src/compiler/builtins.zc')
| -rw-r--r-- | src/compiler/builtins.zc | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/src/compiler/builtins.zc b/src/compiler/builtins.zc index 8c00636..44ed3b1 100644 --- a/src/compiler/builtins.zc +++ b/src/compiler/builtins.zc @@ -670,13 +670,18 @@ int typearg() { } // len(a), cap(a), push(a, x), pop(a), resize(a, n): growable arrays. // len of a T[n] is just n. +// arrroot: the local the array belongs to (itself, or the owner of the struct it is a field of), or -1 +int arrroot = 0 - 1; word arrvalue(int c) { - argloc = -1; arrloc = -1; + argloc = -1; arrloc = -1; arrroot = -1; if (lv && lvk == LV_LOCAL && xty[0] == TY_DYN) { arrloc = lvi; if (o3on && o3cache[lvi]) argloc = lvi; } effect_value = effect_mask(c); rval(); plainuse(c); af_access(xaf, tpack()); + if (arrloc >= 0) arrroot = lroot(arrloc); + else if (c >= C_VAR && tracked(c - C_VAR)) arrroot = lroot(c - C_VAR); + else if (xbor >= 0 && tracked(xbor)) arrroot = lroot(xbor); return xty; } // parse an array argument and retain the receiver's mutation and bounds facts. @@ -803,6 +808,8 @@ int array_pop(word t) { if (isfl(xty)) xfloat = 1; xaf = 0; xbor = -1; effect_value = 0; if (isref(xty)) { + // pop moves the element out: not out of an array with a drop, whose drop may need it (6.15.5) + if (fchk && arrroot >= 0 && ldroppable(arrroot)) cerrn(arrroot, "can't move out of a value with drop"); xcls = C_FRESH; xaf = af_new(-1, 2, tpack()); newsz = -1; newleaf = 0; return C_FRESH; } return 0; |
