summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-01-30 10:29:09 -0800
committerGitHub <noreply@github.com>2017-01-30 10:29:09 -0800
commit5fc308136d6f1d49f7786922ecea232727bcb024 (patch)
treed023c19e81df9b36fb5c0f1eeab4f6cc6c82d6f8
parent3ef1a277c01e5c146cfdeb112c01c6261555c8b9 (diff)
parentf4d4994c1481baaf0a6e643bf3d3466d35bf950b (diff)
Auto merge of #384 - emilio:decltype, r=fitzgen
codegen: Do the same workaround we do for template parameters with `typename` on aliases for `decltypes` we can't resolve. r? @fitzgen
-rw-r--r--src/codegen/mod.rs25
-rw-r--r--src/ir/ty.rs21
-rw-r--r--tests/expectations/tests/381-decltype-alias.rs12
-rw-r--r--tests/headers/381-decltype-alias.hpp7
4 files changed, 62 insertions, 3 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 313ca8b0..c36dd644 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -549,6 +549,26 @@ impl CodeGenerator for Type {
inner_item.to_rust_ty(ctx)
};
+ {
+ // FIXME(emilio): This is a workaround to avoid generating
+ // incorrect type aliases because of types that we haven't
+ // been able to resolve (because, eg, they depend on a
+ // template parameter).
+ //
+ // It's kind of a shame not generating them even when they
+ // could be referenced, but we already do the same for items
+ // with invalid template parameters, and at least this way
+ // they can be replaced, instead of generating plain invalid
+ // code.
+ let inner_canon_type =
+ inner_item.expect_type().canonical_type(ctx);
+ if inner_canon_type.is_invalid_named_type() {
+ warn!("Item contained invalid named type, skipping: \
+ {:?}, {:?}", item, inner_item);
+ return;
+ }
+ }
+
let rust_name = ctx.rust_ident(&name);
let mut typedef = aster::AstBuilder::new().item().pub_();
@@ -586,9 +606,8 @@ impl CodeGenerator for Type {
for template_arg in applicable_template_args.iter() {
let template_arg = ctx.resolve_type(*template_arg);
if template_arg.is_named() {
- let name = template_arg.name().unwrap();
- if name.contains("typename ") {
- warn!("Item contained `typename`'d template \
+ if template_arg.is_invalid_named_type() {
+ warn!("Item contained invalid template \
parameter: {:?}", item);
return;
}
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index f120e180..005cacca 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -292,6 +292,27 @@ impl Type {
}
}
+ /// Whether this named type is an invalid C++ identifier. This is done to
+ /// avoid generating invalid code with some cases we can't handle, see:
+ ///
+ /// tests/headers/381-decltype-alias.hpp
+ pub fn is_invalid_named_type(&self) -> bool {
+ match self.kind {
+ TypeKind::Named(ref name) => {
+ assert!(!name.is_empty());
+ let mut chars = name.chars();
+ let first = chars.next().unwrap();
+ let mut remaining = chars;
+
+ let valid = (first.is_alphabetic() || first == '_') &&
+ remaining.all(|c| c.is_alphanumeric() || c == '_');
+
+ !valid
+ }
+ _ => false,
+ }
+ }
+
/// See safe_canonical_type.
pub fn canonical_type<'tr>(&'tr self,
ctx: &'tr BindgenContext)
diff --git a/tests/expectations/tests/381-decltype-alias.rs b/tests/expectations/tests/381-decltype-alias.rs
new file mode 100644
index 00000000..766be3bc
--- /dev/null
+++ b/tests/expectations/tests/381-decltype-alias.rs
@@ -0,0 +1,12 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct std_allocator_traits<_Alloc> {
+ pub _address: u8,
+ pub _phantom_0: ::std::marker::PhantomData<_Alloc>,
+}
diff --git a/tests/headers/381-decltype-alias.hpp b/tests/headers/381-decltype-alias.hpp
new file mode 100644
index 00000000..0bec2fc7
--- /dev/null
+++ b/tests/headers/381-decltype-alias.hpp
@@ -0,0 +1,7 @@
+// bindgen-flags: -- -std=c++11
+
+namespace std {
+ template<typename _Alloc> struct allocator_traits {
+ typedef decltype ( _S_size_type_helper ( ( _Alloc * ) 0 ) ) __size_type;
+ };
+}