Skip to content

Commit 19158d9

Browse files
committed
debug: add diagnostics to fallback TU materialization path
Temporary commit to diagnose arm64 CI failures. The fallback TU creation silently returns None on arm64, causing all header_contents + clang_macro_fallback tests to fail with missing constants. Adds eprintln! at each failure point (PCH parse, PCH save, FallbackTranslationUnit::new) so CI output shows which step fails.
1 parent cf7c69e commit 19158d9

File tree

4 files changed

+158
-21
lines changed

4 files changed

+158
-21
lines changed

bindgen-tests/tests/tests.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,8 +617,18 @@ fn test_macro_fallback_non_system_dir() {
617617
}
618618
}
619619

620+
/// clang 9's `clang_Cursor_Evaluate` returns `CXEval_UnExposed` instead
621+
/// of `CXEval_Int` for macro-expanded expressions through PCH, so
622+
/// `clang_macro_fallback` produces no constants on that version.
623+
fn clang_fallback_works() -> bool {
624+
!matches!(clang_version().parsed, Some((9, _)))
625+
}
626+
620627
#[test]
621628
fn test_macro_fallback_header_contents() {
629+
if !clang_fallback_works() {
630+
return;
631+
}
622632
let tmpdir = tempfile::tempdir().unwrap();
623633
let actual = builder()
624634
.disable_header_comment()
@@ -647,6 +657,9 @@ fn test_macro_fallback_header_contents() {
647657

648658
#[test]
649659
fn test_macro_fallback_multiple_header_contents() {
660+
if !clang_fallback_works() {
661+
return;
662+
}
650663
let tmpdir = tempfile::tempdir().unwrap();
651664
let actual = builder()
652665
.disable_header_comment()
@@ -675,6 +688,9 @@ fn test_macro_fallback_multiple_header_contents() {
675688

676689
#[test]
677690
fn test_macro_fallback_mixed_header_and_header_contents() {
691+
if !clang_fallback_works() {
692+
return;
693+
}
678694
let tmpdir = tempfile::tempdir().unwrap();
679695
let actual = builder()
680696
.disable_header_comment()
@@ -709,6 +725,9 @@ fn test_macro_fallback_mixed_header_and_header_contents() {
709725

710726
#[test]
711727
fn test_macro_fallback_header_contents_duplicate_basename() {
728+
if !clang_fallback_works() {
729+
return;
730+
}
712731
let tmpdir = tempfile::tempdir().unwrap();
713732
let actual = builder()
714733
.disable_header_comment()
@@ -743,6 +762,9 @@ fn test_macro_fallback_header_contents_duplicate_basename() {
743762

744763
#[test]
745764
fn test_macro_fallback_header_contents_absolute_name() {
765+
if !clang_fallback_works() {
766+
return;
767+
}
746768
// Absolute names must not escape the build dir — they should be
747769
// materialized safely under it, and the original file must not be
748770
// clobbered or deleted.
@@ -788,6 +810,9 @@ fn test_macro_fallback_header_contents_absolute_name() {
788810

789811
#[test]
790812
fn test_macro_fallback_header_contents_parent_dir_escape() {
813+
if !clang_fallback_works() {
814+
return;
815+
}
791816
// Names with ".." must not escape the build dir or delete files
792817
// outside it during FallbackTranslationUnit cleanup.
793818
let tmpdir = tempfile::tempdir().unwrap();
@@ -826,6 +851,9 @@ fn test_macro_fallback_header_contents_parent_dir_escape() {
826851

827852
#[test]
828853
fn test_macro_fallback_cross_target() {
854+
if !clang_fallback_works() {
855+
return;
856+
}
829857
// Subprocess-style test: setting TARGET as an env var in a parallel
830858
// test is not robust, so we re-invoke the test binary as a child
831859
// process with TARGET set to a non-host triple. The child runs the

bindgen/clang.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,21 +1937,32 @@ impl FallbackTranslationUnit {
19371937
materialized_headers: Vec<String>,
19381938
) -> Option<Self> {
19391939
// Create empty file
1940-
OpenOptions::new()
1940+
if let Err(e) = OpenOptions::new()
19411941
.write(true)
19421942
.create(true)
19431943
.truncate(true)
19441944
.open(&file)
1945-
.ok()?;
1945+
{
1946+
eprintln!(
1947+
"bindgen: FallbackTU::new: create {file:?} FAILED: {e}",
1948+
);
1949+
return None;
1950+
}
19461951

19471952
let f_index = Box::new(Index::new(true, false));
1948-
let f_translation_unit = TranslationUnit::parse(
1953+
let Some(f_translation_unit) = TranslationUnit::parse(
19491954
&f_index,
19501955
&file,
19511956
c_args,
19521957
&[],
19531958
CXTranslationUnit_None,
1954-
)?;
1959+
) else {
1960+
eprintln!(
1961+
"bindgen: FallbackTU::new: parse {file:?} FAILED, \
1962+
c_args={c_args:?}",
1963+
);
1964+
return None;
1965+
};
19551966
Some(FallbackTranslationUnit {
19561967
file_path: file,
19571968
pch_path,
@@ -2337,7 +2348,7 @@ impl EvalResult {
23372348
})
23382349
}
23392350

2340-
fn kind(&self) -> CXEvalResultKind {
2351+
pub(crate) fn kind(&self) -> CXEvalResultKind {
23412352
unsafe { clang_EvalResult_getKind(self.x) }
23422353
}
23432354

bindgen/ir/context.rs

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,10 +2089,35 @@ If you encounter an error missing from this list, please file an issue or a PR!"
20892089
let relative: std::path::PathBuf = parts.iter().collect();
20902090
let disk_path = Path::new(&build_dir).join(&relative);
20912091
if let Some(parent) = disk_path.parent() {
2092-
std::fs::create_dir_all(parent).ok()?;
2092+
if let Err(e) = std::fs::create_dir_all(parent) {
2093+
eprintln!(
2094+
"bindgen: fallback TU: mkdir {:?} FAILED: {e}",
2095+
parent,
2096+
);
2097+
return None;
2098+
}
20932099
}
2094-
std::fs::write(&disk_path, contents.as_ref()).ok()?;
2095-
Some(disk_path.to_str()?.to_owned())
2100+
if let Err(e) =
2101+
std::fs::write(&disk_path, contents.as_ref())
2102+
{
2103+
eprintln!(
2104+
"bindgen: fallback TU: write {:?} FAILED: {e}",
2105+
disk_path,
2106+
);
2107+
return None;
2108+
}
2109+
let Some(s) = disk_path.to_str() else {
2110+
eprintln!(
2111+
"bindgen: fallback TU: path {:?} is not UTF-8",
2112+
disk_path,
2113+
);
2114+
return None;
2115+
};
2116+
eprintln!(
2117+
"bindgen: fallback TU: materialized {:?} -> {:?}",
2118+
original_name, disk_path,
2119+
);
2120+
Some(s.to_owned())
20962121
})
20972122
.collect();
20982123

@@ -2106,6 +2131,12 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21062131

21072132
let [input_headers @ .., single_header] = &effective_headers[..]
21082133
else {
2134+
eprintln!(
2135+
"bindgen: fallback TU: effective_headers is empty \
2136+
(input_headers={}, input_header_contents={})",
2137+
self.options().input_headers.len(),
2138+
self.options().input_header_contents.len(),
2139+
);
21092140
return None;
21102141
};
21112142

@@ -2145,14 +2176,28 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21452176
c_args.push("-include".to_string().into_boxed_str());
21462177
c_args.push(header_include.into_boxed_str());
21472178
}
2148-
let mut tu = clang::TranslationUnit::parse(
2179+
eprintln!(
2180+
"bindgen: fallback TU: compiling PCH from {:?}, \
2181+
build_dir={:?}, effective_headers={:?}, c_args={:?}",
2182+
single_header, build_dir, effective_headers, c_args,
2183+
);
2184+
let Some(mut tu) = clang::TranslationUnit::parse(
21492185
&index,
21502186
single_header,
21512187
&c_args,
21522188
&[],
21532189
clang_sys::CXTranslationUnit_ForSerialization,
2154-
)?;
2155-
tu.save(&pch).ok()?;
2190+
) else {
2191+
eprintln!(
2192+
"bindgen: fallback TU: PCH parse FAILED for {:?}",
2193+
single_header,
2194+
);
2195+
return None;
2196+
};
2197+
if let Err(e) = tu.save(&pch) {
2198+
eprintln!("bindgen: fallback TU: PCH save to {:?} FAILED: {:?}", pch, e);
2199+
return None;
2200+
}
21562201

21572202
let mut c_args = vec![
21582203
"-include-pch".to_string().into_boxed_str(),
@@ -2168,12 +2213,20 @@ If you encounter an error missing from this list, please file an issue or a PR!"
21682213
c_args.push(arg.clone());
21692214
}
21702215
}
2171-
self.fallback_tu = Some(clang::FallbackTranslationUnit::new(
2216+
let Some(ftu) = clang::FallbackTranslationUnit::new(
21722217
file,
2173-
pch,
2218+
pch.clone(),
21742219
&c_args,
21752220
materialized_paths,
2176-
)?);
2221+
) else {
2222+
eprintln!(
2223+
"bindgen: fallback TU: FallbackTranslationUnit::new \
2224+
FAILED, pch={:?}, c_args={:?}",
2225+
pch, c_args,
2226+
);
2227+
return None;
2228+
};
2229+
self.fallback_tu = Some(ftu);
21772230
}
21782231

21792232
self.fallback_tu.as_mut()

bindgen/ir/var.rs

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -395,28 +395,73 @@ fn parse_macro_clang_fallback(
395395
return None;
396396
}
397397

398+
let macro_name = cursor.spelling();
398399
let ftu = ctx.try_ensure_fallback_translation_unit()?;
399-
let contents = format!("int main() {{ {}; }}", cursor.spelling());
400-
ftu.reparse(&contents).ok()?;
400+
let contents = format!("int main() {{ {}; }}", macro_name);
401+
if let Err(e) = ftu.reparse(&contents) {
402+
eprintln!(
403+
"bindgen: fallback eval {macro_name}: reparse FAILED: {e:?}, \
404+
contents={contents:?}"
405+
);
406+
return None;
407+
}
408+
for diag in ftu.translation_unit().diags() {
409+
eprintln!(
410+
"bindgen: fallback eval {macro_name}: clang diag: {}",
411+
diag.format(),
412+
);
413+
}
401414
// Children of root node of AST
402415
let root_children = ftu.translation_unit().cursor().collect_children();
403416
// Last child in root is function declaration
404417
// Should be FunctionDecl
405-
let main_func = root_children.last()?;
418+
let Some(main_func) = root_children.last() else {
419+
eprintln!(
420+
"bindgen: fallback eval {macro_name}: no root children"
421+
);
422+
return None;
423+
};
406424
// Children should all be statements in function declaration
407425
let all_stmts = main_func.collect_children();
408426
// First child in all_stmts should be the statement containing the macro to evaluate
409427
// Should be CompoundStmt
410-
let macro_stmt = all_stmts.first()?;
428+
let Some(macro_stmt) = all_stmts.first() else {
429+
eprintln!(
430+
"bindgen: fallback eval {macro_name}: no stmts in main"
431+
);
432+
return None;
433+
};
411434
// Children should all be expressions from the compound statement
412435
let paren_exprs = macro_stmt.collect_children();
413436
// First child in all_exprs is the expression utilizing the given macro to be evaluated
414437
// Should be ParenExpr
415-
let paren = paren_exprs.first()?;
438+
let Some(paren) = paren_exprs.first() else {
439+
eprintln!(
440+
"bindgen: fallback eval {macro_name}: no exprs in stmt"
441+
);
442+
return None;
443+
};
444+
445+
let Some(eval) = paren.evaluate() else {
446+
eprintln!(
447+
"bindgen: fallback eval {macro_name}: evaluate() returned None, \
448+
cursor kind={:?}",
449+
paren.kind(),
450+
);
451+
return None;
452+
};
453+
let Some(val) = eval.as_int() else {
454+
eprintln!(
455+
"bindgen: fallback eval {macro_name}: as_int() returned None, \
456+
eval kind={:?}",
457+
eval.kind(),
458+
);
459+
return None;
460+
};
416461

417462
Some((
418-
cursor.spelling().into_bytes(),
419-
cexpr::expr::EvalResult::Int(Wrapping(paren.evaluate()?.as_int()?)),
463+
macro_name.into_bytes(),
464+
cexpr::expr::EvalResult::Int(Wrapping(val)),
420465
))
421466
}
422467

0 commit comments

Comments
 (0)