From 5907e1d3146628e2b2082f2db64abdfa92ca6d77 Mon Sep 17 00:00:00 2001 From: Graeme Geldenhuys Date: Fri, 24 Apr 2026 17:59:21 +0100 Subject: [PATCH] hand source: TObjectList takes strong refs to stored objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hand-written self-hosting TObjectList stored bare Pointers and took no ARC ref when adding. In loops like while Check(tkIdent) do begin CD := TConstDecl.Create; ... ABlock.ConstDecls.Add(CD); end; reassigning CD on the next iteration released the prior CD (its only strong ref) and the list's pointer dangled. When a later allocation reused that heap slot, the list silently contained the wrong object, and semantic analysis crashed in TSymbol.Create reading CD.Name from an unrelated object's memory. Add/Put/Delete/Clear/Destroy now AddRef on insert and Release on remove or destroy, gated on FOwnsObjects so the semantics match the real compiler's TObjectList. Extract continues to transfer the ref to the caller without release. Lets stage-2 compile the hand source far enough to hit the next bug (currently a nil Self in TRecordTypeDesc.AddVTableSlot during AnalyseTypeDecls) — more hand-source polish to follow. --- tests/blaise-compiler.pas | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/blaise-compiler.pas b/tests/blaise-compiler.pas index 1b32c92..1527994 100644 --- a/tests/blaise-compiler.pas +++ b/tests/blaise-compiler.pas @@ -242,7 +242,20 @@ begin end; procedure TObjectList.Destroy; +var + I: Integer; + Src: ^Pointer; begin + if Self.FOwnsObjects then + begin + I := 0; + while I < Self.FCount do + begin + Src := Self.FData + I * SizeOf(Pointer); + _ClassRelease(Src^); + I := I + 1 + end + end; FreeMem(Self.FData); Self.FData := nil; Self.FCount := 0; @@ -257,6 +270,7 @@ begin Self.Grow; Dest := Self.FData + Self.FCount * SizeOf(Pointer); Dest^ := AObject; + _ClassAddRef(AObject); Self.FCount := Self.FCount + 1; Result := Self.FCount - 1 end; @@ -274,6 +288,9 @@ var Dest: ^Pointer; begin Dest := Self.FData + AIndex * SizeOf(Pointer); + _ClassAddRef(AObject); + if Self.FOwnsObjects then + _ClassRelease(Dest^); Dest^ := AObject end; @@ -302,6 +319,11 @@ var Dst: ^Pointer; Src: ^Pointer; begin + if Self.FOwnsObjects then + begin + Src := Self.FData + AIndex * SizeOf(Pointer); + _ClassRelease(Src^); + end; I := AIndex; while I < Self.FCount - 1 do begin @@ -314,7 +336,20 @@ begin end; procedure TObjectList.Clear; +var + I: Integer; + Src: ^Pointer; begin + if Self.FOwnsObjects then + begin + I := 0; + while I < Self.FCount do + begin + Src := Self.FData + I * SizeOf(Pointer); + _ClassRelease(Src^); + I := I + 1 + end + end; Self.FCount := 0 end;