diff options
Diffstat (limited to 'libbindgen')
-rw-r--r-- | libbindgen/src/clang.rs | 35 | ||||
-rw-r--r-- | libbindgen/src/ir/var.rs | 7 | ||||
-rw-r--r-- | libbindgen/tests/expectations/tests/eval-variadic-template-parameter.rs | 12 | ||||
-rw-r--r-- | libbindgen/tests/headers/eval-variadic-template-parameter.hpp | 8 |
4 files changed, 51 insertions, 11 deletions
diff --git a/libbindgen/src/clang.rs b/libbindgen/src/clang.rs index 6c95b22f..a11903aa 100644 --- a/libbindgen/src/clang.rs +++ b/libbindgen/src/clang.rs @@ -487,7 +487,7 @@ impl Cursor { } /// Try to evaluate this cursor. - pub fn evaluate(&self) -> EvalResult { + pub fn evaluate(&self) -> Option<EvalResult> { EvalResult::new(*self) } } @@ -1286,10 +1286,8 @@ pub struct EvalResult { #[cfg(feature = "llvm_stable")] impl EvalResult { /// Create a dummy EvalResult. - pub fn new(_: Cursor) -> Self { - EvalResult { - x: ptr::null_mut(), - } + pub fn new(_: Cursor) -> Option<Self> { + None } /// Not useful in llvm 3.8. @@ -1306,10 +1304,31 @@ impl EvalResult { #[cfg(not(feature = "llvm_stable"))] impl EvalResult { /// Evaluate `cursor` and return the result. - pub fn new(cursor: Cursor) -> Self { - EvalResult { - x: unsafe { clang_Cursor_Evaluate(cursor.x) }, + pub fn new(cursor: Cursor) -> Option<Self> { + // 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 { + found_cant_eval = true; + CXChildVisit_Break + } else { + CXChildVisit_Recurse + } + }); + if found_cant_eval { + return None; } + + Some(EvalResult { + x: unsafe { clang_Cursor_Evaluate(cursor.x) }, + }) } fn kind(&self) -> Enum_CXEvalResultKind { diff --git a/libbindgen/src/ir/var.rs b/libbindgen/src/ir/var.rs index bbaea939..b819bfa4 100644 --- a/libbindgen/src/ir/var.rs +++ b/libbindgen/src/ir/var.rs @@ -209,8 +209,9 @@ impl ClangSubItemParser for Var { _ => unreachable!(), }; - let mut val = - cursor.evaluate().as_int().map(|val| val as i64); + let mut val = cursor.evaluate() + .and_then(|v| v.as_int()) + .map(|val| val as i64); if val.is_none() || !kind.signedness_matches(val.unwrap()) { let tu = ctx.translation_unit(); val = get_integer_literal_from_cursor(&cursor, tu); @@ -225,7 +226,7 @@ impl ClangSubItemParser for Var { }) } else if is_float { cursor.evaluate() - .as_double() + .and_then(|v| v.as_double()) .map(VarType::Float) } else { None diff --git a/libbindgen/tests/expectations/tests/eval-variadic-template-parameter.rs b/libbindgen/tests/expectations/tests/eval-variadic-template-parameter.rs new file mode 100644 index 00000000..f8c937e2 --- /dev/null +++ b/libbindgen/tests/expectations/tests/eval-variadic-template-parameter.rs @@ -0,0 +1,12 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct B<T> { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData<T>, +} diff --git a/libbindgen/tests/headers/eval-variadic-template-parameter.hpp b/libbindgen/tests/headers/eval-variadic-template-parameter.hpp new file mode 100644 index 00000000..0a9e51c1 --- /dev/null +++ b/libbindgen/tests/headers/eval-variadic-template-parameter.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: -- -std=c++11 + +template <typename... T> +struct B { + // Can't generate anything meaningful in Rust for this, but we shouldn't + // trigger an assertion inside Clang. + static const long c = sizeof...(T); +}; |