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