1use super::super::codegen::{EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME};
4use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult};
5use super::annotations::Annotations;
6use super::comp::{CompKind, MethodKind};
7use super::context::{BindgenContext, ItemId, PartialType, TypeId};
8use super::derive::{
9 CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
10 CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd,
11};
12use super::dot::DotAttributes;
13use super::function::{Function, FunctionKind};
14use super::item_kind::ItemKind;
15use super::layout::Opaque;
16use super::module::Module;
17use super::template::{AsTemplateParam, TemplateParameters};
18use super::traversal::{EdgeKind, Trace, Tracer};
19use super::ty::{Type, TypeKind};
20use crate::callbacks::ItemInfo;
21use crate::clang;
22use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
23
24use std::cell::{Cell, OnceCell};
25use std::collections::BTreeSet;
26use std::fmt::Write;
27use std::io;
28use std::iter;
29use std::sync::OnceLock;
30
31pub(crate) trait ItemCanonicalName {
42 fn canonical_name(&self, ctx: &BindgenContext) -> String;
44}
45
46pub(crate) trait ItemCanonicalPath {
59 fn namespace_aware_canonical_path(
63 &self,
64 ctx: &BindgenContext,
65 ) -> Vec<String>;
66
67 fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String>;
69}
70
71pub(crate) trait IsOpaque {
73 type Extra;
75
76 fn is_opaque(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool;
80}
81
82pub(crate) trait HasTypeParamInArray {
84 fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool;
86}
87
88pub(crate) trait ItemAncestors {
91 fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>;
93}
94
95#[cfg(feature = "__testing_only_extra_assertions")]
96type DebugOnlyItemSet = ItemSet;
97
98#[cfg(not(feature = "__testing_only_extra_assertions"))]
99struct DebugOnlyItemSet;
100
101#[cfg(not(feature = "__testing_only_extra_assertions"))]
102impl DebugOnlyItemSet {
103 fn new() -> Self {
104 DebugOnlyItemSet
105 }
106
107 #[allow(clippy::trivially_copy_pass_by_ref)]
108 fn contains(&self, _id: &ItemId) -> bool {
109 false
110 }
111
112 fn insert(&mut self, _id: ItemId) {}
113}
114
115pub(crate) struct ItemAncestorsIter<'a> {
117 item: ItemId,
118 ctx: &'a BindgenContext,
119 seen: DebugOnlyItemSet,
120}
121
122impl<'a> ItemAncestorsIter<'a> {
123 fn new<Id: Into<ItemId>>(ctx: &'a BindgenContext, id: Id) -> Self {
124 ItemAncestorsIter {
125 item: id.into(),
126 ctx,
127 seen: DebugOnlyItemSet::new(),
128 }
129 }
130}
131
132impl Iterator for ItemAncestorsIter<'_> {
133 type Item = ItemId;
134
135 fn next(&mut self) -> Option<Self::Item> {
136 let item = self.ctx.resolve_item(self.item);
137
138 if item.parent_id() == self.item {
139 None
140 } else {
141 self.item = item.parent_id();
142
143 extra_assert!(!self.seen.contains(&item.id()));
144 self.seen.insert(item.id());
145
146 Some(item.id())
147 }
148 }
149}
150
151impl<T> AsTemplateParam for T
152where
153 T: Copy + Into<ItemId>,
154{
155 type Extra = ();
156
157 fn as_template_param(
158 &self,
159 ctx: &BindgenContext,
160 _: &(),
161 ) -> Option<TypeId> {
162 ctx.resolve_item((*self).into()).as_template_param(ctx, &())
163 }
164}
165
166impl AsTemplateParam for Item {
167 type Extra = ();
168
169 fn as_template_param(
170 &self,
171 ctx: &BindgenContext,
172 _: &(),
173 ) -> Option<TypeId> {
174 self.kind.as_template_param(ctx, self)
175 }
176}
177
178impl AsTemplateParam for ItemKind {
179 type Extra = Item;
180
181 fn as_template_param(
182 &self,
183 ctx: &BindgenContext,
184 item: &Item,
185 ) -> Option<TypeId> {
186 match *self {
187 ItemKind::Type(ref ty) => ty.as_template_param(ctx, item),
188 ItemKind::Module(..) |
189 ItemKind::Function(..) |
190 ItemKind::Var(..) => None,
191 }
192 }
193}
194
195impl<T> ItemCanonicalName for T
196where
197 T: Copy + Into<ItemId>,
198{
199 fn canonical_name(&self, ctx: &BindgenContext) -> String {
200 debug_assert!(
201 ctx.in_codegen_phase(),
202 "You're not supposed to call this yet"
203 );
204 ctx.resolve_item(*self).canonical_name(ctx)
205 }
206}
207
208impl<T> ItemCanonicalPath for T
209where
210 T: Copy + Into<ItemId>,
211{
212 fn namespace_aware_canonical_path(
213 &self,
214 ctx: &BindgenContext,
215 ) -> Vec<String> {
216 debug_assert!(
217 ctx.in_codegen_phase(),
218 "You're not supposed to call this yet"
219 );
220 ctx.resolve_item(*self).namespace_aware_canonical_path(ctx)
221 }
222
223 fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
224 debug_assert!(
225 ctx.in_codegen_phase(),
226 "You're not supposed to call this yet"
227 );
228 ctx.resolve_item(*self).canonical_path(ctx)
229 }
230}
231
232impl<T> ItemAncestors for T
233where
234 T: Copy + Into<ItemId>,
235{
236 fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a> {
237 ItemAncestorsIter::new(ctx, *self)
238 }
239}
240
241impl ItemAncestors for Item {
242 fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a> {
243 self.id().ancestors(ctx)
244 }
245}
246
247impl<Id> Trace for Id
248where
249 Id: Copy + Into<ItemId>,
250{
251 type Extra = ();
252
253 fn trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, extra: &())
254 where
255 T: Tracer,
256 {
257 ctx.resolve_item(*self).trace(ctx, tracer, extra);
258 }
259}
260
261impl Trace for Item {
262 type Extra = ();
263
264 fn trace<T>(&self, ctx: &BindgenContext, tracer: &mut T, _extra: &())
265 where
266 T: Tracer,
267 {
268 match *self.kind() {
276 ItemKind::Type(ref ty) => {
277 if ty.should_be_traced_unconditionally() ||
281 !self.is_opaque(ctx, &())
282 {
283 ty.trace(ctx, tracer, self);
284 }
285 }
286 ItemKind::Function(ref fun) => {
287 tracer.visit(fun.signature().into());
290 }
291 ItemKind::Var(ref var) => {
292 tracer.visit_kind(var.ty().into(), EdgeKind::VarType);
293 }
294 ItemKind::Module(_) => {
295 }
303 }
304 }
305}
306
307impl CanDeriveDebug for Item {
308 fn can_derive_debug(&self, ctx: &BindgenContext) -> bool {
309 self.id().can_derive_debug(ctx)
310 }
311}
312
313impl CanDeriveDefault for Item {
314 fn can_derive_default(&self, ctx: &BindgenContext) -> bool {
315 self.id().can_derive_default(ctx)
316 }
317}
318
319impl CanDeriveCopy for Item {
320 fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
321 self.id().can_derive_copy(ctx)
322 }
323}
324
325impl CanDeriveHash for Item {
326 fn can_derive_hash(&self, ctx: &BindgenContext) -> bool {
327 self.id().can_derive_hash(ctx)
328 }
329}
330
331impl CanDerivePartialOrd for Item {
332 fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool {
333 self.id().can_derive_partialord(ctx)
334 }
335}
336
337impl CanDerivePartialEq for Item {
338 fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
339 self.id().can_derive_partialeq(ctx)
340 }
341}
342
343impl CanDeriveEq for Item {
344 fn can_derive_eq(&self, ctx: &BindgenContext) -> bool {
345 self.id().can_derive_eq(ctx)
346 }
347}
348
349impl CanDeriveOrd for Item {
350 fn can_derive_ord(&self, ctx: &BindgenContext) -> bool {
351 self.id().can_derive_ord(ctx)
352 }
353}
354
355#[derive(Debug)]
373pub(crate) struct Item {
374 id: ItemId,
376
377 local_id: OnceCell<usize>,
385
386 next_child_local_id: Cell<usize>,
388
389 canonical_name: OnceCell<String>,
394
395 path_for_allowlisting: OnceCell<Vec<String>>,
398
399 comment: Option<String>,
401 annotations: Annotations,
404 parent_id: ItemId,
410 kind: ItemKind,
412 location: Option<clang::SourceLocation>,
414}
415
416impl AsRef<ItemId> for Item {
417 fn as_ref(&self) -> &ItemId {
418 &self.id
419 }
420}
421
422impl Item {
423 pub(crate) fn new(
425 id: ItemId,
426 comment: Option<String>,
427 annotations: Option<Annotations>,
428 parent_id: ItemId,
429 kind: ItemKind,
430 location: Option<clang::SourceLocation>,
431 ) -> Self {
432 debug_assert!(id != parent_id || kind.is_module());
433 Item {
434 id,
435 local_id: OnceCell::new(),
436 next_child_local_id: Cell::new(1),
437 canonical_name: OnceCell::new(),
438 path_for_allowlisting: OnceCell::new(),
439 parent_id,
440 comment,
441 annotations: annotations.unwrap_or_default(),
442 kind,
443 location,
444 }
445 }
446
447 pub(crate) fn new_opaque_type(
449 with_id: ItemId,
450 ty: &clang::Type,
451 ctx: &mut BindgenContext,
452 ) -> TypeId {
453 let location = ty.declaration().location();
454 let ty = Opaque::from_clang_ty(ty, ctx);
455 let kind = ItemKind::Type(ty);
456 let parent = ctx.root_module().into();
457 ctx.add_item(
458 Item::new(with_id, None, None, parent, kind, Some(location)),
459 None,
460 None,
461 );
462 with_id.as_type_id_unchecked()
463 }
464
465 pub(crate) fn id(&self) -> ItemId {
467 self.id
468 }
469
470 pub(crate) fn parent_id(&self) -> ItemId {
474 self.parent_id
475 }
476
477 pub(crate) fn set_parent_for_replacement<Id: Into<ItemId>>(
481 &mut self,
482 id: Id,
483 ) {
484 self.parent_id = id.into();
485 }
486
487 pub(crate) fn codegen_depth(&self, ctx: &BindgenContext) -> usize {
491 if !ctx.options().enable_cxx_namespaces {
492 return 0;
493 }
494
495 self.ancestors(ctx)
496 .filter(|id| {
497 ctx.resolve_item(*id).as_module().is_some_and(|module| {
498 !module.is_inline() ||
499 ctx.options().conservative_inline_namespaces
500 })
501 })
502 .count() +
503 1
504 }
505
506 pub(crate) fn comment(&self, ctx: &BindgenContext) -> Option<String> {
509 if !ctx.options().generate_comments {
510 return None;
511 }
512
513 self.comment
514 .as_ref()
515 .map(|comment| ctx.options().process_comment(comment))
516 }
517
518 pub(crate) fn kind(&self) -> &ItemKind {
520 &self.kind
521 }
522
523 pub(crate) fn kind_mut(&mut self) -> &mut ItemKind {
525 &mut self.kind
526 }
527
528 pub(crate) fn location(&self) -> Option<&clang::SourceLocation> {
530 self.location.as_ref()
531 }
532
533 pub(crate) fn local_id(&self, ctx: &BindgenContext) -> usize {
539 *self.local_id.get_or_init(|| {
540 let parent = ctx.resolve_item(self.parent_id);
541 parent.next_child_local_id()
542 })
543 }
544
545 pub(crate) fn next_child_local_id(&self) -> usize {
552 let local_id = self.next_child_local_id.get();
553 self.next_child_local_id.set(local_id + 1);
554 local_id
555 }
556
557 pub(crate) fn is_toplevel(&self, ctx: &BindgenContext) -> bool {
576 if ctx.options().enable_cxx_namespaces &&
579 self.kind().is_module() &&
580 self.id() != ctx.root_module()
581 {
582 return false;
583 }
584
585 let mut parent = self.parent_id;
586 loop {
587 let Some(parent_item) = ctx.resolve_item_fallible(parent) else {
588 return false;
589 };
590
591 if parent_item.id() == ctx.root_module() {
592 return true;
593 } else if ctx.options().enable_cxx_namespaces ||
594 !parent_item.kind().is_module()
595 {
596 return false;
597 }
598
599 parent = parent_item.parent_id();
600 }
601 }
602
603 pub(crate) fn expect_type(&self) -> &Type {
606 self.kind().expect_type()
607 }
608
609 pub(crate) fn as_type(&self) -> Option<&Type> {
612 self.kind().as_type()
613 }
614
615 pub(crate) fn expect_function(&self) -> &Function {
618 self.kind().expect_function()
619 }
620
621 pub(crate) fn is_module(&self) -> bool {
623 matches!(self.kind, ItemKind::Module(..))
624 }
625
626 pub(crate) fn annotations(&self) -> &Annotations {
628 &self.annotations
629 }
630
631 pub(crate) fn is_blocklisted(&self, ctx: &BindgenContext) -> bool {
635 debug_assert!(
636 ctx.in_codegen_phase(),
637 "You're not supposed to call this yet"
638 );
639 if self.annotations.hide() {
640 return true;
641 }
642
643 if !ctx.options().blocklisted_files.is_empty() {
644 if let Some(location) = &self.location {
645 let (file, _, _, _) = location.location();
646 if let Some(filename) = file.name() {
647 if ctx.options().blocklisted_files.matches(filename) {
648 return true;
649 }
650 }
651 }
652 }
653
654 let path = self.path_for_allowlisting(ctx);
655 let name = path[1..].join("::");
656 ctx.options().blocklisted_items.matches(&name) ||
657 match self.kind {
658 ItemKind::Type(..) => {
659 ctx.options().blocklisted_types.matches(&name) ||
660 ctx.is_replaced_type(path, self.id)
661 }
662 ItemKind::Function(..) => {
663 ctx.options().blocklisted_functions.matches(&name)
664 }
665 ItemKind::Var(..) => {
666 ctx.options().blocklisted_vars.matches(&name)
667 }
668 ItemKind::Module(..) => false,
670 }
671 }
672
673 pub(crate) fn name<'a>(
675 &'a self,
676 ctx: &'a BindgenContext,
677 ) -> NameOptions<'a> {
678 NameOptions::new(self, ctx)
679 }
680
681 fn name_target(&self, ctx: &BindgenContext) -> ItemId {
683 let mut targets_seen = DebugOnlyItemSet::new();
684 let mut item = self;
685
686 loop {
687 extra_assert!(!targets_seen.contains(&item.id()));
688 targets_seen.insert(item.id());
689
690 if self.annotations().use_instead_of().is_some() {
691 return self.id();
692 }
693
694 match *item.kind() {
695 ItemKind::Type(ref ty) => match *ty.kind() {
696 TypeKind::ResolvedTypeRef(inner) => {
697 item = ctx.resolve_item(inner);
698 }
699 TypeKind::TemplateInstantiation(ref inst) => {
700 item = ctx.resolve_item(inst.template_definition());
701 }
702 _ => return item.id(),
703 },
704 _ => return item.id(),
705 }
706 }
707 }
708
709 pub(crate) fn full_disambiguated_name(
712 &self,
713 ctx: &BindgenContext,
714 ) -> String {
715 let mut s = String::new();
716 let level = 0;
717 self.push_disambiguated_name(ctx, &mut s, level);
718 s
719 }
720
721 fn push_disambiguated_name(
723 &self,
724 ctx: &BindgenContext,
725 to: &mut String,
726 level: u8,
727 ) {
728 to.push_str(&self.canonical_name(ctx));
729 if let ItemKind::Type(ref ty) = *self.kind() {
730 if let TypeKind::TemplateInstantiation(ref inst) = *ty.kind() {
731 let _ = write!(to, "_open{level}_");
732 for arg in inst.template_arguments() {
733 arg.into_resolver()
734 .through_type_refs()
735 .resolve(ctx)
736 .push_disambiguated_name(ctx, to, level + 1);
737 to.push('_');
738 }
739 let _ = write!(to, "close{level}");
740 }
741 }
742 }
743
744 fn func_name(&self) -> Option<&str> {
746 match *self.kind() {
747 ItemKind::Function(ref func) => Some(func.name()),
748 _ => None,
749 }
750 }
751
752 fn overload_index(&self, ctx: &BindgenContext) -> Option<usize> {
755 self.func_name().and_then(|func_name| {
756 let parent = ctx.resolve_item(self.parent_id());
757 if let ItemKind::Type(ref ty) = *parent.kind() {
758 if let TypeKind::Comp(ref ci) = *ty.kind() {
759 return ci
762 .constructors()
763 .iter()
764 .position(|c| *c == self.id())
765 .or_else(|| {
766 ci.methods()
767 .iter()
768 .filter(|m| {
769 let item = ctx.resolve_item(m.signature());
770 let func = item.expect_function();
771 func.name() == func_name
772 })
773 .position(|m| m.signature() == self.id())
774 });
775 }
776 }
777
778 None
779 })
780 }
781
782 fn base_name(&self, ctx: &BindgenContext) -> String {
784 if let Some(path) = self.annotations().use_instead_of() {
785 return path.last().unwrap().clone();
786 }
787
788 match *self.kind() {
789 ItemKind::Var(ref var) => var.name().to_owned(),
790 ItemKind::Module(ref module) => module.name().map_or_else(
791 || format!("_bindgen_mod_{}", self.exposed_id(ctx)),
792 ToOwned::to_owned,
793 ),
794 ItemKind::Type(ref ty) => ty.sanitized_name(ctx).map_or_else(
795 || format!("_bindgen_ty_{}", self.exposed_id(ctx)),
796 Into::into,
797 ),
798 ItemKind::Function(ref fun) => {
799 let mut name = fun.name().to_owned();
800
801 if let Some(idx) = self.overload_index(ctx) {
802 if idx > 0 {
803 write!(&mut name, "{idx}").unwrap();
804 }
805 }
806
807 name
808 }
809 }
810 }
811
812 fn is_anon(&self) -> bool {
813 match self.kind() {
814 ItemKind::Module(module) => module.name().is_none(),
815 ItemKind::Type(ty) => ty.name().is_none(),
816 ItemKind::Function(_) => false,
817 ItemKind::Var(_) => false,
818 }
819 }
820
821 pub(crate) fn real_canonical_name(
837 &self,
838 ctx: &BindgenContext,
839 opt: &NameOptions,
840 ) -> String {
841 let target = ctx.resolve_item(self.name_target(ctx));
842
843 if let Some(path) = target.annotations.use_instead_of() {
845 if ctx.options().enable_cxx_namespaces {
846 return path.last().unwrap().clone();
847 }
848 return path.join("_");
849 }
850
851 let base_name = target.base_name(ctx);
852
853 if target.is_template_param(ctx, &()) {
856 return base_name;
857 }
858
859 let mut ids_iter = target
861 .parent_id()
862 .ancestors(ctx)
863 .filter(|id| *id != ctx.root_module())
864 .take_while(|id| {
865 !opt.within_namespaces || !ctx.resolve_item(*id).is_module()
868 })
869 .filter(|id| {
870 if !ctx.options().conservative_inline_namespaces {
871 if let ItemKind::Module(ref module) =
872 *ctx.resolve_item(*id).kind()
873 {
874 return !module.is_inline();
875 }
876 }
877
878 true
879 });
880
881 let ids: Vec<_> = if ctx.options().disable_nested_struct_naming {
882 let mut ids = Vec::new();
883
884 if target.is_anon() {
886 for id in ids_iter.by_ref() {
887 ids.push(id);
888
889 if !ctx.resolve_item(id).is_anon() {
890 break;
891 }
892 }
893 }
894
895 ids
896 } else {
897 ids_iter.collect()
898 };
899
900 let mut names: Vec<_> = ids
902 .into_iter()
903 .map(|id| {
904 let item = ctx.resolve_item(id);
905 let target = ctx.resolve_item(item.name_target(ctx));
906 target.base_name(ctx)
907 })
908 .filter(|name| !name.is_empty())
909 .collect();
910
911 names.reverse();
912
913 if !base_name.is_empty() {
914 names.push(base_name);
915 }
916
917 if ctx.options().c_naming {
918 if let Some(prefix) = self.c_naming_prefix() {
919 names.insert(0, prefix.to_string());
920 }
921 }
922
923 let name = names.join("_");
924
925 let name = if opt.user_mangled == UserMangled::Yes {
926 let item_info = ItemInfo {
927 name: &name,
928 kind: match self.kind() {
929 ItemKind::Module(..) => crate::callbacks::ItemKind::Module,
930 ItemKind::Type(..) => crate::callbacks::ItemKind::Type,
931 ItemKind::Function(..) => {
932 crate::callbacks::ItemKind::Function
933 }
934 ItemKind::Var(..) => crate::callbacks::ItemKind::Var,
935 },
936 };
937 ctx.options()
938 .last_callback(|callbacks| callbacks.item_name(item_info))
939 .unwrap_or(name)
940 } else {
941 name
942 };
943
944 ctx.rust_mangle(&name).into_owned()
945 }
946
947 pub(crate) fn exposed_id(&self, ctx: &BindgenContext) -> String {
950 let ty_kind = self.kind().as_type().map(|t| t.kind());
953 if let Some(
954 TypeKind::Comp(..) |
955 TypeKind::TemplateInstantiation(..) |
956 TypeKind::Enum(..),
957 ) = ty_kind
958 {
959 return self.local_id(ctx).to_string();
960 }
961
962 format!("id_{}", self.id().as_usize())
966 }
967
968 pub(crate) fn as_module(&self) -> Option<&Module> {
971 match self.kind {
972 ItemKind::Module(ref module) => Some(module),
973 _ => None,
974 }
975 }
976
977 pub(crate) fn as_module_mut(&mut self) -> Option<&mut Module> {
980 match self.kind {
981 ItemKind::Module(ref mut module) => Some(module),
982 _ => None,
983 }
984 }
985
986 fn is_constified_enum_module(&self, ctx: &BindgenContext) -> bool {
988 let item = self.id.into_resolver().through_type_refs().resolve(ctx);
991 let ItemKind::Type(ref type_) = *item.kind() else {
992 return false;
993 };
994
995 match *type_.kind() {
996 TypeKind::Enum(ref enum_) => {
997 enum_.computed_enum_variation(ctx, self) ==
998 EnumVariation::ModuleConsts
999 }
1000 TypeKind::Alias(inner_id) => {
1001 let inner_item = ctx.resolve_item(inner_id);
1004 let name = item.canonical_name(ctx);
1005
1006 if inner_item.canonical_name(ctx) == name {
1007 inner_item.is_constified_enum_module(ctx)
1008 } else {
1009 false
1010 }
1011 }
1012 _ => false,
1013 }
1014 }
1015
1016 pub(crate) fn is_enabled_for_codegen(&self, ctx: &BindgenContext) -> bool {
1018 let cc = &ctx.options().codegen_config;
1019 match *self.kind() {
1020 ItemKind::Module(..) => true,
1021 ItemKind::Var(_) => cc.vars(),
1022 ItemKind::Type(_) => cc.types(),
1023 ItemKind::Function(ref f) => match f.kind() {
1024 FunctionKind::Function => cc.functions(),
1025 FunctionKind::Method(MethodKind::Constructor) => {
1026 cc.constructors()
1027 }
1028 FunctionKind::Method(
1029 MethodKind::Destructor |
1030 MethodKind::VirtualDestructor { .. },
1031 ) => cc.destructors(),
1032 FunctionKind::Method(
1033 MethodKind::Static |
1034 MethodKind::Normal |
1035 MethodKind::Virtual { .. },
1036 ) => cc.methods(),
1037 },
1038 }
1039 }
1040
1041 pub(crate) fn path_for_allowlisting(
1044 &self,
1045 ctx: &BindgenContext,
1046 ) -> &Vec<String> {
1047 self.path_for_allowlisting
1048 .get_or_init(|| self.compute_path(ctx, UserMangled::No))
1049 }
1050
1051 fn compute_path(
1052 &self,
1053 ctx: &BindgenContext,
1054 mangled: UserMangled,
1055 ) -> Vec<String> {
1056 if let Some(path) = self.annotations().use_instead_of() {
1057 let mut ret =
1058 vec![ctx.resolve_item(ctx.root_module()).name(ctx).get()];
1059 ret.extend_from_slice(path);
1060 return ret;
1061 }
1062
1063 let target = ctx.resolve_item(self.name_target(ctx));
1064 let mut path: Vec<_> = target
1065 .ancestors(ctx)
1066 .chain(iter::once(ctx.root_module().into()))
1067 .map(|id| ctx.resolve_item(id))
1068 .filter(|item| {
1069 item.id() == target.id() ||
1070 item.as_module().is_some_and(|module| {
1071 !module.is_inline() ||
1072 ctx.options().conservative_inline_namespaces
1073 })
1074 })
1075 .map(|item| {
1076 ctx.resolve_item(item.name_target(ctx))
1077 .name(ctx)
1078 .within_namespaces()
1079 .user_mangled(mangled)
1080 .get()
1081 })
1082 .collect();
1083 path.reverse();
1084 path
1085 }
1086
1087 fn c_naming_prefix(&self) -> Option<&str> {
1089 let ItemKind::Type(ref ty) = self.kind else {
1090 return None;
1091 };
1092
1093 Some(match ty.kind() {
1094 TypeKind::Comp(ref ci) => match ci.kind() {
1095 CompKind::Struct => "struct",
1096 CompKind::Union => "union",
1097 },
1098 TypeKind::Enum(..) => "enum",
1099 _ => return None,
1100 })
1101 }
1102
1103 pub(crate) fn must_use(&self, ctx: &BindgenContext) -> bool {
1105 self.annotations().must_use_type() || ctx.must_use_type_by_name(self)
1106 }
1107}
1108
1109impl<T> IsOpaque for T
1110where
1111 T: Copy + Into<ItemId>,
1112{
1113 type Extra = ();
1114
1115 fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool {
1116 debug_assert!(
1117 ctx.in_codegen_phase(),
1118 "You're not supposed to call this yet"
1119 );
1120 ctx.resolve_item((*self).into()).is_opaque(ctx, &())
1121 }
1122}
1123
1124impl IsOpaque for Item {
1125 type Extra = ();
1126
1127 fn is_opaque(&self, ctx: &BindgenContext, _: &()) -> bool {
1128 debug_assert!(
1129 ctx.in_codegen_phase(),
1130 "You're not supposed to call this yet"
1131 );
1132 self.annotations.opaque() ||
1133 self.as_type().is_some_and(|ty| ty.is_opaque(ctx, self)) ||
1134 ctx.opaque_by_name(self.path_for_allowlisting(ctx))
1135 }
1136}
1137
1138impl<T> HasVtable for T
1139where
1140 T: Copy + Into<ItemId>,
1141{
1142 fn has_vtable(&self, ctx: &BindgenContext) -> bool {
1143 let id: ItemId = (*self).into();
1144 id.as_type_id(ctx).is_some_and(|id| {
1145 !matches!(ctx.lookup_has_vtable(id), HasVtableResult::No)
1146 })
1147 }
1148
1149 fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
1150 let id: ItemId = (*self).into();
1151 id.as_type_id(ctx).is_some_and(|id| {
1152 matches!(ctx.lookup_has_vtable(id), HasVtableResult::SelfHasVtable)
1153 })
1154 }
1155}
1156
1157impl HasVtable for Item {
1158 fn has_vtable(&self, ctx: &BindgenContext) -> bool {
1159 self.id().has_vtable(ctx)
1160 }
1161
1162 fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
1163 self.id().has_vtable_ptr(ctx)
1164 }
1165}
1166
1167impl<T> Sizedness for T
1168where
1169 T: Copy + Into<ItemId>,
1170{
1171 fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult {
1172 let id: ItemId = (*self).into();
1173 id.as_type_id(ctx)
1174 .map_or(SizednessResult::default(), |id| ctx.lookup_sizedness(id))
1175 }
1176}
1177
1178impl Sizedness for Item {
1179 fn sizedness(&self, ctx: &BindgenContext) -> SizednessResult {
1180 self.id().sizedness(ctx)
1181 }
1182}
1183
1184impl<T> HasTypeParamInArray for T
1185where
1186 T: Copy + Into<ItemId>,
1187{
1188 fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool {
1189 debug_assert!(
1190 ctx.in_codegen_phase(),
1191 "You're not supposed to call this yet"
1192 );
1193 ctx.lookup_has_type_param_in_array(*self)
1194 }
1195}
1196
1197impl HasTypeParamInArray for Item {
1198 fn has_type_param_in_array(&self, ctx: &BindgenContext) -> bool {
1199 debug_assert!(
1200 ctx.in_codegen_phase(),
1201 "You're not supposed to call this yet"
1202 );
1203 ctx.lookup_has_type_param_in_array(self.id())
1204 }
1205}
1206
1207pub(crate) type ItemSet = BTreeSet<ItemId>;
1209
1210impl DotAttributes for Item {
1211 fn dot_attributes<W>(
1212 &self,
1213 ctx: &BindgenContext,
1214 out: &mut W,
1215 ) -> io::Result<()>
1216 where
1217 W: io::Write,
1218 {
1219 writeln!(
1220 out,
1221 "<tr><td>{:?}</td></tr>
1222 <tr><td>name</td><td>{}</td></tr>",
1223 self.id,
1224 self.name(ctx).get()
1225 )?;
1226
1227 if self.is_opaque(ctx, &()) {
1228 writeln!(out, "<tr><td>opaque</td><td>true</td></tr>")?;
1229 }
1230
1231 self.kind.dot_attributes(ctx, out)
1232 }
1233}
1234
1235impl<T> TemplateParameters for T
1236where
1237 T: Copy + Into<ItemId>,
1238{
1239 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1240 ctx.resolve_item_fallible(*self)
1241 .map_or(vec![], |item| item.self_template_params(ctx))
1242 }
1243}
1244
1245impl TemplateParameters for Item {
1246 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1247 self.kind.self_template_params(ctx)
1248 }
1249}
1250
1251impl TemplateParameters for ItemKind {
1252 fn self_template_params(&self, ctx: &BindgenContext) -> Vec<TypeId> {
1253 match *self {
1254 ItemKind::Type(ref ty) => ty.self_template_params(ctx),
1255 ItemKind::Function(_) | ItemKind::Module(_) | ItemKind::Var(_) => {
1259 vec![]
1260 }
1261 }
1262 }
1263}
1264
1265fn visit_child(
1267 cur: clang::Cursor,
1268 id: ItemId,
1269 ty: &clang::Type,
1270 parent_id: Option<ItemId>,
1271 ctx: &mut BindgenContext,
1272 result: &mut Result<TypeId, ParseError>,
1273) -> clang_sys::CXChildVisitResult {
1274 use clang_sys::*;
1275 if result.is_ok() {
1276 return CXChildVisit_Break;
1277 }
1278
1279 *result = Item::from_ty_with_id(id, ty, cur, parent_id, ctx);
1280
1281 match *result {
1282 Ok(..) => CXChildVisit_Break,
1283 Err(ParseError::Recurse) => {
1284 cur.visit(|c| visit_child(c, id, ty, parent_id, ctx, result));
1285 CXChildVisit_Continue
1286 }
1287 Err(ParseError::Continue) => CXChildVisit_Continue,
1288 }
1289}
1290
1291impl Item {
1292 pub(crate) fn builtin_type(
1294 kind: TypeKind,
1295 is_const: bool,
1296 ctx: &mut BindgenContext,
1297 ) -> TypeId {
1298 match kind {
1300 TypeKind::Void |
1301 TypeKind::Int(..) |
1302 TypeKind::Pointer(..) |
1303 TypeKind::Float(..) => {}
1304 _ => panic!("Unsupported builtin type"),
1305 }
1306
1307 let ty = Type::new(None, None, kind, is_const);
1308 let id = ctx.next_item_id();
1309 let module = ctx.root_module().into();
1310 ctx.add_item(
1311 Item::new(id, None, None, module, ItemKind::Type(ty), None),
1312 None,
1313 None,
1314 );
1315 id.as_type_id_unchecked()
1316 }
1317
1318 pub(crate) fn parse(
1320 cursor: clang::Cursor,
1321 parent_id: Option<ItemId>,
1322 ctx: &mut BindgenContext,
1323 ) -> Result<ItemId, ParseError> {
1324 use crate::ir::var::Var;
1325 use clang_sys::*;
1326
1327 if !cursor.is_valid() {
1328 return Err(ParseError::Continue);
1329 }
1330
1331 let comment = cursor.raw_comment();
1332 let annotations = Annotations::new(&cursor);
1333
1334 let current_module = ctx.current_module().into();
1335 let relevant_parent_id = parent_id.unwrap_or(current_module);
1336
1337 #[allow(clippy::missing_docs_in_private_items)]
1338 macro_rules! try_parse {
1339 ($what:ident) => {
1340 match $what::parse(cursor, ctx) {
1341 Ok(ParseResult::New(item, declaration)) => {
1342 let id = ctx.next_item_id();
1343
1344 ctx.add_item(
1345 Item::new(
1346 id,
1347 comment,
1348 annotations,
1349 relevant_parent_id,
1350 ItemKind::$what(item),
1351 Some(cursor.location()),
1352 ),
1353 declaration,
1354 Some(cursor),
1355 );
1356 return Ok(id);
1357 }
1358 Ok(ParseResult::AlreadyResolved(id)) => {
1359 return Ok(id);
1360 }
1361 Err(ParseError::Recurse) => return Err(ParseError::Recurse),
1362 Err(ParseError::Continue) => {}
1363 }
1364 };
1365 }
1366
1367 try_parse!(Module);
1368
1369 try_parse!(Function);
1377 try_parse!(Var);
1378
1379 {
1382 let definition = cursor.definition();
1383 let applicable_cursor = definition.unwrap_or(cursor);
1384
1385 let relevant_parent_id = match definition {
1386 Some(definition) => {
1387 if definition != cursor {
1388 ctx.add_semantic_parent(definition, relevant_parent_id);
1389 return Ok(Item::from_ty_or_ref(
1390 applicable_cursor.cur_type(),
1391 cursor,
1392 parent_id,
1393 ctx,
1394 )
1395 .into());
1396 }
1397 ctx.known_semantic_parent(definition)
1398 .or(parent_id)
1399 .unwrap_or_else(|| ctx.current_module().into())
1400 }
1401 None => relevant_parent_id,
1402 };
1403
1404 match Item::from_ty(
1405 &applicable_cursor.cur_type(),
1406 applicable_cursor,
1407 Some(relevant_parent_id),
1408 ctx,
1409 ) {
1410 Ok(ty) => return Ok(ty.into()),
1411 Err(ParseError::Recurse) => return Err(ParseError::Recurse),
1412 Err(ParseError::Continue) => {}
1413 }
1414 }
1415
1416 match cursor.kind() {
1417 CXCursor_LinkageSpec | CXCursor_UnexposedDecl => {
1420 Err(ParseError::Recurse)
1421 }
1422
1423 CXCursor_MacroDefinition |
1426 CXCursor_MacroExpansion |
1427 CXCursor_UsingDeclaration |
1428 CXCursor_UsingDirective |
1429 CXCursor_StaticAssert |
1430 CXCursor_FunctionTemplate => {
1431 debug!("Unhandled cursor kind {:?}: {cursor:?}", cursor.kind());
1432 Err(ParseError::Continue)
1433 }
1434
1435 CXCursor_InclusionDirective => {
1436 let file = cursor.get_included_file_name();
1437 match file {
1438 None => {
1439 warn!("Inclusion of a nameless file in {cursor:?}");
1440 }
1441 Some(included_file) => {
1442 for cb in &ctx.options().parse_callbacks {
1443 cb.include_file(&included_file);
1444 }
1445
1446 ctx.add_dep(included_file.into_boxed_str());
1447 }
1448 }
1449 Err(ParseError::Continue)
1450 }
1451
1452 _ => {
1453 let spelling = cursor.spelling();
1455 if !spelling.starts_with("operator") {
1456 warn!(
1457 "Unhandled cursor kind {:?}: {cursor:?}",
1458 cursor.kind(),
1459 );
1460 }
1461 Err(ParseError::Continue)
1462 }
1463 }
1464 }
1465
1466 pub(crate) fn from_ty_or_ref(
1469 ty: clang::Type,
1470 location: clang::Cursor,
1471 parent_id: Option<ItemId>,
1472 ctx: &mut BindgenContext,
1473 ) -> TypeId {
1474 let id = ctx.next_item_id();
1475 Self::from_ty_or_ref_with_id(id, ty, location, parent_id, ctx)
1476 }
1477
1478 pub(crate) fn from_ty_or_ref_with_id(
1489 potential_id: ItemId,
1490 ty: clang::Type,
1491 location: clang::Cursor,
1492 parent_id: Option<ItemId>,
1493 ctx: &mut BindgenContext,
1494 ) -> TypeId {
1495 debug!("from_ty_or_ref_with_id: {potential_id:?} {ty:?}, {location:?}, {parent_id:?}");
1496
1497 if ctx.collected_typerefs() {
1498 debug!("refs already collected, resolving directly");
1499 return Item::from_ty_with_id(
1500 potential_id,
1501 &ty,
1502 location,
1503 parent_id,
1504 ctx,
1505 )
1506 .unwrap_or_else(|_| Item::new_opaque_type(potential_id, &ty, ctx));
1507 }
1508
1509 if let Some(ty) = ctx.builtin_or_resolved_ty(
1510 potential_id,
1511 parent_id,
1512 &ty,
1513 Some(location),
1514 ) {
1515 debug!("{ty:?} already resolved: {location:?}");
1516 return ty;
1517 }
1518
1519 debug!("New unresolved type reference: {ty:?}, {location:?}");
1520
1521 let is_const = ty.is_const();
1522 let kind = TypeKind::UnresolvedTypeRef(ty, location, parent_id);
1523 let current_module = ctx.current_module();
1524
1525 ctx.add_item(
1526 Item::new(
1527 potential_id,
1528 None,
1529 None,
1530 parent_id.unwrap_or_else(|| current_module.into()),
1531 ItemKind::Type(Type::new(None, None, kind, is_const)),
1532 Some(location.location()),
1533 ),
1534 None,
1535 None,
1536 );
1537 potential_id.as_type_id_unchecked()
1538 }
1539
1540 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 pub(crate) fn from_ty_with_id(
1560 id: ItemId,
1561 ty: &clang::Type,
1562 location: clang::Cursor,
1563 parent_id: Option<ItemId>,
1564 ctx: &mut BindgenContext,
1565 ) -> Result<TypeId, ParseError> {
1566 use clang_sys::*;
1567
1568 debug!(
1569 "Item::from_ty_with_id: {id:?}\n\
1570 \tty = {ty:?},\n\
1571 \tlocation = {location:?}",
1572 );
1573
1574 if ty.kind() == CXType_Unexposed ||
1575 location.cur_type().kind() == CXType_Unexposed
1576 {
1577 if ty.is_associated_type() ||
1578 location.cur_type().is_associated_type()
1579 {
1580 return Ok(Item::new_opaque_type(id, ty, ctx));
1581 }
1582
1583 if let Some(param_id) = Item::type_param(None, location, ctx) {
1584 return Ok(ctx.build_ty_wrapper(id, param_id, None, ty));
1585 }
1586 }
1587
1588 if let Some(ref parent) = ty.declaration().fallible_semantic_parent() {
1594 if FunctionKind::from_cursor(parent).is_some() {
1595 debug!("Skipping type declared inside function: {ty:?}");
1596 return Ok(Item::new_opaque_type(id, ty, ctx));
1597 }
1598 }
1599
1600 let decl = {
1601 let canonical_def = ty.canonical_type().declaration().definition();
1602 canonical_def.unwrap_or_else(|| ty.declaration())
1603 };
1604
1605 let comment = location.raw_comment().or_else(|| decl.raw_comment());
1606
1607 let annotations =
1608 Annotations::new(&decl).or_else(|| Annotations::new(&location));
1609
1610 if let Some(ref annotations) = annotations {
1611 if let Some(replaced) = annotations.use_instead_of() {
1612 ctx.replace(replaced, id);
1613 }
1614 }
1615
1616 if let Some(ty) =
1617 ctx.builtin_or_resolved_ty(id, parent_id, ty, Some(location))
1618 {
1619 return Ok(ty);
1620 }
1621
1622 let mut valid_decl = decl.kind() != CXCursor_NoDeclFound;
1624 let declaration_to_look_for = if valid_decl {
1625 decl.canonical()
1626 } else if location.kind() == CXCursor_ClassTemplate {
1627 valid_decl = true;
1628 location
1629 } else {
1630 decl
1631 };
1632
1633 if valid_decl {
1634 if let Some(partial) = ctx
1635 .currently_parsed_types()
1636 .iter()
1637 .find(|ty| *ty.decl() == declaration_to_look_for)
1638 {
1639 debug!("Avoiding recursion parsing type: {ty:?}");
1640 return Ok(partial.id().as_type_id_unchecked());
1642 }
1643 }
1644
1645 let current_module = ctx.current_module().into();
1646 let partial_ty = PartialType::new(declaration_to_look_for, id);
1647 if valid_decl {
1648 ctx.begin_parsing(partial_ty);
1649 }
1650
1651 let result = Type::from_clang_ty(id, ty, location, parent_id, ctx);
1652 let relevant_parent_id = parent_id.unwrap_or(current_module);
1653 let ret = match result {
1654 Ok(ParseResult::AlreadyResolved(ty)) => {
1655 Ok(ty.as_type_id_unchecked())
1656 }
1657 Ok(ParseResult::New(item, declaration)) => {
1658 ctx.add_item(
1659 Item::new(
1660 id,
1661 comment,
1662 annotations,
1663 relevant_parent_id,
1664 ItemKind::Type(item),
1665 Some(location.location()),
1666 ),
1667 declaration,
1668 Some(location),
1669 );
1670 Ok(id.as_type_id_unchecked())
1671 }
1672 Err(ParseError::Continue) => Err(ParseError::Continue),
1673 Err(ParseError::Recurse) => {
1674 debug!("Item::from_ty recursing in the ast");
1675 let mut result = Err(ParseError::Recurse);
1676
1677 if valid_decl {
1683 let finished = ctx.finish_parsing();
1684 assert_eq!(*finished.decl(), declaration_to_look_for);
1685 }
1686
1687 location.visit(|cur| {
1688 visit_child(cur, id, ty, parent_id, ctx, &mut result)
1689 });
1690
1691 if valid_decl {
1692 let partial_ty =
1693 PartialType::new(declaration_to_look_for, id);
1694 ctx.begin_parsing(partial_ty);
1695 }
1696
1697 if let Err(ParseError::Recurse) = result {
1703 warn!(
1704 "Unknown type, assuming named template type: \
1705 id = {:?}; spelling = {}",
1706 id,
1707 ty.spelling()
1708 );
1709 Item::type_param(Some(id), location, ctx)
1710 .ok_or(ParseError::Recurse)
1711 } else {
1712 result
1713 }
1714 }
1715 };
1716
1717 if valid_decl {
1718 let partial_ty = ctx.finish_parsing();
1719 assert_eq!(*partial_ty.decl(), declaration_to_look_for);
1720 }
1721
1722 ret
1723 }
1724
1725 pub(crate) fn type_param(
1728 with_id: Option<ItemId>,
1729 location: clang::Cursor,
1730 ctx: &mut BindgenContext,
1731 ) -> Option<TypeId> {
1732 let ty = location.cur_type();
1733
1734 debug!(
1735 "Item::type_param:\n\
1736 \twith_id = {:?},\n\
1737 \tty = {} {:?},\n\
1738 \tlocation: {:?}",
1739 with_id,
1740 ty.spelling(),
1741 ty,
1742 location
1743 );
1744
1745 if ty.kind() != clang_sys::CXType_Unexposed {
1746 return None;
1751 }
1752
1753 let ty_spelling = ty.spelling();
1754
1755 fn is_template_with_spelling(
1801 refd: &clang::Cursor,
1802 spelling: &str,
1803 ) -> bool {
1804 static ANON_TYPE_PARAM_RE: OnceLock<regex::Regex> = OnceLock::new();
1805 let anon_type_param_re = ANON_TYPE_PARAM_RE.get_or_init(|| {
1806 regex::Regex::new(r"^type\-parameter\-\d+\-\d+$").unwrap()
1807 });
1808
1809 if refd.kind() != clang_sys::CXCursor_TemplateTypeParameter {
1810 return false;
1811 }
1812
1813 let refd_spelling = refd.spelling();
1814 refd_spelling == spelling ||
1815 (refd_spelling.is_empty() && anon_type_param_re.is_match(spelling.as_ref()))
1817 }
1818
1819 let definition = if is_template_with_spelling(&location, &ty_spelling) {
1820 location
1822 } else if location.kind() == clang_sys::CXCursor_TypeRef {
1823 match location.referenced() {
1825 Some(refd)
1826 if is_template_with_spelling(&refd, &ty_spelling) =>
1827 {
1828 refd
1829 }
1830 _ => return None,
1831 }
1832 } else {
1833 let mut definition = None;
1835
1836 location.visit(|child| {
1837 let child_ty = child.cur_type();
1838 if child_ty.kind() == clang_sys::CXCursor_TypeRef &&
1839 child_ty.spelling() == ty_spelling
1840 {
1841 match child.referenced() {
1842 Some(refd)
1843 if is_template_with_spelling(
1844 &refd,
1845 &ty_spelling,
1846 ) =>
1847 {
1848 definition = Some(refd);
1849 return clang_sys::CXChildVisit_Break;
1850 }
1851 _ => {}
1852 }
1853 }
1854
1855 clang_sys::CXChildVisit_Continue
1856 });
1857
1858 definition?
1859 };
1860 assert!(is_template_with_spelling(&definition, &ty_spelling));
1861
1862 let parent = ctx.root_module().into();
1867
1868 if let Some(id) = ctx.get_type_param(&definition) {
1869 return Some(if let Some(with_id) = with_id {
1870 ctx.build_ty_wrapper(with_id, id, Some(parent), &ty)
1871 } else {
1872 id
1873 });
1874 }
1875
1876 let name = ty_spelling.replace("const ", "").replace('.', "");
1879
1880 let id = with_id.unwrap_or_else(|| ctx.next_item_id());
1881 let item = Item::new(
1882 id,
1883 None,
1884 None,
1885 parent,
1886 ItemKind::Type(Type::named(name)),
1887 Some(location.location()),
1888 );
1889 ctx.add_type_param(item, definition);
1890 Some(id.as_type_id_unchecked())
1891 }
1892}
1893
1894impl ItemCanonicalName for Item {
1895 fn canonical_name(&self, ctx: &BindgenContext) -> String {
1896 debug_assert!(
1897 ctx.in_codegen_phase(),
1898 "You're not supposed to call this yet"
1899 );
1900 self.canonical_name
1901 .get_or_init(|| {
1902 let in_namespace = ctx.options().enable_cxx_namespaces ||
1903 ctx.options().disable_name_namespacing;
1904
1905 if in_namespace {
1906 self.name(ctx).within_namespaces().get()
1907 } else {
1908 self.name(ctx).get()
1909 }
1910 })
1911 .clone()
1912 }
1913}
1914
1915impl ItemCanonicalPath for Item {
1916 fn namespace_aware_canonical_path(
1917 &self,
1918 ctx: &BindgenContext,
1919 ) -> Vec<String> {
1920 let mut path = self.canonical_path(ctx);
1921
1922 if ctx.options().disable_name_namespacing {
1926 let split_idx = path.len() - 1;
1928 path = path.split_off(split_idx);
1929 } else if !ctx.options().enable_cxx_namespaces {
1930 path = vec![path[1..].join("_")];
1932 }
1933
1934 if self.is_constified_enum_module(ctx) {
1935 path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into());
1936 }
1937
1938 path
1939 }
1940
1941 fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
1942 self.compute_path(ctx, UserMangled::Yes)
1943 }
1944}
1945
1946#[derive(Copy, Clone, Debug, PartialEq)]
1952enum UserMangled {
1953 No,
1954 Yes,
1955}
1956
1957#[derive(Debug)]
1960pub(crate) struct NameOptions<'a> {
1961 item: &'a Item,
1962 ctx: &'a BindgenContext,
1963 within_namespaces: bool,
1964 user_mangled: UserMangled,
1965}
1966
1967impl<'a> NameOptions<'a> {
1968 pub(crate) fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self {
1970 NameOptions {
1971 item,
1972 ctx,
1973 within_namespaces: false,
1974 user_mangled: UserMangled::Yes,
1975 }
1976 }
1977
1978 pub(crate) fn within_namespaces(&mut self) -> &mut Self {
1981 self.within_namespaces = true;
1982 self
1983 }
1984
1985 fn user_mangled(&mut self, user_mangled: UserMangled) -> &mut Self {
1986 self.user_mangled = user_mangled;
1987 self
1988 }
1989
1990 pub(crate) fn get(&self) -> String {
1992 self.item.real_canonical_name(self.ctx, self)
1993 }
1994}