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