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