What
as370 treats MNOTE as a printing no-op. In the macro-expansion loop it is skipped alongside the listing controls:
/* as370/src/as370.c:1129 */
if (!strcmp(bo, "PRINT") || !strcmp(bo, "SPACE") || !strcmp(bo, "EJECT") || !strcmp(bo, "MNOTE") || !strcmp(bo, "ACTR")) { pc++; continue; }
The operand — including the severity — is never parsed, so an MNOTE 12,'...' neither prints in any diagnostic stream nor influences the exit code. A real assembler (IFOX00, HLASM) folds the MNOTE severity into the return code; -Werror-style builds rely on that.
Why it matters — this has already shipped broken code twice-detectable, once-shipped
The IBM macro error convention is IHBERMAC → MNOTE severity 8/12 → MEXIT: the macro deletes the statement and reports the error only through the MNOTE. Under as370 that means a macro-argument error compiles to silence — no instruction, no diagnostic, rc 0.
Shipped instance: libc370 asm/@@aopen.asm:460 wrote FREEMAIN R,LV=(0),A=(1),SP=SUBPOOL; freemain.macro:171 rejects SP= with LV=(0) (IHB019, MNOTE 12) and MEXITs. The storage-shortage cleanup that mvslovers/libc370#83 added therefore never existed, and the buffer leaked exactly when storage was short — found only by scanning the object for the missing SVC 10, fixed in mvslovers/libc370#90 / PR #92 with an on-target red→green probe (tstabuf, JOB00820 → JOB00822).
The same statement shape is one typo away in every FREEMAIN/GETMAIN caller; nothing in the toolchain would notice the next one either.
Ask
- Parse the MNOTE operand:
MNOTE sev,'text', MNOTE 'text' (severity 0), and the comment form MNOTE *,'text' (stays a no-op).
- Print the text to stderr with the severity, like an ordinary diagnostic.
- Fold the severity into the assembler return code (
rc = max(rc, sev)), so severity >= 8 fails the build under the usual rc checks — mklibc.py already deletes the object and stops on a nonzero rc, so libc370 inherits the protection with no change on its side.
If legacy macros turn out to emit chatty low-severity MNOTEs, a threshold option (e.g. --mnote-level=N, default 8) keeps them printable without failing builds — but the default must not stay "invisible".
Found while fixing mvslovers/libc370#90; the object-scan technique that caught it is not a substitute for the assembler saying so.
What
as370 treats
MNOTEas a printing no-op. In the macro-expansion loop it is skipped alongside the listing controls:The operand — including the severity — is never parsed, so an
MNOTE 12,'...'neither prints in any diagnostic stream nor influences the exit code. A real assembler (IFOX00, HLASM) folds the MNOTE severity into the return code;-Werror-style builds rely on that.Why it matters — this has already shipped broken code twice-detectable, once-shipped
The IBM macro error convention is
IHBERMAC→MNOTEseverity 8/12 →MEXIT: the macro deletes the statement and reports the error only through the MNOTE. Under as370 that means a macro-argument error compiles to silence — no instruction, no diagnostic, rc 0.Shipped instance:
libc370asm/@@aopen.asm:460wroteFREEMAIN R,LV=(0),A=(1),SP=SUBPOOL;freemain.macro:171rejectsSP=withLV=(0)(IHB019, MNOTE 12) and MEXITs. The storage-shortage cleanup that mvslovers/libc370#83 added therefore never existed, and the buffer leaked exactly when storage was short — found only by scanning the object for the missing SVC 10, fixed in mvslovers/libc370#90 / PR #92 with an on-target red→green probe (tstabuf, JOB00820 → JOB00822).The same statement shape is one typo away in every FREEMAIN/GETMAIN caller; nothing in the toolchain would notice the next one either.
Ask
MNOTE sev,'text',MNOTE 'text'(severity 0), and the comment formMNOTE *,'text'(stays a no-op).rc = max(rc, sev)), so severity >= 8 fails the build under the usual rc checks —mklibc.pyalready deletes the object and stops on a nonzero rc, so libc370 inherits the protection with no change on its side.If legacy macros turn out to emit chatty low-severity MNOTEs, a threshold option (e.g.
--mnote-level=N, default 8) keeps them printable without failing builds — but the default must not stay "invisible".Found while fixing mvslovers/libc370#90; the object-scan technique that caught it is not a substitute for the assembler saying so.