Skip to content

The castxml L4 source-ABI extractor does not fold the resolved EMULATED compiler's identity into either fact_set.compiler_version or the D8 TU cache key — attempted once for the persisted half, and REVERTED after a follow-up review caught it as a real regression, not a fix (Codex review, PR #719, three follow-up rounds)

Index: Known gaps

Status (re-verified 2026-10-25): OPEN. buildsource/source_extractors/castxml.py still resolves cc_bin. compiler_version is _castxml_identity_with_stat_fallback(self.castxml_bin) (line 723), and the comment at line 719 says a cc_bin --version probe is still future work.

castxml shells out to the emulated compiler (cc_bin, resolved per compile unit by pick_compiler_binary — the real build's own recorded argv[0], absent an explicit --gcc-path override) purely to discover its built-in defines/include paths (docs/learn/architecture.md), so a header conditional on __GNUC__/_MSC_VER can extract differently once that compiler is upgraded at the same path, even though castxml itself and its own --version probe stay identical — a real gap. The second follow-up round's fix folded a STAT signature (dev/ino/mtime_ns/ size) of the resolved cc_bin into fact_set.compiler_version (_stamp_fact_set_and_coverage() already has the per-TU compile_unit in scope). The third follow-up round found this made things WORSE, not better: those stat fields are filesystem-local, so (1) two TUs in ONE surface resolved to DIFFERENT but same-toolchain drivers (gcc for a .c TU, g++ for a .cpp TU — an entirely ordinary mixed-language build) get different suffixes purely from being different files on disk, tripping rollup_fact_set()'s exact-equality check into fact_set_inconsistent for a perfectly healthy, unchanged surface; and (2) an identical build run on two different machines/paths (baseline collected in one CI run, compared against another — an entirely ordinary workflow) never shares device/inode at all, making every such cross-machine comparison spuriously inconsistent and silently suppressing every structured/opaque/source-edge finding. Between "silently under-detect genuine toolchain drift" (the pre-existing gap) and "spuriously suppress every finding on completely ordinary mixed- language or cross-machine comparisons" (the attempted fix), the second is strictly worse for typical usage, so the stat-based fold was reverted rather than patched further under review pressure. Not fixed here, either half: a correct fix needs a portable SEMANTIC identity — a real cc_bin --version probe, normalized (mirroring _castxml_tool_version's existing shape, but for an arbitrary gcc/clang/MSVC driver rather than castxml specifically) — not filesystem stat fields, for the persisted half; the D8 cache-key half additionally needs a wider, per-instance-hook-signature change to source_replay.py's shared cache-key infra (also used by ClangSourceExtractor, whose analogous --gcc-path case resolves once per extractor construction, not per TU, so its existing zero-arg hook shape doesn't transfer directly), plus a decision on probing cost (a version probe per distinct resolved cc_bin across a build with mixed toolchains, cached the same way _castxml_tool_version's lru_cache already is). Left for a dedicated follow-up with its own MSVC-vs- GCC-vs-Clang version-probe design, not a same-PR reactive patch.