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