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