summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-10-27 17:24:58 -0500
committerGitHub <noreply@github.com>2016-10-27 17:24:58 -0500
commite8aac6350aa29373140baadbfe79023aaefe20c4 (patch)
tree4ffd5eadd1686ac4896c924353bc5fbadfb2ecaf
parenta6088ee904a249890e98ab3e74875af71ed6672b (diff)
parentc70baa86bcf81e419c21505d531eaea59a41b5af (diff)
Auto merge of #155 - fitzgen:doc-ir-mod, r=emilio
Document the `ir` module r? @emilio
-rw-r--r--src/ir/annotations.rs22
-rw-r--r--src/ir/comp.rs87
-rw-r--r--src/ir/context.rs54
-rw-r--r--src/ir/enum_ty.rs25
-rw-r--r--src/ir/function.rs24
-rw-r--r--src/ir/int.rs38
-rw-r--r--src/ir/item.rs64
-rw-r--r--src/ir/item_kind.rs24
-rw-r--r--src/ir/layout.rs8
-rw-r--r--src/ir/module.rs6
-rw-r--r--src/ir/ty.rs49
-rw-r--r--src/ir/var.rs9
-rwxr-xr-xsrc/lib.rs2
-rw-r--r--src/parse.rs2
14 files changed, 372 insertions, 42 deletions
diff --git a/src/ir/annotations.rs b/src/ir/annotations.rs
index 64ab255d..f0d9715e 100644
--- a/src/ir/annotations.rs
+++ b/src/ir/annotations.rs
@@ -1,10 +1,21 @@
+//! Types and functions related to bindgen annotation comments.
+//!
+//! Users can add annotations in doc comments to types that they would like to
+//! replace other types with, mark as opaque, etc. This module deals with all of
+//! that stuff.
+
use clang;
+/// What kind of accessor should we provide for a field?
#[derive(Copy, PartialEq, Clone, Debug)]
pub enum FieldAccessorKind {
+ /// No accessor.
None,
+ /// Plain accessor.
Regular,
+ /// Unsafe accessor.
Unsafe,
+ /// Immutable accessor.
Immutable,
}
@@ -53,6 +64,8 @@ impl Default for Annotations {
}
impl Annotations {
+ /// Construct new annotations for the given cursor and its bindgen comments
+ /// (if any).
pub fn new(cursor: &clang::Cursor) -> Option<Annotations> {
let mut anno = Annotations::default();
let mut matched_one = false;
@@ -65,10 +78,12 @@ impl Annotations {
}
}
+ /// Should this type be hidden?
pub fn hide(&self) -> bool {
self.hide
}
+ /// Should this type be opaque?
pub fn opaque(&self) -> bool {
self.opaque
}
@@ -87,10 +102,10 @@ impl Annotations {
///
/// the generated code would look something like:
///
- /// ```c++
+ /// ```
/// /** <div rustbindgen replaces="Bar"></div> */
/// struct Bar {
- /// int x;
+ /// x: ::std::os::raw::c_int,
/// };
/// ```
///
@@ -99,14 +114,17 @@ impl Annotations {
self.use_instead_of.as_ref().map(|s| &**s)
}
+ /// Should we avoid implementing the `Copy` trait?
pub fn disallow_copy(&self) -> bool {
self.disallow_copy
}
+ /// Should the fields be private?
pub fn private_fields(&self) -> Option<bool> {
self.private_fields
}
+ /// What kind of accessors should we provide for this type's fields?
pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
self.accessor_kind
}
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index f3bcf866..a8583607 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -1,3 +1,5 @@
+//! Compound types (unions and structs) in our intermediate representation.
+
use super::annotations::Annotations;
use super::context::BindgenContext;
use super::layout::Layout;
@@ -8,16 +10,23 @@ use std::cmp;
use parse::{ClangItemParser, ParseError};
use clang;
+/// The kind of compound type.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum CompKind {
+ /// A struct.
Struct,
+ /// A union.
Union,
}
+/// The kind of C++ method.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum MethodKind {
+ /// A static method.
Static,
+ /// A normal method.
Normal,
+ /// A virtual method.
Virtual,
}
@@ -34,6 +43,7 @@ pub struct Method {
}
impl Method {
+ /// Construct a new `Method`.
fn new(kind: MethodKind, signature: ItemId, is_const: bool) -> Self {
Method {
kind: kind,
@@ -42,22 +52,27 @@ impl Method {
}
}
+ /// What kind of method is this?
pub fn kind(&self) -> MethodKind {
self.kind
}
+ /// Is this a virtual method?
pub fn is_virtual(&self) -> bool {
self.kind == MethodKind::Virtual
}
+ /// Is this a static method?
pub fn is_static(&self) -> bool {
self.kind == MethodKind::Static
}
+ /// Get the `ItemId` for the `Function` signature for this method.
pub fn signature(&self) -> ItemId {
self.signature
}
+ /// Is this a const qualified method?
pub fn is_const(&self) -> bool {
self.is_const
}
@@ -81,6 +96,7 @@ pub struct Field {
}
impl Field {
+ /// Construct a new `Field`.
pub fn new(name: Option<String>,
ty: ItemId,
comment: Option<String>,
@@ -97,48 +113,64 @@ impl Field {
}
}
+ /// Get the name of this field.
pub fn name(&self) -> Option<&str> {
self.name.as_ref().map(|n| &**n)
}
+ /// Get the type of this field.
pub fn ty(&self) -> ItemId {
self.ty
}
+ /// Get the comment for this field.
pub fn comment(&self) -> Option<&str> {
self.comment.as_ref().map(|c| &**c)
}
+ /// If this is a bitfield, how many bits does it need?
pub fn bitfield(&self) -> Option<u32> {
self.bitfield
}
+ /// Is this field marked as `mutable`?
pub fn is_mutable(&self) -> bool {
self.mutable
}
+ /// Get the annotations for this field.
pub fn annotations(&self) -> &Annotations {
&self.annotations
}
}
-
+/// A compound type.
+///
+/// Either a struct or union, a compound type is built up from the combination
+/// of fields which also are associated with their own (potentially compound)
+/// type.
#[derive(Debug)]
pub struct CompInfo {
/// Whether this is a struct or a union.
kind: CompKind,
+
/// The members of this struct or union.
fields: Vec<Field>,
+
/// The template parameters of this class. These are non-concrete, and
/// should always be a Type(TypeKind::Named(name)), but still they need to
/// be registered with an unique type id in the context.
template_args: Vec<ItemId>,
+
/// The method declarations inside this class, if in C++ mode.
methods: Vec<Method>,
+
/// Vector of classes this one inherits from.
base_members: Vec<ItemId>,
+
/// The parent reference template if any.
ref_template: Option<ItemId>,
+
/// The inner types that were declared inside this class, in something like:
///
/// class Foo {
@@ -150,23 +182,31 @@ pub struct CompInfo {
///
/// static Foo::Bar const = {3};
inner_types: Vec<ItemId>,
+
/// Set of static constants declared inside this class.
inner_vars: Vec<ItemId>,
+
/// Whether this type should generate an vtable (TODO: Should be able to
/// look at the virtual methods and ditch this field).
has_vtable: bool,
+
/// Whether this type has destructor.
has_destructor: bool,
+
/// Whether this type has a base type with more than one member.
///
/// TODO: We should be able to compute this.
has_nonempty_base: bool,
+
/// If this type has a template parameter which is not a type (e.g.: a size_t)
has_non_type_template_params: bool,
+
/// Whether this struct layout is packed.
packed: bool,
+
/// Whether this struct is anonymous.
is_anonymous: bool,
+
/// Used to know if we've found an opaque attribute that could cause us to
/// generate a type with invalid layout. This is explicitly used to avoid us
/// generating bad alignments when parsing types like max_align_t.
@@ -174,15 +214,18 @@ pub struct CompInfo {
/// It's not clear what the behavior should be here, if generating the item
/// and pray, or behave as an opaque type.
found_unknown_attr: bool,
+
/// Used to detect if we've run in a can_derive_debug cycle while cycling
/// around the template arguments.
detect_derive_debug_cycle: Cell<bool>,
+
/// Used to detect if we've run in a has_destructor cycle while cycling
/// around the template arguments.
detect_has_destructor_cycle: Cell<bool>,
}
impl CompInfo {
+ /// Construct a new compound type.
pub fn new(kind: CompKind) -> Self {
CompInfo {
kind: kind,
@@ -205,6 +248,7 @@ impl CompInfo {
}
}
+ /// Can we derive the `Debug` trait for this compound type?
pub fn can_derive_debug(&self, ctx: &BindgenContext, layout: Option<Layout>) -> bool {
// We can reach here recursively via template parameters of a member,
// for example.
@@ -248,6 +292,7 @@ impl CompInfo {
can_derive_debug
}
+ /// Is this compound type unsized?
pub fn is_unsized(&self, ctx: &BindgenContext) -> bool {
!self.has_vtable(ctx) && self.fields.is_empty() &&
self.base_members.iter().all(|base| {
@@ -261,6 +306,7 @@ impl CompInfo {
})
}
+ /// Does this compound type have a destructor?
pub fn has_destructor(&self, ctx: &BindgenContext) -> bool {
if self.detect_has_destructor_cycle.get() {
warn!("Cycle detected looking for destructors");
@@ -298,6 +344,7 @@ impl CompInfo {
has_destructor
}
+ /// Can we derive the `Copy` trait for this type?
pub fn can_derive_copy(&self, ctx: &BindgenContext, item: &Item) -> bool {
// NOTE: Take into account that while unions in C and C++ are copied by
// default, the may have an explicit destructor in C++, so we can't
@@ -333,21 +380,24 @@ impl CompInfo {
})
}
+ /// Is this type a template specialization?
pub fn is_template_specialization(&self) -> bool {
self.ref_template.is_some()
}
+ /// Get the template declaration this specialization is specializing.
pub fn specialized_template(&self) -> Option<ItemId> {
self.ref_template
}
- // Computes the layout of this type.
- //
- // This is called as a fallback under some circumstances where LLVM doesn't
- // give us the correct layout.
- // If we're a union without known layout, we try to compute it from our
- // members. This is not ideal, but clang fails to report the size for
- // these kind of unions, see test/headers/template_union.hpp
+ /// Compute the layout of this type.
+ ///
+ /// This is called as a fallback under some circumstances where LLVM doesn't
+ /// give us the correct layout.
+ ///
+ /// If we're a union without known layout, we try to compute it from our
+ /// members. This is not ideal, but clang fails to report the size for these
+ /// kind of unions, see test/headers/template_union.hpp
pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
use std::cmp;
@@ -371,18 +421,24 @@ impl CompInfo {
Some(Layout::new(max_size, max_align))
}
+ /// Get this type's set of fields.
pub fn fields(&self) -> &[Field] {
&self.fields
}
+ /// Get this type's set of free template arguments. Empty if this is not a
+ /// template.
pub fn template_args(&self) -> &[ItemId] {
&self.template_args
}
+ /// Does this type have any template parameters that aren't types
+ /// (e.g. int)?
pub fn has_non_type_template_params(&self) -> bool {
self.has_non_type_template_params
}
+ /// Does this type have a virtual table?
pub fn has_vtable(&self, ctx: &BindgenContext) -> bool {
self.has_vtable || self.base_members().iter().any(|base| {
ctx
@@ -393,18 +449,22 @@ impl CompInfo {
})
}
+ /// Get this type's set of methods.
pub fn methods(&self) -> &[Method] {
&self.methods
}
+ /// What kind of compound type is this?
pub fn kind(&self) -> CompKind {
self.kind
}
+ /// The set of types that this one inherits from.
pub fn base_members(&self) -> &[ItemId] {
&self.base_members
}
+ /// Construct a new compound type from a Clang type.
pub fn from_ty(potential_id: ItemId,
ty: &clang::Type,
location: Option<clang::Cursor>,
@@ -427,7 +487,6 @@ impl CompInfo {
debug!("CompInfo::from_ty({:?}, {:?})", kind, cursor);
-
let mut ci = CompInfo::new(kind);
ci.is_anonymous = cursor.is_anonymous();
ci.template_args = match ty.num_template_args() {
@@ -686,6 +745,10 @@ impl CompInfo {
})
}
+ /// Do any of the types that participate in this type's "signature" use the
+ /// named type `ty`?
+ ///
+ /// See also documentation for `ir::Item::signature_contains_named_type`.
pub fn signature_contains_named_type(&self,
ctx: &BindgenContext,
ty: &Type) -> bool {
@@ -700,18 +763,24 @@ impl CompInfo {
})
}
+ /// Get the set of types that were declared within this compound type
+ /// (e.g. nested class definitions).
pub fn inner_types(&self) -> &[ItemId] {
&self.inner_types
}
+ /// Get the set of static variables declared within this compound type.
pub fn inner_vars(&self) -> &[ItemId] {
&self.inner_vars
}
+ /// Have we found a field with an opaque type that could potentially mess up
+ /// the layout of this compound type?
pub fn found_unknown_attr(&self) -> bool {
self.found_unknown_attr
}
+ /// Is this compound type packed?
pub fn packed(&self) -> bool {
self.packed
}
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 8031f5c0..77cd1182 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -1,3 +1,5 @@
+//! Common context that is passed around during parsing and codegen.
+
use super::ty::{Type, TypeKind, FloatKind};
use super::item::{Item, ItemCanonicalName, ItemId};
use super::item_kind::ItemKind;
@@ -97,6 +99,7 @@ pub struct BindgenContext<'ctx> {
}
impl<'ctx> BindgenContext<'ctx> {
+ /// Construct the context for the given `options`.
pub fn new(options: BindgenOptions) -> Self {
use clangll;
@@ -130,6 +133,10 @@ impl<'ctx> BindgenContext<'ctx> {
me
}
+ /// Define a new item.
+ ///
+ /// This inserts it into the internal items set, and its type into the
+ /// internal types set.
pub fn add_item(&mut self,
item: Item,
declaration: Option<Cursor>,
@@ -186,10 +193,13 @@ impl<'ctx> BindgenContext<'ctx> {
}
// TODO: Move all this syntax crap to other part of the code.
+
+ /// Given that we are in the codegen phase, get the syntex context.
pub fn ext_cx(&self) -> &ExtCtxt<'ctx> {
&self.gen_ctx.expect("Not in gen phase").0
}
+ /// Given that we are in the codegen phase, get the current syntex span.
pub fn span(&self) -> Span {
self.span
}
@@ -220,20 +230,24 @@ impl<'ctx> BindgenContext<'ctx> {
self.rust_ident_raw(&self.rust_mangle(name))
}
+ /// Returns a mangled name as a rust identifier.
pub fn rust_ident_raw<S>(&self, name: &S) -> Ident
where S: Borrow<str>,
{
self.ext_cx().ident_of(name.borrow())
}
+ /// Iterate over all items that have been defined.
pub fn items<'a>(&'a self) -> btree_map::Iter<'a, ItemId, Item> {
self.items.iter()
}
+ /// Have we collected all unresolved type references yet?
pub fn collected_typerefs(&self) -> bool {
self.collected_typerefs
}
+ /// Gather all the unresolved type references.
fn collect_typerefs(&mut self) -> Vec<(ItemId, clang::Type, Option<clang::Cursor>, Option<ItemId>)> {
debug_assert!(!self.collected_typerefs);
self.collected_typerefs = true;
@@ -255,6 +269,7 @@ impl<'ctx> BindgenContext<'ctx> {
typerefs
}
+ /// Collect all of our unresolved type references and resolve them.
fn resolve_typerefs(&mut self) {
let typerefs = self.collect_typerefs();
@@ -276,6 +291,8 @@ impl<'ctx> BindgenContext<'ctx> {
}
}
+ /// Iterate over all items and replace any item that has been named in a
+ /// `replaces="SomeType"` annotation with the replacement type.
fn process_replacements(&mut self) {
if self.replacements.is_empty() {
return;
@@ -322,7 +339,8 @@ impl<'ctx> BindgenContext<'ctx> {
}
}
- // Enters in the generation phase.
+ /// Enter the code generation phase, invoke the given callback `cb`, and
+ /// leave the code generation phase.
pub fn gen<F, Out>(&mut self, cb: F) -> Out
where F: FnOnce(&Self) -> Out
{
@@ -381,22 +399,36 @@ impl<'ctx> BindgenContext<'ctx> {
Item::new(id, None, None, id, ItemKind::Module(module))
}
+ /// Get the root module.
pub fn root_module(&self) -> ItemId {
self.root_module
}
+ /// Resolve the given `ItemId` as a type.
+ ///
+ /// Panics if there is no item for the given `ItemId` or if the resolved
+ /// item is not a `Type`.
pub fn resolve_type(&self, type_id: ItemId) -> &Type {
self.items.get(&type_id).unwrap().kind().expect_type()
}
+ /// Resolve the given `ItemId` as a type, or `None` if there is no item with
+ /// the given id.
+ ///
+ /// Panics if the id resolves to an item that is not a type.
pub fn safe_resolve_type(&self, type_id: ItemId) -> Option<&Type> {
self.items.get(&type_id).map(|t| t.kind().expect_type())
}
+ /// Resolve the given `ItemId` into an `Item`, or `None` if no such item
+ /// exists.
pub fn resolve_item_fallible(&self, item_id: ItemId) -> Option<&Item> {
self.items.get(&item_id)
}
+ /// Resolve the given `ItemId` into an `Item`.
+ ///
+ /// Panics if the given id does not resolve to any item.
pub fn resolve_item(&self, item_id: ItemId) -> &Item {
match self.items.get(&item_id) {
Some(item) => item,
@@ -404,6 +436,7 @@ impl<'ctx> BindgenContext<'ctx> {
}
}
+ /// Get the current module.
pub fn current_module(&self) -> ItemId {
self.current_module
}
@@ -625,29 +658,38 @@ impl<'ctx> BindgenContext<'ctx> {
Some(id)
}
+ /// Get the current Clang translation unit that is being processed.
pub fn translation_unit(&self) -> &clang::TranslationUnit {
&self.translation_unit
}
+ /// Have we parsed the macro named `macro_name` already?
pub fn parsed_macro(&self, macro_name: &str) -> bool {
self.parsed_macros.contains(macro_name)
}
+ /// Mark the macro named `macro_name` as parsed.
pub fn note_parsed_macro(&mut self, macro_name: String) {
debug_assert!(!self.parsed_macros.contains(&macro_name));
self.parsed_macros.insert(macro_name);
}
+ /// Are we in the codegen phase?
pub fn in_codegen_phase(&self) -> bool {
self.gen_ctx.is_some()
}
- /// This is a bit of a hack, but it's done so using the replaces="xxx"
- /// annotation implies hide in the other type.
+ /// Mark the type with the given `name` as replaced by the type with id
+ /// `potential_ty`.
+ ///
+ /// Replacement types are declared using the `replaces="xxx"` annotation,
+ /// and implies that the original type is hidden.
pub fn replace(&mut self, name: &str, potential_ty: ItemId) {
self.replacements.insert(name.into(), potential_ty);
}
+ /// Is the item with the given `name` hidden? Or is the item with the given
+ /// `name` and `id` replaced by another type, and effectively hidden?
pub fn hidden_by_name(&self, name: &str, id: ItemId) -> bool {
debug_assert!(self.in_codegen_phase(),
"You're not supposed to call this yet");
@@ -655,6 +697,8 @@ impl<'ctx> BindgenContext<'ctx> {
self.is_replaced_type(name, id)
}
+ /// Has the item with the given `name` and `id` been replaced by another
+ /// type?
pub fn is_replaced_type(&self, name: &str, id: ItemId) -> bool {
match self.replacements.get(name) {
Some(replaced_by) if *replaced_by != id => true,
@@ -662,12 +706,14 @@ impl<'ctx> BindgenContext<'ctx> {
}
}
+ /// Is the type with the given `name` marked as opaque?
pub fn opaque_by_name(&self, name: &str) -> bool {
debug_assert!(self.in_codegen_phase(),
"You're not supposed to call this yet");
self.options.opaque_types.contains(name)
}
+ /// Get the options used to configure this bindgen context.
pub fn options(&self) -> &BindgenOptions {
&self.options
}
@@ -704,6 +750,8 @@ impl<'ctx> BindgenContext<'ctx> {
module_id
}
+ /// Start traversing the module with the given `module_id`, invoke the
+ /// callback `cb`, and then return to traversing the original module.
pub fn with_module<F>(&mut self, module_id: ItemId, cb: F)
where F: FnOnce(&mut Self, &mut Vec<ItemId>)
{
diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs
index c85ee07a..aff5130b 100644
--- a/src/ir/enum_ty.rs
+++ b/src/ir/enum_ty.rs
@@ -1,22 +1,27 @@
+//! Intermediate representation for C/C++ enumerations.
+
use super::item::{Item, ItemId};
use super::ty::TypeKind;
use super::context::BindgenContext;
use parse::{ClangItemParser, ParseError};
use clang;
+/// A C/C++ enumeration.
#[derive(Debug)]
pub struct Enum {
- /// The representation used for this enum.
- /// Should be an IntKind type.
+ /// The representation used for this enum; it should be an `IntKind` type or
+ /// an alias to one.
///
- /// It's None if the enum is a forward declaration and isn't defined
- /// anywhere else, see tests/headers/func_ptr_in_struct.h
+ /// It's `None` if the enum is a forward declaration and isn't defined
+ /// anywhere else, see `tests/headers/func_ptr_in_struct.h`.
repr: Option<ItemId>,
+
/// The different variants, with explicit values.
variants: Vec<EnumVariant>,
}
impl Enum {
+ /// Construct a new `Enum` with the given representation and variants.
pub fn new(repr: Option<ItemId>, variants: Vec<EnumVariant>) -> Self {
Enum {
repr: repr,
@@ -24,14 +29,17 @@ impl Enum {
}
}
+ /// Get this enumeration's representation.
pub fn repr(&self) -> Option<ItemId> {
self.repr
}
+ /// Get this enumeration's variants.
pub fn variants(&self) -> &[EnumVariant] {
&self.variants
}
+ /// Construct an enumeration from the given Clang type.
pub fn from_ty(ty: &clang::Type,
ctx: &mut BindgenContext) -> Result<Self, ParseError> {
use clangll::*;
@@ -79,19 +87,26 @@ impl Enum {
pub struct EnumVariant {
/// The name of the variant.
name: String,
+
/// An optional doc comment.
comment: Option<String>,
+
/// The integer value of the variant.
val: EnumVariantValue,
}
+/// A constant value assigned to an enumeration variant.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum EnumVariantValue {
+ /// A signed constant.
Signed(i64),
+
+ /// An unsigned constant.
Unsigned(u64),
}
impl EnumVariant {
+ /// Construct a new enumeration variant from the given parts.
pub fn new(name: String, comment: Option<String>, val: EnumVariantValue) -> Self {
EnumVariant {
name: name,
@@ -100,10 +115,12 @@ impl EnumVariant {
}
}
+ /// Get this variant's name.
pub fn name(&self) -> &str {
&self.name
}
+ /// Get this variant's value.
pub fn val(&self) -> EnumVariantValue {
self.val
}
diff --git a/src/ir/function.rs b/src/ir/function.rs
index af170935..2693eddf 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -1,3 +1,5 @@
+//! Intermediate representation for C/C++ functions and methods.
+
use super::item::{Item, ItemId};
use super::ty::TypeKind;
use super::context::BindgenContext;
@@ -6,22 +8,27 @@ use clang;
use clangll::Enum_CXCallingConv;
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
-/// A function declaration , with a signature, arguments, and argument names.
+/// A function declaration, with a signature, arguments, and argument names.
///
/// The argument names vector must be the same length as the ones in the
/// signature.
#[derive(Debug)]
pub struct Function {
+ /// The name of this function.
name: String,
+
/// The mangled name, that is, the symbol.
mangled_name: Option<String>,
+
/// The id pointing to the current function signature.
signature: ItemId,
+
/// The doc comment on the function, if any.
comment: Option<String>,
}
impl Function {
+ /// Construct a new function.
pub fn new(name: String,
mangled_name: Option<String>,
sig: ItemId,
@@ -34,14 +41,17 @@ impl Function {
}
}
+ /// Get this function's name.
pub fn name(&self) -> &str {
&self.name
}
+ /// Get this function's name.
pub fn mangled_name(&self) -> Option<&str> {
self.mangled_name.as_ref().map(|n| &**n)
}
+ /// Get this function's signature.
pub fn signature(&self) -> ItemId {
self.signature
}
@@ -52,12 +62,15 @@ impl Function {
pub struct FunctionSig {
/// The return type of the function.
return_type: ItemId,
+
/// The type of the arguments, optionally with the name of the argument when
/// declared.
argument_types: Vec<(Option<String>, ItemId)>,
+
/// Whether this function is variadic.
is_variadic: bool,
- /// The abi of this function.
+
+ /// The ABI of this function.
abi: abi::Abi,
}
@@ -74,6 +87,7 @@ fn get_abi(cc: Enum_CXCallingConv) -> abi::Abi {
}
}
+/// Get the mangled name for the cursor's referent.
pub fn cursor_mangling(cursor: &clang::Cursor) -> Option<String> {
// We early return here because libclang may crash in some case
// if we pass in a variable inside a partial specialized template.
@@ -93,6 +107,7 @@ pub fn cursor_mangling(cursor: &clang::Cursor) -> Option<String> {
}
impl FunctionSig {
+ /// Construct a new function signature.
pub fn new(return_type: ItemId,
arguments: Vec<(Option<String>, ItemId)>,
is_variadic: bool,
@@ -105,6 +120,7 @@ impl FunctionSig {
}
}
+ /// Construct a new function signature from the given Clang type.
pub fn from_ty(ty: &clang::Type,
cursor: &clang::Cursor,
ctx: &mut BindgenContext) -> Result<Self, ParseError> {
@@ -176,18 +192,22 @@ impl FunctionSig {
Ok(Self::new(ret, args, ty.is_variadic(), abi))
}
+ /// Get this function signature's return type.
pub fn return_type(&self) -> ItemId {
self.return_type
}
+ /// Get this function signature's argument (name, type) pairs.
pub fn argument_types(&self) -> &[(Option<String>, ItemId)] {
&self.argument_types
}
+ /// Get this function signature's ABI.
pub fn abi(&self) -> abi::Abi {
self.abi
}
+ /// Is this function signature variadic?
pub fn is_variadic(&self) -> bool {
// Clang reports some functions as variadic when they *might* be
// variadic. We do the argument check because rust doesn't codegen well
diff --git a/src/ir/int.rs b/src/ir/int.rs
index 75e576d4..ed26acc4 100644
--- a/src/ir/int.rs
+++ b/src/ir/int.rs
@@ -1,24 +1,58 @@
+//! Intermediate representation for integral types.
+
+/// Which integral type are we dealing with?
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum IntKind {
+ /// A `bool`.
Bool,
+
+ /// A `char`.
Char,
+
+ /// An `unsigned char`.
UChar,
+
+ /// A `short`.
Short,
+
+ /// An `unsigned short`.
UShort,
+
+ /// An `int`.
Int,
+
+ /// An `unsigned int`.
UInt,
+
+ /// A `long`.
Long,
+
+ /// An `unsigned long`.
ULong,
+
+ /// A `long long`.
LongLong,
+
+ /// An `unsigned long long`.
ULongLong,
- U16, // For Char16 and Wchar
- U32, // For Char32
+
+ /// Either a `char16_t` or a `wchar_t`.
+ U16,
+
+ /// A `char32_t`.
+ U32,
+
+ /// An `int128_t`
I128,
+
+ /// A `uint128_t`.
U128,
+
// Though now we're at it we could add equivalents for the rust types...
}
impl IntKind {
+ /// Is this integral type signed?
pub fn is_signed(&self) -> bool {
use self::IntKind::*;
match *self {
diff --git a/src/ir/item.rs b/src/ir/item.rs
index 6cb6d7c6..8ec4e78a 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -1,3 +1,5 @@
+//! Bindgen's core intermediate representation type.
+
use regex::Regex;
use super::context::BindgenContext;
use super::item_kind::ItemKind;
@@ -22,6 +24,7 @@ use clangll;
/// This name is required to be safe for Rust, that is, is not expected to
/// return any rust keyword from here.
pub trait ItemCanonicalName {
+ /// Get the canonical name for this item.
fn canonical_name(&self, ctx: &BindgenContext) -> String;
}
@@ -35,9 +38,10 @@ pub trait ItemCanonicalName {
/// }
/// ```
///
-/// For bar, the canonical path is foo::BAR, while the canonical name is just
-/// BAR.
+/// For bar, the canonical path is `foo::BAR`, while the canonical name is just
+/// `BAR`.
pub trait ItemCanonicalPath {
+ /// Get the canonical path for this item.
fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String>;
}
@@ -47,10 +51,10 @@ pub trait ItemCanonicalPath {
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ItemId(usize);
-pub static NEXT_ITEM_ID: AtomicUsize = ATOMIC_USIZE_INIT;
-
impl ItemId {
+ /// Allocate the next `ItemId`.
pub fn next() -> Self {
+ static NEXT_ITEM_ID: AtomicUsize = ATOMIC_USIZE_INIT;
ItemId(NEXT_ITEM_ID.fetch_add(1, Ordering::Relaxed))
}
}
@@ -76,10 +80,13 @@ impl ItemCanonicalPath for ItemId {
/// module, a type, a function, or a variable (see `ItemKind` for more
/// information).
///
-/// Items form a graph, and each item only stores the id of the parent.
+/// Items refer to each other by `ItemId`. Every item has its parent's
+/// id. Depending on the kind of item this is, it may also refer to other items,
+/// such as a compound type item referring to other types. Collectively, these
+/// references form a graph.
///
-/// The entry-point of this graph is the "root module", a meta-item used to hold
-/// all the top-level items.
+/// The entry-point to this graph is the "root module": a meta-item used to hold
+/// all top-level items.
///
/// An item may have a comment, and annotations (see the `annotations` module).
///
@@ -111,6 +118,7 @@ pub struct Item {
}
impl Item {
+ /// Construct a new `Item`.
pub fn new(id: ItemId,
comment: Option<String>,
annotations: Option<Annotations>,
@@ -128,26 +136,38 @@ impl Item {
}
}
+ /// Get this `Item`'s identifier.
pub fn id(&self) -> ItemId {
self.id
}
+ /// Get this `Item`'s parent's identifier.
+ ///
+ /// For the root module, the parent's ID is its own ID.
pub fn parent_id(&self) -> ItemId {
self.parent_id
}
+ /// Get this `Item`'s comment, if it has any.
pub fn comment(&self) -> Option<&str> {
self.comment.as_ref().map(|c| &**c)
}
+ /// What kind of item is this?
pub fn kind(&self) -> &ItemKind {
&self.kind
}
+ /// Get a mutable reference to this item's kind.
pub fn kind_mut(&mut self) -> &mut ItemKind {
&mut self.kind
}
+ /// Get an identifier that differentiates this item from its siblings.
+ ///
+ /// This should stay relatively stable in the face of code motion outside or
+ /// below this item's lexical scope, meaning that this can be useful for
+ /// generating relatively stable identifiers within a scope.
pub fn local_id(&self, ctx: &BindgenContext) -> usize {
if self.local_id.get().is_none() {
let parent = ctx.resolve_item(self.parent_id);
@@ -202,10 +222,14 @@ impl Item {
}
}
+ /// Get a reference to this item's underlying `Type`. Panic if this is some
+ /// other kind of item.
pub fn expect_type(&self) -> &Type {
self.kind().expect_type()
}
+ /// Get a reference to this item's underlying `Function`. Panic if this is
+ /// some other kind of item.
pub fn expect_function(&self) -> &Function {
self.kind().expect_function()
}
@@ -214,7 +238,7 @@ impl Item {
///
/// This function is used to avoid unused template parameter errors in Rust
/// when generating typedef declarations, and also to know whether we need
- /// to generate a PhantomData member for a template parameter.
+ /// to generate a `PhantomData` member for a template parameter.
///
/// For example, in code like the following:
///
@@ -229,13 +253,13 @@ impl Item {
/// };
/// ```
///
- /// Both Foo and Baz contain both `T` and `U` template parameters in their
- /// signature:
+ /// Both `Foo` and `Baz` contain both `T` and `U` template parameters in
+ /// their signature:
///
/// * `Foo<T, U>`
/// * `Bar<T, U>`
///
- /// But the structure for `Foo` would look like:
+ /// But the Rust structure for `Foo` would look like:
///
/// ```rust
/// struct Foo<T, U> {
@@ -244,7 +268,7 @@ impl Item {
/// }
/// ```
///
- /// because non of its member fields contained the `U` type in the
+ /// because none of its member fields contained the `U` type in the
/// signature. Similarly, `Bar` would contain a `PhantomData<T>` type, for
/// the same reason.
///
@@ -372,12 +396,14 @@ impl Item {
}
}
+ /// Get this item's annotations.
pub fn annotations(&self) -> &Annotations {
&self.annotations
}
- /// Whether this item should be hidden, either due to annotations, or due to
- /// other kind of configuration.
+ /// Whether this item should be hidden.
+ ///
+ /// This may be due to either annotations or to other kind of configuration.
pub fn is_hidden(&self, ctx: &BindgenContext) -> bool {
debug_assert!(ctx.in_codegen_phase(),
"You're not supposed to call this yet");
@@ -385,6 +411,7 @@ impl Item {
ctx.hidden_by_name(&self.real_canonical_name(ctx, false, true), self.id)
}
+ /// Is this item opaque?
pub fn is_opaque(&self, ctx: &BindgenContext) -> bool {
debug_assert!(ctx.in_codegen_phase(),
"You're not supposed to call this yet");
@@ -520,10 +547,12 @@ impl Item {
static ref RE_ENDS_WITH_BINDGEN_TY: Regex = Regex::new(r"_bindgen_ty(_\d+)+$").unwrap();
static ref RE_ENDS_WITH_BINDGEN_MOD: Regex = Regex::new(r"_bindgen_mod(_\d+)+$").unwrap();
}
+
let (re, kind) = match *self.kind() {
ItemKind::Module(..) => (&*RE_ENDS_WITH_BINDGEN_MOD, "mod"),
_ => (&*RE_ENDS_WITH_BINDGEN_TY, "ty"),
};
+
let parent_name = parent_name.and_then(|n| if n.is_empty() { None } else { Some(n) });
match (parent_name, base_name) {
(Some(parent), Some(base)) => format!("{}_{}", parent, base),
@@ -539,6 +568,8 @@ impl Item {
}
}
+ /// Get a mutable reference to this item's `Module`, or `None` if this is
+ /// not a `Module` item.
pub fn as_module_mut(&mut self) -> Option<&mut Module> {
match self.kind {
ItemKind::Module(ref mut module) => Some(module),
@@ -546,10 +577,15 @@ impl Item {
}
}
+ /// Can we derive an implementation of the `Copy` trait for this type?
pub fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
self.expect_type().can_derive_copy(ctx, self)
}
+ /// Can we derive an implementation of the `Copy` trait for an array of this
+ /// type?
+ ///
+ /// See `Type::can_derive_copy_in_array` for details.
pub fn can_derive_copy_in_array(&self, ctx: &BindgenContext) -> bool {
self.expect_type().can_derive_copy_in_array(ctx, self)
}
diff --git a/src/ir/item_kind.rs b/src/ir/item_kind.rs
index a47d23a3..d9e4690c 100644
--- a/src/ir/item_kind.rs
+++ b/src/ir/item_kind.rs
@@ -1,3 +1,5 @@
+//! Different variants of an `Item` in our intermediate representation.
+
use super::function::Function;
use super::module::Module;
use super::ty::Type;
@@ -21,6 +23,8 @@ pub enum ItemKind {
}
impl ItemKind {
+ /// Get a reference to this `ItemKind`'s underying `Module`, or `None` if it
+ /// is some other kind.
pub fn as_module(&self) -> Option<&Module> {
match *self {
ItemKind::Module(ref module) => Some(module),
@@ -28,14 +32,19 @@ impl ItemKind {
}
}
+ /// Is this a module?
pub fn is_module(&self) -> bool {
self.as_module().is_some()
}
+ /// Get a reference to this `ItemKind`'s underying `Module`, or panic if it
+ /// is some other kind.
pub fn expect_module(&self) -> &Module {
self.as_module().expect("Not a module")
}
+ /// Get a reference to this `ItemKind`'s underying `Function`, or `None` if
+ /// it is some other kind.
pub fn as_function(&self) -> Option<&Function> {
match *self {
ItemKind::Function(ref func) => Some(func),
@@ -43,14 +52,19 @@ impl ItemKind {
}
}
+ /// Is this a function?
pub fn is_function(&self) -> bool {
self.as_function().is_some()
}
+ /// Get a reference to this `ItemKind`'s underying `Function`, or panic if
+ /// it is some other kind.
pub fn expect_function(&self) -> &Function {
self.as_function().expect("Not a function")
}
+ /// Get a reference to this `ItemKind`'s underying `Type`, or `None` if
+ /// it is some other kind.
pub fn as_type(&self) -> Option<&Type> {
match *self {
ItemKind::Type(ref ty) => Some(ty),
@@ -58,6 +72,8 @@ impl ItemKind {
}
}
+ /// Get a mutable reference to this `ItemKind`'s underying `Type`, or `None`
+ /// if it is some other kind.
pub fn as_type_mut(&mut self) -> Option<&mut Type> {
match *self {
ItemKind::Type(ref mut ty) => Some(ty),
@@ -65,14 +81,19 @@ impl ItemKind {
}
}
+ /// Is this a type?
pub fn is_type(&self) -> bool {
self.as_type().is_some()
}
+ /// Get a reference to this `ItemKind`'s underying `Type`, or panic if it is
+ /// some other kind.
pub fn expect_type(&self) -> &Type {
self.as_type().expect("Not a type")
}
+ /// Get a reference to this `ItemKind`'s underying `Var`, or `None` if it is
+ /// some other kind.
pub fn as_var(&self) -> Option<&Var> {
match *self {
ItemKind::Var(ref v) => Some(v),
@@ -80,10 +101,13 @@ impl ItemKind {
}
}
+ /// Is this a variable?
pub fn is_var(&self) -> bool {
self.as_var().is_some()
}
+ /// Get a reference to this `ItemKind`'s underying `Var`, or panic if it is
+ /// some other kind.
pub fn expect_var(&self) -> &Var {
self.as_var().expect("Not a var")
}
diff --git a/src/ir/layout.rs b/src/ir/layout.rs
index d672ebea..3ac4a5f4 100644
--- a/src/ir/layout.rs
+++ b/src/ir/layout.rs
@@ -1,13 +1,19 @@
+//! Intermediate representation for the physical layout of some type.
/// A type that represents the struct layout of a type.
#[derive(Debug, Clone, Copy)]
pub struct Layout {
+ /// The size (in bytes) of this layout.
pub size: usize,
+ /// The alignment (in bytes) of this layout.
pub align: usize,
+ /// Whether this layout's members are packed or not.
pub packed: bool,
}
impl Layout {
+ /// Construct a new `Layout` with the given `size` and `align`. It is not
+ /// packed.
pub fn new(size: usize, align: usize) -> Self {
Layout {
size: size,
@@ -16,10 +22,12 @@ impl Layout {
}
}
+ /// Is this a zero-sized layout?
pub fn is_zero(&self) -> bool {
self.size == 0 && self.align == 0
}
+ /// Construct a zero-sized layout.
pub fn zero() -> Self {
Self::new(0, 0)
}
diff --git a/src/ir/module.rs b/src/ir/module.rs
index 77fee5ef..591a4e3a 100644
--- a/src/ir/module.rs
+++ b/src/ir/module.rs
@@ -1,3 +1,5 @@
+//! Intermediate representation for modules (AKA C++ namespaces).
+
use super::context::BindgenContext;
use super::item::ItemId;
use clang;
@@ -14,6 +16,7 @@ pub struct Module {
}
impl Module {
+ /// Construct a new `Module`.
pub fn new(name: Option<String>) -> Self {
Module {
name: name,
@@ -21,14 +24,17 @@ impl Module {
}
}
+ /// Get this module's name.
pub fn name(&self) -> Option<&str> {
self.name.as_ref().map(|n| &**n)
}
+ /// Get a mutable reference to this module's children.
pub fn children_mut(&mut self) -> &mut Vec<ItemId> {
&mut self.children_ids
}
+ /// Get this module's children.
pub fn children(&self) -> &[ItemId] {
&self.children_ids
}
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index 5765a78c..3a17b374 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -1,3 +1,5 @@
+//! Everything related to types in our intermediate representation.
+
use super::comp::CompInfo;
use super::enum_ty::Enum;
use super::function::FunctionSig;
@@ -25,9 +27,16 @@ pub struct Type {
is_const: bool,
}
-pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32usize;
+/// The maximum number of items in an array for which Rust implements common
+/// traits, and so if we have a type containing an array with more than this
+/// many items, we won't be able to derive common traits on that type.
+///
+/// We need type-level integers yesterday :'(
+pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32;
impl Type {
+ /// Get the underlying `CompInfo` for this type, or `None` if this is some
+ /// other kind of type.
pub fn as_comp(&self) -> Option<&CompInfo> {
match self.kind {
TypeKind::Comp(ref ci) => Some(ci),
@@ -35,6 +44,7 @@ impl Type {
}
}
+ /// Construct a new `Type`.
pub fn new(name: Option<String>,
layout: Option<Layout>,
kind: TypeKind,
@@ -47,18 +57,22 @@ impl Type {
}
}
+ /// Which kind of type is this?
pub fn kind(&self) -> &TypeKind {
&self.kind
}
+ /// Get a mutable reference to this type's kind.
pub fn kind_mut(&mut self) -> &mut TypeKind {
&mut self.kind
}
+ /// Get this type's name.
pub fn name(&self) -> Option<&str> {
self.name.as_ref().map(|name| &**name)
}
+ /// Is this a compound type?
pub fn is_comp(&self) -> bool {
match self.kind {
TypeKind::Comp(..) => true,
@@ -66,6 +80,7 @@ impl Type {
}
}
+ /// Is this a named type?
pub fn is_named(&self) -> bool {
match self.kind {
TypeKind::Named(..) => true,
@@ -73,6 +88,7 @@ impl Type {
}
}
+ /// Is this a function type?
pub fn is_function(&self) -> bool {
match self.kind {
TypeKind::Function(..) => true,
@@ -80,6 +96,7 @@ impl Type {
}
}
+ /// Is this either a builtin or named type?
pub fn is_builtin_or_named(&self) -> bool {
match self.kind {
TypeKind::Void |
@@ -104,6 +121,7 @@ impl Type {
Self::new(Some(name), None, kind, false)
}
+ /// Is this an integer type?
pub fn is_integer(&self, ctx: &BindgenContext) -> bool {
match self.kind {
TypeKind::UnresolvedTypeRef(..) => false,
@@ -114,10 +132,12 @@ impl Type {
}
}
+ /// Is this a `const` qualified type?
pub fn is_const(&self) -> bool {
self.is_const
}
+ /// What is the layout of this type?
pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
use std::mem;
@@ -326,8 +346,11 @@ impl Type {
/// The kind of float this type represents.
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum FloatKind {
+ /// A `float`.
Float,
+ /// A `double`.
Double,
+ /// A `long double`.
LongDouble,
}
@@ -336,33 +359,46 @@ pub enum FloatKind {
pub enum TypeKind {
/// The void type.
Void,
- /// The nullptr_t type.
+
+ /// The `nullptr_t` type.
NullPtr,
+
/// A compound type, that is, a class, struct, or union.
Comp(CompInfo),
+
/// An integer type, of a given kind. `bool` and `char` are also considered
/// integers.
Int(IntKind),
+
/// A floating point type.
Float(FloatKind),
+
/// A type alias, with a name, that points to another type.
Alias(String, ItemId),
- /// A templated alias, pointing to an inner Alias type, with template
+
+ /// A templated alias, pointing to an inner `Alias` type, with template
/// parameters.
TemplateAlias(ItemId, Vec<ItemId>),
+
/// An array of a type and a lenght.
Array(ItemId, usize),
+
/// A function type, with a given signature.
Function(FunctionSig),
- /// An enum type.
+
+ /// An `enum` type.
Enum(Enum),
+
/// A pointer to a type. The bool field represents whether it's const or
/// not.
Pointer(ItemId),
+
/// A pointer to an Apple block.
BlockPointer,
+
/// A reference to a type, as in: int& foo().
Reference(ItemId),
+
/// A reference to a template, with different template parameter names. To
/// see why this is needed, check out the creation of this variant in
/// `Type::from_clang_ty`.
@@ -376,6 +412,11 @@ pub enum TypeKind {
///
/// see tests/headers/typeref.hpp to see somewhere where this is a problem.
UnresolvedTypeRef(clang::Type, Option<clang::Cursor>, /* parent_id */ Option<ItemId>),
+
+ /// An indirection to another type.
+ ///
+ /// These are generated after we resolve a forward declaration, or when we
+ /// replace one type with another.
ResolvedTypeRef(ItemId),
/// A named type, that is, a template parameter, with an optional default
diff --git a/src/ir/var.rs b/src/ir/var.rs
index 623a0636..3dd975ee 100644
--- a/src/ir/var.rs
+++ b/src/ir/var.rs
@@ -1,3 +1,5 @@
+//! Intermediate representation of variables.
+
use super::item::{Item, ItemId};
use super::context::BindgenContext;
use super::ty::TypeKind;
@@ -6,6 +8,7 @@ use super::function::cursor_mangling;
use parse::{ClangItemParser, ClangSubItemParser, ParseResult, ParseError};
use clang;
+/// A `Var` is our intermediate representation of a variable.
#[derive(Debug)]
pub struct Var {
/// The name of the variable.
@@ -22,6 +25,7 @@ pub struct Var {
}
impl Var {
+ /// Construct a new `Var`.
pub fn new(name: String,
mangled: Option<String>,
ty: ItemId,
@@ -37,22 +41,27 @@ impl Var {
}
}
+ /// Is this variable `const` qualified?
pub fn is_const(&self) -> bool {
self.is_const
}
+ /// The value of this constant variable, if any.
pub fn val(&self) -> Option<i64> {
self.val
}
+ /// Get this variable's type.
pub fn ty(&self) -> ItemId {
self.ty
}
+ /// Get this variable's name.
pub fn name(&self) -> &str {
&self.name
}
+ /// Get this variable's mangled name.
pub fn mangled_name(&self) -> Option<&str> {
self.mangled_name.as_ref().map(|n| &**n)
}
diff --git a/src/lib.rs b/src/lib.rs
index 29369d41..76862721 100755
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -54,7 +54,7 @@ macro_rules! doc_mod {
mod clangll;
doc_mod!(clang);
-mod ir;
+doc_mod!(ir);
mod parse;
mod regex_set;
diff --git a/src/parse.rs b/src/parse.rs
index d6c36aa4..c71f4c52 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -16,7 +16,7 @@ pub enum ParseResult<T> {
}
pub trait ClangSubItemParser : Sized {
- /// The fact that is a reference guarantees it's holded by the context, and
+ /// The fact that is a reference guarantees it's held by the context, and
/// allow returning already existing types.
fn parse(cursor: clang::Cursor, context: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError>;
}