summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-02-03 13:55:54 -0800
committerGitHub <noreply@github.com>2017-02-03 13:55:54 -0800
commit9c8b593bfe336fca3d9edb996ca26c0297f33267 (patch)
treeececd37fb551372dd9c64abe1d5909175e96ad6c
parentf4b1309d29719269e39eab22185bfe8953ac0b64 (diff)
parent2723539b0115edf323b9c1222af2281d7b286598 (diff)
Auto merge of #472 - fitzgen:cursor-num-template-args, r=emilio
Make Cursor::num_template_args slightly more reliable This improves the situation slightly, but even `clang_Type_getNumTemplateArgs` doesn't work for most templates... r? @emilio
-rw-r--r--src/clang.rs57
1 files changed, 40 insertions, 17 deletions
diff --git a/src/clang.rs b/src/clang.rs
index 63ee06e0..7e6c357b 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -122,20 +122,37 @@ impl Cursor {
}
/// Return the number of template arguments used by this cursor's referent,
- /// if the referent is either a template specialization or
- /// declaration. Returns -1 otherwise.
+ /// if the referent is either a template specialization or declaration.
+ /// Returns `None` otherwise.
///
/// NOTE: This may not return `Some` for some non-fully specialized
/// templates, see #193 and #194.
pub fn num_template_args(&self) -> Option<u32> {
- let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) };
+ // XXX: `clang_Type_getNumTemplateArguments` is sort of reliable, while
+ // `clang_Cursor_getNumTemplateArguments` is totally unreliable.
+ // Therefore, try former first, and only fallback to the latter if we
+ // have to.
+ self.cur_type().num_template_args()
+ .or_else(|| {
+ let n: c_int = unsafe {
+ clang_Cursor_getNumTemplateArguments(self.x)
+ };
- if n >= 0 {
- Some(n as u32)
- } else {
- debug_assert_eq!(n, -1);
- None
- }
+ if n >= 0 {
+ Some(n as u32)
+ } else {
+ debug_assert_eq!(n, -1);
+ None
+ }
+ })
+ .or_else(|| {
+ let canonical = self.canonical();
+ if canonical != *self {
+ canonical.num_template_args()
+ } else {
+ None
+ }
+ })
}
/// Get a cursor pointing to this referent's containing translation unit.
@@ -672,22 +689,28 @@ impl Type {
Ok(Layout::new(size, align))
}
- /// If this type is a class template specialization, return its
- /// template arguments. Otherwise, return None.
- pub fn template_args(&self) -> Option<TypeTemplateArgIterator> {
+ /// Get the number of template arguments this type has, or `None` if it is
+ /// not some kind of template.
+ pub fn num_template_args(&self) -> Option<u32> {
let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
if n >= 0 {
- Some(TypeTemplateArgIterator {
- x: self.x,
- length: n as u32,
- index: 0,
- })
+ Some(n as u32)
} else {
debug_assert_eq!(n, -1);
None
}
}
+ /// If this type is a class template specialization, return its
+ /// template arguments. Otherwise, return None.
+ pub fn template_args(&self) -> Option<TypeTemplateArgIterator> {
+ self.num_template_args().map(|n| TypeTemplateArgIterator {
+ x: self.x,
+ length: n,
+ index: 0,
+ })
+ }
+
/// Given that this type is a pointer type, return the type that it points
/// to.
pub fn pointee_type(&self) -> Option<Type> {