Skip to content

Commit 9ba68b1

Browse files
committed
ir: Handle templated aliases.
1 parent 94dea55 commit 9ba68b1

File tree

3 files changed

+89
-10
lines changed

3 files changed

+89
-10
lines changed

src/codegen/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,12 @@ impl CodeGenerator for Type {
341341
return;
342342
}
343343
TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
344+
TypeKind::TemplateAlias(inner, _) => {
345+
// NB: The inner Alias will pick the correct
346+
// applicable_template_args.
347+
let inner_item = ctx.resolve_item(inner);
348+
inner_item.expect_type().codegen(ctx, result, inner_item);
349+
}
344350
TypeKind::Alias(ref spelling, inner) => {
345351
let inner_item = ctx.resolve_item(inner);
346352
let name = item.canonical_name(ctx);
@@ -1361,6 +1367,7 @@ impl ToRustTy for Type {
13611367
let path = item.canonical_path(ctx);
13621368
aster::AstBuilder::new().ty().path().ids(path).build()
13631369
}
1370+
TypeKind::TemplateAlias(inner, ref template_args) |
13641371
TypeKind::TemplateRef(inner, ref template_args) => {
13651372
// PS: Sorry for the duplication here.
13661373
let mut inner_ty = inner.to_rust_ty(ctx).unwrap();
@@ -1618,6 +1625,7 @@ impl TypeCollector for Type {
16181625
TypeKind::Pointer(inner) |
16191626
TypeKind::Reference(inner) |
16201627
TypeKind::Array(inner, _) |
1628+
TypeKind::TemplateAlias(inner, _) |
16211629
TypeKind::Alias(_, inner) |
16221630
TypeKind::Named(_, Some(inner)) |
16231631
TypeKind::ResolvedTypeRef(inner)

src/ir/item.rs

+22-7
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ impl Item {
206206
}
207207
// XXX Is this completely correct? Partial template specialization
208208
// is hard anyways, sigh...
209+
TypeKind::TemplateAlias(_, ref args) |
209210
TypeKind::TemplateRef(_, ref args) => {
210211
args.clone()
211212
}
@@ -277,11 +278,20 @@ impl Item {
277278
TypeKind::Named(ref name, _) => {
278279
return name.to_owned();
279280
}
280-
_ => {}
281-
}
282-
283-
ty.name().map(ToOwned::to_owned)
284-
.unwrap_or_else(|| format!("_bindgen_ty{}", self.id()))
281+
// We really codegen and use the inner type, so use an empty
282+
// base name so codegen doesn't get confused.
283+
//
284+
// We should never have this in another kind of type, so...
285+
TypeKind::TemplateAlias(..) => {
286+
Some("")
287+
}
288+
// Else use the proper name, or fallback to a name with an
289+
// id.
290+
_ => {
291+
ty.name()
292+
}
293+
}.map(ToOwned::to_owned)
294+
.unwrap_or_else(|| format!("_bindgen_ty{}", self.id()))
285295
}
286296
ItemKind::Function(ref fun) => {
287297
let mut base = fun.name().to_owned();
@@ -329,7 +339,12 @@ impl Item {
329339

330340
// TODO: allow modification of the mangling functions, maybe even per
331341
// item type?
332-
format!("{}_{}", parent.canonical_name(ctx), base_name)
342+
let parent = parent.canonical_name(ctx);
343+
if parent.is_empty() {
344+
base_name.to_owned()
345+
} else {
346+
format!("{}_{}", parent, base_name)
347+
}
333348
}
334349

335350
pub fn as_module_mut(&mut self) -> Option<&mut Module> {
@@ -444,7 +459,7 @@ impl ClangItemParser for Item {
444459
if cursor.kind() == clangll::CXCursor_UnexposedDecl {
445460
Err(ParseError::Recurse)
446461
} else {
447-
error!("Unhandled cursor kind: {}", ::clang::kind_to_str(cursor.kind()));
462+
error!("Unhandled cursor kind: {} ({})", ::clang::kind_to_str(cursor.kind()), cursor.kind());
448463
Err(ParseError::Continue)
449464
}
450465
}

src/ir/ty.rs

+59-3
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,14 @@ impl Type {
147147
type_resolver.resolve_type(t).can_derive_debug(type_resolver)
148148
}
149149
TypeKind::ResolvedTypeRef(t) |
150+
TypeKind::TemplateAlias(t, _) |
150151
TypeKind::Alias(_, t) => {
151152
type_resolver.resolve_type(t).can_derive_debug(type_resolver)
152153
}
153154
TypeKind::Comp(ref info) => {
154155
info.can_derive_debug(type_resolver, self.layout(type_resolver))
155156
}
156-
_ => true,
157+
_ => true,
157158
}
158159
}
159160

@@ -178,6 +179,7 @@ impl Type {
178179
pub fn can_derive_copy_in_array(&self, type_resolver: &TypeResolver, item: &Item) -> bool {
179180
match self.kind {
180181
TypeKind::ResolvedTypeRef(t) |
182+
TypeKind::TemplateAlias(t, _) |
181183
TypeKind::Alias(_, t) |
182184
TypeKind::Array(t, _) => {
183185
type_resolver.resolve_item(t)
@@ -195,6 +197,7 @@ impl Type {
195197
type_resolver.resolve_item(t).can_derive_copy_in_array(type_resolver)
196198
}
197199
TypeKind::ResolvedTypeRef(t) |
200+
TypeKind::TemplateAlias(t, _) |
198201
TypeKind::TemplateRef(t, _) |
199202
TypeKind::Alias(_, t) => {
200203
type_resolver.resolve_item(t).can_derive_copy(type_resolver)
@@ -210,6 +213,7 @@ impl Type {
210213
// FIXME: Can we do something about template parameters? Huh...
211214
match self.kind {
212215
TypeKind::TemplateRef(t, _) |
216+
TypeKind::TemplateAlias(t, _) |
213217
TypeKind::Alias(_, t) |
214218
TypeKind::ResolvedTypeRef(t) |
215219
TypeKind::Array(t, _) => {
@@ -226,6 +230,7 @@ impl Type {
226230
pub fn has_destructor(&self, type_resolver: &TypeResolver) -> bool {
227231
self.is_opaque(type_resolver) || match self.kind {
228232
TypeKind::TemplateRef(t, _) |
233+
TypeKind::TemplateAlias(t, _) |
229234
TypeKind::Alias(_, t) |
230235
TypeKind::ResolvedTypeRef(t) |
231236
TypeKind::Array(t, _) => {
@@ -264,7 +269,8 @@ impl Type {
264269
type_resolver.resolve_type(sig.return_type())
265270
.signature_contains_named_type(type_resolver, ty)
266271
},
267-
TypeKind::TemplateRef(_inner, ref template_args) => {
272+
TypeKind::TemplateAlias(_, ref template_args) |
273+
TypeKind::TemplateRef(_, ref template_args) => {
268274
template_args.iter().any(|arg| {
269275
type_resolver.resolve_type(*arg)
270276
.signature_contains_named_type(type_resolver, ty)
@@ -293,6 +299,7 @@ impl Type {
293299

294300
TypeKind::ResolvedTypeRef(inner) |
295301
TypeKind::Alias(_, inner) |
302+
TypeKind::TemplateAlias(inner, _) |
296303
TypeKind::TemplateRef(inner, _)
297304
=> type_resolver.resolve_type(inner).canonical_type(type_resolver),
298305

@@ -328,6 +335,9 @@ pub enum TypeKind {
328335
Float(FloatKind),
329336
/// A type alias, with a name, that points to another type.
330337
Alias(String, ItemId),
338+
/// A templated alias, pointing to an inner Alias type, with template
339+
/// parameters.
340+
TemplateAlias(ItemId, Vec<ItemId>),
331341
/// An array of a type and a lenght.
332342
Array(ItemId, usize),
333343
/// A function type, with a given signature.
@@ -372,6 +382,7 @@ impl Type {
372382
}
373383
TypeKind::ResolvedTypeRef(inner) |
374384
TypeKind::Alias(_, inner) |
385+
TypeKind::TemplateAlias(inner, _) |
375386
TypeKind::TemplateRef(inner, _)
376387
=> type_resolver.resolve_type(inner).is_unsized(type_resolver),
377388
TypeKind::Named(..) |
@@ -445,6 +456,51 @@ impl Type {
445456
.expect("C'mon");
446457
TypeKind::Comp(complex)
447458
}
459+
CXCursor_TypeAliasTemplateDecl => {
460+
debug!("TypeAliasTemplateDecl");
461+
462+
// We need to manually unwind this one.
463+
let mut inner = Err(ParseError::Continue);
464+
let mut args = vec![];
465+
466+
location.visit(|cur, _| {
467+
match cur.kind() {
468+
CXCursor_TypeAliasDecl => {
469+
debug_assert!(cur.cur_type().kind() == CXType_Typedef);
470+
inner = Item::from_ty(&cur.cur_type(),
471+
Some(*cur),
472+
Some(potential_id),
473+
ctx);
474+
}
475+
CXCursor_TemplateTypeParameter => {
476+
let default_type =
477+
Item::from_ty(&cur.cur_type(),
478+
Some(*cur),
479+
Some(potential_id),
480+
ctx).ok();
481+
let param =
482+
Item::named_type(cur.spelling(),
483+
default_type,
484+
potential_id, ctx);
485+
args.push(param);
486+
}
487+
_ => {}
488+
}
489+
CXChildVisit_Continue
490+
});
491+
492+
if inner.is_err() {
493+
error!("Failed to parse templated type alias {:?}", location);
494+
return Err(ParseError::Continue);
495+
}
496+
497+
if args.is_empty() {
498+
error!("Failed to get any template parameter, maybe a specialization? {:?}", location);
499+
return Err(ParseError::Continue);
500+
}
501+
502+
TypeKind::TemplateAlias(inner.unwrap(), args)
503+
}
448504
CXCursor_TemplateRef => {
449505
let referenced = location.referenced();
450506
return Self::from_clang_ty(potential_id,
@@ -522,7 +578,7 @@ impl Type {
522578
let signature = try!(FunctionSig::from_ty(ty, &location.unwrap_or(cursor), ctx));
523579
TypeKind::Function(signature)
524580
}
525-
CXType_Typedef => {
581+
CXType_Typedef => {
526582
let inner = cursor.typedef_type();
527583
let inner =
528584
Item::from_ty_or_ref(inner, location, parent_id, ctx);

0 commit comments

Comments
 (0)