Skip to content

Commit f6a2003

Browse files
committed
clang::Type::template_args return Option<TypeTemplateArgIterator>
1 parent 724aa06 commit f6a2003

File tree

3 files changed

+48
-26
lines changed

3 files changed

+48
-26
lines changed

src/clang.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -644,25 +644,19 @@ impl Type {
644644
Ok(Layout::new(size, align))
645645
}
646646

647-
/// If this type is a class template specialization, return its number of
647+
/// If this type is a class template specialization, return its
648648
/// template arguments. Otherwise, return None.
649-
pub fn num_template_args(&self) -> Option<u32> {
649+
pub fn template_args(&self) -> Option<TypeTemplateArgIterator>
650+
{
650651
let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
651652
if n >= 0 {
652-
Some(n as u32)
653+
Some(TypeTemplateArgIterator { x: self.x, length: n as u32, index: 0 })
653654
} else {
654655
debug_assert_eq!(n, -1);
655656
None
656657
}
657658
}
658659

659-
/// Get the type of the `i`th template argument for this template
660-
/// specialization.
661-
pub fn template_arg_type(&self, i: u32) -> Type {
662-
let n = i as c_int;
663-
Type { x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, n) } }
664-
}
665-
666660
/// Given that this type is a pointer type, return the type that it points
667661
/// to.
668662
pub fn pointee_type(&self) -> Type {
@@ -747,6 +741,36 @@ impl Type {
747741
}
748742
}
749743

744+
/// An iterator for a type's template arguments
745+
pub struct TypeTemplateArgIterator {
746+
x: CXType,
747+
length: u32,
748+
index: u32
749+
}
750+
751+
impl Iterator for TypeTemplateArgIterator {
752+
type Item = Type;
753+
fn next(&mut self) -> Option<Type> {
754+
if self.index < self.length {
755+
let idx = self.index as c_int;
756+
self.index += 1;
757+
Some(Type { x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) } })
758+
} else {
759+
None
760+
}
761+
}
762+
}
763+
764+
impl ExactSizeIterator for TypeTemplateArgIterator {
765+
fn len(&self) -> usize {
766+
if self.index < self.length {
767+
(self.length - self.index) as usize
768+
} else {
769+
0
770+
}
771+
}
772+
}
773+
750774
/// A `SourceLocation` is a file, line, column, and byte offset location for
751775
/// some source text.
752776
pub struct SourceLocation {

src/ir/comp.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -489,26 +489,24 @@ impl CompInfo {
489489

490490
let mut ci = CompInfo::new(kind);
491491
ci.is_anonymous = cursor.is_anonymous();
492-
ci.template_args = match ty.num_template_args() {
492+
ci.template_args = match ty.template_args() {
493493
// In forward declarations and not specializations, etc, they are in
494494
// the ast, we'll meet them in CXCursor_TemplateTypeParameter
495495
None => vec![],
496-
Some(len) => {
497-
let mut list = Vec::with_capacity(len as usize);
498-
for i in 0..len {
499-
let arg_type = ty.template_arg_type(i);
500-
if arg_type.kind() != CXType_Invalid {
501-
let type_id =
502-
Item::from_ty_or_ref(arg_type, None, None, ctx);
503-
504-
list.push(type_id);
505-
} else {
506-
ci.has_non_type_template_params = true;
507-
warn!("warning: Template parameter is not a type");
508-
}
496+
Some(arg_types) => {
497+
let num_arg_types = arg_types.len();
498+
499+
let args = arg_types
500+
.filter(|t| t.kind() != CXType_Invalid)
501+
.map(|t| Item::from_ty_or_ref(t, None, None, ctx))
502+
.collect::<Vec<_>>();
503+
504+
if args.len() != num_arg_types {
505+
ci.has_non_type_template_params = true;
506+
warn!("warning: Template parameter is not a type");
509507
}
510508

511-
list
509+
args
512510
}
513511
};
514512

src/ir/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ impl Type {
506506
TypeKind::Function(signature)
507507
// Same here, with template specialisations we can safely assume
508508
// this is a Comp(..)
509-
} else if ty.num_template_args().unwrap_or(0) > 0 {
509+
} else if ty.template_args().map_or(false, |x| x.len() > 0) {
510510
debug!("Template specialization: {:?}", ty);
511511
let complex =
512512
CompInfo::from_ty(potential_id, ty, location, ctx)

0 commit comments

Comments
 (0)