feat(phase-31): pregate_check sees brace-bodied externs (the D_80072780 clash that cost a rebuild); §183 addendum

This commit is contained in:
Drew T
2026-08-16 22:41:01 -06:00
parent b15d195cc0
commit bbd8a6c8e4
2 changed files with 23 additions and 0 deletions
+6
View File
@@ -17976,3 +17976,9 @@ more. `pregate_check`'s CONFLICTING-EXTERN scan should have caught the `D_800727
of them and did not: its declaration regex is single-line, and the offending declaration was a
multi-line `extern struct { ... } *D_x;`. **A pre-gate check that sees 90% of declarations converts a
one-rebuild-per-conflict loop into a single pass — that is where the leverage is, not in the drafting.**
**Shipped the same session**: `pregate_check` now scans brace-bodied externs (`extern struct { ... }
*D_x;`) with the normalized body as part of the signature, so two identical struct declarations stay
silent while a struct-vs-`void *` clash FAILs. Negative-controlled four ways — and one of those
controls caught a trap worth its own line: **a synthetic test using a fake symbol name (`D_x`) reported
CLEAN for a conflict the tool does detect**, because `sym_of` only recognizes real project symbol
spellings. A negative control must use names the system would accept, or it tests nothing.
+17
View File
@@ -62,6 +62,11 @@ def _depth_map(masked):
return out
STRUCT_EXTERN = re.compile(
r'^[ \t]*extern\s+(?:const\s+|volatile\s+)*(struct|union)\s*\{([^{}]*)\}\s*(\**)\s*(\w+)\s*(?:\[[^\]]*\])?\s*;',
re.M | re.S)
def _norm_sig(sig):
"""`void f()` and `void f(void)` are not a conflict worth blocking a rebuild over: C89 calls
the first an unspecified parameter list, and gcc-2.7.2 accepts the pair. Normalize both to
@@ -155,6 +160,18 @@ def check_text(path, text):
# 4. one symbol declared two incompatible ways anywhere in the final text
decls = {}
# BRACE-BODIED EXTERNS FIRST (P31 S53). gm.DECL is single-line, so a draft declaring
# extern struct { u8 pad[0x34]; s32 (*field_0x34)(s32); } *D_80072780;
# was invisible to this check while a sibling declared the same symbol `void *` — the clash
# surfaced only as a compile error, one rebuild later (§183.5). Bodies are flat here (no nested
# braces), and the normalized body is part of the signature so two IDENTICAL struct declarations
# do not read as a conflict.
for m in STRUCT_EXTERN.finditer(masked):
if depth[m.start()]:
continue
body = ' '.join(m.group(2).split())
sig = (f'{m.group(1)}{{{body}}}{m.group(3)}', '')
decls.setdefault(m.group(4), (m.start(), sig))
for m in gm.DECL.finditer(text):
if depth[m.start()]: # block-scope decl: private to its function
continue