Skip to content

Commit 5fc3081

Browse files
author
bors-servo
authored
Auto merge of rust-lang#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
2 parents 3ef1a27 + f4d4994 commit 5fc3081

File tree

4 files changed

+62
-3
lines changed

4 files changed

+62
-3
lines changed

src/codegen/mod.rs

+22-3
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,26 @@ impl CodeGenerator for Type {
549549
inner_item.to_rust_ty(ctx)
550550
};
551551

552+
{
553+
// FIXME(emilio): This is a workaround to avoid generating
554+
// incorrect type aliases because of types that we haven't
555+
// been able to resolve (because, eg, they depend on a
556+
// template parameter).
557+
//
558+
// It's kind of a shame not generating them even when they
559+
// could be referenced, but we already do the same for items
560+
// with invalid template parameters, and at least this way
561+
// they can be replaced, instead of generating plain invalid
562+
// code.
563+
let inner_canon_type =
564+
inner_item.expect_type().canonical_type(ctx);
565+
if inner_canon_type.is_invalid_named_type() {
566+
warn!("Item contained invalid named type, skipping: \
567+
{:?}, {:?}", item, inner_item);
568+
return;
569+
}
570+
}
571+
552572
let rust_name = ctx.rust_ident(&name);
553573
let mut typedef = aster::AstBuilder::new().item().pub_();
554574

@@ -586,9 +606,8 @@ impl CodeGenerator for Type {
586606
for template_arg in applicable_template_args.iter() {
587607
let template_arg = ctx.resolve_type(*template_arg);
588608
if template_arg.is_named() {
589-
let name = template_arg.name().unwrap();
590-
if name.contains("typename ") {
591-
warn!("Item contained `typename`'d template \
609+
if template_arg.is_invalid_named_type() {
610+
warn!("Item contained invalid template \
592611
parameter: {:?}", item);
593612
return;
594613
}

src/ir/ty.rs

+21
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,27 @@ impl Type {
292292
}
293293
}
294294

295+
/// Whether this named type is an invalid C++ identifier. This is done to
296+
/// avoid generating invalid code with some cases we can't handle, see:
297+
///
298+
/// tests/headers/381-decltype-alias.hpp
299+
pub fn is_invalid_named_type(&self) -> bool {
300+
match self.kind {
301+
TypeKind::Named(ref name) => {
302+
assert!(!name.is_empty());
303+
let mut chars = name.chars();
304+
let first = chars.next().unwrap();
305+
let mut remaining = chars;
306+
307+
let valid = (first.is_alphabetic() || first == '_') &&
308+
remaining.all(|c| c.is_alphanumeric() || c == '_');
309+
310+
!valid
311+
}
312+
_ => false,
313+
}
314+
}
315+
295316
/// See safe_canonical_type.
296317
pub fn canonical_type<'tr>(&'tr self,
297318
ctx: &'tr BindgenContext)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(non_snake_case)]
5+
6+
7+
#[repr(C)]
8+
#[derive(Debug, Copy, Clone)]
9+
pub struct std_allocator_traits<_Alloc> {
10+
pub _address: u8,
11+
pub _phantom_0: ::std::marker::PhantomData<_Alloc>,
12+
}

tests/headers/381-decltype-alias.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// bindgen-flags: -- -std=c++11
2+
3+
namespace std {
4+
template<typename _Alloc> struct allocator_traits {
5+
typedef decltype ( _S_size_type_helper ( ( _Alloc * ) 0 ) ) __size_type;
6+
};
7+
}

0 commit comments

Comments
 (0)