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