1 //! A higher level Clang API built on top of the generated bindings in the
2 //! `clang_sys` module.
3
4 #![allow(non_upper_case_globals, dead_code)]
5
6
7 use cexpr;
8 use clang_sys::*;
9 use regex;
10 use ir::context::BindgenContext;
11 use std::{mem, ptr, slice};
12 use std::ffi::{CStr, CString};
13 use std::fmt;
14 use std::hash::Hash;
15 use std::hash::Hasher;
16 use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_longlong, c_ulonglong};
17
18 /// A cursor into the Clang AST, pointing to an AST node.
19 ///
20 /// We call the AST node pointed to by the cursor the cursor's "referent".
21 #[derive(Copy, Clone)]
22 pub struct Cursor {
23 x: CXCursor,
24 }
25
26 impl fmt::Debug for Cursor {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result27 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
28 write!(
29 fmt,
30 "Cursor({} kind: {}, loc: {}, usr: {:?})",
31 self.spelling(),
32 kind_to_str(self.kind()),
33 self.location(),
34 self.usr()
35 )
36 }
37 }
38
39 impl Cursor {
40 /// Get the Unified Symbol Resolution for this cursor's referent, if
41 /// available.
42 ///
43 /// The USR can be used to compare entities across translation units.
usr(&self) -> Option<String>44 pub fn usr(&self) -> Option<String> {
45 let s = unsafe { cxstring_into_string(clang_getCursorUSR(self.x)) };
46 if s.is_empty() { None } else { Some(s) }
47 }
48
49 /// Is this cursor's referent a declaration?
is_declaration(&self) -> bool50 pub fn is_declaration(&self) -> bool {
51 unsafe { clang_isDeclaration(self.kind()) != 0 }
52 }
53
54 /// Get this cursor's referent's spelling.
spelling(&self) -> String55 pub fn spelling(&self) -> String {
56 unsafe { cxstring_into_string(clang_getCursorSpelling(self.x)) }
57 }
58
59 /// Get this cursor's referent's display name.
60 ///
61 /// This is not necessarily a valid identifier. It includes extra
62 /// information, such as parameters for a function, etc.
display_name(&self) -> String63 pub fn display_name(&self) -> String {
64 unsafe { cxstring_into_string(clang_getCursorDisplayName(self.x)) }
65 }
66
67 /// Get the mangled name of this cursor's referent.
mangling(&self) -> String68 pub fn mangling(&self) -> String {
69 if clang_Cursor_getMangling::is_loaded() {
70 unsafe { cxstring_into_string(clang_Cursor_getMangling(self.x)) }
71 } else {
72 self.spelling()
73 }
74 }
75
76 /// Gets the C++ manglings for this cursor, or an error if the function is
77 /// not loaded or the manglings are not available.
cxx_manglings(&self) -> Result<Vec<String>, ()>78 pub fn cxx_manglings(&self) -> Result<Vec<String>, ()> {
79 use clang_sys::*;
80 if !clang_Cursor_getCXXManglings::is_loaded() {
81 return Err(());
82 }
83 unsafe {
84 let manglings = clang_Cursor_getCXXManglings(self.x);
85 if manglings.is_null() {
86 return Err(());
87 }
88 let count = (*manglings).Count as usize;
89
90 let mut result = Vec::with_capacity(count);
91 for i in 0..count {
92 let string_ptr = (*manglings).Strings.offset(i as isize);
93 result.push(cxstring_to_string_leaky(*string_ptr));
94 }
95 clang_disposeStringSet(manglings);
96 Ok(result)
97 }
98 }
99
100 /// Returns whether the cursor refers to a built-in definition.
is_builtin(&self) -> bool101 pub fn is_builtin(&self) -> bool {
102 let (file, _, _, _) = self.location().location();
103 file.name().is_none()
104 }
105
106 /// Get the `Cursor` for this cursor's referent's lexical parent.
107 ///
108 /// The lexical parent is the parent of the definition. The semantic parent
109 /// is the parent of the declaration. Generally, the lexical parent doesn't
110 /// have any effect on semantics, while the semantic parent does.
111 ///
112 /// In the following snippet, the `Foo` class would be the semantic parent
113 /// of the out-of-line `method` definition, while the lexical parent is the
114 /// translation unit.
115 ///
116 /// ```c++
117 /// class Foo {
118 /// void method();
119 /// };
120 ///
121 /// void Foo::method() { /* ... */ }
122 /// ```
lexical_parent(&self) -> Cursor123 pub fn lexical_parent(&self) -> Cursor {
124 unsafe {
125 Cursor {
126 x: clang_getCursorLexicalParent(self.x),
127 }
128 }
129 }
130
131 /// Get the referent's semantic parent, if one is available.
132 ///
133 /// See documentation for `lexical_parent` for details on semantic vs
134 /// lexical parents.
fallible_semantic_parent(&self) -> Option<Cursor>135 pub fn fallible_semantic_parent(&self) -> Option<Cursor> {
136 let sp = unsafe {
137 Cursor {
138 x: clang_getCursorSemanticParent(self.x),
139 }
140 };
141 if sp == *self || !sp.is_valid() {
142 return None;
143 }
144 Some(sp)
145 }
146
147 /// Get the referent's semantic parent.
148 ///
149 /// See documentation for `lexical_parent` for details on semantic vs
150 /// lexical parents.
semantic_parent(&self) -> Cursor151 pub fn semantic_parent(&self) -> Cursor {
152 self.fallible_semantic_parent().unwrap()
153 }
154
155 /// Return the number of template arguments used by this cursor's referent,
156 /// if the referent is either a template instantiation. Returns `None`
157 /// otherwise.
158 ///
159 /// NOTE: This may not return `Some` for partial template specializations,
160 /// see #193 and #194.
num_template_args(&self) -> Option<u32>161 pub fn num_template_args(&self) -> Option<u32> {
162 // XXX: `clang_Type_getNumTemplateArguments` is sort of reliable, while
163 // `clang_Cursor_getNumTemplateArguments` is totally unreliable.
164 // Therefore, try former first, and only fallback to the latter if we
165 // have to.
166 self.cur_type()
167 .num_template_args()
168 .or_else(|| {
169 let n: c_int =
170 unsafe { clang_Cursor_getNumTemplateArguments(self.x) };
171
172 if n >= 0 {
173 Some(n as u32)
174 } else {
175 debug_assert_eq!(n, -1);
176 None
177 }
178 })
179 .or_else(|| {
180 let canonical = self.canonical();
181 if canonical != *self {
182 canonical.num_template_args()
183 } else {
184 None
185 }
186 })
187 }
188
189 /// Get a cursor pointing to this referent's containing translation unit.
190 ///
191 /// Note that we shouldn't create a `TranslationUnit` struct here, because
192 /// bindgen assumes there will only be one of them alive at a time, and
193 /// disposes it on drop. That can change if this would be required, but I
194 /// think we can survive fine without it.
translation_unit(&self) -> Cursor195 pub fn translation_unit(&self) -> Cursor {
196 assert!(self.is_valid());
197 unsafe {
198 let tu = clang_Cursor_getTranslationUnit(self.x);
199 let cursor = Cursor {
200 x: clang_getTranslationUnitCursor(tu),
201 };
202 assert!(cursor.is_valid());
203 cursor
204 }
205 }
206
207 /// Is the referent a top level construct?
is_toplevel(&self) -> bool208 pub fn is_toplevel(&self) -> bool {
209 let mut semantic_parent = self.fallible_semantic_parent();
210
211 while semantic_parent.is_some() &&
212 (semantic_parent.unwrap().kind() == CXCursor_Namespace ||
213 semantic_parent.unwrap().kind() == CXCursor_NamespaceAlias ||
214 semantic_parent.unwrap().kind() == CXCursor_NamespaceRef)
215 {
216 semantic_parent =
217 semantic_parent.unwrap().fallible_semantic_parent();
218 }
219
220 let tu = self.translation_unit();
221 // Yes, this can happen with, e.g., macro definitions.
222 semantic_parent == tu.fallible_semantic_parent()
223 }
224
225 /// There are a few kinds of types that we need to treat specially, mainly
226 /// not tracking the type declaration but the location of the cursor, given
227 /// clang doesn't expose a proper declaration for these types.
is_template_like(&self) -> bool228 pub fn is_template_like(&self) -> bool {
229 match self.kind() {
230 CXCursor_ClassTemplate |
231 CXCursor_ClassTemplatePartialSpecialization |
232 CXCursor_TypeAliasTemplateDecl => true,
233 _ => false,
234 }
235 }
236
237 /// Get the kind of referent this cursor is pointing to.
kind(&self) -> CXCursorKind238 pub fn kind(&self) -> CXCursorKind {
239 self.x.kind
240 }
241
242 /// Returns true is the cursor is a definition
is_definition(&self) -> bool243 pub fn is_definition(&self) -> bool {
244 unsafe { clang_isCursorDefinition(self.x) != 0 }
245 }
246
247 /// Is the referent a template specialization?
is_template_specialization(&self) -> bool248 pub fn is_template_specialization(&self) -> bool {
249 self.specialized().is_some()
250 }
251
252 /// Is the referent a fully specialized template specialization without any
253 /// remaining free template arguments?
is_fully_specialized_template(&self) -> bool254 pub fn is_fully_specialized_template(&self) -> bool {
255 self.is_template_specialization() &&
256 self.kind() != CXCursor_ClassTemplatePartialSpecialization &&
257 self.num_template_args().unwrap_or(0) > 0
258 }
259
260 /// Is the referent a template specialization that still has remaining free
261 /// template arguments?
is_in_non_fully_specialized_template(&self) -> bool262 pub fn is_in_non_fully_specialized_template(&self) -> bool {
263 if self.is_toplevel() {
264 return false;
265 }
266
267 let parent = self.semantic_parent();
268 if parent.is_fully_specialized_template() {
269 return false;
270 }
271
272 if !parent.is_template_like() {
273 return parent.is_in_non_fully_specialized_template();
274 }
275
276 return true;
277 }
278
279 /// Is this cursor pointing a valid referent?
is_valid(&self) -> bool280 pub fn is_valid(&self) -> bool {
281 unsafe { clang_isInvalid(self.kind()) == 0 }
282 }
283
284 /// Get the source location for the referent.
location(&self) -> SourceLocation285 pub fn location(&self) -> SourceLocation {
286 unsafe {
287 SourceLocation {
288 x: clang_getCursorLocation(self.x),
289 }
290 }
291 }
292
293 /// Get the source location range for the referent.
extent(&self) -> CXSourceRange294 pub fn extent(&self) -> CXSourceRange {
295 unsafe { clang_getCursorExtent(self.x) }
296 }
297
298 /// Get the raw declaration comment for this referent, if one exists.
raw_comment(&self) -> Option<String>299 pub fn raw_comment(&self) -> Option<String> {
300 let s = unsafe {
301 cxstring_into_string(clang_Cursor_getRawCommentText(self.x))
302 };
303 if s.is_empty() { None } else { Some(s) }
304 }
305
306 /// Get the referent's parsed comment.
comment(&self) -> Comment307 pub fn comment(&self) -> Comment {
308 unsafe {
309 Comment {
310 x: clang_Cursor_getParsedComment(self.x),
311 }
312 }
313 }
314
315 /// Get the referent's type.
cur_type(&self) -> Type316 pub fn cur_type(&self) -> Type {
317 unsafe {
318 Type {
319 x: clang_getCursorType(self.x),
320 }
321 }
322 }
323
324 /// Given that this cursor's referent is a reference to another type, or is
325 /// a declaration, get the cursor pointing to the referenced type or type of
326 /// the declared thing.
definition(&self) -> Option<Cursor>327 pub fn definition(&self) -> Option<Cursor> {
328 unsafe {
329 let ret = Cursor {
330 x: clang_getCursorDefinition(self.x),
331 };
332
333 if ret.is_valid() && ret.kind() != CXCursor_NoDeclFound {
334 Some(ret)
335 } else {
336 None
337 }
338 }
339 }
340
341 /// Given that this cursor's referent is reference type, get the cursor
342 /// pointing to the referenced type.
referenced(&self) -> Option<Cursor>343 pub fn referenced(&self) -> Option<Cursor> {
344 unsafe {
345 let ret = Cursor {
346 x: clang_getCursorReferenced(self.x),
347 };
348
349 if ret.is_valid() { Some(ret) } else { None }
350 }
351 }
352
353 /// Get the canonical cursor for this referent.
354 ///
355 /// Many types can be declared multiple times before finally being properly
356 /// defined. This method allows us to get the canonical cursor for the
357 /// referent type.
canonical(&self) -> Cursor358 pub fn canonical(&self) -> Cursor {
359 unsafe {
360 Cursor {
361 x: clang_getCanonicalCursor(self.x),
362 }
363 }
364 }
365
366 /// Given that this cursor points to either a template specialization or a
367 /// template instantiation, get a cursor pointing to the template definition
368 /// that is being specialized.
specialized(&self) -> Option<Cursor>369 pub fn specialized(&self) -> Option<Cursor> {
370 unsafe {
371 let ret = Cursor {
372 x: clang_getSpecializedCursorTemplate(self.x),
373 };
374 if ret.is_valid() { Some(ret) } else { None }
375 }
376 }
377
378 /// Assuming that this cursor's referent is a template declaration, get the
379 /// kind of cursor that would be generated for its specializations.
template_kind(&self) -> CXCursorKind380 pub fn template_kind(&self) -> CXCursorKind {
381 unsafe { clang_getTemplateCursorKind(self.x) }
382 }
383
384 /// Traverse this cursor's referent and its children.
385 ///
386 /// Call the given function on each AST node traversed.
visit<Visitor>(&self, mut visitor: Visitor) where Visitor: FnMut(Cursor) -> CXChildVisitResult,387 pub fn visit<Visitor>(&self, mut visitor: Visitor)
388 where
389 Visitor: FnMut(Cursor) -> CXChildVisitResult,
390 {
391 unsafe {
392 clang_visitChildren(
393 self.x,
394 visit_children::<Visitor>,
395 mem::transmute(&mut visitor),
396 );
397 }
398 }
399
400 /// Collect all of this cursor's children into a vec and return them.
collect_children(&self) -> Vec<Cursor>401 pub fn collect_children(&self) -> Vec<Cursor> {
402 let mut children = vec![];
403 self.visit(|c| {
404 children.push(c);
405 CXChildVisit_Continue
406 });
407 children
408 }
409
410 /// Does this cursor have any children?
has_children(&self) -> bool411 pub fn has_children(&self) -> bool {
412 let mut has_children = false;
413 self.visit(|_| {
414 has_children = true;
415 CXChildVisit_Break
416 });
417 has_children
418 }
419
420 /// Does this cursor have at least `n` children?
has_at_least_num_children(&self, n: usize) -> bool421 pub fn has_at_least_num_children(&self, n: usize) -> bool {
422 assert!(n > 0);
423 let mut num_left = n;
424 self.visit(|_| {
425 num_left -= 1;
426 if num_left == 0 {
427 CXChildVisit_Break
428 } else {
429 CXChildVisit_Continue
430 }
431 });
432 num_left == 0
433 }
434
435 /// Returns whether the given location contains a cursor with the given
436 /// kind in the first level of nesting underneath (doesn't look
437 /// recursively).
contains_cursor(&self, kind: CXCursorKind) -> bool438 pub fn contains_cursor(&self, kind: CXCursorKind) -> bool {
439 let mut found = false;
440
441 self.visit(|c| if c.kind() == kind {
442 found = true;
443 CXChildVisit_Break
444 } else {
445 CXChildVisit_Continue
446 });
447
448 found
449 }
450
451 /// Is the referent an inlined function?
is_inlined_function(&self) -> bool452 pub fn is_inlined_function(&self) -> bool {
453 clang_Cursor_isFunctionInlined::is_loaded() &&
454 unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 }
455 }
456
457 /// Get the width of this cursor's referent bit field, or `None` if the
458 /// referent is not a bit field.
bit_width(&self) -> Option<u32>459 pub fn bit_width(&self) -> Option<u32> {
460 unsafe {
461 let w = clang_getFieldDeclBitWidth(self.x);
462 if w == -1 { None } else { Some(w as u32) }
463 }
464 }
465
466 /// Get the integer representation type used to hold this cursor's referent
467 /// enum type.
enum_type(&self) -> Option<Type>468 pub fn enum_type(&self) -> Option<Type> {
469 unsafe {
470 let t = Type {
471 x: clang_getEnumDeclIntegerType(self.x),
472 };
473 if t.is_valid() { Some(t) } else { None }
474 }
475 }
476
477 /// Get the signed constant value for this cursor's enum variant referent.
478 ///
479 /// Returns None if the cursor's referent is not an enum variant.
enum_val_signed(&self) -> Option<i64>480 pub fn enum_val_signed(&self) -> Option<i64> {
481 unsafe {
482 if self.kind() == CXCursor_EnumConstantDecl {
483 Some(clang_getEnumConstantDeclValue(self.x) as i64)
484 } else {
485 None
486 }
487 }
488 }
489
490 /// Get the unsigned constant value for this cursor's enum variant referent.
491 ///
492 /// Returns None if the cursor's referent is not an enum variant.
enum_val_unsigned(&self) -> Option<u64>493 pub fn enum_val_unsigned(&self) -> Option<u64> {
494 unsafe {
495 if self.kind() == CXCursor_EnumConstantDecl {
496 Some(clang_getEnumConstantDeclUnsignedValue(self.x) as u64)
497 } else {
498 None
499 }
500 }
501 }
502
503 /// Does this cursor have the given simple attribute?
504 ///
505 /// Note that this will only work for attributes that don't have an existing libclang
506 /// CursorKind, e.g. pure, const, etc.
has_simple_attr(&self, attr: &str) -> bool507 pub fn has_simple_attr(&self, attr: &str) -> bool {
508 let mut found_attr = false;
509 self.visit(|cur| {
510 if cur.kind() == CXCursor_UnexposedAttr {
511 found_attr = cur.tokens().iter().any(|t| {
512 t.kind == CXToken_Identifier && t.spelling() == attr.as_bytes()
513 });
514
515 if found_attr {
516 return CXChildVisit_Break;
517 }
518 }
519
520 CXChildVisit_Continue
521 });
522
523 found_attr
524 }
525
526 /// Given that this cursor's referent is a `typedef`, get the `Type` that is
527 /// being aliased.
typedef_type(&self) -> Option<Type>528 pub fn typedef_type(&self) -> Option<Type> {
529 let inner = Type {
530 x: unsafe { clang_getTypedefDeclUnderlyingType(self.x) },
531 };
532
533 if inner.is_valid() { Some(inner) } else { None }
534 }
535
536 /// Get the linkage kind for this cursor's referent.
537 ///
538 /// This only applies to functions and variables.
linkage(&self) -> CXLinkageKind539 pub fn linkage(&self) -> CXLinkageKind {
540 unsafe { clang_getCursorLinkage(self.x) }
541 }
542
543 /// Get the visibility of this cursor's referent.
visibility(&self) -> CXVisibilityKind544 pub fn visibility(&self) -> CXVisibilityKind {
545 if clang_getCursorVisibility::is_loaded() {
546 unsafe { clang_getCursorVisibility(self.x) }
547 } else {
548 CXVisibility_Default
549 }
550 }
551
552 /// Given that this cursor's referent is a function, return cursors to its
553 /// parameters.
554 ///
555 /// Returns None if the cursor's referent is not a function/method call or
556 /// declaration.
args(&self) -> Option<Vec<Cursor>>557 pub fn args(&self) -> Option<Vec<Cursor>> {
558 // match self.kind() {
559 // CXCursor_FunctionDecl |
560 // CXCursor_CXXMethod => {
561 self.num_args().ok().map(|num| {
562 (0..num).map(|i| {
563 Cursor {
564 x: unsafe { clang_Cursor_getArgument(self.x, i as c_uint) },
565 }
566 })
567 .collect()
568 })
569 }
570
571 /// Given that this cursor's referent is a function/method call or
572 /// declaration, return the number of arguments it takes.
573 ///
574 /// Returns Err if the cursor's referent is not a function/method call or
575 /// declaration.
num_args(&self) -> Result<u32, ()>576 pub fn num_args(&self) -> Result<u32, ()> {
577 unsafe {
578 let w = clang_Cursor_getNumArguments(self.x);
579 if w == -1 { Err(()) } else { Ok(w as u32) }
580 }
581 }
582
583 /// Get the access specifier for this cursor's referent.
access_specifier(&self) -> CX_CXXAccessSpecifier584 pub fn access_specifier(&self) -> CX_CXXAccessSpecifier {
585 unsafe { clang_getCXXAccessSpecifier(self.x) }
586 }
587
588 /// Is this cursor's referent a field declaration that is marked as
589 /// `mutable`?
is_mutable_field(&self) -> bool590 pub fn is_mutable_field(&self) -> bool {
591 clang_CXXField_isMutable::is_loaded() &&
592 unsafe { clang_CXXField_isMutable(self.x) != 0 }
593 }
594
595 /// Get the offset of the field represented by the Cursor.
offset_of_field(&self) -> Result<usize, LayoutError>596 pub fn offset_of_field(&self) -> Result<usize, LayoutError> {
597 if !clang_Cursor_getOffsetOfField::is_loaded() {
598 return Err(LayoutError::from(-1));
599 }
600
601 let offset = unsafe { clang_Cursor_getOffsetOfField(self.x) };
602
603 if offset < 0 {
604 Err(LayoutError::from(offset as i32))
605 } else {
606 Ok(offset as usize)
607 }
608 }
609
610 /// Is this cursor's referent a member function that is declared `static`?
method_is_static(&self) -> bool611 pub fn method_is_static(&self) -> bool {
612 unsafe { clang_CXXMethod_isStatic(self.x) != 0 }
613 }
614
615 /// Is this cursor's referent a member function that is declared `const`?
method_is_const(&self) -> bool616 pub fn method_is_const(&self) -> bool {
617 unsafe { clang_CXXMethod_isConst(self.x) != 0 }
618 }
619
620 /// Is this cursor's referent a member function that is virtual?
method_is_virtual(&self) -> bool621 pub fn method_is_virtual(&self) -> bool {
622 unsafe { clang_CXXMethod_isVirtual(self.x) != 0 }
623 }
624
625 /// Is this cursor's referent a member function that is pure virtual?
method_is_pure_virtual(&self) -> bool626 pub fn method_is_pure_virtual(&self) -> bool {
627 unsafe { clang_CXXMethod_isPureVirtual(self.x) != 0 }
628 }
629
630 /// Is this cursor's referent a struct or class with virtual members?
is_virtual_base(&self) -> bool631 pub fn is_virtual_base(&self) -> bool {
632 unsafe { clang_isVirtualBase(self.x) != 0 }
633 }
634
635 /// Try to evaluate this cursor.
evaluate(&self) -> Option<EvalResult>636 pub fn evaluate(&self) -> Option<EvalResult> {
637 EvalResult::new(*self)
638 }
639
640 /// Return the result type for this cursor
ret_type(&self) -> Option<Type>641 pub fn ret_type(&self) -> Option<Type> {
642 let rt = Type {
643 x: unsafe { clang_getCursorResultType(self.x) },
644 };
645 if rt.is_valid() { Some(rt) } else { None }
646 }
647
648 /// Gets the tokens that correspond to that cursor.
tokens(&self) -> RawTokens649 pub fn tokens(&self) -> RawTokens {
650 RawTokens::new(self)
651 }
652
653 /// Gets the tokens that correspond to that cursor as `cexpr` tokens.
cexpr_tokens(self) -> Vec<cexpr::token::Token>654 pub fn cexpr_tokens(self) -> Vec<cexpr::token::Token> {
655 use cexpr::token;
656
657 self.tokens().iter().filter_map(|token| {
658 let kind = match token.kind {
659 CXToken_Punctuation => token::Kind::Punctuation,
660 CXToken_Literal => token::Kind::Literal,
661 CXToken_Identifier => token::Kind::Identifier,
662 CXToken_Keyword => token::Kind::Keyword,
663 // NB: cexpr is not too happy about comments inside
664 // expressions, so we strip them down here.
665 CXToken_Comment => return None,
666 _ => {
667 error!("Found unexpected token kind: {:?}", token);
668 return None;
669 }
670 };
671
672 Some(token::Token {
673 kind,
674 raw: token.spelling().to_vec().into_boxed_slice(),
675 })
676 }).collect()
677 }
678 }
679
680 /// A struct that owns the tokenizer result from a given cursor.
681 pub struct RawTokens<'a> {
682 cursor: &'a Cursor,
683 tu: CXTranslationUnit,
684 tokens: *mut CXToken,
685 token_count: c_uint,
686 }
687
688 impl<'a> RawTokens<'a> {
new(cursor: &'a Cursor) -> Self689 fn new(cursor: &'a Cursor) -> Self {
690 let mut tokens = ptr::null_mut();
691 let mut token_count = 0;
692 let range = cursor.extent();
693 let tu = unsafe {
694 clang_Cursor_getTranslationUnit(cursor.x)
695 };
696 unsafe { clang_tokenize(tu, range, &mut tokens, &mut token_count) };
697 Self { cursor, tu, tokens, token_count }
698 }
699
as_slice(&self) -> &[CXToken]700 fn as_slice(&self) -> &[CXToken] {
701 if self.tokens.is_null() {
702 return &[];
703 }
704 unsafe { slice::from_raw_parts(self.tokens, self.token_count as usize) }
705 }
706
707 /// Get an iterator over these tokens.
iter(&self) -> ClangTokenIterator708 pub fn iter(&self) -> ClangTokenIterator {
709 ClangTokenIterator {
710 tu: self.tu,
711 raw: self.as_slice().iter(),
712 }
713 }
714 }
715
716 impl<'a> Drop for RawTokens<'a> {
drop(&mut self)717 fn drop(&mut self) {
718 if !self.tokens.is_null() {
719 unsafe {
720 clang_disposeTokens(self.tu, self.tokens, self.token_count as c_uint);
721 }
722 }
723 }
724 }
725
726 /// A raw clang token, that exposes only the kind and spelling. This is a
727 /// slightly more convenient version of `CXToken` which owns the spelling
728 /// string.
729 #[derive(Debug)]
730 pub struct ClangToken {
731 spelling: CXString,
732 /// The kind of token, this is the same as the relevant member from
733 /// `CXToken`.
734 pub kind: CXTokenKind,
735 }
736
737 impl ClangToken {
738 /// Get the token spelling, without being converted to utf-8.
spelling(&self) -> &[u8]739 pub fn spelling(&self) -> &[u8] {
740 let c_str = unsafe {
741 CStr::from_ptr(clang_getCString(self.spelling) as *const _)
742 };
743 c_str.to_bytes()
744 }
745 }
746
747 impl Drop for ClangToken {
drop(&mut self)748 fn drop(&mut self) {
749 unsafe { clang_disposeString(self.spelling) }
750 }
751 }
752
753 /// An iterator over a set of Tokens.
754 pub struct ClangTokenIterator<'a> {
755 tu: CXTranslationUnit,
756 raw: slice::Iter<'a, CXToken>,
757 }
758
759 impl<'a> Iterator for ClangTokenIterator<'a> {
760 type Item = ClangToken;
761
next(&mut self) -> Option<Self::Item>762 fn next(&mut self) -> Option<Self::Item> {
763 let raw = self.raw.next()?;
764 unsafe {
765 let kind = clang_getTokenKind(*raw);
766 let spelling = clang_getTokenSpelling(self.tu, *raw);
767 Some(ClangToken { kind, spelling })
768 }
769 }
770 }
771
772 /// Checks whether the name looks like an identifier, i.e. is alphanumeric
773 /// (including '_') and does not start with a digit.
is_valid_identifier(name: &str) -> bool774 pub fn is_valid_identifier(name: &str) -> bool {
775 let mut chars = name.chars();
776 let first_valid = chars
777 .next()
778 .map(|c| c.is_alphabetic() || c == '_')
779 .unwrap_or(false);
780
781 first_valid && chars.all(|c| c.is_alphanumeric() || c == '_')
782 }
783
visit_children<Visitor>( cur: CXCursor, _parent: CXCursor, data: CXClientData, ) -> CXChildVisitResult where Visitor: FnMut(Cursor) -> CXChildVisitResult,784 extern "C" fn visit_children<Visitor>(
785 cur: CXCursor,
786 _parent: CXCursor,
787 data: CXClientData,
788 ) -> CXChildVisitResult
789 where
790 Visitor: FnMut(Cursor) -> CXChildVisitResult,
791 {
792 let func: &mut Visitor = unsafe { mem::transmute(data) };
793 let child = Cursor {
794 x: cur,
795 };
796
797 (*func)(child)
798 }
799
800 impl PartialEq for Cursor {
eq(&self, other: &Cursor) -> bool801 fn eq(&self, other: &Cursor) -> bool {
802 unsafe { clang_equalCursors(self.x, other.x) == 1 }
803 }
804 }
805
806 impl Eq for Cursor {}
807
808 impl Hash for Cursor {
hash<H: Hasher>(&self, state: &mut H)809 fn hash<H: Hasher>(&self, state: &mut H) {
810 unsafe { clang_hashCursor(self.x) }.hash(state)
811 }
812 }
813
814 /// The type of a node in clang's AST.
815 #[derive(Clone, Copy)]
816 pub struct Type {
817 x: CXType,
818 }
819
820 impl PartialEq for Type {
eq(&self, other: &Self) -> bool821 fn eq(&self, other: &Self) -> bool {
822 unsafe { clang_equalTypes(self.x, other.x) != 0 }
823 }
824 }
825
826 impl Eq for Type {}
827
828 impl fmt::Debug for Type {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result829 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
830 write!(
831 fmt,
832 "Type({}, kind: {}, cconv: {}, decl: {:?}, canon: {:?})",
833 self.spelling(),
834 type_to_str(self.kind()),
835 self.call_conv(),
836 self.declaration(),
837 self.declaration().canonical()
838 )
839 }
840 }
841
842 /// An error about the layout of a struct, class, or type.
843 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
844 pub enum LayoutError {
845 /// Asked for the layout of an invalid type.
846 Invalid,
847 /// Asked for the layout of an incomplete type.
848 Incomplete,
849 /// Asked for the layout of a dependent type.
850 Dependent,
851 /// Asked for the layout of a type that does not have constant size.
852 NotConstantSize,
853 /// Asked for the layout of a field in a type that does not have such a
854 /// field.
855 InvalidFieldName,
856 /// An unknown layout error.
857 Unknown,
858 }
859
860 impl ::std::convert::From<i32> for LayoutError {
from(val: i32) -> Self861 fn from(val: i32) -> Self {
862 use self::LayoutError::*;
863
864 match val {
865 CXTypeLayoutError_Invalid => Invalid,
866 CXTypeLayoutError_Incomplete => Incomplete,
867 CXTypeLayoutError_Dependent => Dependent,
868 CXTypeLayoutError_NotConstantSize => NotConstantSize,
869 CXTypeLayoutError_InvalidFieldName => InvalidFieldName,
870 _ => Unknown,
871 }
872 }
873 }
874
875 impl Type {
876 /// Get this type's kind.
kind(&self) -> CXTypeKind877 pub fn kind(&self) -> CXTypeKind {
878 self.x.kind
879 }
880
881 /// Get a cursor pointing to this type's declaration.
declaration(&self) -> Cursor882 pub fn declaration(&self) -> Cursor {
883 unsafe {
884 Cursor {
885 x: clang_getTypeDeclaration(self.x),
886 }
887 }
888 }
889
890 /// Get the canonical declaration of this type, if it is available.
canonical_declaration( &self, location: Option<&Cursor>, ) -> Option<CanonicalTypeDeclaration>891 pub fn canonical_declaration(
892 &self,
893 location: Option<&Cursor>,
894 ) -> Option<CanonicalTypeDeclaration> {
895 let mut declaration = self.declaration();
896 if !declaration.is_valid() {
897 if let Some(location) = location {
898 let mut location = *location;
899 if let Some(referenced) = location.referenced() {
900 location = referenced;
901 }
902 if location.is_template_like() {
903 declaration = location;
904 }
905 }
906 }
907
908 let canonical = declaration.canonical();
909 if canonical.is_valid() && canonical.kind() != CXCursor_NoDeclFound {
910 Some(CanonicalTypeDeclaration(*self, canonical))
911 } else {
912 None
913 }
914 }
915
916 /// Get a raw display name for this type.
spelling(&self) -> String917 pub fn spelling(&self) -> String {
918 let s = unsafe { cxstring_into_string(clang_getTypeSpelling(self.x)) };
919 // Clang 5.0 introduced changes in the spelling API so it returned the
920 // full qualified name. Let's undo that here.
921 if s.split("::").all(|s| is_valid_identifier(s)) {
922 if let Some(s) = s.split("::").last() {
923 return s.to_owned();
924 }
925 }
926
927 s
928 }
929
930 /// Is this type const qualified?
is_const(&self) -> bool931 pub fn is_const(&self) -> bool {
932 unsafe { clang_isConstQualifiedType(self.x) != 0 }
933 }
934
935 #[inline]
is_non_deductible_auto_type(&self) -> bool936 fn is_non_deductible_auto_type(&self) -> bool {
937 debug_assert_eq!(self.kind(), CXType_Auto);
938 self.canonical_type() == *self
939 }
940
941 #[inline]
clang_size_of(&self, ctx: &BindgenContext) -> c_longlong942 fn clang_size_of(&self, ctx: &BindgenContext) -> c_longlong {
943 match self.kind() {
944 // Work-around https://bugs.llvm.org/show_bug.cgi?id=40975
945 CXType_RValueReference |
946 CXType_LValueReference => ctx.target_pointer_size() as c_longlong,
947 // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
948 CXType_Auto if self.is_non_deductible_auto_type() => return -6,
949 _ => unsafe { clang_Type_getSizeOf(self.x) },
950 }
951 }
952
953 #[inline]
clang_align_of(&self, ctx: &BindgenContext) -> c_longlong954 fn clang_align_of(&self, ctx: &BindgenContext) -> c_longlong {
955 match self.kind() {
956 // Work-around https://bugs.llvm.org/show_bug.cgi?id=40975
957 CXType_RValueReference |
958 CXType_LValueReference => ctx.target_pointer_size() as c_longlong,
959 // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
960 CXType_Auto if self.is_non_deductible_auto_type() => return -6,
961 _ => unsafe { clang_Type_getAlignOf(self.x) },
962 }
963 }
964
965 /// What is the size of this type? Paper over invalid types by returning `0`
966 /// for them.
size(&self, ctx: &BindgenContext) -> usize967 pub fn size(&self, ctx: &BindgenContext) -> usize {
968 let val = self.clang_size_of(ctx);
969 if val < 0 { 0 } else { val as usize }
970 }
971
972 /// What is the size of this type?
fallible_size(&self, ctx: &BindgenContext) -> Result<usize, LayoutError>973 pub fn fallible_size(&self, ctx: &BindgenContext) -> Result<usize, LayoutError> {
974 let val = self.clang_size_of(ctx);
975 if val < 0 {
976 Err(LayoutError::from(val as i32))
977 } else {
978 Ok(val as usize)
979 }
980 }
981
982 /// What is the alignment of this type? Paper over invalid types by
983 /// returning `0`.
align(&self, ctx: &BindgenContext) -> usize984 pub fn align(&self, ctx: &BindgenContext) -> usize {
985 let val = self.clang_align_of(ctx);
986 if val < 0 { 0 } else { val as usize }
987 }
988
989 /// What is the alignment of this type?
fallible_align(&self, ctx: &BindgenContext) -> Result<usize, LayoutError>990 pub fn fallible_align(&self, ctx: &BindgenContext) -> Result<usize, LayoutError> {
991 let val = self.clang_align_of(ctx);
992 if val < 0 {
993 Err(LayoutError::from(val as i32))
994 } else {
995 Ok(val as usize)
996 }
997 }
998
999 /// Get the layout for this type, or an error describing why it does not
1000 /// have a valid layout.
fallible_layout(&self, ctx: &BindgenContext) -> Result<::ir::layout::Layout, LayoutError>1001 pub fn fallible_layout(&self, ctx: &BindgenContext) -> Result<::ir::layout::Layout, LayoutError> {
1002 use ir::layout::Layout;
1003 let size = self.fallible_size(ctx)?;
1004 let align = self.fallible_align(ctx)?;
1005 Ok(Layout::new(size, align))
1006 }
1007
1008 /// Get the number of template arguments this type has, or `None` if it is
1009 /// not some kind of template.
num_template_args(&self) -> Option<u32>1010 pub fn num_template_args(&self) -> Option<u32> {
1011 // If an old libclang is loaded, we have no hope of answering this
1012 // question correctly. However, that's no reason to panic when
1013 // generating bindings for simple C headers with an old libclang.
1014 if !clang_Type_getNumTemplateArguments::is_loaded() {
1015 return None
1016 }
1017
1018 let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
1019 if n >= 0 {
1020 Some(n as u32)
1021 } else {
1022 debug_assert_eq!(n, -1);
1023 None
1024 }
1025 }
1026
1027 /// If this type is a class template specialization, return its
1028 /// template arguments. Otherwise, return None.
template_args(&self) -> Option<TypeTemplateArgIterator>1029 pub fn template_args(&self) -> Option<TypeTemplateArgIterator> {
1030 self.num_template_args().map(|n| {
1031 TypeTemplateArgIterator {
1032 x: self.x,
1033 length: n,
1034 index: 0,
1035 }
1036 })
1037 }
1038
1039 /// Given that this type is a function prototype, return the types of its parameters.
1040 ///
1041 /// Returns None if the type is not a function prototype.
args(&self) -> Option<Vec<Type>>1042 pub fn args(&self) -> Option<Vec<Type>> {
1043 self.num_args().ok().map(|num| {
1044 (0..num).map(|i| {
1045 Type {
1046 x: unsafe { clang_getArgType(self.x, i as c_uint) },
1047 }
1048 })
1049 .collect()
1050 })
1051 }
1052
1053 /// Given that this type is a function prototype, return the number of arguments it takes.
1054 ///
1055 /// Returns Err if the type is not a function prototype.
num_args(&self) -> Result<u32, ()>1056 pub fn num_args(&self) -> Result<u32, ()> {
1057 unsafe {
1058 let w = clang_getNumArgTypes(self.x);
1059 if w == -1 { Err(()) } else { Ok(w as u32) }
1060 }
1061 }
1062
1063
1064 /// Given that this type is a pointer type, return the type that it points
1065 /// to.
pointee_type(&self) -> Option<Type>1066 pub fn pointee_type(&self) -> Option<Type> {
1067 match self.kind() {
1068 CXType_Pointer |
1069 CXType_RValueReference |
1070 CXType_LValueReference |
1071 CXType_MemberPointer |
1072 CXType_BlockPointer |
1073 CXType_ObjCObjectPointer => {
1074 let ret = Type {
1075 x: unsafe { clang_getPointeeType(self.x) },
1076 };
1077 debug_assert!(ret.is_valid());
1078 Some(ret)
1079 }
1080 _ => None,
1081 }
1082 }
1083
1084 /// Given that this type is an array, vector, or complex type, return the
1085 /// type of its elements.
elem_type(&self) -> Option<Type>1086 pub fn elem_type(&self) -> Option<Type> {
1087 let current_type = Type {
1088 x: unsafe { clang_getElementType(self.x) },
1089 };
1090 if current_type.is_valid() {
1091 Some(current_type)
1092 } else {
1093 None
1094 }
1095 }
1096
1097 /// Given that this type is an array or vector type, return its number of
1098 /// elements.
num_elements(&self) -> Option<usize>1099 pub fn num_elements(&self) -> Option<usize> {
1100 let num_elements_returned = unsafe { clang_getNumElements(self.x) };
1101 if num_elements_returned != -1 {
1102 Some(num_elements_returned as usize)
1103 } else {
1104 None
1105 }
1106 }
1107
1108 /// Get the canonical version of this type. This sees through `typedef`s and
1109 /// aliases to get the underlying, canonical type.
canonical_type(&self) -> Type1110 pub fn canonical_type(&self) -> Type {
1111 unsafe {
1112 Type {
1113 x: clang_getCanonicalType(self.x),
1114 }
1115 }
1116 }
1117
1118 /// Is this type a variadic function type?
is_variadic(&self) -> bool1119 pub fn is_variadic(&self) -> bool {
1120 unsafe { clang_isFunctionTypeVariadic(self.x) != 0 }
1121 }
1122
1123 /// Given that this type is a function type, get the type of its return
1124 /// value.
ret_type(&self) -> Option<Type>1125 pub fn ret_type(&self) -> Option<Type> {
1126 let rt = Type {
1127 x: unsafe { clang_getResultType(self.x) },
1128 };
1129 if rt.is_valid() { Some(rt) } else { None }
1130 }
1131
1132 /// Given that this type is a function type, get its calling convention. If
1133 /// this is not a function type, `CXCallingConv_Invalid` is returned.
call_conv(&self) -> CXCallingConv1134 pub fn call_conv(&self) -> CXCallingConv {
1135 unsafe { clang_getFunctionTypeCallingConv(self.x) }
1136 }
1137
1138 /// For elaborated types (types which use `class`, `struct`, or `union` to
1139 /// disambiguate types from local bindings), get the underlying type.
named(&self) -> Type1140 pub fn named(&self) -> Type {
1141 unsafe {
1142 Type {
1143 x: if clang_Type_getNamedType::is_loaded() {
1144 clang_Type_getNamedType(self.x)
1145 } else {
1146 self.x
1147 },
1148 }
1149 }
1150 }
1151
1152 /// Is this a valid type?
is_valid(&self) -> bool1153 pub fn is_valid(&self) -> bool {
1154 self.kind() != CXType_Invalid
1155 }
1156
1157 /// Is this a valid and exposed type?
is_valid_and_exposed(&self) -> bool1158 pub fn is_valid_and_exposed(&self) -> bool {
1159 self.is_valid() && self.kind() != CXType_Unexposed
1160 }
1161
1162 /// Is this type a fully instantiated template?
is_fully_instantiated_template(&self) -> bool1163 pub fn is_fully_instantiated_template(&self) -> bool {
1164 // Yep, the spelling of this containing type-parameter is extremely
1165 // nasty... But can happen in <type_traits>. Unfortunately I couldn't
1166 // reduce it enough :(
1167 self.template_args().map_or(false, |args| args.len() > 0) &&
1168 match self.declaration().kind() {
1169 CXCursor_ClassTemplatePartialSpecialization |
1170 CXCursor_TypeAliasTemplateDecl |
1171 CXCursor_TemplateTemplateParameter => false,
1172 _ => true,
1173 }
1174 }
1175
1176 /// Is this type an associated template type? Eg `T::Associated` in
1177 /// this example:
1178 ///
1179 /// ```c++
1180 /// template <typename T>
1181 /// class Foo {
1182 /// typename T::Associated member;
1183 /// };
1184 /// ```
is_associated_type(&self) -> bool1185 pub fn is_associated_type(&self) -> bool {
1186 // This is terrible :(
1187 fn hacky_parse_associated_type<S: AsRef<str>>(spelling: S) -> bool {
1188 lazy_static! {
1189 static ref ASSOC_TYPE_RE: regex::Regex =
1190 regex::Regex::new(r"typename type\-parameter\-\d+\-\d+::.+").unwrap();
1191 }
1192 ASSOC_TYPE_RE.is_match(spelling.as_ref())
1193 }
1194
1195 self.kind() == CXType_Unexposed &&
1196 (hacky_parse_associated_type(self.spelling()) ||
1197 hacky_parse_associated_type(self.canonical_type().spelling()))
1198 }
1199 }
1200
1201 /// The `CanonicalTypeDeclaration` type exists as proof-by-construction that its
1202 /// cursor is the canonical declaration for its type. If you have a
1203 /// `CanonicalTypeDeclaration` instance, you know for sure that the type and
1204 /// cursor match up in a canonical declaration relationship, and it simply
1205 /// cannot be otherwise.
1206 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1207 pub struct CanonicalTypeDeclaration(Type, Cursor);
1208
1209 impl CanonicalTypeDeclaration {
1210 /// Get the type.
ty(&self) -> &Type1211 pub fn ty(&self) -> &Type {
1212 &self.0
1213 }
1214
1215 /// Get the type's canonical declaration cursor.
cursor(&self) -> &Cursor1216 pub fn cursor(&self) -> &Cursor {
1217 &self.1
1218 }
1219 }
1220
1221 /// An iterator for a type's template arguments.
1222 pub struct TypeTemplateArgIterator {
1223 x: CXType,
1224 length: u32,
1225 index: u32,
1226 }
1227
1228 impl Iterator for TypeTemplateArgIterator {
1229 type Item = Type;
next(&mut self) -> Option<Type>1230 fn next(&mut self) -> Option<Type> {
1231 if self.index < self.length {
1232 let idx = self.index as c_uint;
1233 self.index += 1;
1234 Some(Type {
1235 x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) },
1236 })
1237 } else {
1238 None
1239 }
1240 }
1241 }
1242
1243 impl ExactSizeIterator for TypeTemplateArgIterator {
len(&self) -> usize1244 fn len(&self) -> usize {
1245 assert!(self.index <= self.length);
1246 (self.length - self.index) as usize
1247 }
1248 }
1249
1250 /// A `SourceLocation` is a file, line, column, and byte offset location for
1251 /// some source text.
1252 pub struct SourceLocation {
1253 x: CXSourceLocation,
1254 }
1255
1256 impl SourceLocation {
1257 /// Get the (file, line, column, byte offset) tuple for this source
1258 /// location.
location(&self) -> (File, usize, usize, usize)1259 pub fn location(&self) -> (File, usize, usize, usize) {
1260 unsafe {
1261 let mut file = mem::zeroed();
1262 let mut line = 0;
1263 let mut col = 0;
1264 let mut off = 0;
1265 clang_getSpellingLocation(
1266 self.x,
1267 &mut file,
1268 &mut line,
1269 &mut col,
1270 &mut off,
1271 );
1272 (
1273 File {
1274 x: file,
1275 },
1276 line as usize,
1277 col as usize,
1278 off as usize,
1279 )
1280 }
1281 }
1282 }
1283
1284 impl fmt::Display for SourceLocation {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1285 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1286 let (file, line, col, _) = self.location();
1287 if let Some(name) = file.name() {
1288 write!(f, "{}:{}:{}", name, line, col)
1289 } else {
1290 "builtin definitions".fmt(f)
1291 }
1292 }
1293 }
1294
1295 /// A comment in the source text.
1296 ///
1297 /// Comments are sort of parsed by Clang, and have a tree structure.
1298 pub struct Comment {
1299 x: CXComment,
1300 }
1301
1302 impl Comment {
1303 /// What kind of comment is this?
kind(&self) -> CXCommentKind1304 pub fn kind(&self) -> CXCommentKind {
1305 unsafe { clang_Comment_getKind(self.x) }
1306 }
1307
1308 /// Get this comment's children comment
get_children(&self) -> CommentChildrenIterator1309 pub fn get_children(&self) -> CommentChildrenIterator {
1310 CommentChildrenIterator {
1311 parent: self.x,
1312 length: unsafe { clang_Comment_getNumChildren(self.x) },
1313 index: 0,
1314 }
1315 }
1316
1317 /// Given that this comment is the start or end of an HTML tag, get its tag
1318 /// name.
get_tag_name(&self) -> String1319 pub fn get_tag_name(&self) -> String {
1320 unsafe { cxstring_into_string(clang_HTMLTagComment_getTagName(self.x)) }
1321 }
1322
1323 /// Given that this comment is an HTML start tag, get its attributes.
get_tag_attrs(&self) -> CommentAttributesIterator1324 pub fn get_tag_attrs(&self) -> CommentAttributesIterator {
1325 CommentAttributesIterator {
1326 x: self.x,
1327 length: unsafe { clang_HTMLStartTag_getNumAttrs(self.x) },
1328 index: 0,
1329 }
1330 }
1331 }
1332
1333 /// An iterator for a comment's children
1334 pub struct CommentChildrenIterator {
1335 parent: CXComment,
1336 length: c_uint,
1337 index: c_uint,
1338 }
1339
1340 impl Iterator for CommentChildrenIterator {
1341 type Item = Comment;
next(&mut self) -> Option<Comment>1342 fn next(&mut self) -> Option<Comment> {
1343 if self.index < self.length {
1344 let idx = self.index;
1345 self.index += 1;
1346 Some(Comment {
1347 x: unsafe { clang_Comment_getChild(self.parent, idx) },
1348 })
1349 } else {
1350 None
1351 }
1352 }
1353 }
1354
1355 /// An HTML start tag comment attribute
1356 pub struct CommentAttribute {
1357 /// HTML start tag attribute name
1358 pub name: String,
1359 /// HTML start tag attribute value
1360 pub value: String,
1361 }
1362
1363 /// An iterator for a comment's attributes
1364 pub struct CommentAttributesIterator {
1365 x: CXComment,
1366 length: c_uint,
1367 index: c_uint,
1368 }
1369
1370 impl Iterator for CommentAttributesIterator {
1371 type Item = CommentAttribute;
next(&mut self) -> Option<CommentAttribute>1372 fn next(&mut self) -> Option<CommentAttribute> {
1373 if self.index < self.length {
1374 let idx = self.index;
1375 self.index += 1;
1376 Some(CommentAttribute {
1377 name: unsafe {
1378 cxstring_into_string(
1379 clang_HTMLStartTag_getAttrName(self.x, idx),
1380 )
1381 },
1382 value: unsafe {
1383 cxstring_into_string(
1384 clang_HTMLStartTag_getAttrValue(self.x, idx),
1385 )
1386 },
1387 })
1388 } else {
1389 None
1390 }
1391 }
1392 }
1393
1394 /// A source file.
1395 pub struct File {
1396 x: CXFile,
1397 }
1398
1399 impl File {
1400 /// Get the name of this source file.
name(&self) -> Option<String>1401 pub fn name(&self) -> Option<String> {
1402 if self.x.is_null() {
1403 return None;
1404 }
1405 Some(unsafe { cxstring_into_string(clang_getFileName(self.x)) })
1406 }
1407 }
1408
cxstring_to_string_leaky(s: CXString) -> String1409 fn cxstring_to_string_leaky(s: CXString) -> String {
1410 if s.data.is_null() {
1411 return "".to_owned();
1412 }
1413 let c_str = unsafe { CStr::from_ptr(clang_getCString(s) as *const _) };
1414 c_str.to_string_lossy().into_owned()
1415 }
1416
cxstring_into_string(s: CXString) -> String1417 fn cxstring_into_string(s: CXString) -> String {
1418 let ret = cxstring_to_string_leaky(s);
1419 unsafe { clang_disposeString(s) };
1420 ret
1421 }
1422
1423 /// An `Index` is an environment for a set of translation units that will
1424 /// typically end up linked together in one final binary.
1425 pub struct Index {
1426 x: CXIndex,
1427 }
1428
1429 impl Index {
1430 /// Construct a new `Index`.
1431 ///
1432 /// The `pch` parameter controls whether declarations in pre-compiled
1433 /// headers are included when enumerating a translation unit's "locals".
1434 ///
1435 /// The `diag` parameter controls whether debugging diagnostics are enabled.
new(pch: bool, diag: bool) -> Index1436 pub fn new(pch: bool, diag: bool) -> Index {
1437 unsafe {
1438 Index {
1439 x: clang_createIndex(pch as c_int, diag as c_int),
1440 }
1441 }
1442 }
1443 }
1444
1445 impl fmt::Debug for Index {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1446 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1447 write!(fmt, "Index {{ }}")
1448 }
1449 }
1450
1451 impl Drop for Index {
drop(&mut self)1452 fn drop(&mut self) {
1453 unsafe {
1454 clang_disposeIndex(self.x);
1455 }
1456 }
1457 }
1458
1459 /// A token emitted by clang's lexer.
1460 #[derive(Debug)]
1461 pub struct Token {
1462 /// The kind of token this is.
1463 pub kind: CXTokenKind,
1464 /// A display name for this token.
1465 pub spelling: String,
1466 }
1467
1468 /// A translation unit (or "compilation unit").
1469 pub struct TranslationUnit {
1470 x: CXTranslationUnit,
1471 }
1472
1473 impl fmt::Debug for TranslationUnit {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1474 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1475 write!(fmt, "TranslationUnit {{ }}")
1476 }
1477 }
1478
1479 impl TranslationUnit {
1480 /// Parse a source file into a translation unit.
parse( ix: &Index, file: &str, cmd_args: &[String], unsaved: &[UnsavedFile], opts: CXTranslationUnit_Flags, ) -> Option<TranslationUnit>1481 pub fn parse(
1482 ix: &Index,
1483 file: &str,
1484 cmd_args: &[String],
1485 unsaved: &[UnsavedFile],
1486 opts: CXTranslationUnit_Flags,
1487 ) -> Option<TranslationUnit> {
1488 let fname = CString::new(file).unwrap();
1489 let _c_args: Vec<CString> = cmd_args
1490 .iter()
1491 .map(|s| CString::new(s.clone()).unwrap())
1492 .collect();
1493 let c_args: Vec<*const c_char> =
1494 _c_args.iter().map(|s| s.as_ptr()).collect();
1495 let mut c_unsaved: Vec<CXUnsavedFile> =
1496 unsaved.iter().map(|f| f.x).collect();
1497 let tu = unsafe {
1498 clang_parseTranslationUnit(
1499 ix.x,
1500 fname.as_ptr(),
1501 c_args.as_ptr(),
1502 c_args.len() as c_int,
1503 c_unsaved.as_mut_ptr(),
1504 c_unsaved.len() as c_uint,
1505 opts,
1506 )
1507 };
1508 if tu.is_null() {
1509 None
1510 } else {
1511 Some(TranslationUnit {
1512 x: tu,
1513 })
1514 }
1515 }
1516
1517 /// Get the Clang diagnostic information associated with this translation
1518 /// unit.
diags(&self) -> Vec<Diagnostic>1519 pub fn diags(&self) -> Vec<Diagnostic> {
1520 unsafe {
1521 let num = clang_getNumDiagnostics(self.x) as usize;
1522 let mut diags = vec![];
1523 for i in 0..num {
1524 diags.push(Diagnostic {
1525 x: clang_getDiagnostic(self.x, i as c_uint),
1526 });
1527 }
1528 diags
1529 }
1530 }
1531
1532 /// Get a cursor pointing to the root of this translation unit's AST.
cursor(&self) -> Cursor1533 pub fn cursor(&self) -> Cursor {
1534 unsafe {
1535 Cursor {
1536 x: clang_getTranslationUnitCursor(self.x),
1537 }
1538 }
1539 }
1540
1541 /// Is this the null translation unit?
is_null(&self) -> bool1542 pub fn is_null(&self) -> bool {
1543 self.x.is_null()
1544 }
1545 }
1546
1547 impl Drop for TranslationUnit {
drop(&mut self)1548 fn drop(&mut self) {
1549 unsafe {
1550 clang_disposeTranslationUnit(self.x);
1551 }
1552 }
1553 }
1554
1555
1556 /// A diagnostic message generated while parsing a translation unit.
1557 pub struct Diagnostic {
1558 x: CXDiagnostic,
1559 }
1560
1561 impl Diagnostic {
1562 /// Format this diagnostic message as a string, using the given option bit
1563 /// flags.
format(&self) -> String1564 pub fn format(&self) -> String {
1565 unsafe {
1566 let opts = clang_defaultDiagnosticDisplayOptions();
1567 cxstring_into_string(clang_formatDiagnostic(self.x, opts))
1568 }
1569 }
1570
1571 /// What is the severity of this diagnostic message?
severity(&self) -> CXDiagnosticSeverity1572 pub fn severity(&self) -> CXDiagnosticSeverity {
1573 unsafe { clang_getDiagnosticSeverity(self.x) }
1574 }
1575 }
1576
1577 impl Drop for Diagnostic {
1578 /// Destroy this diagnostic message.
drop(&mut self)1579 fn drop(&mut self) {
1580 unsafe {
1581 clang_disposeDiagnostic(self.x);
1582 }
1583 }
1584 }
1585
1586 /// A file which has not been saved to disk.
1587 pub struct UnsavedFile {
1588 x: CXUnsavedFile,
1589 /// The name of the unsaved file. Kept here to avoid leaving dangling pointers in
1590 /// `CXUnsavedFile`.
1591 pub name: CString,
1592 contents: CString,
1593 }
1594
1595 impl UnsavedFile {
1596 /// Construct a new unsaved file with the given `name` and `contents`.
new(name: &str, contents: &str) -> UnsavedFile1597 pub fn new(name: &str, contents: &str) -> UnsavedFile {
1598 let name = CString::new(name).unwrap();
1599 let contents = CString::new(contents).unwrap();
1600 let x = CXUnsavedFile {
1601 Filename: name.as_ptr(),
1602 Contents: contents.as_ptr(),
1603 Length: contents.as_bytes().len() as c_ulong,
1604 };
1605 UnsavedFile {
1606 x: x,
1607 name: name,
1608 contents: contents,
1609 }
1610 }
1611 }
1612
1613 impl fmt::Debug for UnsavedFile {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1614 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1615 write!(
1616 fmt,
1617 "UnsavedFile(name: {:?}, contents: {:?})",
1618 self.name,
1619 self.contents
1620 )
1621 }
1622 }
1623
1624 /// Convert a cursor kind into a static string.
kind_to_str(x: CXCursorKind) -> String1625 pub fn kind_to_str(x: CXCursorKind) -> String {
1626 unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) }
1627 }
1628
1629 /// Convert a type kind to a static string.
type_to_str(x: CXTypeKind) -> String1630 pub fn type_to_str(x: CXTypeKind) -> String {
1631 unsafe { cxstring_into_string(clang_getTypeKindSpelling(x)) }
1632 }
1633
1634 /// Dump the Clang AST to stdout for debugging purposes.
ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult1635 pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
1636 fn print_indent<S: AsRef<str>>(depth: isize, s: S) {
1637 for _ in 0..depth {
1638 print!(" ");
1639 }
1640 println!("{}", s.as_ref());
1641 }
1642
1643 fn print_cursor<S: AsRef<str>>(depth: isize, prefix: S, c: &Cursor) {
1644 let prefix = prefix.as_ref();
1645 print_indent(
1646 depth,
1647 format!(" {}kind = {}", prefix, kind_to_str(c.kind())),
1648 );
1649 print_indent(
1650 depth,
1651 format!(" {}spelling = \"{}\"", prefix, c.spelling()),
1652 );
1653 print_indent(depth, format!(" {}location = {}", prefix, c.location()));
1654 print_indent(
1655 depth,
1656 format!(" {}is-definition? {}", prefix, c.is_definition()),
1657 );
1658 print_indent(
1659 depth,
1660 format!(" {}is-declaration? {}", prefix, c.is_declaration()),
1661 );
1662 print_indent(
1663 depth,
1664 format!(
1665 " {}is-inlined-function? {}",
1666 prefix,
1667 c.is_inlined_function()
1668 ),
1669 );
1670
1671 let templ_kind = c.template_kind();
1672 if templ_kind != CXCursor_NoDeclFound {
1673 print_indent(
1674 depth,
1675 format!(" {}template-kind = {}", prefix, kind_to_str(templ_kind)),
1676 );
1677 }
1678 if let Some(usr) = c.usr() {
1679 print_indent(depth, format!(" {}usr = \"{}\"", prefix, usr));
1680 }
1681 if let Ok(num) = c.num_args() {
1682 print_indent(depth, format!(" {}number-of-args = {}", prefix, num));
1683 }
1684 if let Some(num) = c.num_template_args() {
1685 print_indent(
1686 depth,
1687 format!(" {}number-of-template-args = {}", prefix, num),
1688 );
1689 }
1690 if let Some(width) = c.bit_width() {
1691 print_indent(depth, format!(" {}bit-width = {}", prefix, width));
1692 }
1693 if let Some(ty) = c.enum_type() {
1694 print_indent(
1695 depth,
1696 format!(" {}enum-type = {}", prefix, type_to_str(ty.kind())),
1697 );
1698 }
1699 if let Some(val) = c.enum_val_signed() {
1700 print_indent(depth, format!(" {}enum-val = {}", prefix, val));
1701 }
1702 if let Some(ty) = c.typedef_type() {
1703 print_indent(
1704 depth,
1705 format!(" {}typedef-type = {}", prefix, type_to_str(ty.kind())),
1706 );
1707 }
1708 if let Some(ty) = c.ret_type() {
1709 print_indent(
1710 depth,
1711 format!(" {}ret-type = {}", prefix, type_to_str(ty.kind())),
1712 );
1713 }
1714
1715 if let Some(refd) = c.referenced() {
1716 if refd != *c {
1717 println!("");
1718 print_cursor(
1719 depth,
1720 String::from(prefix) + "referenced.",
1721 &refd,
1722 );
1723 }
1724 }
1725
1726 let canonical = c.canonical();
1727 if canonical != *c {
1728 println!("");
1729 print_cursor(
1730 depth,
1731 String::from(prefix) + "canonical.",
1732 &canonical,
1733 );
1734 }
1735
1736 if let Some(specialized) = c.specialized() {
1737 if specialized != *c {
1738 println!("");
1739 print_cursor(
1740 depth,
1741 String::from(prefix) + "specialized.",
1742 &specialized,
1743 );
1744 }
1745 }
1746
1747 if let Some(parent) = c.fallible_semantic_parent() {
1748 println!("");
1749 print_cursor(
1750 depth,
1751 String::from(prefix) + "semantic-parent.",
1752 &parent,
1753 );
1754 }
1755 }
1756
1757 fn print_type<S: AsRef<str>>(depth: isize, prefix: S, ty: &Type) {
1758 let prefix = prefix.as_ref();
1759
1760 let kind = ty.kind();
1761 print_indent(depth, format!(" {}kind = {}", prefix, type_to_str(kind)));
1762 if kind == CXType_Invalid {
1763 return;
1764 }
1765
1766 print_indent(depth, format!(" {}cconv = {}", prefix, ty.call_conv()));
1767
1768 print_indent(
1769 depth,
1770 format!(" {}spelling = \"{}\"", prefix, ty.spelling()),
1771 );
1772 let num_template_args = if clang_Type_getNumTemplateArguments::is_loaded() {
1773 unsafe { clang_Type_getNumTemplateArguments(ty.x) }
1774 } else {
1775 -1
1776 };
1777 if num_template_args >= 0 {
1778 print_indent(
1779 depth,
1780 format!(
1781 " {}number-of-template-args = {}",
1782 prefix,
1783 num_template_args
1784 ),
1785 );
1786 }
1787 if let Some(num) = ty.num_elements() {
1788 print_indent(
1789 depth,
1790 format!(" {}number-of-elements = {}", prefix, num),
1791 );
1792 }
1793 print_indent(
1794 depth,
1795 format!(" {}is-variadic? {}", prefix, ty.is_variadic()),
1796 );
1797
1798 let canonical = ty.canonical_type();
1799 if canonical != *ty {
1800 println!("");
1801 print_type(depth, String::from(prefix) + "canonical.", &canonical);
1802 }
1803
1804 if let Some(pointee) = ty.pointee_type() {
1805 if pointee != *ty {
1806 println!("");
1807 print_type(depth, String::from(prefix) + "pointee.", &pointee);
1808 }
1809 }
1810
1811 if let Some(elem) = ty.elem_type() {
1812 if elem != *ty {
1813 println!("");
1814 print_type(depth, String::from(prefix) + "elements.", &elem);
1815 }
1816 }
1817
1818 if let Some(ret) = ty.ret_type() {
1819 if ret != *ty {
1820 println!("");
1821 print_type(depth, String::from(prefix) + "return.", &ret);
1822 }
1823 }
1824
1825 let named = ty.named();
1826 if named != *ty && named.is_valid() {
1827 println!("");
1828 print_type(depth, String::from(prefix) + "named.", &named);
1829 }
1830 }
1831
1832 print_indent(depth, "(");
1833 print_cursor(depth, "", c);
1834
1835 println!("");
1836 let ty = c.cur_type();
1837 print_type(depth, "type.", &ty);
1838
1839 let declaration = ty.declaration();
1840 if declaration != *c && declaration.kind() != CXCursor_NoDeclFound {
1841 println!("");
1842 print_cursor(depth, "type.declaration.", &declaration);
1843 }
1844
1845 // Recurse.
1846 let mut found_children = false;
1847 c.visit(|s| {
1848 if !found_children {
1849 println!("");
1850 found_children = true;
1851 }
1852 ast_dump(&s, depth + 1)
1853 });
1854
1855 print_indent(depth, ")");
1856
1857 CXChildVisit_Continue
1858 }
1859
1860 /// Try to extract the clang version to a string
extract_clang_version() -> String1861 pub fn extract_clang_version() -> String {
1862 unsafe { cxstring_into_string(clang_getClangVersion()) }
1863 }
1864
1865 /// A wrapper for the result of evaluating an expression.
1866 #[derive(Debug)]
1867 pub struct EvalResult {
1868 x: CXEvalResult,
1869 }
1870
1871 impl EvalResult {
1872 /// Evaluate `cursor` and return the result.
new(cursor: Cursor) -> Option<Self>1873 pub fn new(cursor: Cursor) -> Option<Self> {
1874 if !clang_Cursor_Evaluate::is_loaded() {
1875 return None;
1876 }
1877
1878 // Clang has an internal assertion we can trigger if we try to evaluate
1879 // a cursor containing a variadic template type reference. Triggering
1880 // the assertion aborts the process, and we don't want that. Clang
1881 // *also* doesn't expose any API for finding variadic vs non-variadic
1882 // template type references, let alone whether a type referenced is a
1883 // template type, instead they seem to show up as type references to an
1884 // unexposed type. Our solution is to just flat out ban all
1885 // `CXType_Unexposed` from evaluation.
1886 let mut found_cant_eval = false;
1887 cursor.visit(|c| if c.kind() == CXCursor_TypeRef &&
1888 c.cur_type().kind() == CXType_Unexposed
1889 {
1890 found_cant_eval = true;
1891 CXChildVisit_Break
1892 } else {
1893 CXChildVisit_Recurse
1894 });
1895 if found_cant_eval {
1896 return None;
1897 }
1898
1899 Some(EvalResult {
1900 x: unsafe { clang_Cursor_Evaluate(cursor.x) },
1901 })
1902 }
1903
kind(&self) -> CXEvalResultKind1904 fn kind(&self) -> CXEvalResultKind {
1905 unsafe { clang_EvalResult_getKind(self.x) }
1906 }
1907
1908 /// Try to get back the result as a double.
as_double(&self) -> Option<f64>1909 pub fn as_double(&self) -> Option<f64> {
1910 match self.kind() {
1911 CXEval_Float => {
1912 Some(unsafe { clang_EvalResult_getAsDouble(self.x) } as f64)
1913 }
1914 _ => None,
1915 }
1916 }
1917
1918 /// Try to get back the result as an integer.
as_int(&self) -> Option<i64>1919 pub fn as_int(&self) -> Option<i64> {
1920 if self.kind() != CXEval_Int {
1921 return None;
1922 }
1923
1924 if !clang_EvalResult_isUnsignedInt::is_loaded() {
1925 // FIXME(emilio): There's no way to detect underflow here, and clang
1926 // will just happily give us a value.
1927 return Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i64)
1928 }
1929
1930 if unsafe { clang_EvalResult_isUnsignedInt(self.x) } != 0 {
1931 let value = unsafe { clang_EvalResult_getAsUnsigned(self.x) };
1932 if value > i64::max_value() as c_ulonglong {
1933 return None;
1934 }
1935
1936 return Some(value as i64)
1937 }
1938
1939 let value = unsafe { clang_EvalResult_getAsLongLong(self.x) };
1940 if value > i64::max_value() as c_longlong {
1941 return None;
1942 }
1943 if value < i64::min_value() as c_longlong {
1944 return None;
1945 }
1946 Some(value as i64)
1947 }
1948
1949 /// Evaluates the expression as a literal string, that may or may not be
1950 /// valid utf-8.
as_literal_string(&self) -> Option<Vec<u8>>1951 pub fn as_literal_string(&self) -> Option<Vec<u8>> {
1952 match self.kind() {
1953 CXEval_StrLiteral => {
1954 let ret = unsafe {
1955 CStr::from_ptr(clang_EvalResult_getAsStr(self.x))
1956 };
1957 Some(ret.to_bytes().to_vec())
1958 }
1959 _ => None,
1960 }
1961 }
1962 }
1963
1964 impl Drop for EvalResult {
drop(&mut self)1965 fn drop(&mut self) {
1966 unsafe { clang_EvalResult_dispose(self.x) };
1967 }
1968 }
1969
1970 /// Target information obtained from libclang.
1971 #[derive(Debug)]
1972 pub struct TargetInfo {
1973 /// The target triple.
1974 pub triple: String,
1975 /// The width of the pointer _in bits_.
1976 pub pointer_width: usize,
1977 }
1978
1979 impl TargetInfo {
1980 /// Tries to obtain target information from libclang.
new(tu: &TranslationUnit) -> Option<Self>1981 pub fn new(tu: &TranslationUnit) -> Option<Self> {
1982 if !clang_getTranslationUnitTargetInfo::is_loaded() {
1983 return None;
1984 }
1985 let triple;
1986 let pointer_width;
1987 unsafe {
1988 let ti = clang_getTranslationUnitTargetInfo(tu.x);
1989 triple = cxstring_into_string(clang_TargetInfo_getTriple(ti));
1990 pointer_width = clang_TargetInfo_getPointerWidth(ti);
1991 clang_TargetInfo_dispose(ti);
1992 }
1993 assert!(pointer_width > 0);
1994 assert_eq!(pointer_width % 8, 0);
1995 Some(TargetInfo {
1996 triple,
1997 pointer_width: pointer_width as usize,
1998 })
1999 }
2000 }
2001