Skip to content

fix: clang_macro_fallback with header_contents() and implicit --target#3353

Open
zRedShift wants to merge 3 commits intorust-lang:mainfrom
zRedShift:fix-macro-fallback-header-contents-target
Open

fix: clang_macro_fallback with header_contents() and implicit --target#3353
zRedShift wants to merge 3 commits intorust-lang:mainfrom
zRedShift:fix-macro-fallback-header-contents-target

Conversation

@zRedShift
Copy link

Summary

Fixes #3351 and #3352.

Two bugs in clang_macro_fallback:

  1. header_contents() silently skipped (clang_macro_fallback() silently skipped when using header_contents() #3351): try_ensure_fallback_translation_unit() only checked input_headers (populated by .header()). When headers were provided via .header_contents(), input_headers was empty, the fallback returned None, and every macro that needed it was silently dropped. Additionally, Builder::generate() used std::mem::take() on input_header_contents, so even if the fallback checked it, the data was already gone.

  2. Implicit --target not propagated (clang_macro_fallback doesn't propagate implicit --target to fallback translation unit #3352): fallback_clang_args was populated from clang_args in Builder::generate() before Bindings::generate() inserted the inferred --target= triple. Cross-compilation would evaluate sizeof-dependent macros (e.g. ioctl constants via _IOR/_IOW) with the host's struct layouts instead of the target's.

Fixes rust-lang#3351

clang_macro_fallback() silently produced no output when headers were
provided via header_contents() instead of header(). This happened
because try_ensure_fallback_translation_unit() only looked at
input_headers (populated by .header()), returning None when it was
empty.

Fix: materialize input_header_contents to disk in the fallback build
directory so clang can consume them for PCH compilation. Both
input_headers and input_header_contents are now included in the
fallback PCH, so mixed .header() + .header_contents() setups work.

The materialized paths are sanitized (roots stripped, ".." resolved)
to prevent escaping the build directory, and tracked in
FallbackTranslationUnit for cleanup on drop.

Also stop using std::mem::take on input_header_contents in
Builder::generate(), preserving the data for the fallback TU (and
fixing a pre-existing bug where serialize_items in codegen couldn't
see header contents).

Also store the original user-provided name in input_header_contents
at header_contents() time so the fallback can reconstruct relative
paths without depending on the current working directory.
Fixes rust-lang#3352

When bindgen infers the target triple from the Rust target (i.e., no
explicit --target in clang_args), it inserts --target= into clang_args
at Bindings::generate() time. However, fallback_clang_args was already
populated from clang_args earlier in Builder::generate(), before this
insertion. This meant the fallback translation unit used for
clang_macro_fallback would use the host architecture instead of the
target architecture.

For cross-compilation, this caused sizeof-dependent macros (e.g., ioctl
constants using _IOR/_IOW) to evaluate with the host's struct layouts
instead of the target's, producing silently wrong values.

Fix: when inserting the inferred target into clang_args, also insert it
into fallback_clang_args.
@zRedShift zRedShift force-pushed the fix-macro-fallback-header-contents-target branch 4 times, most recently from 19158d9 to a499369 Compare March 14, 2026 22:20
clang 9's clang_Cursor_Evaluate returns CXEval_UnExposed instead of
CXEval_Int for macro-expanded expressions loaded through a PCH, so
clang_macro_fallback produces no constants on that version. The
existing header-based fallback tests already handle this with
clang-9-specific empty expectation files; apply the same pattern to
the new inline tests by skipping when libclang 9 is detected.
@zRedShift zRedShift force-pushed the fix-macro-fallback-header-contents-target branch from a499369 to e9fcc7c Compare March 14, 2026 22:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

clang_macro_fallback() silently skipped when using header_contents()

1 participant