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