From 6744fac650eea606ced40f8051e2533b4f7eeee8 Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:07:11 -0600 Subject: [PATCH] =?UTF-8?q?feat(phase-31):=20gate=5Fmain=20strips=20a=20dr?= =?UTF-8?q?aft's=20FORWARD=20typedef=20instead=20of=20renaming=20it=20(?= =?UTF-8?q?=C2=A7184b)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/gate_main.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/gate_main.py b/tools/gate_main.py index ad4520921..1ef9518ec 100644 --- a/tools/gate_main.py +++ b/tools/gate_main.py @@ -190,6 +190,9 @@ TYPEDEF_BLOCK = re.compile( r'^[ \t]*typedef\s+(?:struct|union|enum)?[^;{]*\{[^{}]*\}\s*(\w+)\s*;' + _EOL, re.M) TYPEDEF_PLAIN = re.compile(r'^[ \t]*typedef\s+[\w\s\*]+?\s(\w+)\s*;' + _EOL, re.M) +FORWARD_TD = re.compile(r'^typedef\s+(?:struct|union|enum)\s+(\w+)\s+\1\s*;$') + + def _norm_td(text): """Normalize a typedef definition for COMPARISON: strip comments, then collapse whitespace. @@ -240,8 +243,16 @@ def strip_dup_typedefs(body, already, suffix=''): known = already.get(name, defined.get(name)) if known is None: defined[name] = text - elif known == text: - spans.append((m.start(), m.end())) # exact duplicate, reuse the visible one + elif known == text or FORWARD_TD.match(text): + # exact duplicate, OR a FORWARD declaration (`typedef struct X X;`) whose full + # definition the file already provides. A forward typedef is not a competing shape -- + # it is the same type, deliberately incomplete so the draft compiles standalone for + # match_one. Renaming it (the old behaviour) turned two CORRECT pointer-only drafts + # into `extern Owner4EE8_8002C8F4 *D_800A4EE8;`, which then contradicted the file's own + # `extern Owner4EE8 *D_800A4EE8;` — a conflict manufactured entirely by this tool. + # Stripping is safe because hoist_typedefs has already lifted the real definition above + # every insertion point (P31 S53). + spans.append((m.start(), m.end())) # reuse the visible/hoisted definition else: new = '%s_%s' % (name, suffix) # same name, different shape renames[name] = new