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