aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/analyzer.zc5
-rw-r--r--tests/conformance/6-ownership/back_link_alias.zc6
-rw-r--r--tests/conformance/6-ownership/back_link_block_ok.zc6
-rw-r--r--tests/conformance/6-ownership/back_link_cont.zc6
-rw-r--r--tests/conformance/6-ownership/back_link_cycle.zc17
-rw-r--r--tests/conformance/6-ownership/back_link_free.zc6
-rw-r--r--tests/conformance/6-ownership/back_link_glob.zc7
-rw-r--r--tests/conformance/6-ownership/back_link_move.zc7
-rw-r--r--tests/conformance/6-ownership/back_link_reasg.zc6
-rw-r--r--tests/conformance/6-ownership/back_link_ret.zc7
10 files changed, 72 insertions, 1 deletions
diff --git a/src/compiler/analyzer.zc b/src/compiler/analyzer.zc
index a1588e8..839c1ef 100644
--- a/src/compiler/analyzer.zc
+++ b/src/compiler/analyzer.zc
@@ -1009,7 +1009,7 @@ int end_owner(int i) {
end_why = 0; end_whom = 0;
local_ended[i] = info[2]; local_end_info[i] = info; lstate[i] = S_DEAD;
while (j < nloc) {
- if (j != i && isalias(j) && lroot(j) == i) { local_ended[j] = info[2]; local_end_info[j] = info; lstate[j] = S_DEAD; }
+ if (j != i && lstate[j] == S_CHILD && lroot(j) == i) { local_ended[j] = info[2]; local_end_info[j] = info; lstate[j] = S_DEAD; } // aliases and owned children go with it
j++;
}
return 0;
@@ -1612,6 +1612,9 @@ int assigncheck(int k, int i, int rc) {
touch(i);
if (rc == C_FRESH) { emitown(i); return C_PLAIN; }
if (j < 0) return C_PLAIN;
+ // a back link: storing the container's own owner (or the container itself)
+ // into it. it stays a plain reference; ownership would form a cycle.
+ if (r == j) { touch(j); return C_PLAIN; }
js = lstate[j];
if (js == S_CHILD) cerrn(j, "already belongs to a container");
else if (js == S_BORROW) cerrn(j, "is borrowed and can't be stored");
diff --git a/tests/conformance/6-ownership/back_link_alias.zc b/tests/conformance/6-ownership/back_link_alias.zc
new file mode 100644
index 0000000..58db710
--- /dev/null
+++ b/tests/conformance/6-ownership/back_link_alias.zc
@@ -0,0 +1,6 @@
+// expect error: b: is an owned object and can't be copied into another variable
+// spec 6.6
+include rt;
+struct node { int value; node* prev; node* next; };
+fn main() { node* p; { node* a = rt.new(node); node* b = rt.new(node); a.next = b; b.prev = a; p = b; } rt.put_n(p.prev.value); }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/back_link_block_ok.zc b/tests/conformance/6-ownership/back_link_block_ok.zc
new file mode 100644
index 0000000..7955081
--- /dev/null
+++ b/tests/conformance/6-ownership/back_link_block_ok.zc
@@ -0,0 +1,6 @@
+// expect: 40
+// spec 6.6
+include rt;
+struct node { int value; node* prev; node* next; };
+fn main() { memdebug on; { node* a = rt.new(node); node* b = rt.new(node); a.next = b; b.prev = a; a.value = 4; rt.put_n(b.prev.value); } rt.put_n(rt.memreport()); }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/back_link_cont.zc b/tests/conformance/6-ownership/back_link_cont.zc
new file mode 100644
index 0000000..d8083fd
--- /dev/null
+++ b/tests/conformance/6-ownership/back_link_cont.zc
@@ -0,0 +1,6 @@
+// expect error: b: already belongs to a container
+// spec 6.6
+include rt;
+struct node { int value; node* prev; node* next; };
+fn main() { node* c = rt.new(node); node* a = rt.new(node); node* b = rt.new(node); a.next = b; b.prev = a; c.next = b; rt.put_n(c.value); }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/back_link_cycle.zc b/tests/conformance/6-ownership/back_link_cycle.zc
new file mode 100644
index 0000000..fc47100
--- /dev/null
+++ b/tests/conformance/6-ownership/back_link_cycle.zc
@@ -0,0 +1,17 @@
+// expect: 0/
+// spec 6.6
+include rt;
+struct node { int value; node* prev; node* next; };
+fn main() {
+ memdebug on;
+ for (int round = 0; round < 50; round++) {
+ node* a = rt.new(node);
+ node* b = rt.new(node);
+ a.next = b;
+ b.prev = a;
+ a.value = round;
+ b.value = b.prev.value;
+ }
+ rt.put_n(rt.memreport()); rt.put_c(10);
+}
+// zc0: skip
diff --git a/tests/conformance/6-ownership/back_link_free.zc b/tests/conformance/6-ownership/back_link_free.zc
new file mode 100644
index 0000000..a8fb5e8
--- /dev/null
+++ b/tests/conformance/6-ownership/back_link_free.zc
@@ -0,0 +1,6 @@
+// expect error: b: used after it was given away; b borrows a, and a was freed
+// spec 6.6
+include rt;
+struct node { int value; node* prev; node* next; };
+fn main() { node* a = rt.new(node); node* b = rt.new(node); a.next = b; b.prev = a; rt.free(a); rt.put_n(b.prev.value); }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/back_link_glob.zc b/tests/conformance/6-ownership/back_link_glob.zc
new file mode 100644
index 0000000..ecba2e5
--- /dev/null
+++ b/tests/conformance/6-ownership/back_link_glob.zc
@@ -0,0 +1,7 @@
+// expect error: b: is not an owner, so it can't be stored in a global
+// spec 6.6
+include rt;
+struct node { int value; node* prev; node* next; };
+node* keep;
+fn main() { node* a = rt.new(node); node* b = rt.new(node); a.next = b; b.prev = a; keep = b; }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/back_link_move.zc b/tests/conformance/6-ownership/back_link_move.zc
new file mode 100644
index 0000000..47490d6
--- /dev/null
+++ b/tests/conformance/6-ownership/back_link_move.zc
@@ -0,0 +1,7 @@
+// expect error: a was stored in a global or untracked memory
+// spec 6.6
+include rt;
+struct node { int value; node* prev; node* next; };
+node* keep2;
+fn main() { node* a = rt.new(node); node* b = rt.new(node); a.next = b; b.prev = a; keep2 = a; rt.put_n(b.prev.value); }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/back_link_reasg.zc b/tests/conformance/6-ownership/back_link_reasg.zc
new file mode 100644
index 0000000..02709a8
--- /dev/null
+++ b/tests/conformance/6-ownership/back_link_reasg.zc
@@ -0,0 +1,6 @@
+// expect error: b: used after it was given away; b borrows a, and a was freed by reassigning it
+// spec 6.6
+include rt;
+struct node { int value; node* prev; node* next; };
+fn main() { node* a = rt.new(node); node* b = rt.new(node); a.next = b; b.prev = a; a = rt.new(node); a.value = 1; rt.put_n(b.prev.value); }
+// zc0: skip
diff --git a/tests/conformance/6-ownership/back_link_ret.zc b/tests/conformance/6-ownership/back_link_ret.zc
new file mode 100644
index 0000000..ee10fce
--- /dev/null
+++ b/tests/conformance/6-ownership/back_link_ret.zc
@@ -0,0 +1,7 @@
+// expect error: b: has to be u to be returned
+// spec 6.6
+include rt;
+struct node { int value; node* prev; node* next; };
+node* g() { node* a = rt.new(node); node* b = rt.new(node); a.next = b; b.prev = a; return b; }
+fn main() { node* x = g(); rt.put_n(x.value); }
+// zc0: skip