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