Skip to content

Commit

Permalink
Auto merge of #384 - emilio:decltype, r=fitzgen
Browse files Browse the repository at this point in the history
codegen: Do the same workaround we do for template parameters with `typename` on aliases for `decltypes` we can't resolve.

r? @fitzgen
  • Loading branch information
bors-servo authored Jan 30, 2017
2 parents 3ef1a27 + f4d4994 commit 5fc3081
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 3 deletions.
25 changes: 22 additions & 3 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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_();

Expand Down Expand Up @@ -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;
}
Expand Down
21 changes: 21 additions & 0 deletions src/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 12 additions & 0 deletions tests/expectations/tests/381-decltype-alias.rs
Original file line number Diff line number Diff line change
@@ -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>,
}
7 changes: 7 additions & 0 deletions tests/headers/381-decltype-alias.hpp
Original file line number Diff line number Diff line change
@@ -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;
};
}

0 comments on commit 5fc3081

Please sign in to comment.