From 23bdb06ba885dd5b6839cf1a62beee4893156512 Mon Sep 17 00:00:00 2001 From: TetzkatLipHoka Date: Sat, 11 Jul 2026 10:51:36 +0200 Subject: [PATCH] Fix compiler state corruption after an exception in the OnUses handler With PS_USESSUPPORT, ProcessUses sets fModule to the name of the unit being imported before invoking the OnUses callback. The regular failure path (OnUses returning False) restores fModule and FParser afterwards, but the exception handler did not. The stale fModule survives Cleanup: Compile saves it as OldFileName on entry and restores it after the System import, so every following Compile on the same instance treats the main module as the previously failed unit and rejects any 'uses ;' with a bogus cross-reference error. Reproduction (one compiler instance): 1. Compile a script whose OnUses handler raises (e.g. a failing AddTypeS registration) -> correct error is reported. 2. Compile any script with 'uses ;' again -> before: 'Cross-Reference error of ' -> after: compiles normally (or reports the real error again). The exception handler now restores FParser and fModule exactly like the regular failure path. MakeError stays first so the error keeps being attributed to the failed unit. Co-Authored-By: Claude Fable 5 --- Source/uPSCompiler.pas | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/uPSCompiler.pas b/Source/uPSCompiler.pas index f13307e2..6a915dc3 100644 --- a/Source/uPSCompiler.pas +++ b/Source/uPSCompiler.pas @@ -12593,8 +12593,14 @@ function TPSPascalCompiler.Compile(const s: tbtString): Boolean; except on e: Exception do begin - MakeError('', ecCustomError, tbtstring(e.Message)); - {$IFNDEF PS_USESSUPPORT} + MakeError('', ecCustomError, tbtstring(e.Message)); // still attributed to the used unit + {$IFDEF PS_USESSUPPORT} + // restore what the regular failure path above restores: a stale + // fModule survives Cleanup and makes every following Compile of + // this instance fail with a bogus cross-reference error + FParser:=ParserPos; + fModule:=OldFileName; + {$ELSE} FUses.Free; {$ENDIF} Result := False;