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                 ItemKind::Var(..) => {
672                     ctx.options().blocklisted_vars.matches(&name)
673                 }
674                 // TODO: Add namespace blocklisting?
675                 ItemKind::Module(..) => false,
676             }
677     }
678 
679     /// Take out item NameOptions
name<'a>( &'a self, ctx: &'a BindgenContext, ) -> NameOptions<'a>680     pub(crate) fn name<'a>(
681         &'a self,
682         ctx: &'a BindgenContext,
683     ) -> NameOptions<'a> {
684         NameOptions::new(self, ctx)
685     }
686 
687     /// Get the target item ID for name generation.
name_target(&self, ctx: &BindgenContext) -> ItemId688     fn name_target(&self, ctx: &BindgenContext) -> ItemId {
689         let mut targets_seen = DebugOnlyItemSet::new();
690         let mut item = self;
691 
692         loop {
693             extra_assert!(!targets_seen.contains(&item.id()));
694             targets_seen.insert(item.id());
695 
696             if self.annotations().use_instead_of().is_some() {
697                 return self.id();
698             }
699 
700             match *item.kind() {
701                 ItemKind::Type(ref ty) => match *ty.kind() {
702                     TypeKind::ResolvedTypeRef(inner) => {
703                         item = ctx.resolve_item(inner);
704                     }
705                     TypeKind::TemplateInstantiation(ref inst) => {
706                         item = ctx.resolve_item(inst.template_definition());
707                     }
708                     _ => return item.id(),
709                 },
710                 _ => return item.id(),
711             }
712         }
713     }
714 
715     /// Create a fully disambiguated name for an item, including template
716     /// parameters if it is a type
full_disambiguated_name( &self, ctx: &BindgenContext, ) -> String717     pub(crate) fn full_disambiguated_name(
718         &self,
719         ctx: &BindgenContext,
720     ) -> String {
721         let mut s = String::new();
722         let level = 0;
723         self.push_disambiguated_name(ctx, &mut s, level);
724         s
725     }
726 
727     /// Helper function for full_disambiguated_name
push_disambiguated_name( &self, ctx: &BindgenContext, to: &mut String, level: u8, )728     fn push_disambiguated_name(
729         &self,
730         ctx: &BindgenContext,
731         to: &mut String,
732         level: u8,
733     ) {
734         to.push_str(&self.canonical_name(ctx));
735         if let ItemKind::Type(ref ty) = *self.kind() {
736             if let TypeKind::TemplateInstantiation(ref inst) = *ty.kind() {
737                 to.push_str(&format!("_open{}_", level));
738                 for arg in inst.template_arguments() {
739                     arg.into_resolver()
740                         .through_type_refs()
741                         .resolve(ctx)
742                         .push_disambiguated_name(ctx, to, level + 1);
743                     to.push('_');
744                 }
745                 to.push_str(&format!("close{}", level));
746             }
747         }
748     }
749 
750     /// Get this function item's name, or `None` if this item is not a function.
func_name(&self) -> Option<&str>751     fn func_name(&self) -> Option<&str> {
752         match *self.kind() {
753             ItemKind::Function(ref func) => Some(func.name()),
754             _ => None,
755         }
756     }
757 
758     /// Get the overload index for this method. If this is not a method, return
759     /// `None`.
overload_index(&self, ctx: &BindgenContext) -> Option<usize>760     fn overload_index(&self, ctx: &BindgenContext) -> Option<usize> {
761         self.func_name().and_then(|func_name| {
762             let parent = ctx.resolve_item(self.parent_id());
763             if let ItemKind::Type(ref ty) = *parent.kind() {
764                 if let TypeKind::Comp(ref ci) = *ty.kind() {
765                     // All the constructors have the same name, so no need to
766                     // resolve and check.
767                     return ci
768                         .constructors()
769                         .iter()
770                         .position(|c| *c == self.id())
771                         .or_else(|| {
772                             ci.methods()
773                                 .iter()
774                                 .filter(|m| {
775                                     let item = ctx.resolve_item(m.signature());
776                                     let func = item.expect_function();
777                                     func.name() == func_name
778                                 })
779                                 .position(|m| m.signature() == self.id())
780                         });
781                 }
782             }
783 
784             None
785         })
786     }
787 
788     /// Get this item's base name (aka non-namespaced name).
base_name(&self, ctx: &BindgenContext) -> String789     fn base_name(&self, ctx: &BindgenContext) -> String {
790         if let Some(path) = self.annotations().use_instead_of() {
791             return path.last().unwrap().clone();
792         }
793 
794         match *self.kind() {
795             ItemKind::Var(ref var) => var.name().to_owned(),
796             ItemKind::Module(ref module) => {
797                 module.name().map(ToOwned::to_owned).unwrap_or_else(|| {
798                     format!("_bindgen_mod_{}", self.exposed_id(ctx))
799                 })
800             }
801             ItemKind::Type(ref ty) => {
802                 ty.sanitized_name(ctx).map(Into::into).unwrap_or_else(|| {
803                     format!("_bindgen_ty_{}", self.exposed_id(ctx))
804                 })
805             }
806             ItemKind::Function(ref fun) => {
807                 let mut name = fun.name().to_owned();
808 
809                 if let Some(idx) = self.overload_index(ctx) {
810                     if idx > 0 {
811                         write!(&mut name, "{}", idx).unwrap();
812                     }
813                 }
814 
815                 name
816             }
817         }
818     }
819 
is_anon(&self) -> bool820     fn is_anon(&self) -> bool {
821         match self.kind() {
822             ItemKind::Module(module) => module.name().is_none(),
823             ItemKind::Type(ty) => ty.name().is_none(),
824             ItemKind::Function(_) => false,
825             ItemKind::Var(_) => false,
826         }
827     }
828 
829     /// Get the canonical name without taking into account the replaces
830     /// annotation.
831     ///
832     /// This is the base logic used to implement hiding and replacing via
833     /// annotations, and also to implement proper name mangling.
834     ///
835     /// The idea is that each generated type in the same "level" (read: module
836     /// or namespace) has a unique canonical name.
837     ///
838     /// This name should be derived from the immutable state contained in the
839     /// type and the parent chain, since it should be consistent.
840     ///
841     /// If `BindgenOptions::disable_nested_struct_naming` is true then returned
842     /// name is the inner most non-anonymous name plus all the anonymous base names
843     /// that follows.
real_canonical_name( &self, ctx: &BindgenContext, opt: &NameOptions, ) -> String844     pub(crate) fn real_canonical_name(
845         &self,
846         ctx: &BindgenContext,
847         opt: &NameOptions,
848     ) -> String {
849         let target = ctx.resolve_item(self.name_target(ctx));
850 
851         // Short-circuit if the target has an override, and just use that.
852         if let Some(path) = target.annotations.use_instead_of() {
853             if ctx.options().enable_cxx_namespaces {
854                 return path.last().unwrap().clone();
855             }
856             return path.join("_");
857         }
858 
859         let base_name = target.base_name(ctx);
860 
861         // Named template type arguments are never namespaced, and never
862         // mangled.
863         if target.is_template_param(ctx, &()) {
864             return base_name;
865         }
866 
867         // Ancestors' ID iter
868         let mut ids_iter = target
869             .parent_id()
870             .ancestors(ctx)
871             .filter(|id| *id != ctx.root_module())
872             .take_while(|id| {
873                 // Stop iterating ancestors once we reach a non-inline namespace
874                 // when opt.within_namespaces is set.
875                 !opt.within_namespaces || !ctx.resolve_item(*id).is_module()
876             })
877             .filter(|id| {
878                 if !ctx.options().conservative_inline_namespaces {
879                     if let ItemKind::Module(ref module) =
880                         *ctx.resolve_item(*id).kind()
881                     {
882                         return !module.is_inline();
883                     }
884                 }
885 
886                 true
887             });
888 
889         let ids: Vec<_> = if ctx.options().disable_nested_struct_naming {
890             let mut ids = Vec::new();
891 
892             // If target is anonymous we need find its first named ancestor.
893             if target.is_anon() {
894                 for id in ids_iter.by_ref() {
895                     ids.push(id);
896 
897                     if !ctx.resolve_item(id).is_anon() {
898                         break;
899                     }
900                 }
901             }
902 
903             ids
904         } else {
905             ids_iter.collect()
906         };
907 
908         // Concatenate this item's ancestors' names together.
909         let mut names: Vec<_> = ids
910             .into_iter()
911             .map(|id| {
912                 let item = ctx.resolve_item(id);
913                 let target = ctx.resolve_item(item.name_target(ctx));
914                 target.base_name(ctx)
915             })
916             .filter(|name| !name.is_empty())
917             .collect();
918 
919         names.reverse();
920 
921         if !base_name.is_empty() {
922             names.push(base_name);
923         }
924 
925         if ctx.options().c_naming {
926             if let Some(prefix) = self.c_naming_prefix() {
927                 names.insert(0, prefix.to_string());
928             }
929         }
930 
931         let name = names.join("_");
932 
933         let name = if opt.user_mangled == UserMangled::Yes {
934             ctx.options()
935                 .last_callback(|callbacks| callbacks.item_name(&name))
936                 .unwrap_or(name)
937         } else {
938             name
939         };
940 
941         ctx.rust_mangle(&name).into_owned()
942     }
943 
944     /// The exposed ID that represents an unique ID among the siblings of a
945     /// given item.
exposed_id(&self, ctx: &BindgenContext) -> String946     pub(crate) fn exposed_id(&self, ctx: &BindgenContext) -> String {
947         // Only use local ids for enums, classes, structs and union types.  All
948         // other items use their global ID.
949         let ty_kind = self.kind().as_type().map(|t| t.kind());
950         if let Some(ty_kind) = ty_kind {
951             match *ty_kind {
952                 TypeKind::Comp(..) |
953                 TypeKind::TemplateInstantiation(..) |
954                 TypeKind::Enum(..) => return self.local_id(ctx).to_string(),
955                 _ => {}
956             }
957         }
958 
959         // Note that this `id_` prefix prevents (really unlikely) collisions
960         // between the global ID and the local ID of an item with the same
961         // parent.
962         format!("id_{}", self.id().as_usize())
963     }
964 
965     /// Get a reference to this item's `Module`, or `None` if this is not a
966     /// `Module` item.
as_module(&self) -> Option<&Module>967     pub(crate) fn as_module(&self) -> Option<&Module> {
968         match self.kind {
969             ItemKind::Module(ref module) => Some(module),
970             _ => None,
971         }
972     }
973 
974     /// Get a mutable reference to this item's `Module`, or `None` if this is
975     /// not a `Module` item.
as_module_mut(&mut self) -> Option<&mut Module>976     pub(crate) fn as_module_mut(&mut self) -> Option<&mut Module> {
977         match self.kind {
978             ItemKind::Module(ref mut module) => Some(module),
979             _ => None,
980         }
981     }
982 
983     /// Returns whether the item is a constified module enum
is_constified_enum_module(&self, ctx: &BindgenContext) -> bool984     fn is_constified_enum_module(&self, ctx: &BindgenContext) -> bool {
985         // Do not jump through aliases, except for aliases that point to a type
986         // with the same name, since we dont generate coe for them.
987         let item = self.id.into_resolver().through_type_refs().resolve(ctx);
988         let type_ = match *item.kind() {
989             ItemKind::Type(ref type_) => type_,
990             _ => return false,
991         };
992 
993         match *type_.kind() {
994             TypeKind::Enum(ref enum_) => {
995                 enum_.computed_enum_variation(ctx, self) ==
996                     EnumVariation::ModuleConsts
997             }
998             TypeKind::Alias(inner_id) => {
999                 // TODO(emilio): Make this "hop through type aliases that aren't
1000                 // really generated" an option in `ItemResolver`?
1001                 let inner_item = ctx.resolve_item(inner_id);
1002                 let name = item.canonical_name(ctx);
1003 
1004                 if inner_item.canonical_name(ctx) == name {
1005                     inner_item.is_constified_enum_module(ctx)
1006                 } else {
1007                     false
1008                 }
1009             }
1010             _ => false,
1011         }
1012     }
1013 
1014     /// Is this item of a kind that is enabled for code generation?
is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool1015     pub(crate) fn is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool {
1016         let cc = &ctx.options().codegen_config;
1017         match *self.kind() {
1018             ItemKind::Module(..) => true,
1019             ItemKind::Var(_) => cc.vars(),
1020             ItemKind::Type(_) => cc.types(),
1021             ItemKind::Function(ref f) => match f.kind() {
1022                 FunctionKind::Function => cc.functions(),
1023                 FunctionKind::Method(MethodKind::Constructor) => {
1024                     cc.constructors()
1025                 }
1026                 FunctionKind::Method(MethodKind::Destructor) |
1027                 FunctionKind::Method(MethodKind::VirtualDestructor {
1028                     ..
1029                 }) => cc.destructors(),
1030                 FunctionKind::Method(MethodKind::Static) |
1031                 FunctionKind::Method(MethodKind::Normal) |
1032                 FunctionKind::Method(MethodKind::Virtual { .. }) => {
1033                     cc.methods()
1034                 }
1035             },
1036         }
1037     }
1038 
1039     /// Returns the path we should use for allowlisting / blocklisting, which
1040     /// doesn't include user-mangling.
path_for_allowlisting( &self, ctx: &BindgenContext, ) -> &Vec<String>1041     pub(crate) fn path_for_allowlisting(
1042         &self,
1043         ctx: &BindgenContext,
1044     ) -> &Vec<String> {
1045         self.path_for_allowlisting
1046             .borrow_with(|| self.compute_path(ctx, UserMangled::No))
1047     }
1048 
compute_path( &self, ctx: &BindgenContext, mangled: UserMangled, ) -> Vec<String>1049     fn compute_path(
1050         &self,
1051         ctx: &BindgenContext,
1052         mangled: UserMangled,
1053     ) -> Vec<String> {
1054         if let Some(path) = self.annotations().use_instead_of() {
1055             let mut ret =
1056                 vec![ctx.resolve_item(ctx.root_module()).name(ctx).get()];
1057             ret.extend_from_slice(path);
1058             return ret;
1059         }
1060 
1061         let target = ctx.resolve_item(self.name_target(ctx));
1062         let mut path: Vec<_> = target
1063             .ancestors(ctx)
1064             .chain(iter::once(ctx.root_module().into()))
1065             .map(|id| ctx.resolve_item(id))
1066             .filter(|item| {
1067                 item.id() == target.id() ||
1068                     item.as_module().map_or(false, |module| {
1069                         !module.is_inline() ||
1070                             ctx.options().conservative_inline_namespaces
1071                     })
1072             })
1073             .map(|item| {
1074                 ctx.resolve_item(item.name_target(ctx))
1075                     .name(ctx)
1076                     .within_namespaces()
1077                     .user_mangled(mangled)
1078                     .get()
1079             })
1080             .collect();
1081         path.reverse();
1082         path
1083     }
1084 
1085     /// Returns a prefix for the canonical name when C naming is enabled.
c_naming_prefix(&self) -> Option<&str>1086     fn c_naming_prefix(&self) -> Option<&str> {
1087         let ty = match self.kind {
1088             ItemKind::Type(ref ty) => ty,
1089             _ => return None,
1090         };
1091 
1092         Some(match ty.kind() {
1093             TypeKind::Comp(ref ci) => match ci.kind() {
1094                 CompKind::Struct => "struct",
1095                 CompKind::Union => "union",
1096             },
1097             TypeKind::Enum(..) => "enum",
1098             _ => return None,
1099         })
1100     }
1101 
1102     /// Whether this is a `#[must_use]` type.
must_use(&self, ctx: &BindgenContext) -> bool1103     pub(crate) fn must_use(&self, ctx: &BindgenContext) -> bool {
1104         self.annotations().must_use_type() || ctx.must_use_type_by_name(self)
1105     }
1106 }
1107 
1108 impl<T> IsOpaque for T
1109 where
1110     T: Copy + Into<ItemId>,
1111 {
1112     type Extra = ();
1113 
is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool1114     fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool {
1115         debug_assert!(
1116             ctx.in_codegen_phase(),
1117             "You're not supposed to call this yet"
1118         );
1119         ctx.resolve_item((*self).into()).is_opaque(ctx, &())
1120     }
1121 }
1122 
1123 impl IsOpaque for Item {
1124     type Extra = ();
1125 
is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool1126     fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool {
1127         debug_assert!(
1128             ctx.in_codegen_phase(),
1129             "You're not supposed to call this yet"
1130         );
1131         self.annotations.opaque() ||
1132             self.as_type().map_or(false, |ty| ty.is_opaque(ctx, self)) ||
1133             ctx.opaque_by_name(self.path_for_allowlisting(ctx))
1134     }
1135 }
1136 
1137 impl<T> HasVtable for T
1138 where
1139     T: Copy + Into<ItemId>,
1140 {
has_vtable(&self, ctx: &BindgenContext) -> bool1141     fn has_vtable(&self, ctx: &BindgenContext) -> bool {
1142         let id: ItemId = (*self).into();
1143         id.as_type_id(ctx).map_or(false, |id| {
1144             !matches!(ctx.lookup_has_vtable(id), HasVtableResult::No)
1145         })
1146     }
1147 
has_vtable_ptr(&self, ctx: &BindgenContext) -> bool1148     fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
1149         let id: ItemId = (*self).into();
1150         id.as_type_id(ctx).map_or(false, |id| {
1151             matches!(ctx.lookup_has_vtable(id), HasVtableResult::SelfHasVtable)
1152         })
1153     }
1154 }
1155 
1156 impl HasVtable for Item {
has_vtable(&self, ctx: &BindgenContext) -> bool1157     fn has_vtable(&self, ctx: &BindgenContext) -> bool {
1158         self.id().has_vtable(ctx)
1159     }
1160 
has_vtable_ptr(&self, ctx: &BindgenContext) -> bool1161     fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
1162         self.id().has_vtable_ptr(ctx)
1163     }
1164 }
1165 
1166 impl<T> Sizedness for T
1167 where
1168     T: Copy + Into<ItemId>,
1169 {
sizedness(&self, ctx: &BindgenContext) -> SizednessResult1170     fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult {
1171         let id: ItemId = (*self).into();
1172         id.as_type_id(ctx)
1173             .map_or(SizednessResult::default(), |id| ctx.lookup_sizedness(id))
1174     }
1175 }
1176 
1177 impl Sizedness for Item {
sizedness(&self, ctx: &BindgenContext) -> SizednessResult1178     fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult {
1179         self.id().sizedness(ctx)
1180     }
1181 }
1182 
1183 impl<T> HasTypeParamInArray for T
1184 where
1185     T: Copy + Into<ItemId>,
1186 {
has_type_param_in_array(&self, ctx: &BindgenContext) -> bool1187     fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool {
1188         debug_assert!(
1189             ctx.in_codegen_phase(),
1190             "You're not supposed to call this yet"
1191         );
1192         ctx.lookup_has_type_param_in_array(*self)
1193     }
1194 }
1195 
1196 impl HasTypeParamInArray for Item {
has_type_param_in_array(&self, ctx: &BindgenContext) -> bool1197     fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool {
1198         debug_assert!(
1199             ctx.in_codegen_phase(),
1200             "You're not supposed to call this yet"
1201         );
1202         ctx.lookup_has_type_param_in_array(self.id())
1203     }
1204 }
1205 
1206 impl<T> HasFloat for T
1207 where
1208     T: Copy + Into<ItemId>,
1209 {
has_float(&self, ctx: &BindgenContext) -> bool1210     fn has_float(&self, ctx: &BindgenContext) -> bool {
1211         debug_assert!(
1212             ctx.in_codegen_phase(),
1213             "You're not supposed to call this yet"
1214         );
1215         ctx.lookup_has_float(*self)
1216     }
1217 }
1218 
1219 impl HasFloat for Item {
has_float(&self, ctx: &BindgenContext) -> bool1220     fn has_float(&self, ctx: &BindgenContext) -> bool {
1221         debug_assert!(
1222             ctx.in_codegen_phase(),
1223             "You're not supposed to call this yet"
1224         );
1225         ctx.lookup_has_float(self.id())
1226     }
1227 }
1228 
1229 /// A set of items.
1230 pub(crate) type ItemSet = BTreeSet<ItemId>;
1231 
1232 impl DotAttributes for Item {
dot_attributes<W>( &self, ctx: &BindgenContext, out: &mut W, ) -> io::Result<()> where W: io::Write,1233     fn dot_attributes<W>(
1234         &self,
1235         ctx: &BindgenContext,
1236         out: &mut W,
1237     ) -> io::Result<()>
1238     where
1239         W: io::Write,
1240     {
1241         writeln!(
1242             out,
1243             "<tr><td>{:?}</td></tr>
1244                        <tr><td>name</td><td>{}</td></tr>",
1245             self.id,
1246             self.name(ctx).get()
1247         )?;
1248 
1249         if self.is_opaque(ctx, &()) {
1250             writeln!(out, "<tr><td>opaque</td><td>true</td></tr>")?;
1251         }
1252 
1253         self.kind.dot_attributes(ctx, out)
1254     }
1255 }
1256 
1257 impl<T> TemplateParameters for T
1258 where
1259     T: Copy + Into<ItemId>,
1260 {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>1261     fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1262         ctx.resolve_item_fallible(*self)
1263             .map_or(vec![], |item| item.self_template_params(ctx))
1264     }
1265 }
1266 
1267 impl TemplateParameters for Item {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>1268     fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1269         self.kind.self_template_params(ctx)
1270     }
1271 }
1272 
1273 impl TemplateParameters for ItemKind {
self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId>1274     fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1275         match *self {
1276             ItemKind::Type(ref ty) => ty.self_template_params(ctx),
1277             // If we start emitting bindings to explicitly instantiated
1278             // functions, then we'll need to check ItemKind::Function for
1279             // template params.
1280             ItemKind::Function(_) | ItemKind::Module(_) | ItemKind::Var(_) => {
1281                 vec![]
1282             }
1283         }
1284     }
1285 }
1286 
1287 // 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::CXChildVisitResult1288 fn visit_child(
1289     cur: clang::Cursor,
1290     id: ItemId,
1291     ty: &clang::Type,
1292     parent_id: Option<ItemId>,
1293     ctx: &mut BindgenContext,
1294     result: &mut Result<TypeId, ParseError>,
1295 ) -> clang_sys::CXChildVisitResult {
1296     use clang_sys::*;
1297     if result.is_ok() {
1298         return CXChildVisit_Break;
1299     }
1300 
1301     *result = Item::from_ty_with_id(id, ty, cur, parent_id, ctx);
1302 
1303     match *result {
1304         Ok(..) => CXChildVisit_Break,
1305         Err(ParseError::Recurse) => {
1306             cur.visit(|c| visit_child(c, id, ty, parent_id, ctx, result));
1307             CXChildVisit_Continue
1308         }
1309         Err(ParseError::Continue) => CXChildVisit_Continue,
1310     }
1311 }
1312 
1313 impl Item {
1314     /// Create a builtin type.
builtin_type( kind: TypeKind, is_const: bool, ctx: &mut BindgenContext, ) -> TypeId1315     pub(crate) fn builtin_type(
1316         kind: TypeKind,
1317         is_const: bool,
1318         ctx: &mut BindgenContext,
1319     ) -> TypeId {
1320         // Feel free to add more here, I'm just lazy.
1321         match kind {
1322             TypeKind::Void |
1323             TypeKind::Int(..) |
1324             TypeKind::Pointer(..) |
1325             TypeKind::Float(..) => {}
1326             _ => panic!("Unsupported builtin type"),
1327         }
1328 
1329         let ty = Type::new(None, None, kind, is_const);
1330         let id = ctx.next_item_id();
1331         let module = ctx.root_module().into();
1332         ctx.add_item(
1333             Item::new(id, None, None, module, ItemKind::Type(ty), None),
1334             None,
1335             None,
1336         );
1337         id.as_type_id_unchecked()
1338     }
1339 
1340     /// Parse this item from the given Clang cursor.
parse( cursor: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> Result<ItemId, ParseError>1341     pub(crate) fn parse(
1342         cursor: clang::Cursor,
1343         parent_id: Option<ItemId>,
1344         ctx: &mut BindgenContext,
1345     ) -> Result<ItemId, ParseError> {
1346         use crate::ir::var::Var;
1347         use clang_sys::*;
1348 
1349         if !cursor.is_valid() {
1350             return Err(ParseError::Continue);
1351         }
1352 
1353         let comment = cursor.raw_comment();
1354         let annotations = Annotations::new(&cursor);
1355 
1356         let current_module = ctx.current_module().into();
1357         let relevant_parent_id = parent_id.unwrap_or(current_module);
1358 
1359         #[allow(clippy::missing_docs_in_private_items)]
1360         macro_rules! try_parse {
1361             ($what:ident) => {
1362                 match $what::parse(cursor, ctx) {
1363                     Ok(ParseResult::New(item, declaration)) => {
1364                         let id = ctx.next_item_id();
1365 
1366                         ctx.add_item(
1367                             Item::new(
1368                                 id,
1369                                 comment,
1370                                 annotations,
1371                                 relevant_parent_id,
1372                                 ItemKind::$what(item),
1373                                 Some(cursor.location()),
1374                             ),
1375                             declaration,
1376                             Some(cursor),
1377                         );
1378                         return Ok(id);
1379                     }
1380                     Ok(ParseResult::AlreadyResolved(id)) => {
1381                         return Ok(id);
1382                     }
1383                     Err(ParseError::Recurse) => return Err(ParseError::Recurse),
1384                     Err(ParseError::Continue) => {}
1385                 }
1386             };
1387         }
1388 
1389         try_parse!(Module);
1390 
1391         // NOTE: Is extremely important to parse functions and vars **before**
1392         // types.  Otherwise we can parse a function declaration as a type
1393         // (which is legal), and lose functions to generate.
1394         //
1395         // In general, I'm not totally confident this split between
1396         // ItemKind::Function and TypeKind::FunctionSig is totally worth it, but
1397         // I guess we can try.
1398         try_parse!(Function);
1399         try_parse!(Var);
1400 
1401         // Types are sort of special, so to avoid parsing template classes
1402         // twice, handle them separately.
1403         {
1404             let definition = cursor.definition();
1405             let applicable_cursor = definition.unwrap_or(cursor);
1406 
1407             let relevant_parent_id = match definition {
1408                 Some(definition) => {
1409                     if definition != cursor {
1410                         ctx.add_semantic_parent(definition, relevant_parent_id);
1411                         return Ok(Item::from_ty_or_ref(
1412                             applicable_cursor.cur_type(),
1413                             cursor,
1414                             parent_id,
1415                             ctx,
1416                         )
1417                         .into());
1418                     }
1419                     ctx.known_semantic_parent(definition)
1420                         .or(parent_id)
1421                         .unwrap_or_else(|| ctx.current_module().into())
1422                 }
1423                 None => relevant_parent_id,
1424             };
1425 
1426             match Item::from_ty(
1427                 &applicable_cursor.cur_type(),
1428                 applicable_cursor,
1429                 Some(relevant_parent_id),
1430                 ctx,
1431             ) {
1432                 Ok(ty) => return Ok(ty.into()),
1433                 Err(ParseError::Recurse) => return Err(ParseError::Recurse),
1434                 Err(ParseError::Continue) => {}
1435             }
1436         }
1437 
1438         match cursor.kind() {
1439             // On Clang 18+, extern "C" is reported accurately as a LinkageSpec.
1440             // Older LLVM treat it as UnexposedDecl.
1441             CXCursor_LinkageSpec | CXCursor_UnexposedDecl => {
1442                 Err(ParseError::Recurse)
1443             }
1444 
1445             // We allowlist cursors here known to be unhandled, to prevent being
1446             // too noisy about this.
1447             CXCursor_MacroDefinition |
1448             CXCursor_MacroExpansion |
1449             CXCursor_UsingDeclaration |
1450             CXCursor_UsingDirective |
1451             CXCursor_StaticAssert |
1452             CXCursor_FunctionTemplate => {
1453                 debug!(
1454                     "Unhandled cursor kind {:?}: {:?}",
1455                     cursor.kind(),
1456                     cursor
1457                 );
1458                 Err(ParseError::Continue)
1459             }
1460 
1461             CXCursor_InclusionDirective => {
1462                 let file = cursor.get_included_file_name();
1463                 match file {
1464                     None => {
1465                         warn!("Inclusion of a nameless file in {:?}", cursor);
1466                     }
1467                     Some(included_file) => {
1468                         for cb in &ctx.options().parse_callbacks {
1469                             cb.include_file(&included_file);
1470                         }
1471 
1472                         ctx.add_dep(included_file.into_boxed_str());
1473                     }
1474                 }
1475                 Err(ParseError::Continue)
1476             }
1477 
1478             _ => {
1479                 // ignore toplevel operator overloads
1480                 let spelling = cursor.spelling();
1481                 if !spelling.starts_with("operator") {
1482                     warn!(
1483                         "Unhandled cursor kind {:?}: {:?}",
1484                         cursor.kind(),
1485                         cursor
1486                     );
1487                 }
1488                 Err(ParseError::Continue)
1489             }
1490         }
1491     }
1492 
1493     /// Parse this item from the given Clang type, or if we haven't resolved all
1494     /// 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, ) -> TypeId1495     pub(crate) fn from_ty_or_ref(
1496         ty: clang::Type,
1497         location: clang::Cursor,
1498         parent_id: Option<ItemId>,
1499         ctx: &mut BindgenContext,
1500     ) -> TypeId {
1501         let id = ctx.next_item_id();
1502         Self::from_ty_or_ref_with_id(id, ty, location, parent_id, ctx)
1503     }
1504 
1505     /// Parse a C++ type. If we find a reference to a type that has not been
1506     /// defined yet, use `UnresolvedTypeRef` as a placeholder.
1507     ///
1508     /// This logic is needed to avoid parsing items with the incorrect parent
1509     /// and it's sort of complex to explain, so I'll just point to
1510     /// `tests/headers/typeref.hpp` to see the kind of constructs that forced
1511     /// this.
1512     ///
1513     /// Typerefs are resolved once parsing is completely done, see
1514     /// `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, ) -> TypeId1515     pub(crate) fn from_ty_or_ref_with_id(
1516         potential_id: ItemId,
1517         ty: clang::Type,
1518         location: clang::Cursor,
1519         parent_id: Option<ItemId>,
1520         ctx: &mut BindgenContext,
1521     ) -> TypeId {
1522         debug!(
1523             "from_ty_or_ref_with_id: {:?} {:?}, {:?}, {:?}",
1524             potential_id, ty, location, parent_id
1525         );
1526 
1527         if ctx.collected_typerefs() {
1528             debug!("refs already collected, resolving directly");
1529             return Item::from_ty_with_id(
1530                 potential_id,
1531                 &ty,
1532                 location,
1533                 parent_id,
1534                 ctx,
1535             )
1536             .unwrap_or_else(|_| Item::new_opaque_type(potential_id, &ty, ctx));
1537         }
1538 
1539         if let Some(ty) = ctx.builtin_or_resolved_ty(
1540             potential_id,
1541             parent_id,
1542             &ty,
1543             Some(location),
1544         ) {
1545             debug!("{:?} already resolved: {:?}", ty, location);
1546             return ty;
1547         }
1548 
1549         debug!("New unresolved type reference: {:?}, {:?}", ty, location);
1550 
1551         let is_const = ty.is_const();
1552         let kind = TypeKind::UnresolvedTypeRef(ty, location, parent_id);
1553         let current_module = ctx.current_module();
1554 
1555         ctx.add_item(
1556             Item::new(
1557                 potential_id,
1558                 None,
1559                 None,
1560                 parent_id.unwrap_or_else(|| current_module.into()),
1561                 ItemKind::Type(Type::new(None, None, kind, is_const)),
1562                 Some(location.location()),
1563             ),
1564             None,
1565             None,
1566         );
1567         potential_id.as_type_id_unchecked()
1568     }
1569 
1570     /// 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>1571     pub(crate) fn from_ty(
1572         ty: &clang::Type,
1573         location: clang::Cursor,
1574         parent_id: Option<ItemId>,
1575         ctx: &mut BindgenContext,
1576     ) -> Result<TypeId, ParseError> {
1577         let id = ctx.next_item_id();
1578         Item::from_ty_with_id(id, ty, location, parent_id, ctx)
1579     }
1580 
1581     /// This is one of the trickiest methods you'll find (probably along with
1582     /// some of the ones that handle templates in `BindgenContext`).
1583     ///
1584     /// This method parses a type, given the potential ID of that type (if
1585     /// parsing it was correct), an optional location we're scanning, which is
1586     /// critical some times to obtain information, an optional parent item ID,
1587     /// that will, if it's `None`, become the current module ID, and the
1588     /// context.
from_ty_with_id( id: ItemId, ty: &clang::Type, location: clang::Cursor, parent_id: Option<ItemId>, ctx: &mut BindgenContext, ) -> Result<TypeId, ParseError>1589     pub(crate) fn from_ty_with_id(
1590         id: ItemId,
1591         ty: &clang::Type,
1592         location: clang::Cursor,
1593         parent_id: Option<ItemId>,
1594         ctx: &mut BindgenContext,
1595     ) -> Result<TypeId, ParseError> {
1596         use clang_sys::*;
1597 
1598         debug!(
1599             "Item::from_ty_with_id: {:?}\n\
1600              \tty = {:?},\n\
1601              \tlocation = {:?}",
1602             id, ty, location
1603         );
1604 
1605         if ty.kind() == clang_sys::CXType_Unexposed ||
1606             location.cur_type().kind() == clang_sys::CXType_Unexposed
1607         {
1608             if ty.is_associated_type() ||
1609                 location.cur_type().is_associated_type()
1610             {
1611                 return Ok(Item::new_opaque_type(id, ty, ctx));
1612             }
1613 
1614             if let Some(param_id) = Item::type_param(None, location, ctx) {
1615                 return Ok(ctx.build_ty_wrapper(id, param_id, None, ty));
1616             }
1617         }
1618 
1619         // Treat all types that are declared inside functions as opaque. The Rust binding
1620         // won't be able to do anything with them anyway.
1621         //
1622         // (If we don't do this check here, we can have subtle logic bugs because we generally
1623         // ignore function bodies. See issue #2036.)
1624         if let Some(ref parent) = ty.declaration().fallible_semantic_parent() {
1625             if FunctionKind::from_cursor(parent).is_some() {
1626                 debug!("Skipping type declared inside function: {:?}", ty);
1627                 return Ok(Item::new_opaque_type(id, ty, ctx));
1628             }
1629         }
1630 
1631         let decl = {
1632             let canonical_def = ty.canonical_type().declaration().definition();
1633             canonical_def.unwrap_or_else(|| ty.declaration())
1634         };
1635 
1636         let comment = location
1637             .raw_comment()
1638             .or_else(|| decl.raw_comment())
1639             .or_else(|| location.raw_comment());
1640 
1641         let annotations =
1642             Annotations::new(&decl).or_else(|| Annotations::new(&location));
1643 
1644         if let Some(ref annotations) = annotations {
1645             if let Some(replaced) = annotations.use_instead_of() {
1646                 ctx.replace(replaced, id);
1647             }
1648         }
1649 
1650         if let Some(ty) =
1651             ctx.builtin_or_resolved_ty(id, parent_id, ty, Some(location))
1652         {
1653             return Ok(ty);
1654         }
1655 
1656         // First, check we're not recursing.
1657         let mut valid_decl = decl.kind() != CXCursor_NoDeclFound;
1658         let declaration_to_look_for = if valid_decl {
1659             decl.canonical()
1660         } else if location.kind() == CXCursor_ClassTemplate {
1661             valid_decl = true;
1662             location
1663         } else {
1664             decl
1665         };
1666 
1667         if valid_decl {
1668             if let Some(partial) = ctx
1669                 .currently_parsed_types()
1670                 .iter()
1671                 .find(|ty| *ty.decl() == declaration_to_look_for)
1672             {
1673                 debug!("Avoiding recursion parsing type: {:?}", ty);
1674                 // Unchecked because we haven't finished this type yet.
1675                 return Ok(partial.id().as_type_id_unchecked());
1676             }
1677         }
1678 
1679         let current_module = ctx.current_module().into();
1680         let partial_ty = PartialType::new(declaration_to_look_for, id);
1681         if valid_decl {
1682             ctx.begin_parsing(partial_ty);
1683         }
1684 
1685         let result = Type::from_clang_ty(id, ty, location, parent_id, ctx);
1686         let relevant_parent_id = parent_id.unwrap_or(current_module);
1687         let ret = match result {
1688             Ok(ParseResult::AlreadyResolved(ty)) => {
1689                 Ok(ty.as_type_id_unchecked())
1690             }
1691             Ok(ParseResult::New(item, declaration)) => {
1692                 ctx.add_item(
1693                     Item::new(
1694                         id,
1695                         comment,
1696                         annotations,
1697                         relevant_parent_id,
1698                         ItemKind::Type(item),
1699                         Some(location.location()),
1700                     ),
1701                     declaration,
1702                     Some(location),
1703                 );
1704                 Ok(id.as_type_id_unchecked())
1705             }
1706             Err(ParseError::Continue) => Err(ParseError::Continue),
1707             Err(ParseError::Recurse) => {
1708                 debug!("Item::from_ty recursing in the ast");
1709                 let mut result = Err(ParseError::Recurse);
1710 
1711                 // Need to pop here, otherwise we'll get stuck.
1712                 //
1713                 // TODO: Find a nicer interface, really. Also, the
1714                 // declaration_to_look_for suspiciously shares a lot of
1715                 // logic with ir::context, so we should refactor that.
1716                 if valid_decl {
1717                     let finished = ctx.finish_parsing();
1718                     assert_eq!(*finished.decl(), declaration_to_look_for);
1719                 }
1720 
1721                 location.visit(|cur| {
1722                     visit_child(cur, id, ty, parent_id, ctx, &mut result)
1723                 });
1724 
1725                 if valid_decl {
1726                     let partial_ty =
1727                         PartialType::new(declaration_to_look_for, id);
1728                     ctx.begin_parsing(partial_ty);
1729                 }
1730 
1731                 // If we have recursed into the AST all we know, and we still
1732                 // haven't found what we've got, let's just try and make a named
1733                 // type.
1734                 //
1735                 // This is what happens with some template members, for example.
1736                 if let Err(ParseError::Recurse) = result {
1737                     warn!(
1738                         "Unknown type, assuming named template type: \
1739                          id = {:?}; spelling = {}",
1740                         id,
1741                         ty.spelling()
1742                     );
1743                     Item::type_param(Some(id), location, ctx)
1744                         .map(Ok)
1745                         .unwrap_or(Err(ParseError::Recurse))
1746                 } else {
1747                     result
1748                 }
1749             }
1750         };
1751 
1752         if valid_decl {
1753             let partial_ty = ctx.finish_parsing();
1754             assert_eq!(*partial_ty.decl(), declaration_to_look_for);
1755         }
1756 
1757         ret
1758     }
1759 
1760     /// A named type is a template parameter, e.g., the `T` in `Foo<T>`. They're always local so
1761     /// 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>1762     pub(crate) fn type_param(
1763         with_id: Option<ItemId>,
1764         location: clang::Cursor,
1765         ctx: &mut BindgenContext,
1766     ) -> Option<TypeId> {
1767         let ty = location.cur_type();
1768 
1769         debug!(
1770             "Item::type_param:\n\
1771              \twith_id = {:?},\n\
1772              \tty = {} {:?},\n\
1773              \tlocation: {:?}",
1774             with_id,
1775             ty.spelling(),
1776             ty,
1777             location
1778         );
1779 
1780         if ty.kind() != clang_sys::CXType_Unexposed {
1781             // If the given cursor's type's kind is not Unexposed, then we
1782             // aren't looking at a template parameter. This check may need to be
1783             // updated in the future if they start properly exposing template
1784             // type parameters.
1785             return None;
1786         }
1787 
1788         let ty_spelling = ty.spelling();
1789 
1790         // Clang does not expose any information about template type parameters
1791         // via their clang::Type, nor does it give us their canonical cursors
1792         // the straightforward way. However, there are three situations from
1793         // which we can find the definition of the template type parameter, if
1794         // the cursor is indeed looking at some kind of a template type
1795         // parameter or use of one:
1796         //
1797         // 1. The cursor is pointing at the template type parameter's
1798         // definition. This is the trivial case.
1799         //
1800         //     (kind = TemplateTypeParameter, ...)
1801         //
1802         // 2. The cursor is pointing at a TypeRef whose referenced() cursor is
1803         // situation (1).
1804         //
1805         //     (kind = TypeRef,
1806         //      referenced = (kind = TemplateTypeParameter, ...),
1807         //      ...)
1808         //
1809         // 3. The cursor is pointing at some use of a template type parameter
1810         // (for example, in a FieldDecl), and this cursor has a child cursor
1811         // whose spelling is the same as the parent's type's spelling, and whose
1812         // kind is a TypeRef of the situation (2) variety.
1813         //
1814         //    (kind = FieldDecl,
1815         //     type = (kind = Unexposed,
1816         //             spelling = "T",
1817         //             ...),
1818         //     children =
1819         //        (kind = TypeRef,
1820         //         spelling = "T",
1821         //         referenced = (kind = TemplateTypeParameter,
1822         //                       spelling = "T",
1823         //                       ...),
1824         //         ...)
1825         //     ...)
1826         //
1827         // TODO: The alternative to this hacky pattern matching would be to
1828         // maintain proper scopes of template parameters while parsing and use
1829         // de Brujin indices to access template parameters, which clang exposes
1830         // in the cursor's type's canonical type's spelling:
1831         // "type-parameter-x-y". That is probably a better approach long-term,
1832         // but maintaining these scopes properly would require more changes to
1833         // the whole libclang -> IR parsing code.
1834 
1835         fn is_template_with_spelling(
1836             refd: &clang::Cursor,
1837             spelling: &str,
1838         ) -> bool {
1839             lazy_static! {
1840                 static ref ANON_TYPE_PARAM_RE: regex::Regex =
1841                     regex::Regex::new(r"^type\-parameter\-\d+\-\d+$").unwrap();
1842             }
1843 
1844             if refd.kind() != clang_sys::CXCursor_TemplateTypeParameter {
1845                 return false;
1846             }
1847 
1848             let refd_spelling = refd.spelling();
1849             refd_spelling == spelling ||
1850                 // Allow for anonymous template parameters.
1851                 (refd_spelling.is_empty() && ANON_TYPE_PARAM_RE.is_match(spelling.as_ref()))
1852         }
1853 
1854         let definition = if is_template_with_spelling(&location, &ty_spelling) {
1855             // Situation (1)
1856             location
1857         } else if location.kind() == clang_sys::CXCursor_TypeRef {
1858             // Situation (2)
1859             match location.referenced() {
1860                 Some(refd)
1861                     if is_template_with_spelling(&refd, &ty_spelling) =>
1862                 {
1863                     refd
1864                 }
1865                 _ => return None,
1866             }
1867         } else {
1868             // Situation (3)
1869             let mut definition = None;
1870 
1871             location.visit(|child| {
1872                 let child_ty = child.cur_type();
1873                 if child_ty.kind() == clang_sys::CXCursor_TypeRef &&
1874                     child_ty.spelling() == ty_spelling
1875                 {
1876                     match child.referenced() {
1877                         Some(refd)
1878                             if is_template_with_spelling(
1879                                 &refd,
1880                                 &ty_spelling,
1881                             ) =>
1882                         {
1883                             definition = Some(refd);
1884                             return clang_sys::CXChildVisit_Break;
1885                         }
1886                         _ => {}
1887                     }
1888                 }
1889 
1890                 clang_sys::CXChildVisit_Continue
1891             });
1892 
1893             definition?
1894         };
1895         assert!(is_template_with_spelling(&definition, &ty_spelling));
1896 
1897         // Named types are always parented to the root module. They are never
1898         // referenced with namespace prefixes, and they can't inherit anything
1899         // from their parent either, so it is simplest to just hang them off
1900         // something we know will always exist.
1901         let parent = ctx.root_module().into();
1902 
1903         if let Some(id) = ctx.get_type_param(&definition) {
1904             if let Some(with_id) = with_id {
1905                 return Some(ctx.build_ty_wrapper(
1906                     with_id,
1907                     id,
1908                     Some(parent),
1909                     &ty,
1910                 ));
1911             } else {
1912                 return Some(id);
1913             }
1914         }
1915 
1916         // See tests/headers/const_tparam.hpp and
1917         // tests/headers/variadic_tname.hpp.
1918         let name = ty_spelling.replace("const ", "").replace('.', "");
1919 
1920         let id = with_id.unwrap_or_else(|| ctx.next_item_id());
1921         let item = Item::new(
1922             id,
1923             None,
1924             None,
1925             parent,
1926             ItemKind::Type(Type::named(name)),
1927             Some(location.location()),
1928         );
1929         ctx.add_type_param(item, definition);
1930         Some(id.as_type_id_unchecked())
1931     }
1932 }
1933 
1934 impl ItemCanonicalName for Item {
canonical_name(&self, ctx: &BindgenContext) -> String1935     fn canonical_name(&self, ctx: &BindgenContext) -> String {
1936         debug_assert!(
1937             ctx.in_codegen_phase(),
1938             "You're not supposed to call this yet"
1939         );
1940         self.canonical_name
1941             .borrow_with(|| {
1942                 let in_namespace = ctx.options().enable_cxx_namespaces ||
1943                     ctx.options().disable_name_namespacing;
1944 
1945                 if in_namespace {
1946                     self.name(ctx).within_namespaces().get()
1947                 } else {
1948                     self.name(ctx).get()
1949                 }
1950             })
1951             .clone()
1952     }
1953 }
1954 
1955 impl ItemCanonicalPath for Item {
namespace_aware_canonical_path( &self, ctx: &BindgenContext, ) -> Vec<String>1956     fn namespace_aware_canonical_path(
1957         &self,
1958         ctx: &BindgenContext,
1959     ) -> Vec<String> {
1960         let mut path = self.canonical_path(ctx);
1961 
1962         // ASSUMPTION: (disable_name_namespacing && cxx_namespaces)
1963         // is equivalent to
1964         // disable_name_namespacing
1965         if ctx.options().disable_name_namespacing {
1966             // Only keep the last item in path
1967             let split_idx = path.len() - 1;
1968             path = path.split_off(split_idx);
1969         } else if !ctx.options().enable_cxx_namespaces {
1970             // Ignore first item "root"
1971             path = vec![path[1..].join("_")];
1972         }
1973 
1974         if self.is_constified_enum_module(ctx) {
1975             path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into());
1976         }
1977 
1978         path
1979     }
1980 
canonical_path(&self, ctx: &BindgenContext) -> Vec<String>1981     fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
1982         self.compute_path(ctx, UserMangled::Yes)
1983     }
1984 }
1985 
1986 /// Whether to use the user-mangled name (mangled by the `item_name` callback or
1987 /// not.
1988 ///
1989 /// Most of the callers probably want just yes, but the ones dealing with
1990 /// allowlisting and blocklisting don't.
1991 #[derive(Copy, Clone, Debug, PartialEq)]
1992 enum UserMangled {
1993     No,
1994     Yes,
1995 }
1996 
1997 /// Builder struct for naming variations, which hold inside different
1998 /// flags for naming options.
1999 #[derive(Debug)]
2000 pub(crate) struct NameOptions<'a> {
2001     item: &'a Item,
2002     ctx: &'a BindgenContext,
2003     within_namespaces: bool,
2004     user_mangled: UserMangled,
2005 }
2006 
2007 impl<'a> NameOptions<'a> {
2008     /// Construct a new `NameOptions`
new(item: &'a Item, ctx: &'a BindgenContext) -> Self2009     pub(crate) fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self {
2010         NameOptions {
2011             item,
2012             ctx,
2013             within_namespaces: false,
2014             user_mangled: UserMangled::Yes,
2015         }
2016     }
2017 
2018     /// Construct the name without the item's containing C++ namespaces mangled
2019     /// into it. In other words, the item's name within the item's namespace.
within_namespaces(&mut self) -> &mut Self2020     pub(crate) fn within_namespaces(&mut self) -> &mut Self {
2021         self.within_namespaces = true;
2022         self
2023     }
2024 
user_mangled(&mut self, user_mangled: UserMangled) -> &mut Self2025     fn user_mangled(&mut self, user_mangled: UserMangled) -> &mut Self {
2026         self.user_mangled = user_mangled;
2027         self
2028     }
2029 
2030     /// Construct a name `String`
get(&self) -> String2031     pub(crate) fn get(&self) -> String {
2032         self.item.real_canonical_name(self.ctx, self)
2033     }
2034 }
2035