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