@@ -122,20 +122,37 @@ impl Cursor {
122
122
}
123
123
124
124
/// Return the number of template arguments used by this cursor's referent,
125
- /// if the referent is either a template specialization or
126
- /// declaration. Returns -1 otherwise.
125
+ /// if the referent is either a template specialization or declaration.
126
+ /// Returns `None` otherwise.
127
127
///
128
128
/// NOTE: This may not return `Some` for some non-fully specialized
129
129
/// templates, see #193 and #194.
130
130
pub fn num_template_args ( & self ) -> Option < u32 > {
131
- let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments ( self . x ) } ;
131
+ // XXX: `clang_Type_getNumTemplateArguments` is sort of reliable, while
132
+ // `clang_Cursor_getNumTemplateArguments` is totally unreliable.
133
+ // Therefore, try former first, and only fallback to the latter if we
134
+ // have to.
135
+ self . cur_type ( ) . num_template_args ( )
136
+ . or_else ( || {
137
+ let n: c_int = unsafe {
138
+ clang_Cursor_getNumTemplateArguments ( self . x )
139
+ } ;
132
140
133
- if n >= 0 {
134
- Some ( n as u32 )
135
- } else {
136
- debug_assert_eq ! ( n, -1 ) ;
137
- None
138
- }
141
+ if n >= 0 {
142
+ Some ( n as u32 )
143
+ } else {
144
+ debug_assert_eq ! ( n, -1 ) ;
145
+ None
146
+ }
147
+ } )
148
+ . or_else ( || {
149
+ let canonical = self . canonical ( ) ;
150
+ if canonical != * self {
151
+ canonical. num_template_args ( )
152
+ } else {
153
+ None
154
+ }
155
+ } )
139
156
}
140
157
141
158
/// Get a cursor pointing to this referent's containing translation unit.
@@ -672,22 +689,28 @@ impl Type {
672
689
Ok ( Layout :: new ( size, align) )
673
690
}
674
691
675
- /// If this type is a class template specialization, return its
676
- /// template arguments. Otherwise, return None .
677
- pub fn template_args ( & self ) -> Option < TypeTemplateArgIterator > {
692
+ /// Get the number of template arguments this type has, or `None` if it is
693
+ /// not some kind of template .
694
+ pub fn num_template_args ( & self ) -> Option < u32 > {
678
695
let n = unsafe { clang_Type_getNumTemplateArguments ( self . x ) } ;
679
696
if n >= 0 {
680
- Some ( TypeTemplateArgIterator {
681
- x : self . x ,
682
- length : n as u32 ,
683
- index : 0 ,
684
- } )
697
+ Some ( n as u32 )
685
698
} else {
686
699
debug_assert_eq ! ( n, -1 ) ;
687
700
None
688
701
}
689
702
}
690
703
704
+ /// If this type is a class template specialization, return its
705
+ /// template arguments. Otherwise, return None.
706
+ pub fn template_args ( & self ) -> Option < TypeTemplateArgIterator > {
707
+ self . num_template_args ( ) . map ( |n| TypeTemplateArgIterator {
708
+ x : self . x ,
709
+ length : n,
710
+ index : 0 ,
711
+ } )
712
+ }
713
+
691
714
/// Given that this type is a pointer type, return the type that it points
692
715
/// to.
693
716
pub fn pointee_type ( & self ) -> Option < Type > {
0 commit comments