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