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