diff options
| author | 2026-10-15 09:56:19 +0330 | |
|---|---|---|
| committer | 2026-10-15 09:56:19 +0330 | |
| commit | 6bbac2edf7c50dac4d755a364b6dfd16471284d7 (patch) | |
| tree | e83b493f55ed07287cd2ab4e3a940c04871d9a14 /src/compiler/decl.zc | |
| parent | analyzer: use-after-end messages name the borrower, the owner and how the own... (diff) | |
analyzer: check borrow returns of forward-called functions at the unit's end; borrows clause for prototypes, definitions, externs and function types, checked against the body
Diffstat (limited to 'src/compiler/decl.zc')
| -rw-r--r-- | src/compiler/decl.zc | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/src/compiler/decl.zc b/src/compiler/decl.zc index dfcff4f..52d08c7 100644 --- a/src/compiler/decl.zc +++ b/src/compiler/decl.zc @@ -282,6 +282,18 @@ int body() { // (this is also where a function's signature is packed into ssig and its type // into stype, checked against any earlier prototype or prescan result, and // where the o3 region for an o3 function is handed to the core) +// a body against its borrows clause: it may return a borrow only of the parameters the clause names. +int borrows_check(int s, int np, char** pn, word pty) { + int mask = sig_borrows(ssig[s]), i = 0; + if (!mask || !fchk || !effect_current || effect_current[0] != 1) return 0; + while (i < np && i < 24) { + if (!((mask >> i) & 1) && (effect_current[26 + i] & (EF_ALIAS | EF_IDENTITY)) && (isptr(pty[i]) || pty[i] == tword)) { + if (!panic && !dry) { errat(); rt.put_s(sname[s]); rt.put_s(": returns a borrow of "); if (pn[i]) rt.put_s(pn[i]); else rt.put_n(i); rt.put_s(", but its borrows clause doesn't name it"); errend(); } + } + i++; + } + return 0; +} int fndef(int chk, int rty, int ret, int n) { int s, np = 0, tags = 0, t, sig, i; char*[24] pn; word[24] pt; word[24] pty; int typed = 0, ft, explicit_rty = !!rty, o3f = o3nxt, lo, hi, pk, lt, lend, lfl = tline, redef, amb = 0, nonm = 0; o3nxt = 0; @@ -348,6 +360,10 @@ int fndef(int chk, int rty, int ret, int n) { amb = amb >> 1; i++; } sig = ret + np + np + tags * 64; + lo = borrows_clause(pn, np, 1); + // a definition after a prototype keeps the prototype's borrows clause + if (!lo && (sflag[s] & F_SIG) && !(sflag[s] & F_PRE)) lo = sig_borrows(ssig[s]); + sig = sig + (lo << SIG_BORROWS); if ((sflag[s] & F_SIG) && !(sflag[s] & F_PRE)) { if (ssig[s] != sig) serrn(n, "doesn't match its earlier declaration"); } @@ -408,6 +424,7 @@ int fndef(int chk, int rty, int ret, int n) { i = 0; while (i < np) { t = lbase + i; o3mkcache(t); o3refresh(t); i++; } } body(); + borrows_check(s, np, pn, pty); if (!explicit_rty && fn_return_type > 0 && fn_return_type != tword) { stype[s] = tfn(fn_return_type, np, pty, ssig[s]); sig_attach(n, fn_return_type, np, pn, pty, 1); |
