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