@@ -206,29 +206,24 @@ TEST(HostFlags, CfgBypassLinuxOnlyDiffersFromAlwaysOffLinux) {
206206 }
207207}
208208
209- // ── Every exit of host_link_tokens names the toolchain's runtime dirs ─ ──────
209+ // ── Which exit of host_link_tokens names the toolchain's runtime dirs ──────
210210//
211- // THE DEFECT THIS STATES. `host_link_tokens` has two exits: one that spells
212- // clang's configuration out and one that trusts the bundled `<driver>.cfg`.
213- // The second returned early, before the block that emits `-L` and `-rpath`
214- // for `Toolchain::linkRuntimeDirs`. Trusting the cfg decides WHICH runtimes
215- // are linked; it never decided WHERE they are found, and on macOS `-lc++`
216- // then resolved through the SDK to the system library while the headers came
217- // from the payload. Measured on macos-14, compiling a build program that does
218- // nothing but `import std`:
211+ // THE ASYMMETRY IS A DECISION, AND THIS IS WHERE IT IS STATED. The spelled-out
212+ // exit emits `-L` and `-rpath` for `Toolchain::linkRuntimeDirs`; the
213+ // cfg-trusting exit does not, and both halves were measured.
219214//
220- // ld64.lld: error: undefined symbol: std::__1::__is_posix_terminal(__sFILE*)
215+ // Emitting them there makes `-lc++` resolve to the toolchain's own dylib on
216+ // macOS, which is the ToolchainCoupled contract `dist::mechanism_for` refuses
217+ // on Mach-O: LLVM's macOS libc++abi and libunwind dylibs upward-link
218+ // /usr/lib/libc++, so a second libc++ loads into the process. The link does not
219+ // even get that far -- it stops on `__cxa_end_catch` and the rest of the ABI
220+ // surface the system libc++ re-exports and the payload's does not.
221221//
222- // -- a symbol `std::print`'s inline machinery references and that release's
223- // libc++ does not export. The payload ships its own copy, one directory the
224- // early return had dropped.
225- //
226- // AND WHY THIS TEST CAN RUN ON LINUX. The branch is chosen by the host: with
227- // `LinuxOnly`, a Linux build always takes the spelled-out exit, so the exit
228- // that had the defect is unreachable from a Linux runner. `CfgBypass::Never`
229- // exists to make it reachable -- the defect lived in a branch that only two
230- // of the three CI hosts could execute, and a test that could only run there
231- // would inherit the same blind spot.
222+ // AND WHY THIS TEST CAN RUN ON LINUX. The exit is chosen by the host: with
223+ // `LinuxOnly`, a Linux build always takes the spelled-out one, so the other is
224+ // unreachable from a Linux runner. `CfgBypass::Never` exists to make it
225+ // reachable -- a decision that only two of the three CI hosts can execute
226+ // would otherwise be stated only in prose.
232227namespace {
233228
234229// A directory that looks enough like a clang payload for `resolve_clang_driver`
@@ -255,7 +250,7 @@ bool names_dir(const std::vector<std::string>& tokens, std::string_view dir) {
255250
256251} // namespace
257252
258- TEST (HostFlags, EveryExitNamesTheToolchainRuntimeDirs ) {
253+ TEST (HostFlags, OnlyTheSpelledOutExitNamesTheToolchainRuntimeDirs ) {
259254 FakeClangPayload payload{" runtime-dirs" };
260255 auto tc = tc_for (CompilerId::Clang);
261256 tc.binaryPath = payload.root / " bin" / " clang++" ;
@@ -264,21 +259,23 @@ TEST(HostFlags, EveryExitNamesTheToolchainRuntimeDirs) {
264259 HostFlagOptions opt;
265260 opt.runtimeLibDirs = true ;
266261
267- // The cfg-trusting exit -- the one that returned early.
268- opt.cfgBypass = HostFlagOptions::CfgBypass::Never;
269- auto trusting = mcpp::toolchain::host_link_tokens (tc, opt, mcpp::toolchain::no_escape);
270- EXPECT_TRUE (names_dir (trusting, (payload.root / " lib" ).string ()))
271- << " the cfg-trusting exit dropped the toolchain's own runtime directory, "
272- " so `-lc++` resolves to whatever the system has" ;
273-
274- // The spelled-out exit, which always did.
262+ // Spelled out: the payload's own runtime directories are named.
275263 opt.cfgBypass = HostFlagOptions::CfgBypass::Always;
276264 auto spelled = mcpp::toolchain::host_link_tokens (tc, opt, mcpp::toolchain::no_escape);
277265 EXPECT_TRUE (names_dir (spelled, (payload.root / " lib" ).string ()));
278266
279- // And the option is still an option: nothing is emitted when it is off.
280- opt. runtimeLibDirs = false ;
267+ // Trusting the cfg: they are NOT, and the comment above says what naming
268+ // them costs.
281269 opt.cfgBypass = HostFlagOptions::CfgBypass::Never;
270+ auto trusting = mcpp::toolchain::host_link_tokens (tc, opt, mcpp::toolchain::no_escape);
271+ EXPECT_FALSE (names_dir (trusting, (payload.root / " lib" ).string ()))
272+ << " the cfg-trusting exit now points `-lc++` at the toolchain's own "
273+ " dylib; on Mach-O that link fails on the C++ ABI symbols the system "
274+ " libc++ re-exports" ;
275+
276+ // And the option is still an option on the exit that honours it.
277+ opt.runtimeLibDirs = false ;
278+ opt.cfgBypass = HostFlagOptions::CfgBypass::Always;
282279 auto off = mcpp::toolchain::host_link_tokens (tc, opt, mcpp::toolchain::no_escape);
283280 EXPECT_FALSE (names_dir (off, (payload.root / " lib" ).string ()));
284281}
0 commit comments