summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbindgen/src/clang.rs35
-rw-r--r--libbindgen/src/ir/var.rs7
-rw-r--r--libbindgen/tests/expectations/tests/eval-variadic-template-parameter.rs12
-rw-r--r--libbindgen/tests/headers/eval-variadic-template-parameter.hpp8
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);
+};