Opaque interfaces and private state (RFC 0028)
Core’s Interface.h/Interface.cpp define a bounded graph of storage types and
its canonical it1 codec. Edges represent pointer referents, function arguments,
fixed-array elements and record fields. Validation rejects invalid references,
overlapping fields, duplicate names, by-value cycles, malformed numbers and
exhausted bounds before Analysis sees a description. Conflicting descriptions
for one key merge to an absorbing unavailable value.
Analysis’s InterfaceTypes.cpp captures Clang’s target layouts and materializes
implicit analysis-only declarations. Every reconstructed size, alignment, field
offset and record identity must match. A materialized record is outside the
translation unit’s declaration list and cannot complete a source forward
declaration. GlobalTable keeps the private declaration identity separate from
its description: the identity contains the normalized defining translation
unit, declaration source, source offset and name. Macro-generated declarations
also include their spelling/expansion chain so repeated private names remain
distinct within one outer expansion.
UnitExports and ProgramDatabase carry private-root and object-view maps.
Sidecar.cpp validates global-interface and object-interface records before
import, with duplicate rejection and a finite inventory. Metadata participates
in convergence and checkpoint inputs. SummaryStore caches immutable adapters
by their complete encoding and records interface dependencies for contextual
reuse. An import-generation change invalidates consulting specializations.
DataflowViews.cpp recovers opaque representations only from the current
value’s established object, buffer or container evidence. Ordinary typed view
checks still apply. Container nomination can infer entry predicates for opaque
parameters forwarded to verified helpers. Those predicates remain explicit
caller requirements, with their allocation footprint and compatible view.
A local or forged pointer never receives an input predicate by nomination.
Fully typed layout validation can reuse the result for the exact call/path and
same live immutable summary. This cache holds at most 1,024 paths per function
analysis. A path that needed opaque value evidence is always revalidated against
current state. No memory permission or lifetime result is cached with the layout.
Private numeric cells use ordinary scalar state, call-entry snapshots and numeric outputs. Setters that copy callback inputs also record those inputs for specialization. Unknown calls invalidate reachable private state. Direct numeric configuration writes preserve independent heap-container evidence; possibly overlapping array writes invalidate known scalar cells, while proven disjoint indices retain their values. Actual heap writes and cleanup still use structural and lifetime invalidation. Returned buffer predicates activate under a non-null result, retain capacity bounds captured before effects, and preserve the backing identity through accessors. Numeric output alternatives retain their own guarded value interval without narrowing unrelated outcomes or caller inputs.
Primitive allocation-consumed outputs record historical must-evidence about
direct entry allocations, including the empty null case. Joins intersect this
evidence. Applying the output accounts for only the actual head allocation;
container-consumed retains the distinct whole-footprint guarantee.
RFC 0028 keeps accumulated callback/memory requests separate from computed specializations. Sidecars carry up to 65,536 requests per symbol and kind; the existing 32-context analysis limits still govern computed results. Checkpoint fingerprints retain the complete represented demand set. Checkpoint units and diagnostics stream directly into the payload; bulk string escaping preserves decoded JSON values. Shared explanation tables use owned hash indexes while first-use vectors determine every serialized id and row. Producer validation, checksums, compression and all analysis bounds remain.
Run scripts/checked-opaque-interfaces.py for the frozen source, object and cache
populations and independent regressions. The optional upstream and
upstream-objects populations require the pinned cJSON checkout and verify its
commit and file digests. The harness rejects syntax failures, missing reports,
crashes and unrelated negative outcomes; it retains full compressed reports.