summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-11-01 05:52:55 -0500
committerGitHub <noreply@github.com>2016-11-01 05:52:55 -0500
commit54d87d37f3eb2f1a19fc53b8c92558417a27d47e (patch)
tree5d863c10a5eeb029316e6d426f12a2df94e616a1
parentdaa9ab77c2ade0967a53d76903ee647bfc3d86a0 (diff)
parentc8c2bdb65e4b71b710c4aee634aaca0036eccdb2 (diff)
Auto merge of #175 - jeanphilippeD:issue136, r=fitzgen,emilio
clang::Type::template_args return Option<TypeTemplateArgIterator> Fix #136 by providing a bound checked iterator replacing the interface.
-rwxr-xr-xsrc/clang.rs44
-rw-r--r--src/ir/comp.rs28
-rw-r--r--src/ir/ty.rs2
3 files changed, 48 insertions, 26 deletions
diff --git a/src/clang.rs b/src/clang.rs
index f9b3e083..07680367 100755
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -644,25 +644,22 @@ impl Type {
Ok(Layout::new(size, align))
}
- /// If this type is a class template specialization, return its number of
+ /// If this type is a class template specialization, return its
/// template arguments. Otherwise, return None.
- pub fn num_template_args(&self) -> Option<u32> {
+ pub fn template_args(&self) -> Option<TypeTemplateArgIterator> {
let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
if n >= 0 {
- Some(n as u32)
+ Some(TypeTemplateArgIterator {
+ x: self.x,
+ length: n as u32,
+ index: 0
+ })
} else {
debug_assert_eq!(n, -1);
None
}
}
- /// Get the type of the `i`th template argument for this template
- /// specialization.
- pub fn template_arg_type(&self, i: u32) -> Type {
- let n = i as c_int;
- Type { x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, n) } }
- }
-
/// Given that this type is a pointer type, return the type that it points
/// to.
pub fn pointee_type(&self) -> Type {
@@ -750,6 +747,33 @@ impl Type {
}
}
+/// An iterator for a type's template arguments.
+pub struct TypeTemplateArgIterator {
+ x: CXType,
+ length: u32,
+ index: u32
+}
+
+impl Iterator for TypeTemplateArgIterator {
+ type Item = Type;
+ fn next(&mut self) -> Option<Type> {
+ if self.index < self.length {
+ let idx = self.index as c_int;
+ self.index += 1;
+ Some(Type { x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) } })
+ } else {
+ None
+ }
+ }
+}
+
+impl ExactSizeIterator for TypeTemplateArgIterator {
+ fn len(&self) -> usize {
+ assert!(self.index <= self.length);
+ (self.length - self.index) as usize
+ }
+}
+
/// A `SourceLocation` is a file, line, column, and byte offset location for
/// some source text.
pub struct SourceLocation {
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index 13eaa6db..98003936 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -490,26 +490,24 @@ impl CompInfo {
let mut ci = CompInfo::new(kind);
ci.is_anonymous = cursor.is_anonymous();
- ci.template_args = match ty.num_template_args() {
+ ci.template_args = match ty.template_args() {
// In forward declarations and not specializations, etc, they are in
// the ast, we'll meet them in CXCursor_TemplateTypeParameter
None => vec![],
- Some(len) => {
- let mut list = Vec::with_capacity(len as usize);
- for i in 0..len {
- let arg_type = ty.template_arg_type(i);
- if arg_type.kind() != CXType_Invalid {
- let type_id =
- Item::from_ty_or_ref(arg_type, None, None, ctx);
-
- list.push(type_id);
- } else {
- ci.has_non_type_template_params = true;
- warn!("warning: Template parameter is not a type");
- }
+ Some(arg_types) => {
+ let num_arg_types = arg_types.len();
+
+ let args = arg_types
+ .filter(|t| t.kind() != CXType_Invalid)
+ .map(|t| Item::from_ty_or_ref(t, None, None, ctx))
+ .collect::<Vec<_>>();
+
+ if args.len() != num_arg_types {
+ ci.has_non_type_template_params = true;
+ warn!("warning: Template parameter is not a type");
}
- list
+ args
}
};
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index 59f12eb8..a914ce14 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -507,7 +507,7 @@ impl Type {
TypeKind::Function(signature)
// Same here, with template specialisations we can safely assume
// this is a Comp(..)
- } else if ty.num_template_args().unwrap_or(0) > 0 {
+ } else if ty.template_args().map_or(false, |x| x.len() > 0) {
debug!("Template specialization: {:?}", ty);
let complex =
CompInfo::from_ty(potential_id, ty, location, ctx)