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 use crate::ir::context::BindgenContext;
7 use clang_sys::*;
8 use std::ffi::{CStr, CString};
9 use std::fmt;
10 use std::hash::Hash;
11 use std::hash::Hasher;
12 use std::os::raw::{c_char, c_int, c_longlong, c_uint, c_ulong, c_ulonglong};
13 use 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.
19 pub struct Attribute {
20 name: &'static [u8],
21 kind: Option<CXCursorKind>,
22 token_kind: CXTokenKind,
23 }
24
25 impl 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)]
53 pub struct Cursor {
54 x: CXCursor,
55 }
56
57 impl fmt::Debug for Cursor {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result58 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
70 impl 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.
usr(&self) -> Option<String>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?
is_declaration(&self) -> bool85 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?
is_anonymous(&self) -> bool90 pub fn is_anonymous(&self) -> bool {
91 unsafe { clang_Cursor_isAnonymous(self.x) != 0 }
92 }
93
94 /// Get this cursor's referent's spelling.
spelling(&self) -> String95 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.
display_name(&self) -> String103 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.
mangling(&self) -> String108 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.
cxx_manglings(&self) -> Result<Vec<String>, ()>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.
is_builtin(&self) -> bool134 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 /// ```
lexical_parent(&self) -> Cursor156 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.
fallible_semantic_parent(&self) -> Option<Cursor>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.
semantic_parent(&self) -> Cursor184 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.
num_template_args(&self) -> Option<u32>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.
translation_unit(&self) -> Cursor228 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?
is_toplevel(&self) -> bool241 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.
is_template_like(&self) -> bool262 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?
is_macro_function_like(&self) -> bool272 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.
kind(&self) -> CXCursorKind277 pub fn kind(&self) -> CXCursorKind {
278 self.x.kind
279 }
280
281 /// Returns true if the cursor is a definition
is_definition(&self) -> bool282 pub fn is_definition(&self) -> bool {
283 unsafe { clang_isCursorDefinition(self.x) != 0 }
284 }
285
286 /// Is the referent a template specialization?
is_template_specialization(&self) -> bool287 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?
is_fully_specialized_template(&self) -> bool293 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?
is_in_non_fully_specialized_template(&self) -> bool301 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?
is_template_parameter(&self) -> bool319 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?
is_dependent_on_template_parameter(&self) -> bool329 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?
is_valid(&self) -> bool369 pub fn is_valid(&self) -> bool {
370 unsafe { clang_isInvalid(self.kind()) == 0 }
371 }
372
373 /// Get the source location for the referent.
location(&self) -> SourceLocation374 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.
extent(&self) -> CXSourceRange383 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.
raw_comment(&self) -> Option<String>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.
comment(&self) -> Comment400 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.
cur_type(&self) -> Type409 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.
definition(&self) -> Option<Cursor>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.
referenced(&self) -> Option<Cursor>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.
canonical(&self) -> Cursor455 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.
specialized(&self) -> Option<Cursor>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.
template_kind(&self) -> CXCursorKind481 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.
visit<Visitor>(&self, mut visitor: Visitor) where Visitor: FnMut(Cursor) -> CXChildVisitResult,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.
collect_children(&self) -> Vec<Cursor>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?
has_children(&self) -> bool509 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?
has_at_least_num_children(&self, n: usize) -> bool519 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).
contains_cursor(&self, kind: CXCursorKind) -> bool536 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?
is_inlined_function(&self) -> bool552 pub fn is_inlined_function(&self) -> bool {
553 unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 }
554 }
555
556 /// Is the referent a defaulted function?
is_defaulted_function(&self) -> bool557 pub fn is_defaulted_function(&self) -> bool {
558 unsafe { clang_CXXMethod_isDefaulted(self.x) != 0 }
559 }
560
561 /// Is the referent a deleted function?
is_deleted_function(&self) -> bool562 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?
is_bit_field(&self) -> bool578 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.
bit_width_expr(&self) -> Option<Cursor>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.
bit_width(&self) -> Option<u32>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.
enum_type(&self) -> Option<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.
enum_val_boolean(&self) -> Option<bool>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.
enum_val_signed(&self) -> Option<i64>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.
enum_val_unsigned(&self) -> Option<u64>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?
has_attrs<const N: usize>( &self, attrs: &[Attribute; N], ) -> [bool; N]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.
typedef_type(&self) -> Option<Type>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.
linkage(&self) -> CXLinkageKind736 pub fn linkage(&self) -> CXLinkageKind {
737 unsafe { clang_getCursorLinkage(self.x) }
738 }
739
740 /// Get the visibility of this cursor's referent.
visibility(&self) -> CXVisibilityKind741 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.
args(&self) -> Option<Vec<Cursor>>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.
num_args(&self) -> Result<u32, ()>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.
access_specifier(&self) -> CX_CXXAccessSpecifier780 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`.
public_accessible(&self) -> bool788 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`?
is_mutable_field(&self) -> bool795 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.
offset_of_field(&self) -> Result<usize, LayoutError>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`?
method_is_static(&self) -> bool811 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`?
method_is_const(&self) -> bool816 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?
method_is_virtual(&self) -> bool821 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?
method_is_pure_virtual(&self) -> bool826 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?
is_virtual_base(&self) -> bool831 pub fn is_virtual_base(&self) -> bool {
832 unsafe { clang_isVirtualBase(self.x) != 0 }
833 }
834
835 /// Try to evaluate this cursor.
evaluate(&self) -> Option<EvalResult>836 pub fn evaluate(&self) -> Option<EvalResult> {
837 EvalResult::new(*self)
838 }
839
840 /// Return the result type for this cursor
ret_type(&self) -> Option<Type>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.
tokens(&self) -> RawTokens853 pub fn tokens(&self) -> RawTokens {
854 RawTokens::new(self)
855 }
856
857 /// Gets the tokens that correspond to that cursor as `cexpr` tokens.
cexpr_tokens(self) -> Vec<cexpr::token::Token>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
get_included_file_name(&self) -> Option<String>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.
881 pub struct RawTokens<'a> {
882 cursor: &'a Cursor,
883 tu: CXTranslationUnit,
884 tokens: *mut CXToken,
885 token_count: c_uint,
886 }
887
888 impl<'a> RawTokens<'a> {
new(cursor: &'a Cursor) -> Self889 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
as_slice(&self) -> &[CXToken]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.
iter(&self) -> ClangTokenIterator911 pub fn iter(&self) -> ClangTokenIterator {
912 ClangTokenIterator {
913 tu: self.tu,
914 raw: self.as_slice().iter(),
915 }
916 }
917 }
918
919 impl<'a> Drop for RawTokens<'a> {
drop(&mut self)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)]
937 pub 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
947 impl ClangToken {
948 /// Get the token spelling, without being converted to utf-8.
spelling(&self) -> &[u8]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.
as_cexpr_token(&self) -> Option<cexpr::token::Token>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
981 impl Drop for ClangToken {
drop(&mut self)982 fn drop(&mut self) {
983 unsafe { clang_disposeString(self.spelling) }
984 }
985 }
986
987 /// An iterator over a set of Tokens.
988 pub struct ClangTokenIterator<'a> {
989 tu: CXTranslationUnit,
990 raw: slice::Iter<'a, CXToken>,
991 }
992
993 impl<'a> Iterator for ClangTokenIterator<'a> {
994 type Item = ClangToken;
995
next(&mut self) -> Option<Self::Item>996 fn next(&mut self) -> Option<Self::Item> {
997 let raw = self.raw.next()?;
998 unsafe {
999 let kind = clang_getTokenKind(*raw);
1000 let spelling = clang_getTokenSpelling(self.tu, *raw);
1001 let extent = 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.
is_valid_identifier(name: &str) -> bool1013 pub fn is_valid_identifier(name: &str) -> bool {
1014 let mut chars = name.chars();
1015 let first_valid = chars
1016 .next()
1017 .map(|c| c.is_alphabetic() || c == '_')
1018 .unwrap_or(false);
1019
1020 first_valid && chars.all(|c| c.is_alphanumeric() || c == '_')
1021 }
1022
visit_children<Visitor>( cur: CXCursor, _parent: CXCursor, data: CXClientData, ) -> CXChildVisitResult where Visitor: FnMut(Cursor) -> CXChildVisitResult,1023 extern "C" fn visit_children<Visitor>(
1024 cur: CXCursor,
1025 _parent: CXCursor,
1026 data: CXClientData,
1027 ) -> CXChildVisitResult
1028 where
1029 Visitor: FnMut(Cursor) -> CXChildVisitResult,
1030 {
1031 let func: &mut Visitor = unsafe { &mut *(data as *mut Visitor) };
1032 let child = Cursor { x: cur };
1033
1034 (*func)(child)
1035 }
1036
1037 impl PartialEq for Cursor {
eq(&self, other: &Cursor) -> bool1038 fn eq(&self, other: &Cursor) -> bool {
1039 unsafe { clang_equalCursors(self.x, other.x) == 1 }
1040 }
1041 }
1042
1043 impl Eq for Cursor {}
1044
1045 impl Hash for Cursor {
hash<H: Hasher>(&self, state: &mut H)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)]
1053 pub struct Type {
1054 x: CXType,
1055 }
1056
1057 impl PartialEq for Type {
eq(&self, other: &Self) -> bool1058 fn eq(&self, other: &Self) -> bool {
1059 unsafe { clang_equalTypes(self.x, other.x) != 0 }
1060 }
1061 }
1062
1063 impl Eq for Type {}
1064
1065 impl fmt::Debug for Type {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1066 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)]
1081 pub 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
1097 impl ::std::convert::From<i32> for LayoutError {
from(val: i32) -> Self1098 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
1112 impl Type {
1113 /// Get this type's kind.
kind(&self) -> CXTypeKind1114 pub fn kind(&self) -> CXTypeKind {
1115 self.x.kind
1116 }
1117
1118 /// Get a cursor pointing to this type's declaration.
declaration(&self) -> Cursor1119 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.
canonical_declaration( &self, location: Option<&Cursor>, ) -> Option<CanonicalTypeDeclaration>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.
spelling(&self) -> String1154 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?
is_const(&self) -> bool1168 pub fn is_const(&self) -> bool {
1169 unsafe { clang_isConstQualifiedType(self.x) != 0 }
1170 }
1171
1172 #[inline]
is_non_deductible_auto_type(&self) -> bool1173 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]
clang_size_of(&self, ctx: &BindgenContext) -> c_longlong1179 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]
clang_align_of(&self, ctx: &BindgenContext) -> c_longlong1192 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.
size(&self, ctx: &BindgenContext) -> usize1206 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?
fallible_size( &self, ctx: &BindgenContext, ) -> Result<usize, LayoutError>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`.
align(&self, ctx: &BindgenContext) -> usize1230 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?
fallible_align( &self, ctx: &BindgenContext, ) -> Result<usize, LayoutError>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.
fallible_layout( &self, ctx: &BindgenContext, ) -> Result<crate::ir::layout::Layout, LayoutError>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.
num_template_args(&self) -> Option<u32>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.
template_args(&self) -> Option<TypeTemplateArgIterator>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.
args(&self) -> Option<Vec<Type>>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.
num_args(&self) -> Result<u32, ()>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.
pointee_type(&self) -> Option<Type>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.
elem_type(&self) -> Option<Type>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.
num_elements(&self) -> Option<usize>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.
canonical_type(&self) -> Type1359 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?
is_variadic(&self) -> bool1368 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.
ret_type(&self) -> Option<Type>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.
call_conv(&self) -> CXCallingConv1387 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.
named(&self) -> Type1393 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?
is_valid(&self) -> bool1402 pub fn is_valid(&self) -> bool {
1403 self.kind() != CXType_Invalid
1404 }
1405
1406 /// Is this a valid and exposed type?
is_valid_and_exposed(&self) -> bool1407 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?
is_fully_instantiated_template(&self) -> bool1412 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 /// ```
is_associated_type(&self) -> bool1434 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)]
1460 pub struct CanonicalTypeDeclaration(Type, Cursor);
1461
1462 impl CanonicalTypeDeclaration {
1463 /// Get the type.
ty(&self) -> &Type1464 pub fn ty(&self) -> &Type {
1465 &self.0
1466 }
1467
1468 /// Get the type's canonical declaration cursor.
cursor(&self) -> &Cursor1469 pub fn cursor(&self) -> &Cursor {
1470 &self.1
1471 }
1472 }
1473
1474 /// An iterator for a type's template arguments.
1475 pub struct TypeTemplateArgIterator {
1476 x: CXType,
1477 length: u32,
1478 index: u32,
1479 }
1480
1481 impl Iterator for TypeTemplateArgIterator {
1482 type Item = Type;
next(&mut self) -> Option<Type>1483 fn next(&mut self) -> Option<Type> {
1484 if self.index < self.length {
1485 let idx = self.index as c_uint;
1486 self.index += 1;
1487 Some(Type {
1488 x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) },
1489 })
1490 } else {
1491 None
1492 }
1493 }
1494 }
1495
1496 impl ExactSizeIterator for TypeTemplateArgIterator {
len(&self) -> usize1497 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.
1505 pub struct SourceLocation {
1506 x: CXSourceLocation,
1507 }
1508
1509 impl SourceLocation {
1510 /// Get the (file, line, column, byte offset) tuple for this source
1511 /// location.
location(&self) -> (File, usize, usize, usize)1512 pub fn location(&self) -> (File, usize, usize, usize) {
1513 unsafe {
1514 let mut file = mem::zeroed();
1515 let mut line = 0;
1516 let mut col = 0;
1517 let mut off = 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
1526 impl fmt::Display for SourceLocation {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1527 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1528 let (file, line, col, _) = self.location();
1529 if let Some(name) = file.name() {
1530 write!(f, "{}:{}:{}", name, line, col)
1531 } else {
1532 "builtin definitions".fmt(f)
1533 }
1534 }
1535 }
1536
1537 impl fmt::Debug for SourceLocation {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1538 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.
1546 pub struct Comment {
1547 x: CXComment,
1548 }
1549
1550 impl Comment {
1551 /// What kind of comment is this?
kind(&self) -> CXCommentKind1552 pub fn kind(&self) -> CXCommentKind {
1553 unsafe { clang_Comment_getKind(self.x) }
1554 }
1555
1556 /// Get this comment's children comment
get_children(&self) -> CommentChildrenIterator1557 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.
get_tag_name(&self) -> String1567 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.
get_tag_attrs(&self) -> CommentAttributesIterator1572 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
1582 pub struct CommentChildrenIterator {
1583 parent: CXComment,
1584 length: c_uint,
1585 index: c_uint,
1586 }
1587
1588 impl Iterator for CommentChildrenIterator {
1589 type Item = Comment;
next(&mut self) -> Option<Comment>1590 fn next(&mut self) -> Option<Comment> {
1591 if self.index < self.length {
1592 let idx = self.index;
1593 self.index += 1;
1594 Some(Comment {
1595 x: unsafe { clang_Comment_getChild(self.parent, idx) },
1596 })
1597 } else {
1598 None
1599 }
1600 }
1601 }
1602
1603 /// An HTML start tag comment attribute
1604 pub 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
1612 pub struct CommentAttributesIterator {
1613 x: CXComment,
1614 length: c_uint,
1615 index: c_uint,
1616 }
1617
1618 impl Iterator for CommentAttributesIterator {
1619 type Item = CommentAttribute;
next(&mut self) -> Option<CommentAttribute>1620 fn next(&mut self) -> Option<CommentAttribute> {
1621 if self.index < self.length {
1622 let idx = self.index;
1623 self.index += 1;
1624 Some(CommentAttribute {
1625 name: unsafe {
1626 cxstring_into_string(clang_HTMLStartTag_getAttrName(
1627 self.x, idx,
1628 ))
1629 },
1630 value: unsafe {
1631 cxstring_into_string(clang_HTMLStartTag_getAttrValue(
1632 self.x, idx,
1633 ))
1634 },
1635 })
1636 } else {
1637 None
1638 }
1639 }
1640 }
1641
1642 /// A source file.
1643 pub struct File {
1644 x: CXFile,
1645 }
1646
1647 impl File {
1648 /// Get the name of this source file.
name(&self) -> Option<String>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
cxstring_to_string_leaky(s: CXString) -> String1657 fn cxstring_to_string_leaky(s: CXString) -> String {
1658 if s.data.is_null() {
1659 return "".to_owned();
1660 }
1661 let c_str = unsafe { CStr::from_ptr(clang_getCString(s) as *const _) };
1662 c_str.to_string_lossy().into_owned()
1663 }
1664
cxstring_into_string(s: CXString) -> String1665 fn cxstring_into_string(s: CXString) -> String {
1666 let ret = cxstring_to_string_leaky(s);
1667 unsafe { clang_disposeString(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.
1673 pub struct Index {
1674 x: CXIndex,
1675 }
1676
1677 impl 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.
new(pch: bool, diag: bool) -> Index1684 pub fn new(pch: bool, diag: bool) -> Index {
1685 unsafe {
1686 Index {
1687 x: clang_createIndex(pch as c_int, diag as c_int),
1688 }
1689 }
1690 }
1691 }
1692
1693 impl fmt::Debug for Index {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1694 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1695 write!(fmt, "Index {{ }}")
1696 }
1697 }
1698
1699 impl Drop for Index {
drop(&mut self)1700 fn drop(&mut self) {
1701 unsafe {
1702 clang_disposeIndex(self.x);
1703 }
1704 }
1705 }
1706
1707 /// A translation unit (or "compilation unit").
1708 pub struct TranslationUnit {
1709 x: CXTranslationUnit,
1710 }
1711
1712 impl fmt::Debug for TranslationUnit {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1713 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1714 write!(fmt, "TranslationUnit {{ }}")
1715 }
1716 }
1717
1718 impl TranslationUnit {
1719 /// Parse a source file into a translation unit.
parse( ix: &Index, file: &str, cmd_args: &[String], unsaved: &[UnsavedFile], opts: CXTranslationUnit_Flags, ) -> Option<TranslationUnit>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.
diags(&self) -> Vec<Diagnostic>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.
cursor(&self) -> Cursor1770 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?
is_null(&self) -> bool1779 pub fn is_null(&self) -> bool {
1780 self.x.is_null()
1781 }
1782 }
1783
1784 impl Drop for TranslationUnit {
drop(&mut self)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.
1793 pub struct Diagnostic {
1794 x: CXDiagnostic,
1795 }
1796
1797 impl Diagnostic {
1798 /// Format this diagnostic message as a string, using the given option bit
1799 /// flags.
format(&self) -> String1800 pub fn format(&self) -> String {
1801 unsafe {
1802 let opts = clang_defaultDiagnosticDisplayOptions();
1803 cxstring_into_string(clang_formatDiagnostic(self.x, opts))
1804 }
1805 }
1806
1807 /// What is the severity of this diagnostic message?
severity(&self) -> CXDiagnosticSeverity1808 pub fn severity(&self) -> CXDiagnosticSeverity {
1809 unsafe { clang_getDiagnosticSeverity(self.x) }
1810 }
1811 }
1812
1813 impl Drop for Diagnostic {
1814 /// Destroy this diagnostic message.
drop(&mut self)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.
1823 pub 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
1831 impl UnsavedFile {
1832 /// Construct a new unsaved file with the given `name` and `contents`.
new(name: String, contents: String) -> UnsavedFile1833 pub fn new(name: String, contents: String) -> UnsavedFile {
1834 let name = CString::new(name).unwrap();
1835 let contents = CString::new(contents).unwrap();
1836 let x = 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
1845 impl fmt::Debug for UnsavedFile {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1846 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.
kind_to_str(x: CXCursorKind) -> String1856 pub fn kind_to_str(x: CXCursorKind) -> String {
1857 unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) }
1858 }
1859
1860 /// Convert a type kind to a static string.
type_to_str(x: CXTypeKind) -> String1861 pub fn type_to_str(x: CXTypeKind) -> String {
1862 unsafe { cxstring_into_string(clang_getTypeKindSpelling(x)) }
1863 }
1864
1865 /// Dump the Clang AST to stdout for debugging purposes.
ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult1866 pub 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
extract_clang_version() -> String2098 pub 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)]
2104 pub struct EvalResult {
2105 x: CXEvalResult,
2106 }
2107
2108 impl EvalResult {
2109 /// Evaluate `cursor` and return the result.
new(cursor: Cursor) -> Option<Self>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
kind(&self) -> CXEvalResultKind2136 fn kind(&self) -> CXEvalResultKind {
2137 unsafe { clang_EvalResult_getKind(self.x) }
2138 }
2139
2140 /// Try to get back the result as a double.
as_double(&self) -> Option<f64>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.
as_int(&self) -> Option<i64>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.
as_literal_string(&self) -> Option<Vec<u8>>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
2191 impl Drop for EvalResult {
drop(&mut self)2192 fn drop(&mut self) {
2193 unsafe { clang_EvalResult_dispose(self.x) };
2194 }
2195 }
2196
2197 /// Target information obtained from libclang.
2198 #[derive(Debug)]
2199 pub 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
2206 impl TargetInfo {
2207 /// Tries to obtain target information from libclang.
new(tu: &TranslationUnit) -> Self2208 pub fn new(tu: &TranslationUnit) -> Self {
2209 let triple;
2210 let pointer_width;
2211 unsafe {
2212 let ti = clang_getTranslationUnitTargetInfo(tu.x);
2213 triple = cxstring_into_string(clang_TargetInfo_getTriple(ti));
2214 pointer_width = clang_TargetInfo_getPointerWidth(ti);
2215 clang_TargetInfo_dispose(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