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