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