← board

COM interface managed lifetime — refcount an interface var like an ansistring

Model (settled with the user)

pxx supports BOTH interface flavours, mode-switched, ZERO conflict — they already have distinct IMT layouts and a per-interface UClsIsComInterface flag:

Current state (what exists / what's missing)

Exists (COM ~half-built, gated OFF behind InterfacesComMode):

Missing (the plumbing this ticket adds — mirror the ansistring managed-local machinery, which already exists per-backend, e.g. EmitAnsiStrReleaseLocked / EmitAnsiStrReleaseForSym and the store-time retain/release-old at ir_codegen.inc IR_STORE_SYM tyAnsiString):

  1. Scope-exit release of a COM interface local — a COM interface local going out of scope must PXXIntfRelease at the proc epilogue, exactly where an ansistring local is finalized. Verified missing: a procedure Use; var it: IThing; begin it := TThing.Create; end; leaks — no destructor. Item 1, do first. Entry point: find where ansistring/dynarray locals get their scope-exit release and add the UClsIsComInterface case (nil-init at prologue too, so an early exit / never-assigned local releases nothing garbage).
  2. Param / result rules — AddRef a function's interface result before return (the caller owns the +1, like a returned ansistring); value-param retain-on-entry / release-on-exit; const interface param skips refcount.
  3. Field init/final — a COM interface field in a record/class: nil-init on construction, release on finalize. RecordHasManagedFields already walks managed fields — include COM interfaces so the managed-record path covers them.
  4. Default flip — default {$interfaces com} (FPC parity), CORBA behind the directive. Add {$interfaces corba} to the ~7 GUID-less CORBA-lenient tests (test_interfaces, _as/_is/_inherit/_param/_multi_secondary) — under real FPC they'd need it too. DO THIS AFTER item 1 — flipping first would leak on every scope exit.
  5. as / Supports via QueryInterface (optional, defer) — strict COM runtime query by GUID. pxx recovers the IMT from RTTI by id for calls; the QI protocol path is separate. Not needed for lifetime; pick up only if a corpus needs it.

Sequencing

1 (scope-exit) → 2 (param/result) → 3 (fields) → then 4 (default flip). 5 last / optional.

Acceptance

Log

Resolution (2026-07-15, agent-A)

Landed the COM managed-lifetime arc:

Remaining (filed separately — NOT part of this arc's acceptance)