bindgen/ir/
item.rs

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