1 //! Bindgen's core intermediate representation type.
2 
3 use super::super::codegen::{EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME};
4 use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult};
5 use super::annotations::Annotations;
6 use super::comment;
7 use super::comp::MethodKind;
8 use super::context::{BindgenContext, ItemId, PartialType, TypeId};
9 use super::derive::{
10     CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
11     CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd,
12 };
13 use super::dot::DotAttributes;
14 use super::function::{Function, FunctionKind};
15 use super::item_kind::ItemKind;
16 use super::layout::Opaque;
17 use super::module::Module;
18 use super::template::{AsTemplateParam, TemplateParameters};
19 use super::traversal::{EdgeKind, Trace, Tracer};
20 use super::ty::{Type, TypeKind};
21 use clang;
22 use clang_sys;
23 use lazycell::LazyCell;
24 use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
25 use regex;
26 use std::cell::Cell;
27 use std::collections::BTreeSet;
28 use std::fmt::Write;
29 use std::io;
30 use std::iter;
31 
32 /// A trait to get the canonical name from an item.
33 ///
34 /// This is the trait that will eventually isolate all the logic related to name
35 /// mangling and that kind of stuff.
36 ///
37 /// This assumes no nested paths, at some point I'll have to make it a more
38 /// complex thing.
39 ///
40 /// This name is required to be safe for Rust, that is, is not expected to
41 /// return any rust keyword from here.
42 pub trait ItemCanonicalName {
43     /// Get the canonical name for this item.
canonical_name(&self, ctx: &BindgenContext) -> String44     fn canonical_name(&self, ctx: &BindgenContext) -> String;
45 }
46 
47 /// The same, but specifies the path that needs to be followed to reach an item.
48 ///
49 /// To contrast with canonical_name, here's an example:
50 ///
51 /// ```c++
52 /// namespace foo {
53 ///     const BAR = 3;
54 /// }
55 /// ```
56 ///
57 /// For bar, the canonical path is `vec!["foo", "BAR"]`, while the canonical
58 /// name is just `"BAR"`.
59 pub trait ItemCanonicalPath {
60     /// Get the namespace-aware canonical path for this item. This means that if
61     /// namespaces are disabled, you'll get a single item, and otherwise you get
62     /// the whole path.
namespace_aware_canonical_path( &self, ctx: &BindgenContext, ) -> Vec<String>63     fn namespace_aware_canonical_path(
64         &self,
65         ctx: &BindgenContext,
66     ) -> Vec<String>;
67 
68     /// Get the canonical path for this item.
canonical_path(&self, ctx: &BindgenContext) -> Vec<String>69     fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String>;
70 }
71 
72 /// A trait for determining if some IR thing is opaque or not.
73 pub trait IsOpaque {
74     /// Extra context the IR thing needs to determine if it is opaque or not.
75     type Extra;
76 
77     /// Returns `true` if the thing is opaque, and `false` otherwise.
78     ///
79     /// May only be called when `ctx` is in the codegen phase.
is_opaque(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool80     fn is_opaque(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool;
81 }
82 
83 /// A trait for determining if some IR thing has type parameter in array or not.
84 pub trait HasTypeParamInArray {
85     /// Returns `true` if the thing has Array, and `false` otherwise.
has_type_param_in_array(&self, ctx: &BindgenContext) -> bool86     fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool;
87 }
88 
89 /// A trait for determining if some IR thing has float or not.
90 pub trait HasFloat {
91     /// Returns `true` if the thing has float, and `false` otherwise.
has_float(&self, ctx: &BindgenContext) -> bool92     fn has_float(&self, ctx: &BindgenContext) -> bool;
93 }
94 
95 /// A trait for iterating over an item and its parents and up its ancestor chain
96 /// up to (but not including) the implicit root module.
97 pub trait ItemAncestors {
98     /// Get an iterable over this item's ancestors.
ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>99     fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>;
100 }
101 
102 cfg_if! {
103     if #[cfg(testing_only_extra_assertions)] {
104         type DebugOnlyItemSet = ItemSet;
105     } else {
106         struct DebugOnlyItemSet;
107 
108         impl DebugOnlyItemSet {
109             fn new() -> Self {
110                 DebugOnlyItemSet
111             }
112 
113             fn contains(&self, _id: &ItemId) -> bool {
114                 false
115             }
116 
117             fn insert(&mut self, _id: ItemId) {}
118         }
119     }
120 }
121 
122 /// An iterator over an item and its ancestors.
123 pub struct ItemAncestorsIter<'a> {
124     item: ItemId,
125     ctx: &'a BindgenContext,
126     seen: DebugOnlyItemSet,
127 }
128 
129 impl<'a> ItemAncestorsIter<'a> {
new<Id: Into<ItemId>>(ctx: &'a BindgenContext, id: Id) -> Self130     fn new<Id: Into<ItemId>>(ctx: &'a BindgenContext, id: Id) -> Self {
131         ItemAncestorsIter {
132             item: id.into(),
133             ctx: ctx,
134             seen: DebugOnlyItemSet::new(),
135         }
136     }
137 }
138 
139 impl<'a> Iterator for ItemAncestorsIter<'a> {
140     type Item = ItemId;
141 
next(&mut self) -> Option<Self::Item>142     fn next(&mut self) -> Option<Self::Item> {
143         let item = self.ctx.resolve_item(self.item);
144 
145         if item.parent_id() == self.item {
146             None
147         } else {
148             self.item = item.parent_id();
149 
150             extra_assert!(!self.seen.contains(&item.id()));
151             self.seen.insert(item.id());
152 
153             Some(item.id())
154         }
155     }
156 }
157 
158 impl<T> AsTemplateParam for T
159 where
160     T: Copy + Into<ItemId>,
161 {
162     type Extra = ();
163 
as_template_param( &self, ctx: &BindgenContext, _: &(), ) -> Option<TypeId>164     fn as_template_param(
165         &self,
166         ctx: &BindgenContext,
167         _: &(),
168     ) -> Option<TypeId> {
169         ctx.resolve_item((*self).into()).as_template_param(ctx, &())
170     }
171 }
172 
173 impl AsTemplateParam for Item {
174     type Extra = ();
175 
as_template_param( &self, ctx: &BindgenContext, _: &(), ) -> Option<TypeId>176     fn as_template_param(
177         &self,
178         ctx: &BindgenContext,
179         _: &(),
180     ) -> Option<TypeId> {
181         self.kind.as_template_param(ctx, self)
182     }
183 }
184 
185 impl AsTemplateParam for ItemKind {
186     type Extra = Item;
187 
as_template_param( &self, ctx: &BindgenContext, item: &Item, ) -> Option<TypeId>188     fn as_template_param(
189         &self,
190         ctx: &BindgenContext,
191         item: &Item,
192     ) -> Option<TypeId> {
193         match *self {
194             ItemKind::Type(ref ty) => ty.as_template_param(ctx, item),
195             ItemKind::Module(..) |
196             ItemKind::Function(..) |
197             ItemKind::Var(..) => None,
198         }
199     }
200 }
201 
202 impl<T> ItemCanonicalName for T
203 where
204     T: Copy + Into<ItemId>,
205 {
canonical_name(&self, ctx: &BindgenContext) -> String206     fn canonical_name(&self, ctx: &BindgenContext) -> String {
207         debug_assert!(
208             ctx.in_codegen_phase(),
209             "You're not supposed to call this yet"
210         );
211         ctx.resolve_item(*self).canonical_name(ctx)
212     }
213 }
214 
215 impl<T> ItemCanonicalPath for T
216 where
217     T: Copy + Into<ItemId>,
218 {
namespace_aware_canonical_path( &self, ctx: &BindgenContext, ) -> Vec<String>219     fn namespace_aware_canonical_path(
220         &self,
221         ctx: &BindgenContext,
222     ) -> Vec<String> {
223         debug_assert!(
224             ctx.in_codegen_phase(),
225             "You're not supposed to call this yet"
226         );
227         ctx.resolve_item(*self).namespace_aware_canonical_path(ctx)
228     }
229 
canonical_path(&self, ctx: &BindgenContext) -> Vec<String>230     fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
231         debug_assert!(
232             ctx.in_codegen_phase(),
233             "You're not supposed to call this yet"
234         );
235         ctx.resolve_item(*self).canonical_path(ctx)
236     }
237 }
238 
239 impl<T> ItemAncestors for T
240 where
241     T: Copy + Into<ItemId>,
242 {
ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>243     fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a> {
244         ItemAncestorsIter::new(ctx, *self)
245     }
246 }
247 
248 impl ItemAncestors for Item {
ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>249     fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a> {
250         self.id().ancestors(ctx)
251     }
252 }
253 
254 impl<Id> Trace for Id
255 where
256     Id: Copy + Into<ItemId>,
257 {
258     type Extra = ();
259 
trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, extra: &()) where T: Tracer,260     fn trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, extra: &())
261     where
262         T: Tracer,
263     {
264         ctx.resolve_item(*self).trace(ctx, tracer, extra);
265     }
266 }
267 
268 impl Trace for Item {
269     type Extra = ();
270 
trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, _extra: &()) where T: Tracer,271     fn trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, _extra: &())
272     where
273         T: Tracer,
274     {
275         // Even if this item is blacklisted/hidden, we want to trace it. It is
276         // traversal iterators' consumers' responsibility to filter items as
277         // needed. Generally, this filtering happens in the implementation of
278         // `Iterator` for `WhitelistedItems`. Fully tracing blacklisted items is
279         // necessary for things like the template parameter usage analysis to
280         // function correctly.
281 
282         match *self.kind() {
283             ItemKind::Type(ref ty) => {
284                 // There are some types, like resolved type references, where we
285                 // don't want to stop collecting types even though they may be
286                 // opaque.
287                 if ty.should_be_traced_unconditionally() ||
288                     !self.is_opaque(ctx, &())
289                 {
290                     ty.trace(ctx, tracer, self);
291                 }
292             }
293             ItemKind::Function(ref fun) => {
294                 // Just the same way, it has not real meaning for a function to
295                 // be opaque, so we trace across it.
296                 tracer.visit(fun.signature().into());
297             }
298             ItemKind::Var(ref var) => {
299                 tracer.visit_kind(var.ty().into(), EdgeKind::VarType);
300             }
301             ItemKind::Module(_) => {
302                 // Module -> children edges are "weak", and we do not want to
303                 // trace them. If we did, then whitelisting wouldn't work as
304                 // expected: everything in every module would end up
305                 // whitelisted.
306                 //
307                 // TODO: make a new edge kind for module -> children edges and
308                 // filter them during whitelisting traversals.
309             }
310         }
311     }
312 }
313 
314 impl CanDeriveDebug for Item {
can_derive_debug(&self, ctx: &BindgenContext) -> bool315     fn can_derive_debug(&self, ctx: &BindgenContext) -> bool {
316         self.id().can_derive_debug(ctx)
317     }
318 }
319 
320 impl CanDeriveDefault for Item {
can_derive_default(&self, ctx: &BindgenContext) -> bool321     fn can_derive_default(&self, ctx: &BindgenContext) -> bool {
322         self.id().can_derive_default(ctx)
323     }
324 }
325 
326 impl CanDeriveCopy for Item {
can_derive_copy(&self, ctx: &BindgenContext) -> bool327     fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
328         self.id().can_derive_copy(ctx)
329     }
330 }
331 
332 impl CanDeriveHash for Item {
can_derive_hash(&self, ctx: &BindgenContext) -> bool333     fn can_derive_hash(&self, ctx: &BindgenContext) -> bool {
334         self.id().can_derive_hash(ctx)
335     }
336 }
337 
338 impl CanDerivePartialOrd for Item {
can_derive_partialord(&self, ctx: &BindgenContext) -> bool339     fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool {
340         self.id().can_derive_partialord(ctx)
341     }
342 }
343 
344 impl CanDerivePartialEq for Item {
can_derive_partialeq(&self, ctx: &BindgenContext) -> bool345     fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
346         self.id().can_derive_partialeq(ctx)
347     }
348 }
349 
350 impl CanDeriveEq for Item {
can_derive_eq(&self, ctx: &BindgenContext) -> bool351     fn can_derive_eq(&self, ctx: &BindgenContext) -> bool {
352         self.id().can_derive_eq(ctx)
353     }
354 }
355 
356 impl CanDeriveOrd for Item {
can_derive_ord(&self, ctx: &BindgenContext) -> bool357     fn can_derive_ord(&self, ctx: &BindgenContext) -> bool {
358         self.id().can_derive_ord(ctx)
359     }
360 }
361 
362 /// An item is the base of the bindgen representation, it can be either a
363 /// module, a type, a function, or a variable (see `ItemKind` for more
364 /// information).
365 ///
366 /// Items refer to each other by `ItemId`. Every item has its parent's
367 /// id. Depending on the kind of item this is, it may also refer to other items,
368 /// such as a compound type item referring to other types. Collectively, these
369 /// references form a graph.
370 ///
371 /// The entry-point to this graph is the "root module": a meta-item used to hold
372 /// all top-level items.
373 ///
374 /// An item may have a comment, and annotations (see the `annotations` module).
375 ///
376 /// Note that even though we parse all the types of annotations in comments, not
377 /// all of them apply to every item. Those rules are described in the
378 /// `annotations` module.
379 #[derive(Debug)]
380 pub struct Item {
381     /// This item's id.
382     id: ItemId,
383 
384     /// The item's local id, unique only amongst its siblings. Only used for
385     /// anonymous items.
386     ///
387     /// Lazily initialized in local_id().
388     ///
389     /// Note that only structs, unions, and enums get a local type id. In any
390     /// case this is an implementation detail.
391     local_id: LazyCell<usize>,
392 
393     /// The next local id to use for a child or template instantiation.
394     next_child_local_id: Cell<usize>,
395 
396     /// A cached copy of the canonical name, as returned by `canonical_name`.
397     ///
398     /// This is a fairly used operation during codegen so this makes bindgen
399     /// considerably faster in those cases.
400     canonical_name: LazyCell<String>,
401 
402     /// The path to use for whitelisting and other name-based checks, as
403     /// returned by `path_for_whitelisting`, lazily constructed.
404     path_for_whitelisting: LazyCell<Vec<String>>,
405 
406     /// A doc comment over the item, if any.
407     comment: Option<String>,
408     /// Annotations extracted from the doc comment, or the default ones
409     /// otherwise.
410     annotations: Annotations,
411     /// An item's parent id. This will most likely be a class where this item
412     /// was declared, or a module, etc.
413     ///
414     /// All the items have a parent, except the root module, in which case the
415     /// parent id is its own id.
416     parent_id: ItemId,
417     /// The item kind.
418     kind: ItemKind,
419 }
420 
421 impl AsRef<ItemId> for Item {
as_ref(&self) -> &ItemId422     fn as_ref(&self) -> &ItemId {
423         &self.id
424     }
425 }
426 
427 impl Item {
428     /// Construct a new `Item`.
new( id: ItemId, comment: Option<String>, annotations: Option<Annotations>, parent_id: ItemId, kind: ItemKind, ) -> Self429     pub fn new(
430         id: ItemId,
431         comment: Option<String>,
432         annotations: Option<Annotations>,
433         parent_id: ItemId,
434         kind: ItemKind,
435     ) -> Self {
436         debug_assert!(id != parent_id || kind.is_module());
437         Item {
438             id: id,
439             local_id: LazyCell::new(),
440             next_child_local_id: Cell::new(1),
441             canonical_name: LazyCell::new(),
442             path_for_whitelisting: LazyCell::new(),
443             parent_id: parent_id,
444             comment: comment,
445             annotations: annotations.unwrap_or_default(),
446             kind: kind,
447         }
448     }
449 
450     /// Construct a new opaque item type.
new_opaque_type( with_id: ItemId, ty: &clang::Type, ctx: &mut BindgenContext, ) -> TypeId451     pub fn new_opaque_type(
452         with_id: ItemId,
453         ty: &clang::Type,
454         ctx: &mut BindgenContext,
455     ) -> TypeId {
456         let ty = Opaque::from_clang_ty(ty, ctx);
457         let kind = ItemKind::Type(ty);
458         let parent = ctx.root_module().into();
459         ctx.add_item(Item::new(with_id, None, None, parent, kind), None, None);
460         with_id.as_type_id_unchecked()
461     }
462 
463     /// Get this `Item`'s identifier.
id(&self) -> ItemId464     pub fn id(&self) -> ItemId {
465         self.id
466     }
467 
468     /// Get this `Item`'s parent's identifier.
469     ///
470     /// For the root module, the parent's ID is its own ID.
parent_id(&self) -> ItemId471     pub fn parent_id(&self) -> ItemId {
472         self.parent_id
473     }
474 
475     /// Set this item's parent id.
476     ///
477     /// This is only used so replacements get generated in the proper module.
set_parent_for_replacement<Id: Into<ItemId>>(&mut self, id: Id)478     pub fn set_parent_for_replacement<Id: Into<ItemId>>(&mut self, id: Id) {
479         self.parent_id = id.into();
480     }
481 
482     /// Returns the depth this item is indented to.
483     ///
484     /// FIXME(emilio): This may need fixes for the enums within modules stuff.
codegen_depth(&self, ctx: &BindgenContext) -> usize485     pub fn codegen_depth(&self, ctx: &BindgenContext) -> usize {
486         if !ctx.options().enable_cxx_namespaces {
487             return 0;
488         }
489 
490         self.ancestors(ctx)
491             .filter(|id| {
492                 ctx.resolve_item(*id).as_module().map_or(false, |module| {
493                     !module.is_inline() ||
494                         ctx.options().conservative_inline_namespaces
495                 })
496             })
497             .count() +
498             1
499     }
500 
501     /// Get this `Item`'s comment, if it has any, already preprocessed and with
502     /// the right indentation.
comment(&self, ctx: &BindgenContext) -> Option<String>503     pub fn comment(&self, ctx: &BindgenContext) -> Option<String> {
504         if !ctx.options().generate_comments {
505             return None;
506         }
507 
508         self.comment.as_ref().map(|comment| {
509             comment::preprocess(comment, self.codegen_depth(ctx))
510         })
511     }
512 
513     /// What kind of item is this?
kind(&self) -> &ItemKind514     pub fn kind(&self) -> &ItemKind {
515         &self.kind
516     }
517 
518     /// Get a mutable reference to this item's kind.
kind_mut(&mut self) -> &mut ItemKind519     pub fn kind_mut(&mut self) -> &mut ItemKind {
520         &mut self.kind
521     }
522 
523     /// Get an identifier that differentiates this item from its siblings.
524     ///
525     /// This should stay relatively stable in the face of code motion outside or
526     /// below this item's lexical scope, meaning that this can be useful for
527     /// generating relatively stable identifiers within a scope.
local_id(&self, ctx: &BindgenContext) -> usize528     pub fn local_id(&self, ctx: &BindgenContext) -> usize {
529         *self.local_id.borrow_with(|| {
530             let parent = ctx.resolve_item(self.parent_id);
531             parent.next_child_local_id()
532         })
533     }
534 
535     /// Get an identifier that differentiates a child of this item of other
536     /// related items.
537     ///
538     /// This is currently used for anonymous items, and template instantiation
539     /// tests, in both cases in order to reduce noise when system headers are at
540     /// place.
next_child_local_id(&self) -> usize541     pub fn next_child_local_id(&self) -> usize {
542         let local_id = self.next_child_local_id.get();
543         self.next_child_local_id.set(local_id + 1);
544         local_id
545     }
546 
547     /// Returns whether this item is a top-level item, from the point of view of
548     /// bindgen.
549     ///
550     /// This point of view changes depending on whether namespaces are enabled
551     /// or not. That way, in the following example:
552     ///
553     /// ```c++
554     /// namespace foo {
555     ///     static int var;
556     /// }
557     /// ```
558     ///
559     /// `var` would be a toplevel item if namespaces are disabled, but won't if
560     /// they aren't.
561     ///
562     /// This function is used to determine when the codegen phase should call
563     /// `codegen` on an item, since any item that is not top-level will be
564     /// generated by its parent.
is_toplevel(&self, ctx: &BindgenContext) -> bool565     pub fn is_toplevel(&self, ctx: &BindgenContext) -> bool {
566         // FIXME: Workaround for some types falling behind when parsing weird
567         // stl classes, for example.
568         if ctx.options().enable_cxx_namespaces &&
569             self.kind().is_module() &&
570             self.id() != ctx.root_module()
571         {
572             return false;
573         }
574 
575         let mut parent = self.parent_id;
576         loop {
577             let parent_item = match ctx.resolve_item_fallible(parent) {
578                 Some(item) => item,
579                 None => return false,
580             };
581 
582             if parent_item.id() == ctx.root_module() {
583                 return true;
584             } else if ctx.options().enable_cxx_namespaces ||
585                 !parent_item.kind().is_module()
586             {
587                 return false;
588             }
589 
590             parent = parent_item.parent_id();
591         }
592     }
593 
594     /// Get a reference to this item's underlying `Type`. Panic if this is some
595     /// other kind of item.
expect_type(&self) -> &Type596     pub fn expect_type(&self) -> &Type {
597         self.kind().expect_type()
598     }
599 
600     /// Get a reference to this item's underlying `Type`, or `None` if this is
601     /// some other kind of item.
as_type(&self) -> Option<&Type>602     pub fn as_type(&self) -> Option<&Type> {
603         self.kind().as_type()
604     }
605 
606     /// Get a reference to this item's underlying `Function`. Panic if this is
607     /// some other kind of item.
expect_function(&self) -> &Function608     pub fn expect_function(&self) -> &Function {
609         self.kind().expect_function()
610     }
611 
612     /// Is this item a module?
is_module(&self) -> bool613     pub fn is_module(&self) -> bool {
614         match self.kind {
615             ItemKind::Module(..) => true,
616             _ => false,
617         }
618     }
619 
620     /// Get this item's annotations.
annotations(&self) -> &Annotations621     pub fn annotations(&self) -> &Annotations {
622         &self.annotations
623     }
624 
625     /// Whether this item should be blacklisted.
626     ///
627     /// This may be due to either annotations or to other kind of configuration.
is_blacklisted(&self, ctx: &BindgenContext) -> bool628     pub fn is_blacklisted(&self, ctx: &BindgenContext) -> bool {
629         debug_assert!(
630             ctx.in_codegen_phase(),
631             "You're not supposed to call this yet"
632         );
633         if self.annotations.hide() {
634             return true;
635         }
636 
637         let path = self.path_for_whitelisting(ctx);
638         let name = path[1..].join("::");
639         ctx.options().blacklisted_items.matches(&name) ||
640             match self.kind {
641                 ItemKind::Type(..) => {
642                     ctx.options().blacklisted_types.matches(&name) ||
643                         ctx.is_replaced_type(&path, self.id)
644                 }
645                 ItemKind::Function(..) => {
646                     ctx.options().blacklisted_functions.matches(&name)
647                 }
648                 // TODO: Add constant / namespace blacklisting?
649                 ItemKind::Var(..) | ItemKind::Module(..) => false,
650             }
651     }
652 
653     /// Is this a reference to another type?
is_type_ref(&self) -> bool654     pub fn is_type_ref(&self) -> bool {
655         self.as_type().map_or(false, |ty| ty.is_type_ref())
656     }
657 
658     /// Is this item a var type?
is_var(&self) -> bool659     pub fn is_var(&self) -> bool {
660         match *self.kind() {
661             ItemKind::Var(..) => true,
662             _ => false,
663         }
664     }
665 
666     /// Take out item NameOptions
name<'a>(&'a self, ctx: &'a BindgenContext) -> NameOptions<'a>667     pub fn name<'a>(&'a self, ctx: &'a BindgenContext) -> NameOptions<'a> {
668         NameOptions::new(self, ctx)
669     }
670 
671     /// Get the target item id for name generation.
name_target(&self, ctx: &BindgenContext) -> ItemId672     fn name_target(&self, ctx: &BindgenContext) -> ItemId {
673         let mut targets_seen = DebugOnlyItemSet::new();
674         let mut item = self;
675 
676         loop {
677             extra_assert!(!targets_seen.contains(&item.id()));
678             targets_seen.insert(item.id());
679 
680             if self.annotations().use_instead_of().is_some() {
681                 return self.id();
682             }
683 
684             match *item.kind() {
685                 ItemKind::Type(ref ty) => match *ty.kind() {
686                     TypeKind::ResolvedTypeRef(inner) => {
687                         item = ctx.resolve_item(inner);
688                     }
689                     TypeKind::TemplateInstantiation(ref inst) => {
690                         item = ctx.resolve_item(inst.template_definition());
691                     }
692                     _ => return item.id(),
693                 },
694                 _ => return item.id(),
695             }
696         }
697     }
698 
699     /// Create a fully disambiguated name for an item, including template
700     /// parameters if it is a type
full_disambiguated_name(&self, ctx: &BindgenContext) -> String701     pub fn full_disambiguated_name(&self, ctx: &BindgenContext) -> String {
702         let mut s = String::new();
703         let level = 0;
704         self.push_disambiguated_name(ctx, &mut s, level);
705         s
706     }
707 
708     /// Helper function for full_disambiguated_name
push_disambiguated_name( &self, ctx: &BindgenContext, to: &mut String, level: u8, )709     fn push_disambiguated_name(
710         &self,
711         ctx: &BindgenContext,
712         to: &mut String,
713         level: u8,
714     ) {
715         to.push_str(&self.canonical_name(ctx));
716         if let ItemKind::Type(ref ty) = *self.kind() {
717             if let TypeKind::TemplateInstantiation(ref inst) = *ty.kind() {
718                 to.push_str(&format!("_open{}_", level));
719                 for arg in inst.template_arguments() {
720                     arg.into_resolver()
721                         .through_type_refs()
722                         .resolve(ctx)
723                         .push_disambiguated_name(ctx, to, level + 1);
724                     to.push_str("_");
725                 }
726                 to.push_str(&format!("close{}", level));
727             }
728         }
729     }
730 
731     /// Get this function item's name, or `None` if this item is not a function.
func_name(&self) -> Option<&str>732     fn func_name(&self) -> Option<&str> {
733         match *self.kind() {
734             ItemKind::Function(ref func) => Some(func.name()),
735             _ => None,
736         }
737     }
738 
739     /// Get the overload index for this method. If this is not a method, return
740     /// `None`.
overload_index(&self, ctx: &BindgenContext) -> Option<usize>741     fn overload_index(&self, ctx: &BindgenContext) -> Option<usize> {
742         self.func_name().and_then(|func_name| {
743             let parent = ctx.resolve_item(self.parent_id());
744             if let ItemKind::Type(ref ty) = *parent.kind() {
745                 if let TypeKind::Comp(ref ci) = *ty.kind() {
746                     // All the constructors have the same name, so no need to
747                     // resolve and check.
748                     return ci
749                         .constructors()
750                         .iter()
751                         .position(|c| *c == self.id())
752                         .or_else(|| {
753                             ci.methods()
754                                 .iter()
755                                 .filter(|m| {
756                                     let item = ctx.resolve_item(m.signature());
757                                     let func = item.expect_function();
758                                     func.name() == func_name
759                                 })
760                                 .position(|m| m.signature() == self.id())
761                         });
762                 }
763             }
764 
765             None
766         })
767     }
768 
769     /// Get this item's base name (aka non-namespaced name).
base_name(&self, ctx: &BindgenContext) -> String770     fn base_name(&self, ctx: &BindgenContext) -> String {
771         if let Some(path) = self.annotations().use_instead_of() {
772             return path.last().unwrap().clone();
773         }
774 
775         match *self.kind() {
776             ItemKind::Var(ref var) => var.name().to_owned(),
777             ItemKind::Module(ref module) => {
778                 module.name().map(ToOwned::to_owned).unwrap_or_else(|| {
779                     format!("_bindgen_mod_{}", self.exposed_id(ctx))
780                 })
781             }
782             ItemKind::Type(ref ty) => {
783                 ty.sanitized_name(ctx).map(Into::into).unwrap_or_else(|| {
784                     format!("_bindgen_ty_{}", self.exposed_id(ctx))
785                 })
786             }
787             ItemKind::Function(ref fun) => {
788                 let mut name = fun.name().to_owned();
789 
790                 if let Some(idx) = self.overload_index(ctx) {
791                     if idx > 0 {
792                         write!(&mut name, "{}", idx).unwrap();
793                     }
794                 }
795 
796                 name
797             }
798         }
799     }
800 
is_anon(&self) -> bool801     fn is_anon(&self) -> bool {
802         match self.kind() {
803             ItemKind::Module(module) => module.name().is_none(),
804             ItemKind::Type(ty) => ty.name().is_none(),
805             ItemKind::Function(_) => false,
806             ItemKind::Var(_) => false,
807         }
808     }
809 
810     /// Get the canonical name without taking into account the replaces
811     /// annotation.
812     ///
813     /// This is the base logic used to implement hiding and replacing via
814     /// annotations, and also to implement proper name mangling.
815     ///
816     /// The idea is that each generated type in the same "level" (read: module
817     /// or namespace) has a unique canonical name.
818     ///
819     /// This name should be derived from the immutable state contained in the
820     /// type and the parent chain, since it should be consistent.
821     ///
822     /// If `BindgenOptions::disable_nested_struct_naming` is true then returned
823     /// name is the inner most non-anonymous name plus all the anonymous base names
824     /// that follows.
real_canonical_name( &self, ctx: &BindgenContext, opt: &NameOptions, ) -> String825     pub fn real_canonical_name(
826         &self,
827         ctx: &BindgenContext,
828         opt: &NameOptions,
829     ) -> String {
830         let target = ctx.resolve_item(self.name_target(ctx));
831 
832         // Short-circuit if the target has an override, and just use that.
833         if let Some(path) = target.annotations.use_instead_of() {
834             if ctx.options().enable_cxx_namespaces {
835                 return path.last().unwrap().clone();
836             }
837             return path.join("_").to_owned();
838         }
839 
840         let base_name = target.base_name(ctx);
841 
842         // Named template type arguments are never namespaced, and never
843         // mangled.
844         if target.is_template_param(ctx, &()) {
845             return base_name;
846         }
847 
848         // Ancestors' id iter
849         let mut ids_iter = target
850             .parent_id()
851             .ancestors(ctx)
852             .filter(|id| *id != ctx.root_module())
853             .take_while(|id| {
854                 // Stop iterating ancestors once we reach a non-inline namespace
855                 // when opt.within_namespaces is set.
856                 !opt.within_namespaces || !ctx.resolve_item(*id).is_module()
857             })
858             .filter(|id| {
859                 if !ctx.options().conservative_inline_namespaces {
860                     if let ItemKind::Module(ref module) =
861                         *ctx.resolve_item(*id).kind()
862                     {
863                         return !module.is_inline();
864                     }
865                 }
866 
867                 true
868             });
869 
870         let ids: Vec<_> = if ctx.options().disable_nested_struct_naming {
871             let mut ids = Vec::new();
872 
873             // If target is anonymous we need find its first named ancestor.
874             if target.is_anon() {
875                 while let Some(id) = ids_iter.next() {
876                     ids.push(id);
877 
878                     if !ctx.resolve_item(id).is_anon() {
879                         break;
880                     }
881                 }
882             }
883 
884             ids
885         } else {
886             ids_iter.collect()
887         };
888 
889         // Concatenate this item's ancestors' names together.
890         let mut names: Vec<_> = ids
891             .into_iter()
892             .map(|id| {
893                 let item = ctx.resolve_item(id);
894                 let target = ctx.resolve_item(item.name_target(ctx));
895                 target.base_name(ctx)
896             })
897             .filter(|name| !name.is_empty())
898             .collect();
899 
900         names.reverse();
901 
902         if !base_name.is_empty() {
903             names.push(base_name);
904         }
905 
906         let name = names.join("_");
907 
908         let name = if opt.user_mangled == UserMangled::Yes {
909             ctx.parse_callbacks()
910                 .and_then(|callbacks| callbacks.item_name(&name))
911                 .unwrap_or(name)
912         } else {
913             name
914         };
915 
916         ctx.rust_mangle(&name).into_owned()
917     }
918 
919     /// The exposed id that represents an unique id among the siblings of a
920     /// given item.
exposed_id(&self, ctx: &BindgenContext) -> String921     pub fn exposed_id(&self, ctx: &BindgenContext) -> String {
922         // Only use local ids for enums, classes, structs and union types.  All
923         // other items use their global id.
924         let ty_kind = self.kind().as_type().map(|t| t.kind());
925         if let Some(ty_kind) = ty_kind {
926             match *ty_kind {
927                 TypeKind::Comp(..) |
928                 TypeKind::TemplateInstantiation(..) |
929                 TypeKind::Enum(..) => return self.local_id(ctx).to_string(),
930                 _ => {}
931             }
932         }
933 
934         // Note that this `id_` prefix prevents (really unlikely) collisions
935         // between the global id and the local id of an item with the same
936         // parent.
937         format!("id_{}", self.id().as_usize())
938     }
939 
940     /// Get a reference to this item's `Module`, or `None` if this is not a
941     /// `Module` item.
as_module(&self) -> Option<&Module>942     pub fn as_module(&self) -> Option<&Module> {
943         match self.kind {
944             ItemKind::Module(ref module) => Some(module),
945             _ => None,
946         }
947     }
948 
949     /// Get a mutable reference to this item's `Module`, or `None` if this is
950     /// not a `Module` item.
as_module_mut(&mut self) -> Option<&mut Module>951     pub fn as_module_mut(&mut self) -> Option<&mut Module> {
952         match self.kind {
953             ItemKind::Module(ref mut module) => Some(module),
954             _ => None,
955         }
956     }
957 
958     /// Returns whether the item is a constified module enum
is_constified_enum_module(&self, ctx: &BindgenContext) -> bool959     fn is_constified_enum_module(&self, ctx: &BindgenContext) -> bool {
960         // Do not jump through aliases, except for aliases that point to a type
961         // with the same name, since we dont generate coe for them.
962         let item = self.id.into_resolver().through_type_refs().resolve(ctx);
963         let type_ = match *item.kind() {
964             ItemKind::Type(ref type_) => type_,
965             _ => return false,
966         };
967 
968         match *type_.kind() {
969             TypeKind::Enum(ref enum_) => {
970                 enum_.computed_enum_variation(ctx, self) ==
971                     EnumVariation::ModuleConsts
972             }
973             TypeKind::Alias(inner_id) => {
974                 // TODO(emilio): Make this "hop through type aliases that aren't
975                 // really generated" an option in `ItemResolver`?
976                 let inner_item = ctx.resolve_item(inner_id);
977                 let name = item.canonical_name(ctx);
978 
979                 if inner_item.canonical_name(ctx) == name {
980                     inner_item.is_constified_enum_module(ctx)
981                 } else {
982                     false
983                 }
984             }
985             _ => false,
986         }
987     }
988 
989     /// Is this item of a kind that is enabled for code generation?
is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool990     pub fn is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool {
991         let cc = &ctx.options().codegen_config;
992         match *self.kind() {
993             ItemKind::Module(..) => true,
994             ItemKind::Var(_) => cc.vars(),
995             ItemKind::Type(_) => cc.types(),
996             ItemKind::Function(ref f) => match f.kind() {
997                 FunctionKind::Function => cc.functions(),
998                 FunctionKind::Method(MethodKind::Constructor) => {
999                     cc.constructors()
1000                 }
1001                 FunctionKind::Method(MethodKind::Destructor) |
1002                 FunctionKind::Method(MethodKind::VirtualDestructor {
1003                     ..
1004                 }) => cc.destructors(),
1005                 FunctionKind::Method(MethodKind::Static) |
1006                 FunctionKind::Method(MethodKind::Normal) |
1007                 FunctionKind::Method(MethodKind::Virtual { .. }) => {
1008                     cc.methods()
1009                 }
1010             },
1011         }
1012     }
1013 
1014     /// Returns the path we should use for whitelisting / blacklisting, which
1015     /// doesn't include user-mangling.
path_for_whitelisting(&self, ctx: &BindgenContext) -> &Vec<String>1016     pub fn path_for_whitelisting(&self, ctx: &BindgenContext) -> &Vec<String> {
1017         self.path_for_whitelisting
1018             .borrow_with(|| self.compute_path(ctx, UserMangled::No))
1019     }
1020 
compute_path( &self, ctx: &BindgenContext, mangled: UserMangled, ) -> Vec<String>1021     fn compute_path(
1022         &self,
1023         ctx: &BindgenContext,
1024         mangled: UserMangled,
1025     ) -> Vec<String> {
1026         if let Some(path) = self.annotations().use_instead_of() {
1027             let mut ret =
1028                 vec![ctx.resolve_item(ctx.root_module()).name(ctx).get()];
1029             ret.extend_from_slice(path);
1030             return ret;
1031         }
1032 
1033         let target = ctx.resolve_item(self.name_target(ctx));
1034         let mut path: Vec<_> = target
1035             .ancestors(ctx)
1036             .chain(iter::once(ctx.root_module().into()))
1037             .map(|id| ctx.resolve_item(id))
1038             .filter(|item| {
1039                 item.id() == target.id() ||
1040                     item.as_module().map_or(false, |module| {
1041                         !module.is_inline() ||
1042                             ctx.options().conservative_inline_namespaces
1043                     })
1044             })
1045             .map(|item| {
1046                 ctx.resolve_item(item.name_target(ctx))
1047                     .name(ctx)
1048                     .within_namespaces()
1049                     .user_mangled(mangled)
1050                     .get()
1051             })
1052             .collect();
1053         path.reverse();
1054         path
1055     }
1056 }
1057 
1058 impl<T> IsOpaque for T
1059 where
1060     T: Copy + Into<ItemId>,
1061 {
1062     type Extra = ();
1063 
is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool1064     fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool {
1065         debug_assert!(
1066             ctx.in_codegen_phase(),
1067             "You're not supposed to call this yet"
1068         );
1069         ctx.resolve_item((*self).into()).is_opaque(ctx, &())
1070     }
1071 }
1072 
1073 impl IsOpaque for Item {
1074     type Extra = ();
1075 
is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool1076     fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool {
1077         debug_assert!(
1078             ctx.in_codegen_phase(),
1079             "You're not supposed to call this yet"
1080         );
1081         self.annotations.opaque() ||
1082             self.as_type().map_or(false, |ty| ty.is_opaque(ctx, self)) ||
1083             ctx.opaque_by_name(&self.path_for_whitelisting(ctx))
1084     }
1085 }
1086 
1087 impl<T> HasVtable for T
1088 where
1089     T: Copy + Into<ItemId>,
1090 {
has_vtable(&self, ctx: &BindgenContext) -> bool1091     fn has_vtable(&self, ctx: &BindgenContext) -> bool {
1092         let id: ItemId = (*self).into();
1093         id.as_type_id(ctx)
1094             .map_or(false, |id| match ctx.lookup_has_vtable(id) {
1095                 HasVtableResult::No => false,
1096                 _ => true,
1097             })
1098     }
1099 
has_vtable_ptr(&self, ctx: &BindgenContext) -> bool1100     fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
1101         let id: ItemId = (*self).into();
1102         id.as_type_id(ctx)
1103             .map_or(false, |id| match ctx.lookup_has_vtable(id) {
1104                 HasVtableResult::SelfHasVtable => true,
1105                 _ => false,
1106             })
1107     }
1108 }
1109 
1110 impl HasVtable for Item {
has_vtable(&self, ctx: &BindgenContext) -> bool1111     fn has_vtable(&self, ctx: &BindgenContext) -> bool {
1112         self.id().has_vtable(ctx)
1113     }
1114 
has_vtable_ptr(&self, ctx: &BindgenContext) -> bool1115     fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
1116         self.id().has_vtable_ptr(ctx)
1117     }
1118 }
1119 
1120 impl<T> Sizedness for T
1121 where
1122     T: Copy + Into<ItemId>,
1123 {
sizedness(&self, ctx: &BindgenContext) -> SizednessResult1124     fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult {
1125         let id: ItemId = (*self).into();
1126         id.as_type_id(ctx)
1127             .map_or(SizednessResult::default(), |id| ctx.lookup_sizedness(id))
1128     }
1129 }
1130 
1131 impl Sizedness for Item {
sizedness(&self, ctx: &BindgenContext) -> SizednessResult1132     fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult {
1133         self.id().sizedness(ctx)
1134     }
1135 }
1136 
1137 impl<T> HasTypeParamInArray for T
1138 where
1139     T: Copy + Into<ItemId>,
1140 {
has_type_param_in_array(&self, ctx: &BindgenContext) -> bool1141     fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool {
1142         debug_assert!(
1143             ctx.in_codegen_phase(),
1144             "You're not supposed to call this yet"
1145         );
1146         ctx.lookup_has_type_param_in_array(*self)
1147     }
1148 }
1149 
1150 impl HasTypeParamInArray for Item {
has_type_param_in_array(&self, ctx: &BindgenContext) -> bool1151     fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool {
1152         debug_assert!(
1153             ctx.in_codegen_phase(),
1154             "You're not supposed to call this yet"
1155         );
1156         ctx.lookup_has_type_param_in_array(self.id())
1157     }
1158 }
1159 
1160 impl<T> HasFloat for T
1161 where
1162     T: Copy + Into<ItemId>,
1163 {
has_float(&self, ctx: &BindgenContext) -> bool1164     fn has_float(&self, ctx: &BindgenContext) -> bool {
1165         debug_assert!(
1166             ctx.in_codegen_phase(),
1167             "You're not supposed to call this yet"
1168         );
1169         ctx.lookup_has_float(*self)
1170     }
1171 }
1172 
1173 impl HasFloat for Item {
has_float(&self, ctx: &BindgenContext) -> bool1174     fn has_float(&self, ctx: &BindgenContext) -> bool {
1175         debug_assert!(
1176             ctx.in_codegen_phase(),
1177             "You're not supposed to call this yet"
1178         );
1179         ctx.lookup_has_float(self.id())
1180     }
1181 }
1182 
1183 /// A set of items.
1184 pub type ItemSet = BTreeSet<ItemId>;
1185 
1186 impl DotAttributes for Item {
dot_attributes<W>( &self, ctx: &BindgenContext, out: &mut W, ) -> io::Result<()> where W: io::Write,1187     fn dot_attributes<W>(
1188         &self,
1189         ctx: &BindgenContext,
1190         out: &mut W,
1191     ) -> io::Result<()>
1192     where
1193         W: io::Write,
1194     {
1195         writeln!(
1196             out,
1197             "<tr><td>{:?}</td></tr>
1198                        <tr><td>name</td><td>{}</td></tr>",
1199             self.id,
1200             self.name(ctx).get()
1201         )?;
1202 
1203         if self.is_opaque(ctx, &()) {
1204             writeln!(out, "<tr><td>opaque</td><td>true</td></tr>")?;
1205         }
1206 
1207         self.kind.dot_attributes(ctx, out)
1208     }
1209 }
1210 
1211 impl<T> TemplateParameters for T
1212 where
1213     T: Copy + Into<ItemId>,
1214 {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>1215     fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1216         ctx.resolve_item_fallible(*self)
1217             .map_or(vec![], |item| item.self_template_params(ctx))
1218     }
1219 }
1220 
1221 impl TemplateParameters for Item {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>1222     fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1223         self.kind.self_template_params(ctx)
1224     }
1225 }
1226 
1227 impl TemplateParameters for ItemKind {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>1228     fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1229         match *self {
1230             ItemKind::Type(ref ty) => ty.self_template_params(ctx),
1231             // If we start emitting bindings to explicitly instantiated
1232             // functions, then we'll need to check ItemKind::Function for
1233             // template params.
1234             ItemKind::Function(_) | ItemKind::Module(_) | ItemKind::Var(_) => {
1235                 vec![]
1236             }
1237         }
1238     }
1239 }
1240 
1241 // An utility function to handle recursing inside nested types.
visit_child( cur: clang::Cursor, id: ItemId, ty: &clang::Type, parent_id: Option<ItemId>, ctx: &mut BindgenContext, result: &mut Result<TypeId, ParseError>, ) -> clang_sys::CXChildVisitResult1242 fn visit_child(
1243     cur: clang::Cursor,
1244     id: ItemId,
1245     ty: &clang::Type,
1246     parent_id: Option<ItemId>,
1247     ctx: &mut BindgenContext,
1248     result: &mut Result<TypeId, ParseError>,
1249 ) -> clang_sys::CXChildVisitResult {
1250     use clang_sys::*;
1251     if result.is_ok() {
1252         return CXChildVisit_Break;
1253     }
1254 
1255     *result = Item::from_ty_with_id(id, ty, cur, parent_id, ctx);
1256 
1257     match *result {
1258         Ok(..) => CXChildVisit_Break,
1259         Err(ParseError::Recurse) => {
1260             cur.visit(|c| visit_child(c, id, ty, parent_id, ctx, result));
1261             CXChildVisit_Continue
1262         }
1263         Err(ParseError::Continue) => CXChildVisit_Continue,
1264     }
1265 }
1266 
1267 impl ClangItemParser for Item {
builtin_type( kind: TypeKind, is_const: bool, ctx: &mut BindgenContext, ) -> TypeId1268     fn builtin_type(
1269         kind: TypeKind,
1270         is_const: bool,
1271         ctx: &mut BindgenContext,
1272     ) -> TypeId {
1273         // Feel free to add more here, I'm just lazy.
1274         match kind {
1275             TypeKind::Void |
1276             TypeKind::Int(..) |
1277             TypeKind::Pointer(..) |
1278             TypeKind::Float(..) => {}
1279             _ => panic!("Unsupported builtin type"),
1280         }
1281 
1282         let ty = Type::new(None, None, kind, is_const);
1283         let id = ctx.next_item_id();
1284         let module = ctx.root_module().into();
1285         ctx.add_item(
1286             Item::new(id, None, None, module, ItemKind::Type(ty)),
1287             None,
1288             None,
1289         );
1290         id.as_type_id_unchecked()
1291     }
1292 
parse( cursor: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> Result<ItemId, ParseError>1293     fn parse(
1294         cursor: clang::Cursor,
1295         parent_id: Option<ItemId>,
1296         ctx: &mut BindgenContext,
1297     ) -> Result<ItemId, ParseError> {
1298         use clang_sys::*;
1299         use ir::var::Var;
1300 
1301         if !cursor.is_valid() {
1302             return Err(ParseError::Continue);
1303         }
1304 
1305         let comment = cursor.raw_comment();
1306         let annotations = Annotations::new(&cursor);
1307 
1308         let current_module = ctx.current_module().into();
1309         let relevant_parent_id = parent_id.unwrap_or(current_module);
1310 
1311         macro_rules! try_parse {
1312             ($what:ident) => {
1313                 match $what::parse(cursor, ctx) {
1314                     Ok(ParseResult::New(item, declaration)) => {
1315                         let id = ctx.next_item_id();
1316 
1317                         ctx.add_item(
1318                             Item::new(
1319                                 id,
1320                                 comment,
1321                                 annotations,
1322                                 relevant_parent_id,
1323                                 ItemKind::$what(item),
1324                             ),
1325                             declaration,
1326                             Some(cursor),
1327                         );
1328                         return Ok(id);
1329                     }
1330                     Ok(ParseResult::AlreadyResolved(id)) => {
1331                         return Ok(id);
1332                     }
1333                     Err(ParseError::Recurse) => {
1334                         return Err(ParseError::Recurse)
1335                     }
1336                     Err(ParseError::Continue) => {}
1337                 }
1338             };
1339         }
1340 
1341         try_parse!(Module);
1342 
1343         // NOTE: Is extremely important to parse functions and vars **before**
1344         // types.  Otherwise we can parse a function declaration as a type
1345         // (which is legal), and lose functions to generate.
1346         //
1347         // In general, I'm not totally confident this split between
1348         // ItemKind::Function and TypeKind::FunctionSig is totally worth it, but
1349         // I guess we can try.
1350         try_parse!(Function);
1351         try_parse!(Var);
1352 
1353         // Types are sort of special, so to avoid parsing template classes
1354         // twice, handle them separately.
1355         {
1356             let definition = cursor.definition();
1357             let applicable_cursor = definition.unwrap_or(cursor);
1358 
1359             let relevant_parent_id = match definition {
1360                 Some(definition) => {
1361                     if definition != cursor {
1362                         ctx.add_semantic_parent(definition, relevant_parent_id);
1363                         return Ok(Item::from_ty_or_ref(
1364                             applicable_cursor.cur_type(),
1365                             cursor,
1366                             parent_id,
1367                             ctx,
1368                         )
1369                         .into());
1370                     }
1371                     ctx.known_semantic_parent(definition)
1372                         .or(parent_id)
1373                         .unwrap_or(ctx.current_module().into())
1374                 }
1375                 None => relevant_parent_id,
1376             };
1377 
1378             match Item::from_ty(
1379                 &applicable_cursor.cur_type(),
1380                 applicable_cursor,
1381                 Some(relevant_parent_id),
1382                 ctx,
1383             ) {
1384                 Ok(ty) => return Ok(ty.into()),
1385                 Err(ParseError::Recurse) => return Err(ParseError::Recurse),
1386                 Err(ParseError::Continue) => {}
1387             }
1388         }
1389 
1390         // Guess how does clang treat extern "C" blocks?
1391         if cursor.kind() == CXCursor_UnexposedDecl {
1392             Err(ParseError::Recurse)
1393         } else {
1394             // We whitelist cursors here known to be unhandled, to prevent being
1395             // too noisy about this.
1396             match cursor.kind() {
1397                 CXCursor_MacroDefinition |
1398                 CXCursor_MacroExpansion |
1399                 CXCursor_UsingDeclaration |
1400                 CXCursor_UsingDirective |
1401                 CXCursor_StaticAssert |
1402                 CXCursor_FunctionTemplate => {
1403                     debug!(
1404                         "Unhandled cursor kind {:?}: {:?}",
1405                         cursor.kind(),
1406                         cursor
1407                     );
1408                 }
1409                 CXCursor_InclusionDirective => {
1410                     let file = cursor.get_included_file_name();
1411                     match file {
1412                         None => {
1413                             warn!(
1414                                 "Inclusion of a nameless file in {:?}",
1415                                 cursor
1416                             );
1417                         }
1418                         Some(filename) => {
1419                             if let Some(cb) = ctx.parse_callbacks() {
1420                                 cb.include_file(&filename)
1421                             }
1422                         }
1423                     }
1424                 }
1425                 _ => {
1426                     // ignore toplevel operator overloads
1427                     let spelling = cursor.spelling();
1428                     if !spelling.starts_with("operator") {
1429                         error!(
1430                             "Unhandled cursor kind {:?}: {:?}",
1431                             cursor.kind(),
1432                             cursor
1433                         );
1434                     }
1435                 }
1436             }
1437 
1438             Err(ParseError::Continue)
1439         }
1440     }
1441 
from_ty_or_ref( ty: clang::Type, location: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> TypeId1442     fn from_ty_or_ref(
1443         ty: clang::Type,
1444         location: clang::Cursor,
1445         parent_id: Option<ItemId>,
1446         ctx: &mut BindgenContext,
1447     ) -> TypeId {
1448         let id = ctx.next_item_id();
1449         Self::from_ty_or_ref_with_id(id, ty, location, parent_id, ctx)
1450     }
1451 
1452     /// Parse a C++ type. If we find a reference to a type that has not been
1453     /// defined yet, use `UnresolvedTypeRef` as a placeholder.
1454     ///
1455     /// This logic is needed to avoid parsing items with the incorrect parent
1456     /// and it's sort of complex to explain, so I'll just point to
1457     /// `tests/headers/typeref.hpp` to see the kind of constructs that forced
1458     /// this.
1459     ///
1460     /// Typerefs are resolved once parsing is completely done, see
1461     /// `BindgenContext::resolve_typerefs`.
from_ty_or_ref_with_id( potential_id: ItemId, ty: clang::Type, location: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> TypeId1462     fn from_ty_or_ref_with_id(
1463         potential_id: ItemId,
1464         ty: clang::Type,
1465         location: clang::Cursor,
1466         parent_id: Option<ItemId>,
1467         ctx: &mut BindgenContext,
1468     ) -> TypeId {
1469         debug!(
1470             "from_ty_or_ref_with_id: {:?} {:?}, {:?}, {:?}",
1471             potential_id, ty, location, parent_id
1472         );
1473 
1474         if ctx.collected_typerefs() {
1475             debug!("refs already collected, resolving directly");
1476             return Item::from_ty_with_id(
1477                 potential_id,
1478                 &ty,
1479                 location,
1480                 parent_id,
1481                 ctx,
1482             )
1483             .unwrap_or_else(|_| Item::new_opaque_type(potential_id, &ty, ctx));
1484         }
1485 
1486         if let Some(ty) = ctx.builtin_or_resolved_ty(
1487             potential_id,
1488             parent_id,
1489             &ty,
1490             Some(location),
1491         ) {
1492             debug!("{:?} already resolved: {:?}", ty, location);
1493             return ty;
1494         }
1495 
1496         debug!("New unresolved type reference: {:?}, {:?}", ty, location);
1497 
1498         let is_const = ty.is_const();
1499         let kind = TypeKind::UnresolvedTypeRef(ty, location, parent_id);
1500         let current_module = ctx.current_module();
1501 
1502         ctx.add_item(
1503             Item::new(
1504                 potential_id,
1505                 None,
1506                 None,
1507                 parent_id.unwrap_or(current_module.into()),
1508                 ItemKind::Type(Type::new(None, None, kind, is_const)),
1509             ),
1510             None,
1511             None,
1512         );
1513         potential_id.as_type_id_unchecked()
1514     }
1515 
from_ty( ty: &clang::Type, location: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> Result<TypeId, ParseError>1516     fn from_ty(
1517         ty: &clang::Type,
1518         location: clang::Cursor,
1519         parent_id: Option<ItemId>,
1520         ctx: &mut BindgenContext,
1521     ) -> Result<TypeId, ParseError> {
1522         let id = ctx.next_item_id();
1523         Item::from_ty_with_id(id, ty, location, parent_id, ctx)
1524     }
1525 
1526     /// This is one of the trickiest methods you'll find (probably along with
1527     /// some of the ones that handle templates in `BindgenContext`).
1528     ///
1529     /// This method parses a type, given the potential id of that type (if
1530     /// parsing it was correct), an optional location we're scanning, which is
1531     /// critical some times to obtain information, an optional parent item id,
1532     /// that will, if it's `None`, become the current module id, and the
1533     /// context.
from_ty_with_id( id: ItemId, ty: &clang::Type, location: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> Result<TypeId, ParseError>1534     fn from_ty_with_id(
1535         id: ItemId,
1536         ty: &clang::Type,
1537         location: clang::Cursor,
1538         parent_id: Option<ItemId>,
1539         ctx: &mut BindgenContext,
1540     ) -> Result<TypeId, ParseError> {
1541         use clang_sys::*;
1542 
1543         debug!(
1544             "Item::from_ty_with_id: {:?}\n\
1545              \tty = {:?},\n\
1546              \tlocation = {:?}",
1547             id, ty, location
1548         );
1549 
1550         if ty.kind() == clang_sys::CXType_Unexposed ||
1551             location.cur_type().kind() == clang_sys::CXType_Unexposed
1552         {
1553             if ty.is_associated_type() ||
1554                 location.cur_type().is_associated_type()
1555             {
1556                 return Ok(Item::new_opaque_type(id, ty, ctx));
1557             }
1558 
1559             if let Some(param_id) = Item::type_param(None, location, ctx) {
1560                 return Ok(ctx.build_ty_wrapper(id, param_id, None, ty));
1561             }
1562         }
1563 
1564         let decl = {
1565             let decl = ty.declaration();
1566             decl.definition().unwrap_or(decl)
1567         };
1568 
1569         let comment = decl.raw_comment().or_else(|| location.raw_comment());
1570         let annotations =
1571             Annotations::new(&decl).or_else(|| Annotations::new(&location));
1572 
1573         if let Some(ref annotations) = annotations {
1574             if let Some(ref replaced) = annotations.use_instead_of() {
1575                 ctx.replace(replaced, id);
1576             }
1577         }
1578 
1579         if let Some(ty) =
1580             ctx.builtin_or_resolved_ty(id, parent_id, ty, Some(location))
1581         {
1582             return Ok(ty);
1583         }
1584 
1585         // First, check we're not recursing.
1586         let mut valid_decl = decl.kind() != CXCursor_NoDeclFound;
1587         let declaration_to_look_for = if valid_decl {
1588             decl.canonical()
1589         } else if location.kind() == CXCursor_ClassTemplate {
1590             valid_decl = true;
1591             location
1592         } else {
1593             decl
1594         };
1595 
1596         if valid_decl {
1597             if let Some(partial) = ctx
1598                 .currently_parsed_types()
1599                 .iter()
1600                 .find(|ty| *ty.decl() == declaration_to_look_for)
1601             {
1602                 debug!("Avoiding recursion parsing type: {:?}", ty);
1603                 // Unchecked because we haven't finished this type yet.
1604                 return Ok(partial.id().as_type_id_unchecked());
1605             }
1606         }
1607 
1608         let current_module = ctx.current_module().into();
1609         let partial_ty = PartialType::new(declaration_to_look_for, id);
1610         if valid_decl {
1611             ctx.begin_parsing(partial_ty);
1612         }
1613 
1614         let result = Type::from_clang_ty(id, ty, location, parent_id, ctx);
1615         let relevant_parent_id = parent_id.unwrap_or(current_module);
1616         let ret = match result {
1617             Ok(ParseResult::AlreadyResolved(ty)) => {
1618                 Ok(ty.as_type_id_unchecked())
1619             }
1620             Ok(ParseResult::New(item, declaration)) => {
1621                 ctx.add_item(
1622                     Item::new(
1623                         id,
1624                         comment,
1625                         annotations,
1626                         relevant_parent_id,
1627                         ItemKind::Type(item),
1628                     ),
1629                     declaration,
1630                     Some(location),
1631                 );
1632                 Ok(id.as_type_id_unchecked())
1633             }
1634             Err(ParseError::Continue) => Err(ParseError::Continue),
1635             Err(ParseError::Recurse) => {
1636                 debug!("Item::from_ty recursing in the ast");
1637                 let mut result = Err(ParseError::Recurse);
1638 
1639                 // Need to pop here, otherwise we'll get stuck.
1640                 //
1641                 // TODO: Find a nicer interface, really. Also, the
1642                 // declaration_to_look_for suspiciously shares a lot of
1643                 // logic with ir::context, so we should refactor that.
1644                 if valid_decl {
1645                     let finished = ctx.finish_parsing();
1646                     assert_eq!(*finished.decl(), declaration_to_look_for);
1647                 }
1648 
1649                 location.visit(|cur| {
1650                     visit_child(cur, id, ty, parent_id, ctx, &mut result)
1651                 });
1652 
1653                 if valid_decl {
1654                     let partial_ty =
1655                         PartialType::new(declaration_to_look_for, id);
1656                     ctx.begin_parsing(partial_ty);
1657                 }
1658 
1659                 // If we have recursed into the AST all we know, and we still
1660                 // haven't found what we've got, let's just try and make a named
1661                 // type.
1662                 //
1663                 // This is what happens with some template members, for example.
1664                 if let Err(ParseError::Recurse) = result {
1665                     warn!(
1666                         "Unknown type, assuming named template type: \
1667                          id = {:?}; spelling = {}",
1668                         id,
1669                         ty.spelling()
1670                     );
1671                     Item::type_param(Some(id), location, ctx)
1672                         .map(Ok)
1673                         .unwrap_or(Err(ParseError::Recurse))
1674                 } else {
1675                     result
1676                 }
1677             }
1678         };
1679 
1680         if valid_decl {
1681             let partial_ty = ctx.finish_parsing();
1682             assert_eq!(*partial_ty.decl(), declaration_to_look_for);
1683         }
1684 
1685         ret
1686     }
1687 
1688     /// A named type is a template parameter, e.g., the "T" in Foo<T>. They're
1689     /// always local so it's the only exception when there's no declaration for
1690     /// a type.
type_param( with_id: Option<ItemId>, location: clang::Cursor, ctx: &mut BindgenContext, ) -> Option<TypeId>1691     fn type_param(
1692         with_id: Option<ItemId>,
1693         location: clang::Cursor,
1694         ctx: &mut BindgenContext,
1695     ) -> Option<TypeId> {
1696         let ty = location.cur_type();
1697 
1698         debug!(
1699             "Item::type_param:\n\
1700              \twith_id = {:?},\n\
1701              \tty = {} {:?},\n\
1702              \tlocation: {:?}",
1703             with_id,
1704             ty.spelling(),
1705             ty,
1706             location
1707         );
1708 
1709         if ty.kind() != clang_sys::CXType_Unexposed {
1710             // If the given cursor's type's kind is not Unexposed, then we
1711             // aren't looking at a template parameter. This check may need to be
1712             // updated in the future if they start properly exposing template
1713             // type parameters.
1714             return None;
1715         }
1716 
1717         let ty_spelling = ty.spelling();
1718 
1719         // Clang does not expose any information about template type parameters
1720         // via their clang::Type, nor does it give us their canonical cursors
1721         // the straightforward way. However, there are three situations from
1722         // which we can find the definition of the template type parameter, if
1723         // the cursor is indeed looking at some kind of a template type
1724         // parameter or use of one:
1725         //
1726         // 1. The cursor is pointing at the template type parameter's
1727         // definition. This is the trivial case.
1728         //
1729         //     (kind = TemplateTypeParameter, ...)
1730         //
1731         // 2. The cursor is pointing at a TypeRef whose referenced() cursor is
1732         // situation (1).
1733         //
1734         //     (kind = TypeRef,
1735         //      referenced = (kind = TemplateTypeParameter, ...),
1736         //      ...)
1737         //
1738         // 3. The cursor is pointing at some use of a template type parameter
1739         // (for example, in a FieldDecl), and this cursor has a child cursor
1740         // whose spelling is the same as the parent's type's spelling, and whose
1741         // kind is a TypeRef of the situation (2) variety.
1742         //
1743         //    (kind = FieldDecl,
1744         //     type = (kind = Unexposed,
1745         //             spelling = "T",
1746         //             ...),
1747         //     children =
1748         //        (kind = TypeRef,
1749         //         spelling = "T",
1750         //         referenced = (kind = TemplateTypeParameter,
1751         //                       spelling = "T",
1752         //                       ...),
1753         //         ...)
1754         //     ...)
1755         //
1756         // TODO: The alternative to this hacky pattern matching would be to
1757         // maintain proper scopes of template parameters while parsing and use
1758         // de Brujin indices to access template parameters, which clang exposes
1759         // in the cursor's type's canonical type's spelling:
1760         // "type-parameter-x-y". That is probably a better approach long-term,
1761         // but maintaining these scopes properly would require more changes to
1762         // the whole libclang -> IR parsing code.
1763 
1764         fn is_template_with_spelling(
1765             refd: &clang::Cursor,
1766             spelling: &str,
1767         ) -> bool {
1768             lazy_static! {
1769                 static ref ANON_TYPE_PARAM_RE: regex::Regex =
1770                     regex::Regex::new(r"^type\-parameter\-\d+\-\d+$").unwrap();
1771             }
1772 
1773             if refd.kind() != clang_sys::CXCursor_TemplateTypeParameter {
1774                 return false;
1775             }
1776 
1777             let refd_spelling = refd.spelling();
1778             refd_spelling == spelling ||
1779                 // Allow for anonymous template parameters.
1780                 (refd_spelling.is_empty() && ANON_TYPE_PARAM_RE.is_match(spelling.as_ref()))
1781         }
1782 
1783         let definition = if is_template_with_spelling(&location, &ty_spelling) {
1784             // Situation (1)
1785             location
1786         } else if location.kind() == clang_sys::CXCursor_TypeRef {
1787             // Situation (2)
1788             match location.referenced() {
1789                 Some(refd)
1790                     if is_template_with_spelling(&refd, &ty_spelling) =>
1791                 {
1792                     refd
1793                 }
1794                 _ => return None,
1795             }
1796         } else {
1797             // Situation (3)
1798             let mut definition = None;
1799 
1800             location.visit(|child| {
1801                 let child_ty = child.cur_type();
1802                 if child_ty.kind() == clang_sys::CXCursor_TypeRef &&
1803                     child_ty.spelling() == ty_spelling
1804                 {
1805                     match child.referenced() {
1806                         Some(refd)
1807                             if is_template_with_spelling(
1808                                 &refd,
1809                                 &ty_spelling,
1810                             ) =>
1811                         {
1812                             definition = Some(refd);
1813                             return clang_sys::CXChildVisit_Break;
1814                         }
1815                         _ => {}
1816                     }
1817                 }
1818 
1819                 clang_sys::CXChildVisit_Continue
1820             });
1821 
1822             if let Some(def) = definition {
1823                 def
1824             } else {
1825                 return None;
1826             }
1827         };
1828         assert!(is_template_with_spelling(&definition, &ty_spelling));
1829 
1830         // Named types are always parented to the root module. They are never
1831         // referenced with namespace prefixes, and they can't inherit anything
1832         // from their parent either, so it is simplest to just hang them off
1833         // something we know will always exist.
1834         let parent = ctx.root_module().into();
1835 
1836         if let Some(id) = ctx.get_type_param(&definition) {
1837             if let Some(with_id) = with_id {
1838                 return Some(ctx.build_ty_wrapper(
1839                     with_id,
1840                     id,
1841                     Some(parent),
1842                     &ty,
1843                 ));
1844             } else {
1845                 return Some(id);
1846             }
1847         }
1848 
1849         // See tests/headers/const_tparam.hpp and
1850         // tests/headers/variadic_tname.hpp.
1851         let name = ty_spelling.replace("const ", "").replace(".", "");
1852 
1853         let id = with_id.unwrap_or_else(|| ctx.next_item_id());
1854         let item = Item::new(
1855             id,
1856             None,
1857             None,
1858             parent,
1859             ItemKind::Type(Type::named(name)),
1860         );
1861         ctx.add_type_param(item, definition);
1862         Some(id.as_type_id_unchecked())
1863     }
1864 }
1865 
1866 impl ItemCanonicalName for Item {
canonical_name(&self, ctx: &BindgenContext) -> String1867     fn canonical_name(&self, ctx: &BindgenContext) -> String {
1868         debug_assert!(
1869             ctx.in_codegen_phase(),
1870             "You're not supposed to call this yet"
1871         );
1872         self.canonical_name
1873             .borrow_with(|| {
1874                 let in_namespace = ctx.options().enable_cxx_namespaces ||
1875                     ctx.options().disable_name_namespacing;
1876 
1877                 if in_namespace {
1878                     self.name(ctx).within_namespaces().get()
1879                 } else {
1880                     self.name(ctx).get()
1881                 }
1882             })
1883             .clone()
1884     }
1885 }
1886 
1887 impl ItemCanonicalPath for Item {
namespace_aware_canonical_path( &self, ctx: &BindgenContext, ) -> Vec<String>1888     fn namespace_aware_canonical_path(
1889         &self,
1890         ctx: &BindgenContext,
1891     ) -> Vec<String> {
1892         let mut path = self.canonical_path(ctx);
1893 
1894         // ASSUMPTION: (disable_name_namespacing && cxx_namespaces)
1895         // is equivalent to
1896         // disable_name_namespacing
1897         if ctx.options().disable_name_namespacing {
1898             // Only keep the last item in path
1899             let split_idx = path.len() - 1;
1900             path = path.split_off(split_idx);
1901         } else if !ctx.options().enable_cxx_namespaces {
1902             // Ignore first item "root"
1903             path = vec![path[1..].join("_")];
1904         }
1905 
1906         if self.is_constified_enum_module(ctx) {
1907             path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into());
1908         }
1909 
1910         return path;
1911     }
1912 
canonical_path(&self, ctx: &BindgenContext) -> Vec<String>1913     fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
1914         self.compute_path(ctx, UserMangled::Yes)
1915     }
1916 }
1917 
1918 /// Whether to use the user-mangled name (mangled by the `item_name` callback or
1919 /// not.
1920 ///
1921 /// Most of the callers probably want just yes, but the ones dealing with
1922 /// whitelisting and blacklisting don't.
1923 #[derive(Copy, Clone, Debug, PartialEq)]
1924 enum UserMangled {
1925     No,
1926     Yes,
1927 }
1928 
1929 /// Builder struct for naming variations, which hold inside different
1930 /// flags for naming options.
1931 #[derive(Debug)]
1932 pub struct NameOptions<'a> {
1933     item: &'a Item,
1934     ctx: &'a BindgenContext,
1935     within_namespaces: bool,
1936     user_mangled: UserMangled,
1937 }
1938 
1939 impl<'a> NameOptions<'a> {
1940     /// Construct a new `NameOptions`
new(item: &'a Item, ctx: &'a BindgenContext) -> Self1941     pub fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self {
1942         NameOptions {
1943             item: item,
1944             ctx: ctx,
1945             within_namespaces: false,
1946             user_mangled: UserMangled::Yes,
1947         }
1948     }
1949 
1950     /// Construct the name without the item's containing C++ namespaces mangled
1951     /// into it. In other words, the item's name within the item's namespace.
within_namespaces(&mut self) -> &mut Self1952     pub fn within_namespaces(&mut self) -> &mut Self {
1953         self.within_namespaces = true;
1954         self
1955     }
1956 
user_mangled(&mut self, user_mangled: UserMangled) -> &mut Self1957     fn user_mangled(&mut self, user_mangled: UserMangled) -> &mut Self {
1958         self.user_mangled = user_mangled;
1959         self
1960     }
1961 
1962     /// Construct a name `String`
get(&self) -> String1963     pub fn get(&self) -> String {
1964         self.item.real_canonical_name(self.ctx, self)
1965     }
1966 }
1967