Skip to content

Commit 54d87d3

Browse files
author
bors-servo
authored
Auto merge of rust-lang#175 - jeanphilippeD:issue136, r=fitzgen,emilio
clang::Type::template_args return Option<TypeTemplateArgIterator> Fix rust-lang#136 by providing a bound checked iterator replacing the interface.
2 parents daa9ab7 + c8c2bdb commit 54d87d3

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,22 @@ 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> {
650650
let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
651651
if n >= 0 {
652-
Some(n as u32)
652+
Some(TypeTemplateArgIterator {
653+
x: self.x,
654+
length: n as u32,
655+
index: 0
656+
})
653657
} else {
654658
debug_assert_eq!(n, -1);
655659
None
656660
}
657661
}
658662

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-
666663
/// Given that this type is a pointer type, return the type that it points
667664
/// to.
668665
pub fn pointee_type(&self) -> Type {
@@ -750,6 +747,33 @@ impl Type {
750747
}
751748
}
752749

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

src/ir/comp.rs

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

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

512-
list
510+
args
513511
}
514512
};
515513

src/ir/ty.rs

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

0 commit comments

Comments
 (0)