aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/builtins.zc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/builtins.zc')
-rw-r--r--src/compiler/builtins.zc9
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;