diff options
-rw-r--r-- | src/codegen/mod.rs | 8 | ||||
-rw-r--r-- | src/ir/item.rs | 29 | ||||
-rw-r--r-- | src/ir/ty.rs | 62 |
3 files changed, 89 insertions, 10 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 4ebc48bf..a5159c98 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -341,6 +341,12 @@ impl CodeGenerator for Type { return; } TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item), + TypeKind::TemplateAlias(inner, _) => { + // NB: The inner Alias will pick the correct + // applicable_template_args. + let inner_item = ctx.resolve_item(inner); + inner_item.expect_type().codegen(ctx, result, inner_item); + } TypeKind::Alias(ref spelling, inner) => { let inner_item = ctx.resolve_item(inner); let name = item.canonical_name(ctx); @@ -1361,6 +1367,7 @@ impl ToRustTy for Type { let path = item.canonical_path(ctx); aster::AstBuilder::new().ty().path().ids(path).build() } + TypeKind::TemplateAlias(inner, ref template_args) | TypeKind::TemplateRef(inner, ref template_args) => { // PS: Sorry for the duplication here. let mut inner_ty = inner.to_rust_ty(ctx).unwrap(); @@ -1618,6 +1625,7 @@ impl TypeCollector for Type { TypeKind::Pointer(inner) | TypeKind::Reference(inner) | TypeKind::Array(inner, _) | + TypeKind::TemplateAlias(inner, _) | TypeKind::Alias(_, inner) | TypeKind::Named(_, Some(inner)) | TypeKind::ResolvedTypeRef(inner) diff --git a/src/ir/item.rs b/src/ir/item.rs index 56ddf639..0c1de20a 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -206,6 +206,7 @@ impl Item { } // XXX Is this completely correct? Partial template specialization // is hard anyways, sigh... + TypeKind::TemplateAlias(_, ref args) | TypeKind::TemplateRef(_, ref args) => { args.clone() } @@ -277,11 +278,20 @@ impl Item { TypeKind::Named(ref name, _) => { return name.to_owned(); } - _ => {} - } - - ty.name().map(ToOwned::to_owned) - .unwrap_or_else(|| format!("_bindgen_ty{}", self.id())) + // We really codegen and use the inner type, so use an empty + // base name so codegen doesn't get confused. + // + // We should never have this in another kind of type, so... + TypeKind::TemplateAlias(..) => { + Some("") + } + // Else use the proper name, or fallback to a name with an + // id. + _ => { + ty.name() + } + }.map(ToOwned::to_owned) + .unwrap_or_else(|| format!("_bindgen_ty{}", self.id())) } ItemKind::Function(ref fun) => { let mut base = fun.name().to_owned(); @@ -329,7 +339,12 @@ impl Item { // TODO: allow modification of the mangling functions, maybe even per // item type? - format!("{}_{}", parent.canonical_name(ctx), base_name) + let parent = parent.canonical_name(ctx); + if parent.is_empty() { + base_name.to_owned() + } else { + format!("{}_{}", parent, base_name) + } } pub fn as_module_mut(&mut self) -> Option<&mut Module> { @@ -444,7 +459,7 @@ impl ClangItemParser for Item { if cursor.kind() == clangll::CXCursor_UnexposedDecl { Err(ParseError::Recurse) } else { - error!("Unhandled cursor kind: {}", ::clang::kind_to_str(cursor.kind())); + error!("Unhandled cursor kind: {} ({})", ::clang::kind_to_str(cursor.kind()), cursor.kind()); Err(ParseError::Continue) } } diff --git a/src/ir/ty.rs b/src/ir/ty.rs index bae2fd88..769b7650 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -146,13 +146,14 @@ impl Type { type_resolver.resolve_type(t).can_derive_debug(type_resolver) } TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | TypeKind::Alias(_, t) => { type_resolver.resolve_type(t).can_derive_debug(type_resolver) } TypeKind::Comp(ref info) => { info.can_derive_debug(type_resolver, self.layout(type_resolver)) } - _ => true, + _ => true, } } @@ -177,6 +178,7 @@ impl Type { pub fn can_derive_copy_in_array(&self, type_resolver: &BindgenContext, item: &Item) -> bool { match self.kind { TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | TypeKind::Alias(_, t) | TypeKind::Array(t, _) => { type_resolver.resolve_item(t) @@ -194,6 +196,7 @@ impl Type { type_resolver.resolve_item(t).can_derive_copy_in_array(type_resolver) } TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | TypeKind::TemplateRef(t, _) | TypeKind::Alias(_, t) => { type_resolver.resolve_item(t).can_derive_copy(type_resolver) @@ -209,6 +212,7 @@ impl Type { // FIXME: Can we do something about template parameters? Huh... match self.kind { TypeKind::TemplateRef(t, _) | + TypeKind::TemplateAlias(t, _) | TypeKind::Alias(_, t) | TypeKind::ResolvedTypeRef(t) | TypeKind::Array(t, _) => { @@ -225,6 +229,7 @@ impl Type { pub fn has_destructor(&self, type_resolver: &BindgenContext) -> bool { self.is_opaque(type_resolver) || match self.kind { TypeKind::TemplateRef(t, _) | + TypeKind::TemplateAlias(t, _) | TypeKind::Alias(_, t) | TypeKind::ResolvedTypeRef(t) | TypeKind::Array(t, _) => { @@ -263,7 +268,8 @@ impl Type { type_resolver.resolve_type(sig.return_type()) .signature_contains_named_type(type_resolver, ty) }, - TypeKind::TemplateRef(_inner, ref template_args) => { + TypeKind::TemplateAlias(_, ref template_args) | + TypeKind::TemplateRef(_, ref template_args) => { template_args.iter().any(|arg| { type_resolver.resolve_type(*arg) .signature_contains_named_type(type_resolver, ty) @@ -292,6 +298,7 @@ impl Type { TypeKind::ResolvedTypeRef(inner) | TypeKind::Alias(_, inner) | + TypeKind::TemplateAlias(inner, _) | TypeKind::TemplateRef(inner, _) => type_resolver.resolve_type(inner).canonical_type(type_resolver), @@ -327,6 +334,9 @@ pub enum TypeKind { Float(FloatKind), /// A type alias, with a name, that points to another type. Alias(String, ItemId), + /// A templated alias, pointing to an inner Alias type, with template + /// parameters. + TemplateAlias(ItemId, Vec<ItemId>), /// An array of a type and a lenght. Array(ItemId, usize), /// A function type, with a given signature. @@ -371,6 +381,7 @@ impl Type { } TypeKind::ResolvedTypeRef(inner) | TypeKind::Alias(_, inner) | + TypeKind::TemplateAlias(inner, _) | TypeKind::TemplateRef(inner, _) => type_resolver.resolve_type(inner).is_unsized(type_resolver), TypeKind::Named(..) | @@ -444,6 +455,51 @@ impl Type { .expect("C'mon"); TypeKind::Comp(complex) } + CXCursor_TypeAliasTemplateDecl => { + debug!("TypeAliasTemplateDecl"); + + // We need to manually unwind this one. + let mut inner = Err(ParseError::Continue); + let mut args = vec![]; + + location.visit(|cur, _| { + match cur.kind() { + CXCursor_TypeAliasDecl => { + debug_assert!(cur.cur_type().kind() == CXType_Typedef); + inner = Item::from_ty(&cur.cur_type(), + Some(*cur), + Some(potential_id), + ctx); + } + CXCursor_TemplateTypeParameter => { + let default_type = + Item::from_ty(&cur.cur_type(), + Some(*cur), + Some(potential_id), + ctx).ok(); + let param = + Item::named_type(cur.spelling(), + default_type, + potential_id, ctx); + args.push(param); + } + _ => {} + } + CXChildVisit_Continue + }); + + if inner.is_err() { + error!("Failed to parse templated type alias {:?}", location); + return Err(ParseError::Continue); + } + + if args.is_empty() { + error!("Failed to get any template parameter, maybe a specialization? {:?}", location); + return Err(ParseError::Continue); + } + + TypeKind::TemplateAlias(inner.unwrap(), args) + } CXCursor_TemplateRef => { let referenced = location.referenced(); return Self::from_clang_ty(potential_id, @@ -521,7 +577,7 @@ impl Type { let signature = try!(FunctionSig::from_ty(ty, &location.unwrap_or(cursor), ctx)); TypeKind::Function(signature) } - CXType_Typedef => { + CXType_Typedef => { let inner = cursor.typedef_type(); let inner = Item::from_ty_or_ref(inner, location, parent_id, ctx); |