diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-11-01 05:52:55 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-01 05:52:55 -0500 |
commit | 54d87d37f3eb2f1a19fc53b8c92558417a27d47e (patch) | |
tree | 5d863c10a5eeb029316e6d426f12a2df94e616a1 | |
parent | daa9ab77c2ade0967a53d76903ee647bfc3d86a0 (diff) | |
parent | c8c2bdb65e4b71b710c4aee634aaca0036eccdb2 (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-x | src/clang.rs | 44 | ||||
-rw-r--r-- | src/ir/comp.rs | 28 | ||||
-rw-r--r-- | src/ir/ty.rs | 2 |
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) |