From 6f92b1c1f2086dfe7b478290e76469e64d24bfbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 9 Jul 2019 15:34:07 +0200 Subject: [PATCH] Improve workaround for LLVM bug when evaluating value-dependent expressions. Using the canonical type makes it work across typedefs. Fixes #1590 --- src/clang.rs | 36 +++++++++---------- .../tests/eval-value-dependent.rs | 15 ++++++++ tests/headers/eval-value-dependent.hpp | 6 ++++ 3 files changed, 38 insertions(+), 19 deletions(-) create mode 100644 tests/expectations/tests/eval-value-dependent.rs create mode 100644 tests/headers/eval-value-dependent.hpp diff --git a/src/clang.rs b/src/clang.rs index e02d363fb9..b470e224ad 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -1875,27 +1875,25 @@ impl EvalResult { return None; } - // Clang has an internal assertion we can trigger if we try to evaluate - // a cursor containing a variadic template type reference. Triggering - // the assertion aborts the process, and we don't want that. Clang - // *also* doesn't expose any API for finding variadic vs non-variadic - // template type references, let alone whether a type referenced is a - // template type, instead they seem to show up as type references to an - // unexposed type. Our solution is to just flat out ban all - // `CXType_Unexposed` from evaluation. - let mut found_cant_eval = false; - cursor.visit(|c| if c.kind() == CXCursor_TypeRef && - c.cur_type().kind() == CXType_Unexposed + // Work around https://bugs.llvm.org/show_bug.cgi?id=42532, see: + // * https://github.com/rust-lang/rust-bindgen/issues/283 + // * https://github.com/rust-lang/rust-bindgen/issues/1590 { - found_cant_eval = true; - CXChildVisit_Break - } else { - CXChildVisit_Recurse - }); - if found_cant_eval { - return None; - } + let mut found_cant_eval = false; + cursor.visit(|c| { + if c.kind() == CXCursor_TypeRef && + c.cur_type().canonical_type().kind() == CXType_Unexposed { + found_cant_eval = true; + return CXChildVisit_Break; + } + + CXChildVisit_Recurse + }); + if found_cant_eval { + return None; + } + } Some(EvalResult { x: unsafe { clang_Cursor_Evaluate(cursor.x) }, }) diff --git a/tests/expectations/tests/eval-value-dependent.rs b/tests/expectations/tests/eval-value-dependent.rs new file mode 100644 index 0000000000..b290a2e6a1 --- /dev/null +++ b/tests/expectations/tests/eval-value-dependent.rs @@ -0,0 +1,15 @@ +/* automatically generated by rust-bindgen */ + +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct e { + pub _address: u8, +} +pub type e_f = d; diff --git a/tests/headers/eval-value-dependent.hpp b/tests/headers/eval-value-dependent.hpp new file mode 100644 index 0000000000..0f4dc6ab25 --- /dev/null +++ b/tests/headers/eval-value-dependent.hpp @@ -0,0 +1,6 @@ +// bindgen-flags: -- -std=c++11 + +template class e { + using f = d; + static const auto g = alignof(f); +};