diff options
| author | 2026-10-15 09:48:10 +0330 | |
|---|---|---|
| committer | 2026-10-15 09:48:10 +0330 | |
| commit | 0a87c4663fc52bf60f3d440200b3b3ad6b39bd3e (patch) | |
| tree | 40d88acb972080ed90d89c7a866247263c252cae /src/compiler/base.zc | |
| parent | merge work/stdio: std.Io and one-level module completion (diff) | |
analyzer: use-after-end messages name the borrower, the owner and how the owner ended (freed, moved, .d parameter, push, global, reassignment), with fixtures
Diffstat (limited to 'src/compiler/base.zc')
| -rw-r--r-- | src/compiler/base.zc | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/src/compiler/base.zc b/src/compiler/base.zc index dc786b5..32549d4 100644 --- a/src/compiler/base.zc +++ b/src/compiler/base.zc @@ -958,6 +958,27 @@ int cerr(char* msg) { if (fchk && live) serr(msg); return 0; } +// how an owner ended, from end_owner's record: the use, the owner, what ended it and where. +// "r: used after it was given away; r borrows t, and t was freed on line 5 (t declared on line 4)" +int ended_message(char* use, word info, char* root, int cause) { + char* owner = root; int why = 0; char* whom = 0; + if (info) { owner = info[0]; why = info[3]; whom = info[4]; } + rt.put_s(use); rt.put_s(": used after it was given away; "); + if (!rt.eq_w(use, owner)) { rt.put_s(use); rt.put_s(" borrows "); rt.put_s(owner); rt.put_s(", and "); } + rt.put_s(owner); + if (why == 1) rt.put_s(" was freed"); + else if (why == 2) { rt.put_s(" was given to "); rt.put_s(whom); rt.put_s("'s .d parameter"); } + else if (why == 3) { rt.put_s(" was moved into "); rt.put_s(whom); } + else if (why == 4) { rt.put_s(" was stored into "); rt.put_s(whom); } + else if (why == 5) rt.put_s(" was returned"); + else if (why == 6) rt.put_s(" was stored in a global or untracked memory"); + else if (why == 7) rt.put_s(" was freed by reassigning it"); + else if (why == 8) rt.put_s(" was pushed into an array"); + else rt.put_s(" was transferred"); + rt.put_s(" on line "); rt.put_n(cause & 0xFFFFFF); + if (info && info[1]) { rt.put_s(" ("); if (!rt.eq_w(use, owner)) { rt.put_s(owner); rt.put_c(' '); } rt.put_s("declared on line "); rt.put_n(info[1] & 0xFFFFFF); rt.put_c(')'); } + return 0; +} // report an analyzer error about local i, named in the message. int cerrn(int i, char* msg) { int root = i, cause = 0; word info = 0; @@ -967,13 +988,8 @@ int cerrn(int i, char* msg) { if (!info && local_end_info) info = local_end_info[root]; if (info) cause = info[2]; else if (local_ended) cause = local_ended[root]; } - if (cause && !panic && !dry) { - errat(); rt.put_s(lname[i]); rt.put_s(": "); rt.put_s(msg); - rt.put_s("; owner "); if (info) rt.put_s(info[0]); else rt.put_s(lname[root]); - rt.put_s(" was transferred on line "); rt.put_n(cause & 0xFFFFFF); - if (info && info[1]) { rt.put_s(" (declared on line "); rt.put_n(info[1] & 0xFFFFFF); rt.put_c(')'); } - errend(); - } else serrn(lname[i], msg); + if (cause && !panic && !dry) { errat(); ended_message(lname[i], info, lname[root], cause); errend(); } + else serrn(lname[i], msg); } return 0; } |
