fix: escape response-file backslashes for driver linkers - #1853
Merged
Conversation
`write_response_file` assumed one tokenizer for every linker. Its comment claimed an unquoted backslash is literal in the response-file format; that holds for lld and binutils, but a compiler driver treats a backslash as an escape. Object paths were therefore written bare, and clang received `C:buildobjmainProg.st.o` for `C:\build\obj\mainProg.st.o`, failing the link with "no such file or directory" for every object. The defect needed two conditions that could not co-occur on Windows until now: a command line over the 30,000-byte threshold, so the args are routed through a response file, and a driver linker consuming it. Windows always fell back to a direct ld.lld link, which reads backslashes literally, so the existing behaviour was correct for the only linker that could be selected. Including the sysroot in the driver probe made clang selectable on Windows and exposed the writer's assumption. Pick the escaping from the linker family at the point the file is written: drivers get doubled backslashes, direct linkers keep them literal. Quoted arguments already double backslashes under both, so that path is unchanged. Verified by forcing a response file with PLC_LINKER_RESPONSE_FILE=1: clang now links where it previously failed on every object, and a direct ld.lld link is unaffected. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Build Artifacts🐧 Linux
From workflow run 🪟 Windows
From workflow run |
Angus-Bethke-Bachmann
approved these changes
Aug 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Windows, linking a real-sized project through the
clangdriver fails withno such file or directoryfor every object:Every backslash has been stripped:
C:\build\obj\mainProg.st.oarrives asC:buildobjmainProg.st.o.Cause
write_response_fileassumed a single tokenizer for all linkers. Its comment stated "an unquoted backslash is literal in this format" — true forlldand binutils, but a compiler driver treats a backslash as an escape. Object paths were written bare, so the driver consumed the separators.The defect needed two conditions that could not co-occur on Windows until recently:
ld.lldlink, which reads backslashes literally — so the existing behaviour was correct for the only linker that could be selected.Including the sysroot in the driver probe (#1852) made
clangselectable on Windows and switched on condition 2, exposing the writer's assumption. The bug was latent in the writer the whole time; nothing on Windows could reach it.Fix
Choose the escaping from the linker family where the file is written:
clang,cc,gccEscapedBackslashld.lld,ld.bfd,goldLiteralBackslashQuoted arguments (those carrying whitespace) already double backslashes under both families, so that path is unchanged.
Verification
Forcing a response file with
PLC_LINKER_RESPONSE_FILE=1on a Windows host:clang(driver)ld.lld(direct)Tests
30 linker unit tests pass, three of them new and each failing without this change:
response_file_quoting_escapes_backslashes_for_driver_linkerswrite_response_file_escapes_object_paths_for_driver_linkers— asserts the emitted lines and that each unescapes back to the original argumentdriver_linker_response_file_round_trips_windows_paths— goes throughCcLinkerso the style is derived the wayfinalizederives it, rather than asserted against a hand-passed constantNo lit test. A lit case could force a response file with a driver linker, but lit runs on Linux where paths carry no backslashes, so the defect cannot reproduce — it would pass for the wrong reason. The unit tests are the real guard.
🤖 Generated with Claude Code