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