summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/chooser.rs14
-rwxr-xr-xsrc/clang.rs1259
-rw-r--r--src/clangll.rs1439
-rw-r--r--src/codegen/helpers.rs135
-rwxr-xr-xsrc/codegen/mod.rs2121
-rw-r--r--src/ir/annotations.rs157
-rw-r--r--src/ir/comp.rs871
-rw-r--r--src/ir/context.rs1055
-rw-r--r--src/ir/enum_ty.rs137
-rw-r--r--src/ir/function.rs282
-rw-r--r--src/ir/int.rs93
-rw-r--r--src/ir/item.rs1172
-rw-r--r--src/ir/item_kind.rs114
-rw-r--r--src/ir/layout.rs34
-rw-r--r--src/ir/mod.rs18
-rw-r--r--src/ir/module.rs61
-rw-r--r--src/ir/ty.rs869
-rw-r--r--src/ir/type_collector.rs22
-rw-r--r--src/ir/var.rs246
-rwxr-xr-xsrc/lib.rs614
-rw-r--r--[-rwxr-xr-x]src/main.rs (renamed from src/bin/bindgen.rs)7
-rw-r--r--src/options.rs (renamed from src/bin/options.rs)5
-rw-r--r--src/parse.rs106
-rw-r--r--src/regex_set.rs66
-rw-r--r--src/uses.rs102
25 files changed, 3 insertions, 10996 deletions
diff --git a/src/chooser.rs b/src/chooser.rs
deleted file mode 100644
index 10a77dc9..00000000
--- a/src/chooser.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//! A public API for more fine-grained customization of bindgen behavior.
-
-pub use ir::int::IntKind;
-use std::fmt;
-
-/// A trait to allow configuring different kinds of types in different
-/// situations.
-pub trait TypeChooser: fmt::Debug {
- /// The integer kind an integer macro should have, given a name and the
- /// value of that macro, or `None` if you want the default to be chosen.
- fn int_macro(&self, _name: &str, _value: i64) -> Option<IntKind> {
- None
- }
-}
diff --git a/src/clang.rs b/src/clang.rs
deleted file mode 100755
index 7da755ea..00000000
--- a/src/clang.rs
+++ /dev/null
@@ -1,1259 +0,0 @@
-//! A higher level Clang API built on top of the generated bindings in the
-//! `clangll` module.
-
-#![allow(non_upper_case_globals, dead_code)]
-
-
-use cexpr;
-use clangll::*;
-use std::{mem, ptr, slice};
-use std::ffi::{CStr, CString};
-use std::fmt;
-use std::hash::Hash;
-use std::hash::Hasher;
-use std::os::raw::{c_char, c_int, c_uint, c_ulong};
-
-/// A cursor into the Clang AST, pointing to an AST node.
-///
-/// We call the AST node pointed to by the cursor the cursor's "referent".
-#[derive(Copy, Clone)]
-pub struct Cursor {
- x: CXCursor,
-}
-
-impl fmt::Debug for Cursor {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- write!(fmt,
- "Cursor({} kind: {}, loc: {}, usr: {:?})",
- self.spelling(),
- kind_to_str(self.kind()),
- self.location(),
- self.usr())
- }
-}
-
-impl Cursor {
- /// Get the Unified Symbol Resolution for this cursor's referent, if
- /// available.
- ///
- /// The USR can be used to compare entities across translation units.
- pub fn usr(&self) -> Option<String> {
- let s: String = unsafe { clang_getCursorUSR(self.x) }.into();
- if s.is_empty() { None } else { Some(s) }
- }
-
- /// Is this cursor's referent a declaration?
- pub fn is_declaration(&self) -> bool {
- unsafe { clang_isDeclaration(self.kind()) != 0 }
- }
-
- /// Get the null cursor, which has no referent.
- pub fn null() -> Self {
- Cursor {
- x: unsafe { clang_getNullCursor() },
- }
- }
-
- /// Get this cursor's referent's spelling.
- pub fn spelling(&self) -> String {
- unsafe { clang_getCursorSpelling(self.x).into() }
- }
-
- /// Get this cursor's referent's display name.
- ///
- /// This is not necessarily a valid identifier. It includes extra
- /// information, such as parameters for a function, etc.
- pub fn display_name(&self) -> String {
- unsafe { clang_getCursorDisplayName(self.x).into() }
- }
-
- /// Get the mangled name of this cursor's referent.
- pub fn mangling(&self) -> String {
- unsafe { clang_Cursor_getMangling(self.x).into() }
- }
-
- /// Get the `Cursor` for this cursor's referent's lexical parent.
- ///
- /// The lexical parent is the parent of the definition. The semantic parent
- /// is the parent of the declaration. Generally, the lexical parent doesn't
- /// have any effect on semantics, while the semantic parent does.
- ///
- /// In the following snippet, the `Foo` class would be the semantic parent
- /// of the out-of-line `method` definition, while the lexical parent is the
- /// translation unit.
- ///
- /// ```c++
- /// class Foo {
- /// void method();
- /// };
- ///
- /// void Foo::method() { /* ... */ }
- /// ```
- pub fn lexical_parent(&self) -> Cursor {
- unsafe {
- Cursor {
- x: clang_getCursorLexicalParent(self.x),
- }
- }
- }
-
- /// Get the referent's semantic parent, if one is available.
- ///
- /// See documentation for `lexical_parent` for details on semantic vs
- /// lexical parents.
- pub fn fallible_semantic_parent(&self) -> Option<Cursor> {
- let sp = unsafe {
- Cursor {
- x: clang_getCursorSemanticParent(self.x),
- }
- };
- if sp == *self || !sp.is_valid() {
- return None;
- }
- Some(sp)
- }
-
- /// Get the referent's semantic parent.
- ///
- /// See documentation for `lexical_parent` for details on semantic vs
- /// lexical parents.
- pub fn semantic_parent(&self) -> Cursor {
- self.fallible_semantic_parent().unwrap()
- }
-
- /// Return the number of template arguments used by this cursor's referent,
- /// if the referent is either a template specialization or
- /// declaration. Returns -1 otherwise.
- ///
- /// NOTE: This may not return `Some` for some non-fully specialized
- /// templates, see #193 and #194.
- pub fn num_template_args(&self) -> Option<u32> {
- let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) };
-
- if n >= 0 {
- Some(n as u32)
- } else {
- debug_assert_eq!(n, -1);
- None
- }
- }
-
- /// Get a cursor pointing to this referent's containing translation unit.
- ///
- /// Note that we shouldn't create a `TranslationUnit` struct here, because
- /// bindgen assumes there will only be one of them alive at a time, and
- /// disposes it on drop. That can change if this would be required, but I
- /// think we can survive fine without it.
- pub fn translation_unit(&self) -> Cursor {
- assert!(self.is_valid());
- unsafe {
- let tu = clang_Cursor_getTranslationUnit(self.x);
- let cursor = Cursor {
- x: clang_getTranslationUnitCursor(tu),
- };
- assert!(cursor.is_valid());
- cursor
- }
- }
-
- /// Is the referent a top level construct?
- pub fn is_toplevel(&self) -> bool {
- let mut semantic_parent = self.fallible_semantic_parent();
-
- while semantic_parent.is_some() &&
- (semantic_parent.unwrap().kind() == CXCursor_Namespace ||
- semantic_parent.unwrap().kind() == CXCursor_NamespaceAlias ||
- semantic_parent.unwrap().kind() == CXCursor_NamespaceRef) {
- semantic_parent = semantic_parent.unwrap()
- .fallible_semantic_parent();
- }
-
- let tu = self.translation_unit();
- // Yes, this can happen with, e.g., macro definitions.
- semantic_parent == tu.fallible_semantic_parent()
- }
-
- /// Get the kind of referent this cursor is pointing to.
- pub fn kind(&self) -> Enum_CXCursorKind {
- unsafe { clang_getCursorKind(self.x) }
- }
-
- /// Is the referent an anonymous record definition?
- pub fn is_anonymous(&self) -> bool {
- unsafe { clang_Cursor_isAnonymous(self.x) != 0 }
- }
-
- /// Is the referent a template specialization?
- pub fn is_template(&self) -> bool {
- self.specialized().is_some()
- }
-
- /// Is the referent a fully specialized template specialization without any
- /// remaining free template arguments?
- pub fn is_fully_specialized_template(&self) -> bool {
- self.is_template() && self.num_template_args().unwrap_or(0) > 0
- }
-
- /// Is the referent a template specialization that still has remaining free
- /// template arguments?
- pub fn is_in_non_fully_specialized_template(&self) -> bool {
- if self.is_toplevel() {
- return false;
- }
- let parent = self.semantic_parent();
- (parent.is_template() && !parent.is_fully_specialized_template()) ||
- parent.is_in_non_fully_specialized_template()
- }
-
- /// Is this cursor pointing a valid referent?
- pub fn is_valid(&self) -> bool {
- unsafe { clang_isInvalid(self.kind()) == 0 }
- }
-
- /// Get the source location for the referent.
- pub fn location(&self) -> SourceLocation {
- unsafe {
- SourceLocation {
- x: clang_getCursorLocation(self.x),
- }
- }
- }
-
- /// Get the source location range for the referent.
- pub fn extent(&self) -> CXSourceRange {
- unsafe { clang_getCursorExtent(self.x) }
- }
-
- /// Get the raw declaration comment for this referent, if one exists.
- pub fn raw_comment(&self) -> Option<String> {
- let s: String =
- unsafe { clang_Cursor_getRawCommentText(self.x).into() };
- if s.is_empty() { None } else { Some(s) }
- }
-
- /// Get the referent's parsed comment.
- pub fn comment(&self) -> Comment {
- unsafe {
- Comment {
- x: clang_Cursor_getParsedComment(self.x),
- }
- }
- }
-
- /// Get the referent's type.
- pub fn cur_type(&self) -> Type {
- unsafe {
- Type {
- x: clang_getCursorType(self.x),
- }
- }
- }
-
- /// Given that this cursor's referent is a reference to another type, or is
- /// a declaration, get the cursor pointing to the referenced type or type of
- /// the declared thing.
- pub fn definition(&self) -> Option<Cursor> {
- unsafe {
- let ret = Cursor {
- x: clang_getCursorDefinition(self.x),
- };
-
- if ret.is_valid() { Some(ret) } else { None }
- }
- }
-
- /// Given that this cursor's referent is reference type, get the cursor
- /// pointing to the referenced type.
- pub fn referenced(&self) -> Option<Cursor> {
- unsafe {
- let ret = Cursor {
- x: clang_getCursorReferenced(self.x),
- };
-
- if ret.is_valid() { Some(ret) } else { None }
- }
- }
-
- /// Get the canonical cursor for this referent.
- ///
- /// Many types can be declared multiple times before finally being properly
- /// defined. This method allows us to get the canonical cursor for the
- /// referent type.
- pub fn canonical(&self) -> Cursor {
- unsafe {
- Cursor {
- x: clang_getCanonicalCursor(self.x),
- }
- }
- }
-
- /// Given that this cursor points to a template specialization, get a cursor
- /// pointing to the template definition that is being specialized.
- pub fn specialized(&self) -> Option<Cursor> {
- unsafe {
- let ret = Cursor {
- x: clang_getSpecializedCursorTemplate(self.x),
- };
- if ret.is_valid() { Some(ret) } else { None }
- }
- }
-
- /// Assuming that this cursor's referent is a template declaration, get the
- /// kind of cursor that would be generated for its specializations.
- pub fn template_kind(&self) -> Enum_CXCursorKind {
- unsafe { clang_getTemplateCursorKind(self.x) }
- }
-
- /// Traverse this cursor's referent and its children.
- ///
- /// Call the given function on each AST node traversed.
- pub fn visit<Visitor>(&self, mut visitor: Visitor)
- where Visitor: FnMut(Cursor) -> Enum_CXChildVisitResult,
- {
- unsafe {
- clang_visitChildren(self.x,
- Some(visit_children::<Visitor>),
- mem::transmute(&mut visitor));
- }
- }
-
- /// Returns whether the given location contains a cursor with the given
- /// kind in the first level of nesting underneath (doesn't look
- /// recursively).
- pub fn contains_cursor(&self, kind: Enum_CXCursorKind) -> bool {
- let mut found = false;
-
- self.visit(|c| {
- if c.kind() == kind {
- found = true;
- CXChildVisit_Break
- } else {
- CXChildVisit_Continue
- }
- });
-
- found
- }
-
- /// Is the referent an inlined function?
- #[cfg(not(feature="llvm_stable"))]
- pub fn is_inlined_function(&self) -> bool {
- unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 }
- }
-
- // TODO: Remove this when LLVM 3.9 is released.
- //
- // This is currently used for CI purposes.
-
- /// Is the referent an inlined function?
- #[cfg(feature="llvm_stable")]
- pub fn is_inlined_function(&self) -> bool {
- false
- }
-
- /// Get the width of this cursor's referent bit field, or `None` if the
- /// referent is not a bit field.
- pub fn bit_width(&self) -> Option<u32> {
- unsafe {
- let w = clang_getFieldDeclBitWidth(self.x);
- if w == -1 { None } else { Some(w as u32) }
- }
- }
-
- /// Get the integer representation type used to hold this cursor's referent
- /// enum type.
- pub fn enum_type(&self) -> Type {
- unsafe {
- Type {
- x: clang_getEnumDeclIntegerType(self.x),
- }
- }
- }
-
- /// Get the signed constant value for this cursor's enum variant referent.
- ///
- /// Returns None if the cursor's referent is not an enum variant.
- pub fn enum_val_signed(&self) -> Option<i64> {
- unsafe {
- if self.kind() == CXCursor_EnumConstantDecl {
- Some(clang_getEnumConstantDeclValue(self.x) as i64)
- } else {
- None
- }
- }
- }
-
- /// Get the unsigned constant value for this cursor's enum variant referent.
- ///
- /// Returns None if the cursor's referent is not an enum variant.
- pub fn enum_val_unsigned(&self) -> Option<u64> {
- unsafe {
- if self.kind() == CXCursor_EnumConstantDecl {
- Some(clang_getEnumConstantDeclUnsignedValue(self.x) as u64)
- } else {
- None
- }
- }
- }
-
- /// Given that this cursor's referent is a `typedef`, get the `Type` that is
- /// being aliased.
- pub fn typedef_type(&self) -> Type {
- unsafe {
- Type {
- x: clang_getTypedefDeclUnderlyingType(self.x),
- }
- }
- }
-
- /// Get the linkage kind for this cursor's referent.
- ///
- /// This only applies to functions and variables.
- pub fn linkage(&self) -> Enum_CXLinkageKind {
- unsafe { clang_getCursorLinkage(self.x) }
- }
-
- /// Get the visibility of this cursor's referent.
- pub fn visibility(&self) -> Enum_CXVisibilityKind {
- unsafe { clang_getCursorVisibility(self.x) }
- }
-
- /// Given that this cursor's referent is a function, return cursors to its
- /// parameters.
- pub fn args(&self) -> Vec<Cursor> {
- unsafe {
- let num = self.num_args().expect("expected value, got none") as u32;
- let mut args = vec![];
- for i in 0..num {
- args.push(Cursor {
- x: clang_Cursor_getArgument(self.x, i as c_uint),
- });
- }
- args
- }
- }
-
- /// Given that this cursor's referent is a function/method call or
- /// declaration, return the number of arguments it takes.
- ///
- /// Returns -1 if the cursor's referent is not a function/method call or
- /// declaration.
- pub fn num_args(&self) -> Result<u32, ()> {
- unsafe {
- let w = clang_Cursor_getNumArguments(self.x);
- if w == -1 { Err(()) } else { Ok(w as u32) }
- }
- }
-
- /// Get the access specifier for this cursor's referent.
- pub fn access_specifier(&self) -> Enum_CX_CXXAccessSpecifier {
- unsafe { clang_getCXXAccessSpecifier(self.x) }
- }
-
- /// Is this cursor's referent a field declaration that is marked as
- /// `mutable`?
- pub fn is_mutable_field(&self) -> bool {
- unsafe { clang_CXXField_isMutable(self.x) != 0 }
- }
-
- /// Is this cursor's referent a member function that is declared `static`?
- pub fn method_is_static(&self) -> bool {
- unsafe { clang_CXXMethod_isStatic(self.x) != 0 }
- }
-
- /// Is this cursor's referent a member function that is declared `const`?
- pub fn method_is_const(&self) -> bool {
- unsafe { clang_CXXMethod_isConst(self.x) != 0 }
- }
-
- /// Is this cursor's referent a member function that is declared `const`?
- pub fn method_is_virtual(&self) -> bool {
- unsafe { clang_CXXMethod_isVirtual(self.x) != 0 }
- }
-
- /// Is this cursor's referent a struct or class with virtual members?
- pub fn is_virtual_base(&self) -> bool {
- unsafe { clang_isVirtualBase(self.x) != 0 }
- }
-}
-
-extern "C" fn visit_children<Visitor>(cur: CXCursor,
- _parent: CXCursor,
- data: CXClientData)
- -> Enum_CXChildVisitResult
- where Visitor: FnMut(Cursor) -> Enum_CXChildVisitResult,
-{
- let func: &mut Visitor = unsafe { mem::transmute(data) };
- let child = Cursor {
- x: cur,
- };
-
- (*func)(child)
-}
-
-impl PartialEq for Cursor {
- fn eq(&self, other: &Cursor) -> bool {
- unsafe { clang_equalCursors(self.x, other.x) == 1 }
- }
-}
-
-impl Eq for Cursor {}
-
-impl Hash for Cursor {
- fn hash<H: Hasher>(&self, state: &mut H) {
- unsafe { clang_hashCursor(self.x) }.hash(state)
- }
-}
-
-/// The type of a node in clang's AST.
-#[derive(Clone, Hash)]
-pub struct Type {
- x: CXType,
-}
-
-impl PartialEq for Type {
- fn eq(&self, other: &Self) -> bool {
- unsafe { clang_equalTypes(self.x, other.x) != 0 }
- }
-}
-
-impl Eq for Type {}
-
-impl fmt::Debug for Type {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- write!(fmt,
- "Type({}, kind: {}, decl: {:?}, canon: {:?})",
- self.spelling(),
- type_to_str(self.kind()),
- self.declaration(),
- self.declaration().canonical())
- }
-}
-
-/// An error about the layout of a struct, class, or type.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum LayoutError {
- /// Asked for the layout of an invalid type.
- Invalid,
- /// Asked for the layout of an incomplete type.
- Incomplete,
- /// Asked for the layout of a dependent type.
- Dependent,
- /// Asked for the layout of a type that does not have constant size.
- NotConstantSize,
- /// Asked for the layout of a field in a type that does not have such a
- /// field.
- InvalidFieldName,
- /// An unknown layout error.
- Unknown,
-}
-
-impl ::std::convert::From<i32> for LayoutError {
- fn from(val: i32) -> Self {
- use self::LayoutError::*;
- match val {
- CXTypeLayoutError_Invalid => Invalid,
- CXTypeLayoutError_Incomplete => Incomplete,
- CXTypeLayoutError_Dependent => Dependent,
- CXTypeLayoutError_NotConstantSize => NotConstantSize,
- CXTypeLayoutError_InvalidFieldName => InvalidFieldName,
- _ => Unknown,
- }
- }
-}
-
-impl Type {
- /// Get this type's kind.
- pub fn kind(&self) -> Enum_CXTypeKind {
- self.x.kind
- }
-
- /// Get a cursor pointing to this type's declaration.
- pub fn declaration(&self) -> Cursor {
- unsafe {
- Cursor {
- x: clang_getTypeDeclaration(self.x),
- }
- }
- }
-
- /// Get a raw display name for this type.
- pub fn spelling(&self) -> String {
- unsafe { clang_getTypeSpelling(self.x).into() }
- }
-
- /// Is this type const qualified?
- pub fn is_const(&self) -> bool {
- unsafe { clang_isConstQualifiedType(self.x) != 0 }
- }
-
- /// What is the size of this type? Paper over invalid types by returning `0`
- /// for them.
- pub fn size(&self) -> usize {
- unsafe {
- let val = clang_Type_getSizeOf(self.x);
- if val < 0 { 0 } else { val as usize }
- }
- }
-
- /// What is the size of this type?
- pub fn fallible_size(&self) -> Result<usize, LayoutError> {
- let val = unsafe { clang_Type_getSizeOf(self.x) };
- if val < 0 {
- Err(LayoutError::from(val as i32))
- } else {
- Ok(val as usize)
- }
- }
-
- /// What is the alignment of this type? Paper over invalid types by
- /// returning `0`.
- pub fn align(&self) -> usize {
- unsafe {
- let val = clang_Type_getAlignOf(self.x);
- if val < 0 { 0 } else { val as usize }
- }
- }
-
- /// What is the alignment of this type?
- pub fn fallible_align(&self) -> Result<usize, LayoutError> {
- unsafe {
- let val = clang_Type_getAlignOf(self.x);
- if val < 0 {
- Err(LayoutError::from(val as i32))
- } else {
- Ok(val as usize)
- }
- }
- }
-
- /// Get the layout for this type, or an error describing why it does not
- /// have a valid layout.
- pub fn fallible_layout(&self) -> Result<::ir::layout::Layout, LayoutError> {
- use ir::layout::Layout;
- let size = try!(self.fallible_size());
- let align = try!(self.fallible_align());
- Ok(Layout::new(size, align))
- }
-
- /// If this type is a class template specialization, return its
- /// template arguments. Otherwise, return None.
- pub fn template_args(&self) -> Option<TypeTemplateArgIterator> {
- let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
- if n >= 0 {
- Some(TypeTemplateArgIterator {
- x: self.x,
- length: n as u32,
- index: 0,
- })
- } else {
- debug_assert_eq!(n, -1);
- None
- }
- }
-
- /// Given that this type is a pointer type, return the type that it points
- /// to.
- pub fn pointee_type(&self) -> Option<Type> {
- match self.kind() {
- CXType_Pointer |
- CXType_RValueReference |
- CXType_LValueReference |
- CXType_MemberPointer => {
- let ret = Type {
- x: unsafe { clang_getPointeeType(self.x) },
- };
- debug_assert!(ret.is_valid());
- Some(ret)
- }
- _ => None,
- }
- }
-
- /// Given that this type is an array, vector, or complex type, return the
- /// type of its elements.
- pub fn elem_type(&self) -> Option<Type> {
- let current_type = Type {
- x: unsafe { clang_getElementType(self.x) },
- };
- if current_type.is_valid() {
- Some(current_type)
- } else {
- None
- }
- }
-
- /// Given that this type is an array or vector type, return its number of
- /// elements.
- pub fn num_elements(&self) -> Option<usize> {
- let num_elements_returned = unsafe { clang_getNumElements(self.x) };
- if num_elements_returned != -1 {
- Some(num_elements_returned as usize)
- } else {
- None
- }
- }
-
- /// Get the canonical version of this type. This sees through `typdef`s and
- /// aliases to get the underlying, canonical type.
- pub fn canonical_type(&self) -> Type {
- unsafe {
- Type {
- x: clang_getCanonicalType(self.x),
- }
- }
- }
-
- /// Is this type a variadic function type?
- pub fn is_variadic(&self) -> bool {
- unsafe { clang_isFunctionTypeVariadic(self.x) != 0 }
- }
-
- /// Given that this type is a function type, get the type of its return
- /// value.
- pub fn ret_type(&self) -> Option<Type> {
- let rt = Type {
- x: unsafe { clang_getResultType(self.x) },
- };
- if rt.is_valid() { Some(rt) } else { None }
- }
-
- /// Given that this type is a function type, get its calling convention. If
- /// this is not a function type, `CXCallingConv_Invalid` is returned.
- pub fn call_conv(&self) -> Enum_CXCallingConv {
- unsafe { clang_getFunctionTypeCallingConv(self.x) }
- }
-
- /// For elaborated types (types which use `class`, `struct`, or `union` to
- /// disambiguate types from local bindings), get the underlying type.
- #[cfg(not(feature="llvm_stable"))]
- pub fn named(&self) -> Type {
- unsafe {
- Type {
- x: clang_Type_getNamedType(self.x),
- }
- }
- }
-
- /// Is this a valid type?
- pub fn is_valid(&self) -> bool {
- self.kind() != CXType_Invalid
- }
-
- /// Is this a valid and exposed type?
- pub fn is_valid_and_exposed(&self) -> bool {
- self.is_valid() && self.kind() != CXType_Unexposed
- }
-}
-
-/// An iterator for a type's template arguments.
-pub struct TypeTemplateArgIterator {
- x: CXType,
- length: u32,
- index: u32,
-}
-
-impl Iterator for TypeTemplateArgIterator {
- type Item = Type;
- fn next(&mut self) -> Option<Type> {
- if self.index < self.length {
- let idx = self.index as c_int;
- self.index += 1;
- Some(Type {
- x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) },
- })
- } else {
- None
- }
- }
-}
-
-impl ExactSizeIterator for TypeTemplateArgIterator {
- fn len(&self) -> usize {
- assert!(self.index <= self.length);
- (self.length - self.index) as usize
- }
-}
-
-/// A `SourceLocation` is a file, line, column, and byte offset location for
-/// some source text.
-pub struct SourceLocation {
- x: CXSourceLocation,
-}
-
-impl SourceLocation {
- /// Get the (file, line, column, byte offset) tuple for this source
- /// location.
- pub fn location(&self) -> (File, usize, usize, usize) {
- unsafe {
- let mut file = ptr::null_mut();
- let mut line = 0;
- let mut col = 0;
- let mut off = 0;
- clang_getSpellingLocation(self.x,
- &mut file,
- &mut line,
- &mut col,
- &mut off);
- (File {
- x: file,
- },
- line as usize,
- col as usize,
- off as usize)
- }
- }
-}
-
-impl fmt::Display for SourceLocation {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let (file, line, col, _) = self.location();
- if let Some(name) = file.name() {
- write!(f, "{}:{}:{}", name, line, col)
- } else {
- "builtin definitions".fmt(f)
- }
- }
-}
-
-/// A comment in the source text.
-///
-/// Comments are sort of parsed by Clang, and have a tree structure.
-pub struct Comment {
- x: CXComment,
-}
-
-impl Comment {
- /// What kind of comment is this?
- pub fn kind(&self) -> Enum_CXCommentKind {
- unsafe { clang_Comment_getKind(self.x) }
- }
-
- /// Get this comment's children comment
- pub fn get_children(&self) -> CommentChildrenIterator {
- CommentChildrenIterator {
- parent: self.x,
- length: unsafe { clang_Comment_getNumChildren(self.x) },
- index: 0,
- }
- }
-
- /// Given that this comment is the start or end of an HTML tag, get its tag
- /// name.
- pub fn get_tag_name(&self) -> String {
- unsafe { clang_HTMLTagComment_getTagName(self.x).into() }
- }
-
- /// Given that this comment is an HTML start tag, get its attributes.
- pub fn get_tag_attrs(&self) -> CommentAttributesIterator {
- CommentAttributesIterator {
- x: self.x,
- length: unsafe { clang_HTMLStartTag_getNumAttrs(self.x) },
- index: 0,
- }
- }
-}
-
-/// An iterator for a comment's children
-pub struct CommentChildrenIterator {
- parent: CXComment,
- length: c_uint,
- index: c_uint,
-}
-
-impl Iterator for CommentChildrenIterator {
- type Item = Comment;
- fn next(&mut self) -> Option<Comment> {
- if self.index < self.length {
- let idx = self.index;
- self.index += 1;
- Some(Comment {
- x: unsafe { clang_Comment_getChild(self.parent, idx) },
- })
- } else {
- None
- }
- }
-}
-
-/// An HTML start tag comment attribute
-pub struct CommentAttribute {
- /// HTML start tag attribute name
- pub name: String,
- /// HTML start tag attribute value
- pub value: String,
-}
-
-/// An iterator for a comment's attributes
-pub struct CommentAttributesIterator {
- x: CXComment,
- length: c_uint,
- index: c_uint,
-}
-
-impl Iterator for CommentAttributesIterator {
- type Item = CommentAttribute;
- fn next(&mut self) -> Option<CommentAttribute> {
- if self.index < self.length {
- let idx = self.index;
- self.index += 1;
- Some(CommentAttribute {
- name: unsafe {
- clang_HTMLStartTag_getAttrName(self.x, idx).into()
- },
- value: unsafe {
- clang_HTMLStartTag_getAttrValue(self.x, idx).into()
- },
- })
- } else {
- None
- }
- }
-}
-
-/// A source file.
-pub struct File {
- x: CXFile,
-}
-
-impl File {
- /// Get the name of this source file.
- pub fn name(&self) -> Option<String> {
- if self.x.is_null() {
- return None;
- }
- unsafe { Some(clang_getFileName(self.x).into()) }
- }
-}
-
-impl Into<String> for CXString {
- fn into(self) -> String {
- if self.data.is_null() {
- return "".to_owned();
- }
- unsafe {
- let c_str = CStr::from_ptr(clang_getCString(self) as *const _);
- c_str.to_string_lossy().into_owned()
- }
- }
-}
-
-/// An `Index` is an environment for a set of translation units that will
-/// typically end up linked together in one final binary.
-pub struct Index {
- x: CXIndex,
-}
-
-impl Index {
- /// Construct a new `Index`.
- ///
- /// The `pch` parameter controls whether declarations in pre-compiled
- /// headers are included when enumerating a translation unit's "locals".
- ///
- /// The `diag` parameter controls whether debugging diagnostics are enabled.
- pub fn new(pch: bool, diag: bool) -> Index {
- unsafe {
- Index {
- x: clang_createIndex(pch as c_int, diag as c_int),
- }
- }
- }
-}
-
-impl fmt::Debug for Index {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- write!(fmt, "Index {{ }}")
- }
-}
-
-impl Drop for Index {
- fn drop(&mut self) {
- unsafe {
- clang_disposeIndex(self.x);
- }
- }
-}
-
-/// A token emitted by clang's lexer.
-#[derive(Debug)]
-pub struct Token {
- /// The kind of token this is.
- pub kind: CXTokenKind,
- /// A display name for this token.
- pub spelling: String,
-}
-
-/// A translation unit (or "compilation unit").
-pub struct TranslationUnit {
- x: CXTranslationUnit,
-}
-
-impl fmt::Debug for TranslationUnit {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- write!(fmt, "TranslationUnit {{ }}")
- }
-}
-
-impl TranslationUnit {
- /// Parse a source file into a translation unit.
- pub fn parse(ix: &Index,
- file: &str,
- cmd_args: &[String],
- unsaved: &[UnsavedFile],
- opts: ::libc::c_uint)
- -> Option<TranslationUnit> {
- let fname = CString::new(file).unwrap();
- let _c_args: Vec<CString> =
- cmd_args.iter().map(|s| CString::new(s.clone()).unwrap()).collect();
- let c_args: Vec<*const c_char> =
- _c_args.iter().map(|s| s.as_ptr()).collect();
- let mut c_unsaved: Vec<Struct_CXUnsavedFile> =
- unsaved.iter().map(|f| f.x).collect();
- let tu = unsafe {
- clang_parseTranslationUnit(ix.x,
- fname.as_ptr(),
- c_args.as_ptr(),
- c_args.len() as c_int,
- c_unsaved.as_mut_ptr(),
- c_unsaved.len() as c_uint,
- opts)
- };
- if tu.is_null() {
- None
- } else {
- Some(TranslationUnit {
- x: tu,
- })
- }
- }
-
- /// Reparse this translation unit, maybe because the file changed on disk or
- /// something like that.
- pub fn reparse(&self, unsaved: &[UnsavedFile], opts: usize) -> bool {
- let mut c_unsaved: Vec<Struct_CXUnsavedFile> =
- unsaved.iter().map(|f| f.x).collect();
-
- unsafe {
- clang_reparseTranslationUnit(self.x,
- c_unsaved.len() as c_uint,
- c_unsaved.as_mut_ptr(),
- opts as c_uint) == 0
- }
- }
-
- /// Get the Clang diagnostic information associated with this translation
- /// unit.
- pub fn diags(&self) -> Vec<Diagnostic> {
- unsafe {
- let num = clang_getNumDiagnostics(self.x) as usize;
- let mut diags = vec![];
- for i in 0..num {
- diags.push(Diagnostic {
- x: clang_getDiagnostic(self.x, i as c_uint),
- });
- }
- diags
- }
- }
-
- /// Get a cursor pointing to the root of this translation unit's AST.
- pub fn cursor(&self) -> Cursor {
- unsafe {
- Cursor {
- x: clang_getTranslationUnitCursor(self.x),
- }
- }
- }
-
- /// Is this the null translation unit?
- pub fn is_null(&self) -> bool {
- self.x.is_null()
- }
-
- /// Invoke Clang's lexer on this translation unit and get the stream of
- /// tokens that come out.
- pub fn tokens(&self, cursor: &Cursor) -> Option<Vec<Token>> {
- let range = cursor.extent();
- let mut tokens = vec![];
- unsafe {
- let mut token_ptr = ptr::null_mut();
- let mut num_tokens: c_uint = 0;
- clang_tokenize(self.x, range, &mut token_ptr, &mut num_tokens);
- if token_ptr.is_null() {
- return None;
- }
-
- let token_array = slice::from_raw_parts(token_ptr,
- num_tokens as usize);
- for &token in token_array.iter() {
- let kind = clang_getTokenKind(token);
- let spelling = clang_getTokenSpelling(self.x, token).into();
-
- tokens.push(Token {
- kind: kind,
- spelling: spelling,
- });
- }
- clang_disposeTokens(self.x, token_ptr, num_tokens);
- }
- Some(tokens)
- }
-
- /// Convert a set of tokens from clang into `cexpr` tokens, for further
- /// processing.
- pub fn cexpr_tokens(&self,
- cursor: &Cursor)
- -> Option<Vec<cexpr::token::Token>> {
- use cexpr::token;
-
- let mut tokens = match self.tokens(cursor) {
- Some(tokens) => tokens,
- None => return None,
- };
-
- // FIXME(emilio): LLVM 3.9 at least always include an extra token for no
- // good reason (except if we're at EOF). So we do this kind of hack,
- // where we skip known-to-cause problems trailing punctuation and
- // trailing keywords.
- //
- // This is sort of unfortunate, though :(.
- //
- // I'll try to get it fixed in LLVM if I have the time to submit a
- // patch.
- let mut trim_last_token = false;
- if let Some(token) = tokens.last() {
- // The starting of the next macro.
- trim_last_token |= token.spelling == "#" &&
- token.kind == CXToken_Punctuation;
-
- // A following keyword of any kind, like a following declaration.
- trim_last_token |= token.kind == CXToken_Keyword;
- }
-
- if trim_last_token {
- tokens.pop().unwrap();
- }
-
- Some(tokens.into_iter()
- .filter_map(|token| {
- let kind = match token.kind {
- CXToken_Punctuation => token::Kind::Punctuation,
- CXToken_Literal => token::Kind::Literal,
- CXToken_Identifier => token::Kind::Identifier,
- CXToken_Keyword => token::Kind::Keyword,
- // NB: cexpr is not too happy about comments inside
- // expressions, so we strip them down here.
- CXToken_Comment => return None,
- _ => panic!("Found unexpected token kind: {}", token.kind),
- };
-
- Some(token::Token {
- kind: kind,
- raw: token.spelling.into_bytes().into_boxed_slice(),
- })
- })
- .collect::<Vec<_>>())
- }
-}
-
-impl Drop for TranslationUnit {
- fn drop(&mut self) {
- unsafe {
- clang_disposeTranslationUnit(self.x);
- }
- }
-}
-
-
-/// A diagnostic message generated while parsing a translation unit.
-pub struct Diagnostic {
- x: CXDiagnostic,
-}
-
-impl Diagnostic {
- /// Get the default diagnostic display option bit flags.
- pub fn default_opts() -> usize {
- unsafe { clang_defaultDiagnosticDisplayOptions() as usize }
- }
-
- /// Format this diagnostic message as a string, using the given option bit
- /// flags.
- pub fn format(&self, opts: usize) -> String {
- unsafe { clang_formatDiagnostic(self.x, opts as c_uint).into() }
- }
-
- /// What is the severity of this diagnostic message?
- pub fn severity(&self) -> Enum_CXDiagnosticSeverity {
- unsafe { clang_getDiagnosticSeverity(self.x) }
- }
-}
-
-impl Drop for Diagnostic {
- /// Destroy this diagnostic message.
- fn drop(&mut self) {
- unsafe {
- clang_disposeDiagnostic(self.x);
- }
- }
-}
-
-/// A file which has not been saved to disk.
-pub struct UnsavedFile {
- x: Struct_CXUnsavedFile,
- name: CString,
- contents: CString,
-}
-
-impl UnsavedFile {
- /// Construct a new unsaved file with the given `name` and `contents`.
- pub fn new(name: &str, contents: &str) -> UnsavedFile {
- let name = CString::new(name).unwrap();
- let contents = CString::new(contents).unwrap();
- let x = Struct_CXUnsavedFile {
- Filename: name.as_ptr(),
- Contents: contents.as_ptr(),
- Length: contents.as_bytes().len() as c_ulong,
- };
- UnsavedFile {
- x: x,
- name: name,
- contents: contents,
- }
- }
-}
-
-/// Convert a cursor kind into a static string.
-pub fn kind_to_str(x: Enum_CXCursorKind) -> String {
- unsafe { clang_getCursorKindSpelling(x) }.into()
-}
-
-/// Convert a type kind to a static string.
-pub fn type_to_str(x: Enum_CXTypeKind) -> String {
- unsafe { clang_getTypeKindSpelling(x).into() }
-}
-
-/// Dump the Clang AST to stdout for debugging purposes.
-pub fn ast_dump(c: &Cursor, depth: isize) -> Enum_CXVisitorResult {
- fn print_indent(depth: isize, s: &str) {
- let mut i = 0;
- while i < depth {
- print!("\t");
- i += 1;
- }
- println!("{}", s);
- }
- let ct = c.cur_type().kind();
- print_indent(depth,
- &format!("({} {} {}",
- kind_to_str(c.kind()),
- c.spelling(),
- type_to_str(ct)));
- c.visit(|s| ast_dump(&s, depth + 1));
- print_indent(depth, ")");
- CXChildVisit_Continue
-}
-
-/// Try to extract the clang version to a string
-pub fn extract_clang_version() -> String {
- unsafe { clang_getClangVersion().into() }
-}
diff --git a/src/clangll.rs b/src/clangll.rs
deleted file mode 100644
index b9743117..00000000
--- a/src/clangll.rs
+++ /dev/null
@@ -1,1439 +0,0 @@
-/* automatically generated by rust-bindgen */
-
-#![allow(non_camel_case_types)]
-#![allow(dead_code)]
-#![allow(unused_attributes)]
-#![allow(non_snake_case)]
-#![allow(non_upper_case_globals)]
-#![cfg_attr(rustfmt, rustfmt_skip)]
-
-use ::std::os::raw::{ c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void};
-
-pub type ptrdiff_t = c_long;
-pub type size_t = c_ulong;
-pub type wchar_t = c_int;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXString {
- pub data: *const c_void,
- pub private_flags: c_uint,
-}
-pub type CXIndex = *mut c_void;
-pub enum Struct_CXTranslationUnitImpl { }
-pub type CXTranslationUnit = *mut Struct_CXTranslationUnitImpl;
-pub type CXClientData = *mut c_void;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct Struct_CXUnsavedFile {
- pub Filename: *const c_char,
- pub Contents: *const c_char,
- pub Length: c_ulong,
-}
-pub type Enum_CXAvailabilityKind = c_uint;
-pub const CXAvailability_Available: c_uint = 0;
-pub const CXAvailability_Deprecated: c_uint = 1;
-pub const CXAvailability_NotAvailable: c_uint = 2;
-pub const CXAvailability_NotAccessible: c_uint = 3;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct Struct_CXVersion {
- pub Major: c_int,
- pub Minor: c_int,
- pub Subminor: c_int,
-}
-pub type CXVersion = Struct_CXVersion;
-pub type CXGlobalOptFlags = c_uint;
-pub const CXGlobalOpt_None: c_uint = 0;
-pub const CXGlobalOpt_ThreadBackgroundPriorityForIndexing: c_uint =
- 1;
-pub const CXGlobalOpt_ThreadBackgroundPriorityForEditing: c_uint = 2;
-pub const CXGlobalOpt_ThreadBackgroundPriorityForAll: c_uint = 3;
-pub type CXFile = *mut c_void;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXFileUniqueID {
- pub data: [c_ulonglong; 3],
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXSourceLocation {
- pub ptr_data: [*const c_void; 2],
- pub int_data: c_uint,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXSourceRange {
- pub ptr_data: [*const c_void; 2],
- pub begin_int_data: c_uint,
- pub end_int_data: c_uint,
-}
-pub type Enum_CXDiagnosticSeverity = c_uint;
-pub const CXDiagnostic_Ignored: c_uint = 0;
-pub const CXDiagnostic_Note: c_uint = 1;
-pub const CXDiagnostic_Warning: c_uint = 2;
-pub const CXDiagnostic_Error: c_uint = 3;
-pub const CXDiagnostic_Fatal: c_uint = 4;
-pub type CXDiagnostic = *mut c_void;
-pub type CXDiagnosticSet = *mut c_void;
-pub type Enum_CXLoadDiag_Error = c_uint;
-pub const CXLoadDiag_None: c_uint = 0;
-pub const CXLoadDiag_Unknown: c_uint = 1;
-pub const CXLoadDiag_CannotLoad: c_uint = 2;
-pub const CXLoadDiag_InvalidFile: c_uint = 3;
-pub type Enum_CXDiagnosticDisplayOptions = c_uint;
-pub const CXDiagnostic_DisplaySourceLocation: c_uint = 1;
-pub const CXDiagnostic_DisplayColumn: c_uint = 2;
-pub const CXDiagnostic_DisplaySourceRanges: c_uint = 4;
-pub const CXDiagnostic_DisplayOption: c_uint = 8;
-pub const CXDiagnostic_DisplayCategoryId: c_uint = 16;
-pub const CXDiagnostic_DisplayCategoryName: c_uint = 32;
-pub type Enum_CXTranslationUnit_Flags = c_uint;
-pub const CXTranslationUnit_None: c_uint = 0;
-pub const CXTranslationUnit_DetailedPreprocessingRecord: c_uint = 1;
-pub const CXTranslationUnit_Incomplete: c_uint = 2;
-pub const CXTranslationUnit_PrecompiledPreamble: c_uint = 4;
-pub const CXTranslationUnit_CacheCompletionResults: c_uint = 8;
-pub const CXTranslationUnit_ForSerialization: c_uint = 16;
-pub const CXTranslationUnit_CXXChainedPCH: c_uint = 32;
-pub const CXTranslationUnit_SkipFunctionBodies: c_uint = 64;
-pub const CXTranslationUnit_IncludeBriefCommentsInCodeCompletion:
- c_uint =
- 128;
-pub type Enum_CXSaveTranslationUnit_Flags = c_uint;
-pub const CXSaveTranslationUnit_None: c_uint = 0;
-pub type Enum_CXSaveError = c_uint;
-pub const CXSaveError_None: c_uint = 0;
-pub const CXSaveError_Unknown: c_uint = 1;
-pub const CXSaveError_TranslationErrors: c_uint = 2;
-pub const CXSaveError_InvalidTU: c_uint = 3;
-pub type Enum_CXReparse_Flags = c_uint;
-pub const CXReparse_None: c_uint = 0;
-pub type Enum_CXTUResourceUsageKind = c_uint;
-pub const CXTUResourceUsage_AST: c_uint = 1;
-pub const CXTUResourceUsage_Identifiers: c_uint = 2;
-pub const CXTUResourceUsage_Selectors: c_uint = 3;
-pub const CXTUResourceUsage_GlobalCompletionResults: c_uint = 4;
-pub const CXTUResourceUsage_SourceManagerContentCache: c_uint = 5;
-pub const CXTUResourceUsage_AST_SideTables: c_uint = 6;
-pub const CXTUResourceUsage_SourceManager_Membuffer_Malloc: c_uint =
- 7;
-pub const CXTUResourceUsage_SourceManager_Membuffer_MMap: c_uint = 8;
-pub const CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc:
- c_uint =
- 9;
-pub const CXTUResourceUsage_ExternalASTSource_Membuffer_MMap: c_uint
- =
- 10;
-pub const CXTUResourceUsage_Preprocessor: c_uint = 11;
-pub const CXTUResourceUsage_PreprocessingRecord: c_uint = 12;
-pub const CXTUResourceUsage_SourceManager_DataStructures: c_uint =
- 13;
-pub const CXTUResourceUsage_Preprocessor_HeaderSearch: c_uint = 14;
-pub const CXTUResourceUsage_MEMORY_IN_BYTES_BEGIN: c_uint = 1;
-pub const CXTUResourceUsage_MEMORY_IN_BYTES_END: c_uint = 14;
-pub const CXTUResourceUsage_First: c_uint = 1;
-pub const CXTUResourceUsage_Last: c_uint = 14;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct Struct_CXTUResourceUsageEntry {
- pub kind: Enum_CXTUResourceUsageKind,
- pub amount: c_ulong,
-}
-pub type CXTUResourceUsageEntry = Struct_CXTUResourceUsageEntry;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct Struct_CXTUResourceUsage {
- pub data: *mut c_void,
- pub numEntries: c_uint,
- pub entries: *mut CXTUResourceUsageEntry,
-}
-pub type CXTUResourceUsage = Struct_CXTUResourceUsage;
-pub type Enum_CXCursorKind = c_uint;
-pub const CXCursor_UnexposedDecl: c_uint = 1;
-pub const CXCursor_StructDecl: c_uint = 2;
-pub const CXCursor_UnionDecl: c_uint = 3;
-pub const CXCursor_ClassDecl: c_uint = 4;
-pub const CXCursor_EnumDecl: c_uint = 5;
-pub const CXCursor_FieldDecl: c_uint = 6;
-pub const CXCursor_EnumConstantDecl: c_uint = 7;
-pub const CXCursor_FunctionDecl: c_uint = 8;
-pub const CXCursor_VarDecl: c_uint = 9;
-pub const CXCursor_ParmDecl: c_uint = 10;
-pub const CXCursor_ObjCInterfaceDecl: c_uint = 11;
-pub const CXCursor_ObjCCategoryDecl: c_uint = 12;
-pub const CXCursor_ObjCProtocolDecl: c_uint = 13;
-pub const CXCursor_ObjCPropertyDecl: c_uint = 14;
-pub const CXCursor_ObjCIvarDecl: c_uint = 15;
-pub const CXCursor_ObjCInstanceMethodDecl: c_uint = 16;
-pub const CXCursor_ObjCClassMethodDecl: c_uint = 17;
-pub const CXCursor_ObjCImplementationDecl: c_uint = 18;
-pub const CXCursor_ObjCCategoryImplDecl: c_uint = 19;
-pub const CXCursor_TypedefDecl: c_uint = 20;
-pub const CXCursor_CXXMethod: c_uint = 21;
-pub const CXCursor_Namespace: c_uint = 22;
-pub const CXCursor_LinkageSpec: c_uint = 23;
-pub const CXCursor_Constructor: c_uint = 24;
-pub const CXCursor_Destructor: c_uint = 25;
-pub const CXCursor_ConversionFunction: c_uint = 26;
-pub const CXCursor_TemplateTypeParameter: c_uint = 27;
-pub const CXCursor_NonTypeTemplateParameter: c_uint = 28;
-pub const CXCursor_TemplateTemplateParameter: c_uint = 29;
-pub const CXCursor_FunctionTemplate: c_uint = 30;
-pub const CXCursor_ClassTemplate: c_uint = 31;
-pub const CXCursor_ClassTemplatePartialSpecialization: c_uint = 32;
-pub const CXCursor_NamespaceAlias: c_uint = 33;
-pub const CXCursor_UsingDirective: c_uint = 34;
-pub const CXCursor_UsingDeclaration: c_uint = 35;
-pub const CXCursor_TypeAliasDecl: c_uint = 36;
-pub const CXCursor_ObjCSynthesizeDecl: c_uint = 37;
-pub const CXCursor_ObjCDynamicDecl: c_uint = 38;
-pub const CXCursor_CXXAccessSpecifier: c_uint = 39;
-pub const CXCursor_FirstDecl: c_uint = 1;
-pub const CXCursor_LastDecl: c_uint = 39;
-pub const CXCursor_FirstRef: c_uint = 40;
-pub const CXCursor_ObjCSuperClassRef: c_uint = 40;
-pub const CXCursor_ObjCProtocolRef: c_uint = 41;
-pub const CXCursor_ObjCClassRef: c_uint = 42;
-pub const CXCursor_TypeRef: c_uint = 43;
-pub const CXCursor_CXXBaseSpecifier: c_uint = 44;
-pub const CXCursor_TemplateRef: c_uint = 45;
-pub const CXCursor_NamespaceRef: c_uint = 46;
-pub const CXCursor_MemberRef: c_uint = 47;
-pub const CXCursor_LabelRef: c_uint = 48;
-pub const CXCursor_OverloadedDeclRef: c_uint = 49;
-pub const CXCursor_VariableRef: c_uint = 50;
-pub const CXCursor_LastRef: c_uint = 50;
-pub const CXCursor_FirstInvalid: c_uint = 70;
-pub const CXCursor_InvalidFile: c_uint = 70;
-pub const CXCursor_NoDeclFound: c_uint = 71;
-pub const CXCursor_NotImplemented: c_uint = 72;
-pub const CXCursor_InvalidCode: c_uint = 73;
-pub const CXCursor_LastInvalid: c_uint = 73;
-pub const CXCursor_FirstExpr: c_uint = 100;
-pub const CXCursor_UnexposedExpr: c_uint = 100;
-pub const CXCursor_DeclRefExpr: c_uint = 101;
-pub const CXCursor_MemberRefExpr: c_uint = 102;
-pub const CXCursor_CallExpr: c_uint = 103;
-pub const CXCursor_ObjCMessageExpr: c_uint = 104;
-pub const CXCursor_BlockExpr: c_uint = 105;
-pub const CXCursor_IntegerLiteral: c_uint = 106;
-pub const CXCursor_FloatingLiteral: c_uint = 107;
-pub const CXCursor_ImaginaryLiteral: c_uint = 108;
-pub const CXCursor_StringLiteral: c_uint = 109;
-pub const CXCursor_CharacterLiteral: c_uint = 110;
-pub const CXCursor_ParenExpr: c_uint = 111;
-pub const CXCursor_UnaryOperator: c_uint = 112;
-pub const CXCursor_ArraySubscriptExpr: c_uint = 113;
-pub const CXCursor_BinaryOperator: c_uint = 114;
-pub const CXCursor_CompoundAssignOperator: c_uint = 115;
-pub const CXCursor_ConditionalOperator: c_uint = 116;
-pub const CXCursor_CStyleCastExpr: c_uint = 117;
-pub const CXCursor_CompoundLiteralExpr: c_uint = 118;
-pub const CXCursor_InitListExpr: c_uint = 119;
-pub const CXCursor_AddrLabelExpr: c_uint = 120;
-pub const CXCursor_StmtExpr: c_uint = 121;
-pub const CXCursor_GenericSelectionExpr: c_uint = 122;
-pub const CXCursor_GNUNullExpr: c_uint = 123;
-pub const CXCursor_CXXStaticCastExpr: c_uint = 124;
-pub const CXCursor_CXXDynamicCastExpr: c_uint = 125;
-pub const CXCursor_CXXReinterpretCastExpr: c_uint = 126;
-pub const CXCursor_CXXConstCastExpr: c_uint = 127;
-pub const CXCursor_CXXFunctionalCastExpr: c_uint = 128;
-pub const CXCursor_CXXTypeidExpr: c_uint = 129;
-pub const CXCursor_CXXBoolLiteralExpr: c_uint = 130;
-pub const CXCursor_CXXNullPtrLiteralExpr: c_uint = 131;
-pub const CXCursor_CXXThisExpr: c_uint = 132;
-pub const CXCursor_CXXThrowExpr: c_uint = 133;
-pub const CXCursor_CXXNewExpr: c_uint = 134;
-pub const CXCursor_CXXDeleteExpr: c_uint = 135;
-pub const CXCursor_UnaryExpr: c_uint = 136;
-pub const CXCursor_ObjCStringLiteral: c_uint = 137;
-pub const CXCursor_ObjCEncodeExpr: c_uint = 138;
-pub const CXCursor_ObjCSelectorExpr: c_uint = 139;
-pub const CXCursor_ObjCProtocolExpr: c_uint = 140;
-pub const CXCursor_ObjCBridgedCastExpr: c_uint = 141;
-pub const CXCursor_PackExpansionExpr: c_uint = 142;
-pub const CXCursor_SizeOfPackExpr: c_uint = 143;
-pub const CXCursor_LambdaExpr: c_uint = 144;
-pub const CXCursor_ObjCBoolLiteralExpr: c_uint = 145;
-pub const CXCursor_ObjCSelfExpr: c_uint = 146;
-pub const CXCursor_LastExpr: c_uint = 146;
-pub const CXCursor_FirstStmt: c_uint = 200;
-pub const CXCursor_UnexposedStmt: c_uint = 200;
-pub const CXCursor_LabelStmt: c_uint = 201;
-pub const CXCursor_CompoundStmt: c_uint = 202;
-pub const CXCursor_CaseStmt: c_uint = 203;
-pub const CXCursor_DefaultStmt: c_uint = 204;
-pub const CXCursor_IfStmt: c_uint = 205;
-pub const CXCursor_SwitchStmt: c_uint = 206;
-pub const CXCursor_WhileStmt: c_uint = 207;
-pub const CXCursor_DoStmt: c_uint = 208;
-pub const CXCursor_ForStmt: c_uint = 209;
-pub const CXCursor_GotoStmt: c_uint = 210;
-pub const CXCursor_IndirectGotoStmt: c_uint = 211;
-pub const CXCursor_ContinueStmt: c_uint = 212;
-pub const CXCursor_BreakStmt: c_uint = 213;
-pub const CXCursor_ReturnStmt: c_uint = 214;
-pub const CXCursor_GCCAsmStmt: c_uint = 215;
-pub const CXCursor_AsmStmt: c_uint = 215;
-pub const CXCursor_ObjCAtTryStmt: c_uint = 216;
-pub const CXCursor_ObjCAtCatchStmt: c_uint = 217;
-pub const CXCursor_ObjCAtFinallyStmt: c_uint = 218;
-pub const CXCursor_ObjCAtThrowStmt: c_uint = 219;
-pub const CXCursor_ObjCAtSynchronizedStmt: c_uint = 220;
-pub const CXCursor_ObjCAutoreleasePoolStmt: c_uint = 221;
-pub const CXCursor_ObjCForCollectionStmt: c_uint = 222;
-pub const CXCursor_CXXCatchStmt: c_uint = 223;
-pub const CXCursor_CXXTryStmt: c_uint = 224;
-pub const CXCursor_CXXForRangeStmt: c_uint = 225;
-pub const CXCursor_SEHTryStmt: c_uint = 226;
-pub const CXCursor_SEHExceptStmt: c_uint = 227;
-pub const CXCursor_SEHFinallyStmt: c_uint = 228;
-pub const CXCursor_MSAsmStmt: c_uint = 229;
-pub const CXCursor_NullStmt: c_uint = 230;
-pub const CXCursor_DeclStmt: c_uint = 231;
-pub const CXCursor_OMPParallelDirective: c_uint = 232;
-pub const CXCursor_LastStmt: c_uint = 232;
-pub const CXCursor_TranslationUnit: c_uint = 300;
-pub const CXCursor_FirstAttr: c_uint = 400;
-pub const CXCursor_UnexposedAttr: c_uint = 400;
-pub const CXCursor_IBActionAttr: c_uint = 401;
-pub const CXCursor_IBOutletAttr: c_uint = 402;
-pub const CXCursor_IBOutletCollectionAttr: c_uint = 403;
-pub const CXCursor_CXXFinalAttr: c_uint = 404;
-pub const CXCursor_CXXOverrideAttr: c_uint = 405;
-pub const CXCursor_AnnotateAttr: c_uint = 406;
-pub const CXCursor_AsmLabelAttr: c_uint = 407;
-pub const CXCursor_PackedAttr: c_uint = 408;
-pub const CXCursor_LastAttr: c_uint = 408;
-pub const CXCursor_PreprocessingDirective: c_uint = 500;
-pub const CXCursor_MacroDefinition: c_uint = 501;
-pub const CXCursor_MacroExpansion: c_uint = 502;
-pub const CXCursor_MacroInstantiation: c_uint = 502;
-pub const CXCursor_InclusionDirective: c_uint = 503;
-pub const CXCursor_FirstPreprocessing: c_uint = 500;
-pub const CXCursor_LastPreprocessing: c_uint = 503;
-pub const CXCursor_ModuleImportDecl: c_uint = 600;
-pub const CXCursor_TypeAliasTemplateDecl: c_uint = 601;
-pub const CXCursor_StaticAssert: c_uint = 602;
-pub const CXCursor_FirstExtraDecl: c_uint = 600;
-pub const CXCursor_LastExtraDecl: c_uint = 602;
-pub const CXCursor_OverloadCandidate: c_uint = 700;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXCursor {
- pub kind: Enum_CXCursorKind,
- pub xdata: c_int,
- pub data: [*const c_void; 3],
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXComment {
- pub ASTNode: *const c_void,
- pub TranslationUnit: CXTranslationUnit,
-}
-pub type Enum_CXLinkageKind = ::libc::c_uint;
-pub const CXLinkage_Invalid: ::libc::c_uint = 0;
-pub const CXLinkage_NoLinkage: ::libc::c_uint = 1;
-pub const CXLinkage_Internal: ::libc::c_uint = 2;
-pub const CXLinkage_UniqueExternal: ::libc::c_uint = 3;
-pub const CXLinkage_External: ::libc::c_uint = 4;
-pub type Enum_CXVisibilityKind = ::libc::c_uint;
-pub const CXVisibility_Invalid: ::libc::c_uint = 0;
-pub const CXVisibility_Hidden: ::libc::c_uint = 1;
-pub const CXVisibility_Protected: ::libc::c_uint = 2;
-pub const CXVisibility_Default: ::libc::c_uint = 3;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct Struct_CXPlatformAvailability {
- pub Platform: CXString,
- pub Introduced: CXVersion,
- pub Deprecated: CXVersion,
- pub Obsoleted: CXVersion,
- pub Unavailable: c_int,
- pub Message: CXString,
-}
-pub type CXPlatformAvailability = Struct_CXPlatformAvailability;
-pub type Enum_CXLanguageKind = c_uint;
-pub const CXLanguage_Invalid: c_uint = 0;
-pub const CXLanguage_C: c_uint = 1;
-pub const CXLanguage_ObjC: c_uint = 2;
-pub const CXLanguage_CPlusPlus: c_uint = 3;
-pub enum Struct_CXCursorSetImpl { }
-pub type CXCursorSet = *mut Struct_CXCursorSetImpl;
-pub type Enum_CXTypeKind = c_uint;
-pub const CXType_Invalid: c_uint = 0;
-pub const CXType_Unexposed: c_uint = 1;
-pub const CXType_Void: c_uint = 2;
-pub const CXType_Bool: c_uint = 3;
-pub const CXType_Char_U: c_uint = 4;
-pub const CXType_UChar: c_uint = 5;
-pub const CXType_Char16: c_uint = 6;
-pub const CXType_Char32: c_uint = 7;
-pub const CXType_UShort: c_uint = 8;
-pub const CXType_UInt: c_uint = 9;
-pub const CXType_ULong: c_uint = 10;
-pub const CXType_ULongLong: c_uint = 11;
-pub const CXType_UInt128: c_uint = 12;
-pub const CXType_Char_S: c_uint = 13;
-pub const CXType_SChar: c_uint = 14;
-pub const CXType_WChar: c_uint = 15;
-pub const CXType_Short: c_uint = 16;
-pub const CXType_Int: c_uint = 17;
-pub const CXType_Long: c_uint = 18;
-pub const CXType_LongLong: c_uint = 19;
-pub const CXType_Int128: c_uint = 20;
-pub const CXType_Float: c_uint = 21;
-pub const CXType_Double: c_uint = 22;
-pub const CXType_LongDouble: c_uint = 23;
-pub const CXType_NullPtr: c_uint = 24;
-pub const CXType_Overload: c_uint = 25;
-pub const CXType_Dependent: c_uint = 26;
-pub const CXType_ObjCId: c_uint = 27;
-pub const CXType_ObjCClass: c_uint = 28;
-pub const CXType_ObjCSel: c_uint = 29;
-pub const CXType_Float128: c_uint = 30;
-pub const CXType_FirstBuiltin: c_uint = 2;
-pub const CXType_LastBuiltin: c_uint = 29;
-pub const CXType_Complex: c_uint = 100;
-pub const CXType_Pointer: c_uint = 101;
-pub const CXType_BlockPointer: c_uint = 102;
-pub const CXType_LValueReference: c_uint = 103;
-pub const CXType_RValueReference: c_uint = 104;
-pub const CXType_Record: c_uint = 105;
-pub const CXType_Enum: c_uint = 106;
-pub const CXType_Typedef: c_uint = 107;
-pub const CXType_ObjCInterface: c_uint = 108;
-pub const CXType_ObjCObjectPointer: c_uint = 109;
-pub const CXType_FunctionNoProto: c_uint = 110;
-pub const CXType_FunctionProto: c_uint = 111;
-pub const CXType_ConstantArray: c_uint = 112;
-pub const CXType_Vector: c_uint = 113;
-pub const CXType_IncompleteArray: c_uint = 114;
-pub const CXType_VariableArray: c_uint = 115;
-pub const CXType_DependentSizedArray: c_uint = 116;
-pub const CXType_MemberPointer: c_uint = 117;
-#[cfg(not(feature="llvm_stable"))]
-pub const CXType_Auto: c_uint = 118;
-#[cfg(not(feature="llvm_stable"))]
-pub const CXType_Elaborated: c_uint = 119;
-pub type Enum_CXCallingConv = c_uint;
-pub const CXCallingConv_Default: c_uint = 0;
-pub const CXCallingConv_C: c_uint = 1;
-pub const CXCallingConv_X86StdCall: c_uint = 2;
-pub const CXCallingConv_X86FastCall: c_uint = 3;
-pub const CXCallingConv_X86ThisCall: c_uint = 4;
-pub const CXCallingConv_X86Pascal: c_uint = 5;
-pub const CXCallingConv_AAPCS: c_uint = 6;
-pub const CXCallingConv_AAPCS_VFP: c_uint = 7;
-pub const CXCallingConv_PnaclCall: c_uint = 8;
-pub const CXCallingConv_IntelOclBicc: c_uint = 9;
-pub const CXCallingConv_X86_64Win64: c_uint = 10;
-pub const CXCallingConv_X86_64SysV: c_uint = 11;
-pub const CXCallingConv_Invalid: c_uint = 100;
-pub const CXCallingConv_Unexposed: c_uint = 200;
-#[repr(C)]
-#[derive(Copy, Clone, Hash)]
-pub struct CXType {
- pub kind: Enum_CXTypeKind,
- pub data: [*mut c_void; 2],
-}
-pub type Enum_CXTypeLayoutError = c_int;
-pub const CXTypeLayoutError_Invalid: c_int = -1;
-pub const CXTypeLayoutError_Incomplete: c_int = -2;
-pub const CXTypeLayoutError_Dependent: c_int = -3;
-pub const CXTypeLayoutError_NotConstantSize: c_int = -4;
-pub const CXTypeLayoutError_InvalidFieldName: c_int = -5;
-pub type Enum_CXRefQualifierKind = c_uint;
-pub const CXRefQualifier_None: c_uint = 0;
-pub const CXRefQualifier_LValue: c_uint = 1;
-pub const CXRefQualifier_RValue: c_uint = 2;
-pub type Enum_CX_CXXAccessSpecifier = c_uint;
-pub const CX_CXXInvalidAccessSpecifier: c_uint = 0;
-pub const CX_CXXPublic: c_uint = 1;
-pub const CX_CXXProtected: c_uint = 2;
-pub const CX_CXXPrivate: c_uint = 3;
-pub type Enum_CXChildVisitResult = c_uint;
-pub const CXChildVisit_Break: c_uint = 0;
-pub const CXChildVisit_Continue: c_uint = 1;
-pub const CXChildVisit_Recurse: c_uint = 2;
-pub type CXCursorVisitor =
- ::std::option::Option<extern "C" fn
- (arg1: CXCursor, arg2: CXCursor,
- arg3: CXClientData)
- -> Enum_CXChildVisitResult>;
-pub type CXObjCPropertyAttrKind = c_uint;
-pub const CXObjCPropertyAttr_noattr: c_uint = 0;
-pub const CXObjCPropertyAttr_readonly: c_uint = 1;
-pub const CXObjCPropertyAttr_getter: c_uint = 2;
-pub const CXObjCPropertyAttr_assign: c_uint = 4;
-pub const CXObjCPropertyAttr_readwrite: c_uint = 8;
-pub const CXObjCPropertyAttr_retain: c_uint = 16;
-pub const CXObjCPropertyAttr_copy: c_uint = 32;
-pub const CXObjCPropertyAttr_nonatomic: c_uint = 64;
-pub const CXObjCPropertyAttr_setter: c_uint = 128;
-pub const CXObjCPropertyAttr_atomic: c_uint = 256;
-pub const CXObjCPropertyAttr_weak: c_uint = 512;
-pub const CXObjCPropertyAttr_strong: c_uint = 1024;
-pub const CXObjCPropertyAttr_unsafe_unretained: c_uint = 2048;
-pub type CXObjCDeclQualifierKind = c_uint;
-pub const CXObjCDeclQualifier_None: c_uint = 0;
-pub const CXObjCDeclQualifier_In: c_uint = 1;
-pub const CXObjCDeclQualifier_Inout: c_uint = 2;
-pub const CXObjCDeclQualifier_Out: c_uint = 4;
-pub const CXObjCDeclQualifier_Bycopy: c_uint = 8;
-pub const CXObjCDeclQualifier_Byref: c_uint = 16;
-pub const CXObjCDeclQualifier_Oneway: c_uint = 32;
-pub type CXModule = *mut c_void;
-pub type Enum_CXCommentKind = c_uint;
-pub const CXComment_Null: c_uint = 0;
-pub const CXComment_Text: c_uint = 1;
-pub const CXComment_InlineCommand: c_uint = 2;
-pub const CXComment_HTMLStartTag: c_uint = 3;
-pub const CXComment_HTMLEndTag: c_uint = 4;
-pub const CXComment_Paragraph: c_uint = 5;
-pub const CXComment_BlockCommand: c_uint = 6;
-pub const CXComment_ParamCommand: c_uint = 7;
-pub const CXComment_TParamCommand: c_uint = 8;
-pub const CXComment_VerbatimBlockCommand: c_uint = 9;
-pub const CXComment_VerbatimBlockLine: c_uint = 10;
-pub const CXComment_VerbatimLine: c_uint = 11;
-pub const CXComment_FullComment: c_uint = 12;
-pub type Enum_CXCommentInlineCommandRenderKind = c_uint;
-pub const CXCommentInlineCommandRenderKind_Normal: c_uint = 0;
-pub const CXCommentInlineCommandRenderKind_Bold: c_uint = 1;
-pub const CXCommentInlineCommandRenderKind_Monospaced: c_uint = 2;
-pub const CXCommentInlineCommandRenderKind_Emphasized: c_uint = 3;
-pub type Enum_CXCommentParamPassDirection = c_uint;
-pub const CXCommentParamPassDirection_In: c_uint = 0;
-pub const CXCommentParamPassDirection_Out: c_uint = 1;
-pub const CXCommentParamPassDirection_InOut: c_uint = 2;
-pub type Enum_CXNameRefFlags = c_uint;
-pub const CXNameRange_WantQualifier: c_uint = 1;
-pub const CXNameRange_WantTemplateArgs: c_uint = 2;
-pub const CXNameRange_WantSinglePiece: c_uint = 4;
-pub type Enum_CXTokenKind = c_uint;
-pub const CXToken_Punctuation: c_uint = 0;
-pub const CXToken_Keyword: c_uint = 1;
-pub const CXToken_Identifier: c_uint = 2;
-pub const CXToken_Literal: c_uint = 3;
-pub const CXToken_Comment: c_uint = 4;
-pub type CXTokenKind = Enum_CXTokenKind;
-pub type Enum_CXTemplateArgumentKind = c_uint;
-pub const CXTemplateArgumentKind_Null: c_uint = 0;
-pub const CXTemplateArgumentKind_Type: c_uint = 1;
-pub const CXTemplateArgumentKind_Declaration: c_uint = 2;
-pub const CXTemplateArgumentKind_NullPtr: c_uint = 3;
-pub const CXTemplateArgumentKind_Integral: c_uint = 4;
-pub const CXTemplateArgumentKind_Template: c_uint = 5;
-pub const CXTemplateArgumentKind_TemplateExpansion: c_uint = 6;
-pub const CXTemplateArgumentKind_Expression: c_uint = 7;
-pub const CXTemplateArgumentKind_Pack: c_uint = 8;
-pub const CXTemplateArgumentKind_Invalid: c_uint = 9;
-pub type CXTemplateArgumentKind = Enum_CXTemplateArgumentKind;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXToken {
- pub int_data: [c_uint; 4],
- pub ptr_data: *mut c_void,
-}
-pub type CXCompletionString = *mut c_void;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXCompletionResult {
- pub CursorKind: Enum_CXCursorKind,
- pub CompletionString: CXCompletionString,
-}
-pub type Enum_CXCompletionChunkKind = c_uint;
-pub const CXCompletionChunk_Optional: c_uint = 0;
-pub const CXCompletionChunk_TypedText: c_uint = 1;
-pub const CXCompletionChunk_Text: c_uint = 2;
-pub const CXCompletionChunk_Placeholder: c_uint = 3;
-pub const CXCompletionChunk_Informative: c_uint = 4;
-pub const CXCompletionChunk_CurrentParameter: c_uint = 5;
-pub const CXCompletionChunk_LeftParen: c_uint = 6;
-pub const CXCompletionChunk_RightParen: c_uint = 7;
-pub const CXCompletionChunk_LeftBracket: c_uint = 8;
-pub const CXCompletionChunk_RightBracket: c_uint = 9;
-pub const CXCompletionChunk_LeftBrace: c_uint = 10;
-pub const CXCompletionChunk_RightBrace: c_uint = 11;
-pub const CXCompletionChunk_LeftAngle: c_uint = 12;
-pub const CXCompletionChunk_RightAngle: c_uint = 13;
-pub const CXCompletionChunk_Comma: c_uint = 14;
-pub const CXCompletionChunk_ResultType: c_uint = 15;
-pub const CXCompletionChunk_Colon: c_uint = 16;
-pub const CXCompletionChunk_SemiColon: c_uint = 17;
-pub const CXCompletionChunk_Equal: c_uint = 18;
-pub const CXCompletionChunk_HorizontalSpace: c_uint = 19;
-pub const CXCompletionChunk_VerticalSpace: c_uint = 20;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXCodeCompleteResults {
- pub Results: *mut CXCompletionResult,
- pub NumResults: c_uint,
-}
-pub type Enum_CXCodeComplete_Flags = c_uint;
-pub const CXCodeComplete_IncludeMacros: c_uint = 1;
-pub const CXCodeComplete_IncludeCodePatterns: c_uint = 2;
-pub const CXCodeComplete_IncludeBriefComments: c_uint = 4;
-pub type Enum_CXCompletionContext = c_uint;
-pub const CXCompletionContext_Unexposed: c_uint = 0;
-pub const CXCompletionContext_AnyType: c_uint = 1;
-pub const CXCompletionContext_AnyValue: c_uint = 2;
-pub const CXCompletionContext_ObjCObjectValue: c_uint = 4;
-pub const CXCompletionContext_ObjCSelectorValue: c_uint = 8;
-pub const CXCompletionContext_CXXClassTypeValue: c_uint = 16;
-pub const CXCompletionContext_DotMemberAccess: c_uint = 32;
-pub const CXCompletionContext_ArrowMemberAccess: c_uint = 64;
-pub const CXCompletionContext_ObjCPropertyAccess: c_uint = 128;
-pub const CXCompletionContext_EnumTag: c_uint = 256;
-pub const CXCompletionContext_UnionTag: c_uint = 512;
-pub const CXCompletionContext_StructTag: c_uint = 1024;
-pub const CXCompletionContext_ClassTag: c_uint = 2048;
-pub const CXCompletionContext_Namespace: c_uint = 4096;
-pub const CXCompletionContext_NestedNameSpecifier: c_uint = 8192;
-pub const CXCompletionContext_ObjCInterface: c_uint = 16384;
-pub const CXCompletionContext_ObjCProtocol: c_uint = 32768;
-pub const CXCompletionContext_ObjCCategory: c_uint = 65536;
-pub const CXCompletionContext_ObjCInstanceMessage: c_uint = 131072;
-pub const CXCompletionContext_ObjCClassMessage: c_uint = 262144;
-pub const CXCompletionContext_ObjCSelectorName: c_uint = 524288;
-pub const CXCompletionContext_MacroName: c_uint = 1048576;
-pub const CXCompletionContext_NaturalLanguage: c_uint = 2097152;
-pub const CXCompletionContext_Unknown: c_uint = 4194303;
-pub type CXInclusionVisitor =
- ::std::option::Option<extern "C" fn
- (arg1: CXFile, arg2: *mut CXSourceLocation,
- arg3: c_uint, arg4: CXClientData)>;
-pub type CXRemapping = *mut c_void;
-pub type Enum_CXVisitorResult = c_uint;
-pub const CXVisit_Break: c_uint = 0;
-pub const CXVisit_Continue: c_uint = 1;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXCursorAndRangeVisitor {
- pub context: *mut c_void,
- pub visit: ::std::option::Option<extern "C" fn
- (arg1: *mut c_void,
- arg2: CXCursor, arg3: CXSourceRange)
- -> Enum_CXVisitorResult>,
-}
-pub type CXResult = c_uint;
-pub const CXResult_Success: c_uint = 0;
-pub const CXResult_Invalid: c_uint = 1;
-pub const CXResult_VisitBreak: c_uint = 2;
-pub type CXIdxClientFile = *mut c_void;
-pub type CXIdxClientEntity = *mut c_void;
-pub type CXIdxClientContainer = *mut c_void;
-pub type CXIdxClientASTFile = *mut c_void;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxLoc {
- pub ptr_data: [*mut c_void; 2],
- pub int_data: c_uint,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxIncludedFileInfo {
- pub hashLoc: CXIdxLoc,
- pub filename: *const c_char,
- pub file: CXFile,
- pub isImport: c_int,
- pub isAngled: c_int,
- pub isModuleImport: c_int,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxImportedASTFileInfo {
- pub file: CXFile,
- pub module: CXModule,
- pub loc: CXIdxLoc,
- pub isImplicit: c_int,
-}
-pub type CXIdxEntityKind = c_uint;
-pub const CXIdxEntity_Unexposed: c_uint = 0;
-pub const CXIdxEntity_Typedef: c_uint = 1;
-pub const CXIdxEntity_Function: c_uint = 2;
-pub const CXIdxEntity_Variable: c_uint = 3;
-pub const CXIdxEntity_Field: c_uint = 4;
-pub const CXIdxEntity_EnumConstant: c_uint = 5;
-pub const CXIdxEntity_ObjCClass: c_uint = 6;
-pub const CXIdxEntity_ObjCProtocol: c_uint = 7;
-pub const CXIdxEntity_ObjCCategory: c_uint = 8;
-pub const CXIdxEntity_ObjCInstanceMethod: c_uint = 9;
-pub const CXIdxEntity_ObjCClassMethod: c_uint = 10;
-pub const CXIdxEntity_ObjCProperty: c_uint = 11;
-pub const CXIdxEntity_ObjCIvar: c_uint = 12;
-pub const CXIdxEntity_Enum: c_uint = 13;
-pub const CXIdxEntity_Struct: c_uint = 14;
-pub const CXIdxEntity_Union: c_uint = 15;
-pub const CXIdxEntity_CXXClass: c_uint = 16;
-pub const CXIdxEntity_CXXNamespace: c_uint = 17;
-pub const CXIdxEntity_CXXNamespaceAlias: c_uint = 18;
-pub const CXIdxEntity_CXXStaticVariable: c_uint = 19;
-pub const CXIdxEntity_CXXStaticMethod: c_uint = 20;
-pub const CXIdxEntity_CXXInstanceMethod: c_uint = 21;
-pub const CXIdxEntity_CXXConstructor: c_uint = 22;
-pub const CXIdxEntity_CXXDestructor: c_uint = 23;
-pub const CXIdxEntity_CXXConversionFunction: c_uint = 24;
-pub const CXIdxEntity_CXXTypeAlias: c_uint = 25;
-pub const CXIdxEntity_CXXInterface: c_uint = 26;
-pub type CXIdxEntityLanguage = c_uint;
-pub const CXIdxEntityLang_None: c_uint = 0;
-pub const CXIdxEntityLang_C: c_uint = 1;
-pub const CXIdxEntityLang_ObjC: c_uint = 2;
-pub const CXIdxEntityLang_CXX: c_uint = 3;
-pub type CXIdxEntityCXXTemplateKind = c_uint;
-pub const CXIdxEntity_NonTemplate: c_uint = 0;
-pub const CXIdxEntity_Template: c_uint = 1;
-pub const CXIdxEntity_TemplatePartialSpecialization: c_uint = 2;
-pub const CXIdxEntity_TemplateSpecialization: c_uint = 3;
-pub type CXIdxAttrKind = c_uint;
-pub const CXIdxAttr_Unexposed: c_uint = 0;
-pub const CXIdxAttr_IBAction: c_uint = 1;
-pub const CXIdxAttr_IBOutlet: c_uint = 2;
-pub const CXIdxAttr_IBOutletCollection: c_uint = 3;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxAttrInfo {
- pub kind: CXIdxAttrKind,
- pub cursor: CXCursor,
- pub loc: CXIdxLoc,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxEntityInfo {
- pub kind: CXIdxEntityKind,
- pub templateKind: CXIdxEntityCXXTemplateKind,
- pub lang: CXIdxEntityLanguage,
- pub name: *const c_char,
- pub USR: *const c_char,
- pub cursor: CXCursor,
- pub attributes: *const *const CXIdxAttrInfo,
- pub numAttributes: c_uint,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxContainerInfo {
- pub cursor: CXCursor,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxIBOutletCollectionAttrInfo {
- pub attrInfo: *const CXIdxAttrInfo,
- pub objcClass: *const CXIdxEntityInfo,
- pub classCursor: CXCursor,
- pub classLoc: CXIdxLoc,
-}
-pub type CXIdxDeclInfoFlags = c_uint;
-pub const CXIdxDeclFlag_Skipped: c_uint = 1;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxDeclInfo {
- pub entityInfo: *const CXIdxEntityInfo,
- pub cursor: CXCursor,
- pub loc: CXIdxLoc,
- pub semanticContainer: *const CXIdxContainerInfo,
- pub lexicalContainer: *const CXIdxContainerInfo,
- pub isRedeclaration: c_int,
- pub isDefinition: c_int,
- pub isContainer: c_int,
- pub declAsContainer: *const CXIdxContainerInfo,
- pub isImplicit: c_int,
- pub attributes: *const *const CXIdxAttrInfo,
- pub numAttributes: c_uint,
- pub flags: c_uint,
-}
-pub type CXIdxObjCContainerKind = c_uint;
-pub const CXIdxObjCContainer_ForwardRef: c_uint = 0;
-pub const CXIdxObjCContainer_Interface: c_uint = 1;
-pub const CXIdxObjCContainer_Implementation: c_uint = 2;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxObjCContainerDeclInfo {
- pub declInfo: *const CXIdxDeclInfo,
- pub kind: CXIdxObjCContainerKind,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxBaseClassInfo {
- pub base: *const CXIdxEntityInfo,
- pub cursor: CXCursor,
- pub loc: CXIdxLoc,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxObjCProtocolRefInfo {
- pub protocol: *const CXIdxEntityInfo,
- pub cursor: CXCursor,
- pub loc: CXIdxLoc,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxObjCProtocolRefListInfo {
- pub protocols: *const *const CXIdxObjCProtocolRefInfo,
- pub numProtocols: c_uint,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxObjCInterfaceDeclInfo {
- pub containerInfo: *const CXIdxObjCContainerDeclInfo,
- pub superInfo: *const CXIdxBaseClassInfo,
- pub protocols: *const CXIdxObjCProtocolRefListInfo,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxObjCCategoryDeclInfo {
- pub containerInfo: *const CXIdxObjCContainerDeclInfo,
- pub objcClass: *const CXIdxEntityInfo,
- pub classCursor: CXCursor,
- pub classLoc: CXIdxLoc,
- pub protocols: *const CXIdxObjCProtocolRefListInfo,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxObjCPropertyDeclInfo {
- pub declInfo: *const CXIdxDeclInfo,
- pub getter: *const CXIdxEntityInfo,
- pub setter: *const CXIdxEntityInfo,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxCXXClassDeclInfo {
- pub declInfo: *const CXIdxDeclInfo,
- pub bases: *const *const CXIdxBaseClassInfo,
- pub numBases: c_uint,
-}
-pub type CXIdxEntityRefKind = c_uint;
-pub const CXIdxEntityRef_Direct: c_uint = 1;
-pub const CXIdxEntityRef_Implicit: c_uint = 2;
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CXIdxEntityRefInfo {
- pub kind: CXIdxEntityRefKind,
- pub cursor: CXCursor,
- pub loc: CXIdxLoc,
- pub referencedEntity: *const CXIdxEntityInfo,
- pub parentEntity: *const CXIdxEntityInfo,
- pub container: *const CXIdxContainerInfo,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct IndexerCallbacks {
- pub abortQuery: ::std::option::Option<extern "C" fn
- (arg1: CXClientData,
- arg2: *mut c_void)
- -> c_int>,
- pub diagnostic: ::std::option::Option<extern "C" fn
- (arg1: CXClientData,
- arg2: CXDiagnosticSet,
- arg3: *mut c_void)>,
- pub enteredMainFile: ::std::option::Option<extern "C" fn
- (arg1: CXClientData,
- arg2: CXFile,
- arg3: *mut c_void)
- -> CXIdxClientFile>,
- pub ppIncludedFile: ::std::option::Option<extern "C" fn
- (arg1: CXClientData,
- arg2:
- *const CXIdxIncludedFileInfo)
- -> CXIdxClientFile>,
- pub importedASTFile: ::std::option::Option<extern "C" fn
- (arg1: CXClientData,
- arg2:
- *const CXIdxImportedASTFileInfo)
- -> CXIdxClientASTFile>,
- pub startedTranslationUnit: ::std::option::Option<extern "C" fn
- (arg1: CXClientData,
- arg2:
- *mut c_void)
- ->
- CXIdxClientContainer>,
- pub indexDeclaration: ::std::option::Option<extern "C" fn
- (arg1: CXClientData,
- arg2:
- *const CXIdxDeclInfo)>,
- pub indexEntityReference: ::std::option::Option<extern "C" fn
- (arg1: CXClientData,
- arg2:
- *const CXIdxEntityRefInfo)>,
-}
-pub type CXIndexAction = *mut c_void;
-pub type CXIndexOptFlags = c_uint;
-pub const CXIndexOpt_None: c_uint = 0;
-pub const CXIndexOpt_SuppressRedundantRefs: c_uint = 1;
-pub const CXIndexOpt_IndexFunctionLocalSymbols: c_uint = 2;
-pub const CXIndexOpt_IndexImplicitTemplateInstantiations: c_uint = 4;
-pub const CXIndexOpt_SuppressWarnings: c_uint = 8;
-pub const CXIndexOpt_SkipParsedBodiesInSession: c_uint = 16;
-extern "C" {
- pub fn clang_getCString(string: CXString) -> *const c_char;
- pub fn clang_disposeString(string: CXString);
- pub fn clang_createIndex(excludeDeclarationsFromPCH: c_int,
- displayDiagnostics: c_int) -> CXIndex;
- pub fn clang_disposeIndex(index: CXIndex);
- pub fn clang_CXIndex_setGlobalOptions(arg1: CXIndex,
- options: c_uint);
- pub fn clang_CXIndex_getGlobalOptions(arg1: CXIndex) -> c_uint;
- pub fn clang_getFileName(SFile: CXFile) -> CXString;
- pub fn clang_getFileTime(SFile: CXFile) -> ::libc::time_t;
- pub fn clang_getFileUniqueID(file: CXFile, outID: *mut CXFileUniqueID) ->
- c_int;
- pub fn clang_isFileMultipleIncludeGuarded(tu: CXTranslationUnit,
- file: CXFile) -> c_uint;
- pub fn clang_getFile(tu: CXTranslationUnit,
- file_name: *const c_char) -> CXFile;
- pub fn clang_getNullLocation() -> CXSourceLocation;
- pub fn clang_equalLocations(loc1: CXSourceLocation,
- loc2: CXSourceLocation) -> c_uint;
- pub fn clang_getLocation(tu: CXTranslationUnit, file: CXFile,
- line: c_uint, column: c_uint) ->
- CXSourceLocation;
- pub fn clang_getLocationForOffset(tu: CXTranslationUnit, file: CXFile,
- offset: c_uint) ->
- CXSourceLocation;
- pub fn clang_Location_isInSystemHeader(location: CXSourceLocation) ->
- c_int;
- pub fn clang_Location_isFromMainFile(location: CXSourceLocation) ->
- c_int;
- pub fn clang_getNullRange() -> CXSourceRange;
- pub fn clang_getRange(begin: CXSourceLocation, end: CXSourceLocation) ->
- CXSourceRange;
- pub fn clang_equalRanges(range1: CXSourceRange, range2: CXSourceRange) ->
- c_uint;
- pub fn clang_Range_isNull(range: CXSourceRange) -> c_int;
- pub fn clang_getExpansionLocation(location: CXSourceLocation,
- file: *mut CXFile,
- line: *mut c_uint,
- column: *mut c_uint,
- offset: *mut c_uint);
- pub fn clang_getPresumedLocation(location: CXSourceLocation,
- filename: *mut CXString,
- line: *mut c_uint,
- column: *mut c_uint);
- pub fn clang_getInstantiationLocation(location: CXSourceLocation,
- file: *mut CXFile,
- line: *mut c_uint,
- column: *mut c_uint,
- offset: *mut c_uint);
- pub fn clang_getSpellingLocation(location: CXSourceLocation,
- file: *mut CXFile,
- line: *mut c_uint,
- column: *mut c_uint,
- offset: *mut c_uint);
- pub fn clang_getFileLocation(location: CXSourceLocation,
- file: *mut CXFile, line: *mut c_uint,
- column: *mut c_uint,
- offset: *mut c_uint);
- pub fn clang_getRangeStart(range: CXSourceRange) -> CXSourceLocation;
- pub fn clang_getRangeEnd(range: CXSourceRange) -> CXSourceLocation;
- pub fn clang_getNumDiagnosticsInSet(Diags: CXDiagnosticSet) ->
- c_uint;
- pub fn clang_getDiagnosticInSet(Diags: CXDiagnosticSet,
- Index: c_uint) -> CXDiagnostic;
- pub fn clang_loadDiagnostics(file: *const c_char,
- error: *mut Enum_CXLoadDiag_Error,
- errorString: *mut CXString) ->
- CXDiagnosticSet;
- pub fn clang_disposeDiagnosticSet(Diags: CXDiagnosticSet);
- pub fn clang_getChildDiagnostics(D: CXDiagnostic) -> CXDiagnosticSet;
- pub fn clang_getNumDiagnostics(Unit: CXTranslationUnit) -> c_uint;
- pub fn clang_getDiagnostic(Unit: CXTranslationUnit, Index: c_uint)
- -> CXDiagnostic;
- pub fn clang_getDiagnosticSetFromTU(Unit: CXTranslationUnit) ->
- CXDiagnosticSet;
- pub fn clang_disposeDiagnostic(Diagnostic: CXDiagnostic);
- pub fn clang_formatDiagnostic(Diagnostic: CXDiagnostic,
- Options: c_uint) -> CXString;
- pub fn clang_defaultDiagnosticDisplayOptions() -> c_uint;
- pub fn clang_getDiagnosticSeverity(arg1: CXDiagnostic) ->
- Enum_CXDiagnosticSeverity;
- pub fn clang_getDiagnosticLocation(arg1: CXDiagnostic) ->
- CXSourceLocation;
- pub fn clang_getDiagnosticSpelling(arg1: CXDiagnostic) -> CXString;
- pub fn clang_getDiagnosticOption(Diag: CXDiagnostic,
- Disable: *mut CXString) -> CXString;
- pub fn clang_getDiagnosticCategory(arg1: CXDiagnostic) -> c_uint;
- pub fn clang_getDiagnosticCategoryName(Category: c_uint) ->
- CXString;
- pub fn clang_getDiagnosticCategoryText(arg1: CXDiagnostic) -> CXString;
- pub fn clang_getDiagnosticNumRanges(arg1: CXDiagnostic) -> c_uint;
- pub fn clang_getDiagnosticRange(Diagnostic: CXDiagnostic,
- Range: c_uint) -> CXSourceRange;
- pub fn clang_getDiagnosticNumFixIts(Diagnostic: CXDiagnostic) ->
- c_uint;
- pub fn clang_getDiagnosticFixIt(Diagnostic: CXDiagnostic,
- FixIt: c_uint,
- ReplacementRange: *mut CXSourceRange) ->
- CXString;
- pub fn clang_getTranslationUnitSpelling(CTUnit: CXTranslationUnit) ->
- CXString;
- pub fn clang_createTranslationUnitFromSourceFile(CIdx: CXIndex,
- source_filename:
- *const c_char,
- num_clang_command_line_args:
- c_int,
- clang_command_line_args:
- *const *const c_char,
- num_unsaved_files:
- c_uint,
- unsaved_files:
- *mut Struct_CXUnsavedFile)
- -> CXTranslationUnit;
- pub fn clang_createTranslationUnit(arg1: CXIndex,
- ast_filename: *const c_char) ->
- CXTranslationUnit;
- pub fn clang_defaultEditingTranslationUnitOptions() -> c_uint;
- pub fn clang_parseTranslationUnit(CIdx: CXIndex,
- source_filename: *const c_char,
- command_line_args:
- *const *const c_char,
- num_command_line_args: c_int,
- unsaved_files:
- *mut Struct_CXUnsavedFile,
- num_unsaved_files: c_uint,
- options: c_uint) ->
- CXTranslationUnit;
- pub fn clang_defaultSaveOptions(TU: CXTranslationUnit) -> c_uint;
- pub fn clang_saveTranslationUnit(TU: CXTranslationUnit,
- FileName: *const c_char,
- options: c_uint) ->
- c_int;
- pub fn clang_disposeTranslationUnit(arg1: CXTranslationUnit);
- pub fn clang_defaultReparseOptions(TU: CXTranslationUnit) ->
- c_uint;
- pub fn clang_reparseTranslationUnit(TU: CXTranslationUnit,
- num_unsaved_files: c_uint,
- unsaved_files:
- *mut Struct_CXUnsavedFile,
- options: c_uint) ->
- c_int;
- pub fn clang_getTUResourceUsageName(kind: Enum_CXTUResourceUsageKind) ->
- *const c_char;
- pub fn clang_getCXTUResourceUsage(TU: CXTranslationUnit) ->
- CXTUResourceUsage;
- pub fn clang_disposeCXTUResourceUsage(usage: CXTUResourceUsage);
- pub fn clang_getNullCursor() -> CXCursor;
- pub fn clang_getTranslationUnitCursor(arg1: CXTranslationUnit) ->
- CXCursor;
- pub fn clang_equalCursors(arg1: CXCursor, arg2: CXCursor) ->
- c_uint;
- pub fn clang_Cursor_isNull(cursor: CXCursor) -> c_int;
- pub fn clang_hashCursor(arg1: CXCursor) -> c_uint;
- pub fn clang_getCursorKind(arg1: CXCursor) -> Enum_CXCursorKind;
- pub fn clang_isDeclaration(arg1: Enum_CXCursorKind) -> c_uint;
- pub fn clang_isReference(arg1: Enum_CXCursorKind) -> c_uint;
- pub fn clang_isExpression(arg1: Enum_CXCursorKind) -> c_uint;
- pub fn clang_isStatement(arg1: Enum_CXCursorKind) -> c_uint;
- pub fn clang_isAttribute(arg1: Enum_CXCursorKind) -> c_uint;
- pub fn clang_isInvalid(arg1: Enum_CXCursorKind) -> c_uint;
- pub fn clang_isTranslationUnit(arg1: Enum_CXCursorKind) -> c_uint;
- pub fn clang_isPreprocessing(arg1: Enum_CXCursorKind) -> c_uint;
- pub fn clang_isUnexposed(arg1: Enum_CXCursorKind) -> c_uint;
- pub fn clang_getCursorLinkage(cursor: CXCursor) -> Enum_CXLinkageKind;
- pub fn clang_getCursorVisibility(cursor: CXCursor) -> Enum_CXVisibilityKind;
- pub fn clang_getCursorAvailability(cursor: CXCursor) ->
- Enum_CXAvailabilityKind;
- pub fn clang_getCursorPlatformAvailability(cursor: CXCursor,
- always_deprecated:
- *mut c_int,
- deprecated_message:
- *mut CXString,
- always_unavailable:
- *mut c_int,
- unavailable_message:
- *mut CXString,
- availability:
- *mut CXPlatformAvailability,
- availability_size:
- c_int) ->
- c_int;
- pub fn clang_disposeCXPlatformAvailability(availability:
- *mut CXPlatformAvailability);
- pub fn clang_getCursorLanguage(cursor: CXCursor) -> Enum_CXLanguageKind;
- pub fn clang_Cursor_getTranslationUnit(arg1: CXCursor) ->
- CXTranslationUnit;
- pub fn clang_createCXCursorSet() -> CXCursorSet;
- pub fn clang_disposeCXCursorSet(cset: CXCursorSet);
- pub fn clang_CXCursorSet_contains(cset: CXCursorSet, cursor: CXCursor) ->
- c_uint;
- pub fn clang_CXCursorSet_insert(cset: CXCursorSet, cursor: CXCursor) ->
- c_uint;
- pub fn clang_getCursorSemanticParent(cursor: CXCursor) -> CXCursor;
- pub fn clang_getCursorLexicalParent(cursor: CXCursor) -> CXCursor;
- pub fn clang_getOverriddenCursors(cursor: CXCursor,
- overridden: *mut *mut CXCursor,
- num_overridden: *mut c_uint);
- pub fn clang_disposeOverriddenCursors(overridden: *mut CXCursor);
- pub fn clang_getIncludedFile(cursor: CXCursor) -> CXFile;
- pub fn clang_getCursor(arg1: CXTranslationUnit, arg2: CXSourceLocation) ->
- CXCursor;
- pub fn clang_getCursorLocation(arg1: CXCursor) -> CXSourceLocation;
- pub fn clang_getCursorExtent(arg1: CXCursor) -> CXSourceRange;
- pub fn clang_getCursorType(C: CXCursor) -> CXType;
- pub fn clang_getTypeSpelling(CT: CXType) -> CXString;
- pub fn clang_getTypedefDeclUnderlyingType(C: CXCursor) -> CXType;
- pub fn clang_getEnumDeclIntegerType(C: CXCursor) -> CXType;
- pub fn clang_getEnumConstantDeclValue(C: CXCursor) -> c_longlong;
- pub fn clang_getEnumConstantDeclUnsignedValue(C: CXCursor) ->
- c_ulonglong;
- pub fn clang_getFieldDeclBitWidth(C: CXCursor) -> c_int;
- pub fn clang_Cursor_getNumArguments(C: CXCursor) -> c_int;
- pub fn clang_Cursor_getArgument(C: CXCursor, i: c_uint) ->
- CXCursor;
- pub fn clang_Cursor_getNumTemplateArguments(T: CXCursor) -> c_int;
- pub fn clang_Cursor_getTemplateArgumentKind(C: CXCursor, i: c_uint) ->
- CXTemplateArgumentKind;
- pub fn clang_Cursor_getTemplateArgumentValue(C: CXCursor, i: c_uint) ->
- c_longlong;
- pub fn clang_Cursor_getTemplateArgumentUnsignedValue(C: CXCursor, i: c_uint) ->
- c_ulonglong;
- pub fn clang_equalTypes(A: CXType, B: CXType) -> c_uint;
- pub fn clang_getCanonicalType(T: CXType) -> CXType;
- pub fn clang_isConstQualifiedType(T: CXType) -> c_uint;
- pub fn clang_isVolatileQualifiedType(T: CXType) -> c_uint;
- pub fn clang_isRestrictQualifiedType(T: CXType) -> c_uint;
- pub fn clang_getPointeeType(T: CXType) -> CXType;
- pub fn clang_getTypeDeclaration(T: CXType) -> CXCursor;
- pub fn clang_getDeclObjCTypeEncoding(C: CXCursor) -> CXString;
- pub fn clang_getTypeKindSpelling(K: Enum_CXTypeKind) -> CXString;
- pub fn clang_getFunctionTypeCallingConv(T: CXType) -> Enum_CXCallingConv;
- pub fn clang_getResultType(T: CXType) -> CXType;
- pub fn clang_getNumArgTypes(T: CXType) -> c_int;
- pub fn clang_getArgType(T: CXType, i: c_uint) -> CXType;
- pub fn clang_isFunctionTypeVariadic(T: CXType) -> c_uint;
- pub fn clang_getCursorResultType(C: CXCursor) -> CXType;
- pub fn clang_isPODType(T: CXType) -> c_uint;
- pub fn clang_getElementType(T: CXType) -> CXType;
- pub fn clang_getNumElements(T: CXType) -> c_longlong;
- pub fn clang_getArrayElementType(T: CXType) -> CXType;
- pub fn clang_getArraySize(T: CXType) -> c_longlong;
- pub fn clang_Type_getAlignOf(T: CXType) -> c_longlong;
- pub fn clang_Type_getClassType(T: CXType) -> CXType;
- pub fn clang_Type_getSizeOf(T: CXType) -> c_longlong;
- pub fn clang_Type_getOffsetOf(T: CXType, S: *const c_char) ->
- c_longlong;
- pub fn clang_Type_getCXXRefQualifier(T: CXType) ->
- Enum_CXRefQualifierKind;
- pub fn clang_Type_getNumTemplateArguments(T: CXType) -> c_int;
- pub fn clang_Type_getTemplateArgumentAsType(T: CXType, i: c_int) ->
- CXType;
- #[cfg(not(feature="llvm_stable"))]
- pub fn clang_Type_getNamedType(CT: CXType) -> CXType;
- pub fn clang_Cursor_isBitField(C: CXCursor) -> c_uint;
- #[cfg(not(feature="llvm_stable"))]
- pub fn clang_Cursor_isFunctionInlined(C: CXCursor) -> c_uint;
- pub fn clang_isVirtualBase(arg1: CXCursor) -> c_uint;
- pub fn clang_getCXXAccessSpecifier(arg1: CXCursor) ->
- Enum_CX_CXXAccessSpecifier;
- pub fn clang_getNumOverloadedDecls(cursor: CXCursor) -> c_uint;
- pub fn clang_getOverloadedDecl(cursor: CXCursor, index: c_uint) ->
- CXCursor;
- pub fn clang_getIBOutletCollectionType(arg1: CXCursor) -> CXType;
- pub fn clang_visitChildren(parent: CXCursor, visitor: CXCursorVisitor,
- client_data: CXClientData) -> c_uint;
- pub fn clang_getCursorUSR(arg1: CXCursor) -> CXString;
- pub fn clang_constructUSR_ObjCClass(class_name: *const c_char) ->
- CXString;
- pub fn clang_constructUSR_ObjCCategory(class_name: *const c_char,
- category_name:
- *const c_char) ->
- CXString;
- pub fn clang_constructUSR_ObjCProtocol(protocol_name:
- *const c_char) ->
- CXString;
- pub fn clang_constructUSR_ObjCIvar(name: *const c_char,
- classUSR: CXString) -> CXString;
- pub fn clang_constructUSR_ObjCMethod(name: *const c_char,
- isInstanceMethod: c_uint,
- classUSR: CXString) -> CXString;
- pub fn clang_constructUSR_ObjCProperty(property: *const c_char,
- classUSR: CXString) -> CXString;
- pub fn clang_getCursorSpelling(arg1: CXCursor) -> CXString;
- pub fn clang_Cursor_getSpellingNameRange(arg1: CXCursor,
- pieceIndex: c_uint,
- options: c_uint) ->
- CXSourceRange;
- pub fn clang_Cursor_getOffsetOfField(C: CXCursor) -> c_longlong;
- pub fn clang_getCursorDisplayName(arg1: CXCursor) -> CXString;
- pub fn clang_getCursorReferenced(arg1: CXCursor) -> CXCursor;
- pub fn clang_getCursorDefinition(arg1: CXCursor) -> CXCursor;
- pub fn clang_isCursorDefinition(arg1: CXCursor) -> c_uint;
- pub fn clang_getCanonicalCursor(arg1: CXCursor) -> CXCursor;
- pub fn clang_Cursor_getObjCSelectorIndex(arg1: CXCursor) -> c_int;
- pub fn clang_Cursor_isDynamicCall(C: CXCursor) -> c_int;
- pub fn clang_Cursor_getReceiverType(C: CXCursor) -> CXType;
- pub fn clang_Cursor_getObjCPropertyAttributes(C: CXCursor,
- reserved: c_uint) ->
- c_uint;
- pub fn clang_Cursor_getObjCDeclQualifiers(C: CXCursor) -> c_uint;
- pub fn clang_Cursor_isObjCOptional(C: CXCursor) -> c_uint;
- pub fn clang_Cursor_isVariadic(C: CXCursor) -> c_uint;
- pub fn clang_Cursor_getCommentRange(C: CXCursor) -> CXSourceRange;
- pub fn clang_Cursor_getRawCommentText(C: CXCursor) -> CXString;
- pub fn clang_Cursor_getBriefCommentText(C: CXCursor) -> CXString;
- pub fn clang_Cursor_getMangling(C: CXCursor) -> CXString;
- pub fn clang_Cursor_getParsedComment(C: CXCursor) -> CXComment;
- pub fn clang_Cursor_getModule(C: CXCursor) -> CXModule;
- pub fn clang_Cursor_isAnonymous(C: CXCursor) -> c_uint;
- pub fn clang_Module_getASTFile(Module: CXModule) -> CXFile;
- pub fn clang_Module_getParent(Module: CXModule) -> CXModule;
- pub fn clang_Module_getName(Module: CXModule) -> CXString;
- pub fn clang_Module_getFullName(Module: CXModule) -> CXString;
- pub fn clang_Module_getNumTopLevelHeaders(arg1: CXTranslationUnit,
- Module: CXModule) ->
- c_uint;
- pub fn clang_Module_getTopLevelHeader(arg1: CXTranslationUnit,
- Module: CXModule,
- Index: c_uint) -> CXFile;
- pub fn clang_Comment_getKind(Comment: CXComment) -> Enum_CXCommentKind;
- pub fn clang_Comment_getNumChildren(Comment: CXComment) -> c_uint;
- pub fn clang_Comment_getChild(Comment: CXComment,
- ChildIdx: c_uint) -> CXComment;
- pub fn clang_Comment_isWhitespace(Comment: CXComment) -> c_uint;
- pub fn clang_InlineContentComment_hasTrailingNewline(Comment: CXComment)
- -> c_uint;
- pub fn clang_TextComment_getText(Comment: CXComment) -> CXString;
- pub fn clang_InlineCommandComment_getCommandName(Comment: CXComment) ->
- CXString;
- pub fn clang_InlineCommandComment_getRenderKind(Comment: CXComment) ->
- Enum_CXCommentInlineCommandRenderKind;
- pub fn clang_InlineCommandComment_getNumArgs(Comment: CXComment) ->
- c_uint;
- pub fn clang_InlineCommandComment_getArgText(Comment: CXComment,
- ArgIdx: c_uint) ->
- CXString;
- pub fn clang_HTMLTagComment_getTagName(Comment: CXComment) -> CXString;
- pub fn clang_HTMLStartTagComment_isSelfClosing(Comment: CXComment) ->
- c_uint;
- pub fn clang_HTMLStartTag_getNumAttrs(Comment: CXComment) ->
- c_uint;
- pub fn clang_HTMLStartTag_getAttrName(Comment: CXComment,
- AttrIdx: c_uint) ->
- CXString;
- pub fn clang_HTMLStartTag_getAttrValue(Comment: CXComment,
- AttrIdx: c_uint) ->
- CXString;
- pub fn clang_BlockCommandComment_getCommandName(Comment: CXComment) ->
- CXString;
- pub fn clang_BlockCommandComment_getNumArgs(Comment: CXComment) ->
- c_uint;
- pub fn clang_BlockCommandComment_getArgText(Comment: CXComment,
- ArgIdx: c_uint) ->
- CXString;
- pub fn clang_BlockCommandComment_getParagraph(Comment: CXComment) ->
- CXComment;
- pub fn clang_ParamCommandComment_getParamName(Comment: CXComment) ->
- CXString;
- pub fn clang_ParamCommandComment_isParamIndexValid(Comment: CXComment) ->
- c_uint;
- pub fn clang_ParamCommandComment_getParamIndex(Comment: CXComment) ->
- c_uint;
- pub fn clang_ParamCommandComment_isDirectionExplicit(Comment: CXComment)
- -> c_uint;
- pub fn clang_ParamCommandComment_getDirection(Comment: CXComment) ->
- Enum_CXCommentParamPassDirection;
- pub fn clang_TParamCommandComment_getParamName(Comment: CXComment) ->
- CXString;
- pub fn clang_TParamCommandComment_isParamPositionValid(Comment: CXComment)
- -> c_uint;
- pub fn clang_TParamCommandComment_getDepth(Comment: CXComment) ->
- c_uint;
- pub fn clang_TParamCommandComment_getIndex(Comment: CXComment,
- Depth: c_uint) ->
- c_uint;
- pub fn clang_VerbatimBlockLineComment_getText(Comment: CXComment) ->
- CXString;
- pub fn clang_VerbatimLineComment_getText(Comment: CXComment) -> CXString;
- pub fn clang_HTMLTagComment_getAsString(Comment: CXComment) -> CXString;
- pub fn clang_FullComment_getAsHTML(Comment: CXComment) -> CXString;
- pub fn clang_FullComment_getAsXML(Comment: CXComment) -> CXString;
- pub fn clang_CXXMethod_isPureVirtual(C: CXCursor) -> c_uint;
- pub fn clang_CXXMethod_isConst(C: CXCursor) -> c_uint;
- pub fn clang_CXXMethod_isStatic(C: CXCursor) -> c_uint;
- pub fn clang_CXXMethod_isVirtual(C: CXCursor) -> c_uint;
- pub fn clang_CXXField_isMutable(C: CXCursor) -> c_uint;
- pub fn clang_getTemplateCursorKind(C: CXCursor) -> Enum_CXCursorKind;
- pub fn clang_getSpecializedCursorTemplate(C: CXCursor) -> CXCursor;
- pub fn clang_getCursorReferenceNameRange(C: CXCursor,
- NameFlags: c_uint,
- PieceIndex: c_uint) ->
- CXSourceRange;
- pub fn clang_getTokenKind(arg1: CXToken) -> CXTokenKind;
- pub fn clang_getTokenSpelling(arg1: CXTranslationUnit, arg2: CXToken) ->
- CXString;
- pub fn clang_getTokenLocation(arg1: CXTranslationUnit, arg2: CXToken) ->
- CXSourceLocation;
- pub fn clang_getTokenExtent(arg1: CXTranslationUnit, arg2: CXToken) ->
- CXSourceRange;
- pub fn clang_tokenize(TU: CXTranslationUnit, Range: CXSourceRange,
- Tokens: *mut *mut CXToken,
- NumTokens: *mut c_uint);
- pub fn clang_annotateTokens(TU: CXTranslationUnit, Tokens: *mut CXToken,
- NumTokens: c_uint,
- Cursors: *mut CXCursor);
- pub fn clang_disposeTokens(TU: CXTranslationUnit, Tokens: *mut CXToken,
- NumTokens: c_uint);
- pub fn clang_getCursorKindSpelling(Kind: Enum_CXCursorKind) -> CXString;
- pub fn clang_getDefinitionSpellingAndExtent(arg1: CXCursor,
- startBuf:
- *mut *const c_char,
- endBuf:
- *mut *const c_char,
- startLine:
- *mut c_uint,
- startColumn:
- *mut c_uint,
- endLine: *mut c_uint,
- endColumn:
- *mut c_uint);
- pub fn clang_enableStackTraces();
- pub fn clang_executeOnThread(_fn:
- ::std::option::Option<extern "C" fn
- (arg1:
- *mut c_void)>,
- user_data: *mut c_void,
- stack_size: c_uint);
- pub fn clang_getCompletionChunkKind(completion_string: CXCompletionString,
- chunk_number: c_uint) ->
- Enum_CXCompletionChunkKind;
- pub fn clang_getCompletionChunkText(completion_string: CXCompletionString,
- chunk_number: c_uint) ->
- CXString;
- pub fn clang_getCompletionChunkCompletionString(completion_string:
- CXCompletionString,
- chunk_number:
- c_uint) ->
- CXCompletionString;
- pub fn clang_getNumCompletionChunks(completion_string: CXCompletionString)
- -> c_uint;
- pub fn clang_getCompletionPriority(completion_string: CXCompletionString)
- -> c_uint;
- pub fn clang_getCompletionAvailability(completion_string:
- CXCompletionString) ->
- Enum_CXAvailabilityKind;
- pub fn clang_getCompletionNumAnnotations(completion_string:
- CXCompletionString) ->
- c_uint;
- pub fn clang_getCompletionAnnotation(completion_string:
- CXCompletionString,
- annotation_number: c_uint) ->
- CXString;
- pub fn clang_getCompletionParent(completion_string: CXCompletionString,
- kind: *mut Enum_CXCursorKind) ->
- CXString;
- pub fn clang_getCompletionBriefComment(completion_string:
- CXCompletionString) ->
- CXString;
- pub fn clang_getCursorCompletionString(cursor: CXCursor) ->
- CXCompletionString;
- pub fn clang_defaultCodeCompleteOptions() -> c_uint;
- pub fn clang_codeCompleteAt(TU: CXTranslationUnit,
- complete_filename: *const c_char,
- complete_line: c_uint,
- complete_column: c_uint,
- unsaved_files: *mut Struct_CXUnsavedFile,
- num_unsaved_files: c_uint,
- options: c_uint) ->
- *mut CXCodeCompleteResults;
- pub fn clang_sortCodeCompletionResults(Results: *mut CXCompletionResult,
- NumResults: c_uint);
- pub fn clang_disposeCodeCompleteResults(Results:
- *mut CXCodeCompleteResults);
- pub fn clang_codeCompleteGetNumDiagnostics(Results:
- *mut CXCodeCompleteResults)
- -> c_uint;
- pub fn clang_codeCompleteGetDiagnostic(Results:
- *mut CXCodeCompleteResults,
- Index: c_uint) ->
- CXDiagnostic;
- pub fn clang_codeCompleteGetContexts(Results: *mut CXCodeCompleteResults)
- -> c_ulonglong;
- pub fn clang_codeCompleteGetContainerKind(Results:
- *mut CXCodeCompleteResults,
- IsIncomplete:
- *mut c_uint) ->
- Enum_CXCursorKind;
- pub fn clang_codeCompleteGetContainerUSR(Results:
- *mut CXCodeCompleteResults)
- -> CXString;
- pub fn clang_codeCompleteGetObjCSelector(Results:
- *mut CXCodeCompleteResults)
- -> CXString;
- pub fn clang_getClangVersion() -> CXString;
- pub fn clang_toggleCrashRecovery(isEnabled: c_uint);
- pub fn clang_getInclusions(tu: CXTranslationUnit,
- visitor: CXInclusionVisitor,
- client_data: CXClientData);
- pub fn clang_getRemappings(path: *const c_char) -> CXRemapping;
- pub fn clang_getRemappingsFromFileList(filePaths:
- *mut *const c_char,
- numFiles: c_uint) ->
- CXRemapping;
- pub fn clang_remap_getNumFiles(arg1: CXRemapping) -> c_uint;
- pub fn clang_remap_getFilenames(arg1: CXRemapping, index: c_uint,
- original: *mut CXString,
- transformed: *mut CXString);
- pub fn clang_remap_dispose(arg1: CXRemapping);
- pub fn clang_findReferencesInFile(cursor: CXCursor, file: CXFile,
- visitor: CXCursorAndRangeVisitor) ->
- CXResult;
- pub fn clang_findIncludesInFile(TU: CXTranslationUnit, file: CXFile,
- visitor: CXCursorAndRangeVisitor) ->
- CXResult;
- pub fn clang_index_isEntityObjCContainerKind(arg1: CXIdxEntityKind) ->
- c_int;
- pub fn clang_index_getObjCContainerDeclInfo(arg1: *const CXIdxDeclInfo) ->
- *const CXIdxObjCContainerDeclInfo;
- pub fn clang_index_getObjCInterfaceDeclInfo(arg1: *const CXIdxDeclInfo) ->
- *const CXIdxObjCInterfaceDeclInfo;
- pub fn clang_index_getObjCCategoryDeclInfo(arg1: *const CXIdxDeclInfo) ->
- *const CXIdxObjCCategoryDeclInfo;
- pub fn clang_index_getObjCProtocolRefListInfo(arg1: *const CXIdxDeclInfo)
- -> *const CXIdxObjCProtocolRefListInfo;
- pub fn clang_index_getObjCPropertyDeclInfo(arg1: *const CXIdxDeclInfo) ->
- *const CXIdxObjCPropertyDeclInfo;
- pub fn clang_index_getIBOutletCollectionAttrInfo(arg1:
- *const CXIdxAttrInfo)
- -> *const CXIdxIBOutletCollectionAttrInfo;
- pub fn clang_index_getCXXClassDeclInfo(arg1: *const CXIdxDeclInfo) ->
- *const CXIdxCXXClassDeclInfo;
- pub fn clang_index_getClientContainer(arg1: *const CXIdxContainerInfo) ->
- CXIdxClientContainer;
- pub fn clang_index_setClientContainer(arg1: *const CXIdxContainerInfo,
- arg2: CXIdxClientContainer);
- pub fn clang_index_getClientEntity(arg1: *const CXIdxEntityInfo) ->
- CXIdxClientEntity;
- pub fn clang_index_setClientEntity(arg1: *const CXIdxEntityInfo,
- arg2: CXIdxClientEntity);
- pub fn clang_IndexAction_create(CIdx: CXIndex) -> CXIndexAction;
- pub fn clang_IndexAction_dispose(arg1: CXIndexAction);
- pub fn clang_indexSourceFile(arg1: CXIndexAction,
- client_data: CXClientData,
- index_callbacks: *mut IndexerCallbacks,
- index_callbacks_size: c_uint,
- index_options: c_uint,
- source_filename: *const c_char,
- command_line_args:
- *const *const c_char,
- num_command_line_args: c_int,
- unsaved_files: *mut Struct_CXUnsavedFile,
- num_unsaved_files: c_uint,
- out_TU: *mut CXTranslationUnit,
- TU_options: c_uint) -> c_int;
- pub fn clang_indexTranslationUnit(arg1: CXIndexAction,
- client_data: CXClientData,
- index_callbacks: *mut IndexerCallbacks,
- index_callbacks_size: c_uint,
- index_options: c_uint,
- arg2: CXTranslationUnit) ->
- c_int;
- pub fn clang_indexLoc_getFileLocation(loc: CXIdxLoc,
- indexFile: *mut CXIdxClientFile,
- file: *mut CXFile,
- line: *mut c_uint,
- column: *mut c_uint,
- offset: *mut c_uint);
- pub fn clang_indexLoc_getCXSourceLocation(loc: CXIdxLoc) ->
- CXSourceLocation;
-}
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs
deleted file mode 100644
index 6e5a6f0e..00000000
--- a/src/codegen/helpers.rs
+++ /dev/null
@@ -1,135 +0,0 @@
-//! Helpers for code generation that don't need macro expansion.
-
-use aster;
-use ir::layout::Layout;
-use syntax::ast;
-use syntax::ptr::P;
-
-
-pub mod attributes {
- use aster;
- use syntax::ast;
-
- pub fn repr(which: &str) -> ast::Attribute {
- aster::AstBuilder::new().attr().list("repr").words(&[which]).build()
- }
-
- pub fn repr_list(which_ones: &[&str]) -> ast::Attribute {
- aster::AstBuilder::new().attr().list("repr").words(which_ones).build()
- }
-
- pub fn derives(which_ones: &[&str]) -> ast::Attribute {
- aster::AstBuilder::new().attr().list("derive").words(which_ones).build()
- }
-
- pub fn inline() -> ast::Attribute {
- aster::AstBuilder::new().attr().word("inline")
- }
-
- pub fn doc(comment: &str) -> ast::Attribute {
- aster::AstBuilder::new().attr().doc(comment)
- }
-
- pub fn link_name(name: &str) -> ast::Attribute {
- aster::AstBuilder::new().attr().name_value("link_name").str(name)
- }
-}
-
-/// Generates a proper type for a field or type with a given `Layout`, that is,
-/// a type with the correct size and alignment restrictions.
-pub struct BlobTyBuilder {
- layout: Layout,
-}
-
-impl BlobTyBuilder {
- pub fn new(layout: Layout) -> Self {
- BlobTyBuilder {
- layout: layout,
- }
- }
-
- pub fn build(self) -> P<ast::Ty> {
- use std::cmp;
-
- let ty_name = match self.layout.align {
- 8 => "u64",
- 4 => "u32",
- 2 => "u16",
- 1 | _ => "u8",
- };
- let data_len = if ty_name == "u8" {
- self.layout.size
- } else {
- self.layout.size / cmp::max(self.layout.align, 1)
- };
-
- let inner_ty = aster::AstBuilder::new().ty().path().id(ty_name).build();
- if data_len == 1 {
- inner_ty
- } else {
- aster::ty::TyBuilder::new().array(data_len).build(inner_ty)
- }
- }
-}
-
-pub mod ast_ty {
- use aster;
- use ir::context::BindgenContext;
- use ir::ty::FloatKind;
- use syntax::ast;
- use syntax::ptr::P;
-
- pub fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> {
- let ident = ctx.rust_ident_raw(&name);
- match ctx.options().ctypes_prefix {
- Some(ref prefix) => {
- let prefix = ctx.rust_ident_raw(prefix);
- quote_ty!(ctx.ext_cx(), $prefix::$ident)
- }
- None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident),
- }
- }
-
- pub fn float_kind_rust_type(ctx: &BindgenContext,
- fk: FloatKind)
- -> P<ast::Ty> {
- macro_rules! raw {
- ($ty: ident) => {
- raw_type(ctx, stringify!($ty))
- }
- }
- // TODO: we probably should just take the type layout into
- // account?
- //
- // Also, maybe this one shouldn't be the default?
- //
- // FIXME: `c_longdouble` doesn't seem to be defined in some
- // systems, so we use `c_double` directly.
- match (fk, ctx.options().convert_floats) {
- (FloatKind::Float, true) => aster::ty::TyBuilder::new().f32(),
- (FloatKind::Double, true) |
- (FloatKind::LongDouble, true) => aster::ty::TyBuilder::new().f64(),
- (FloatKind::Float, false) => raw!(c_float),
- (FloatKind::Double, false) |
- (FloatKind::LongDouble, false) => raw!(c_double),
- (FloatKind::Float128, _) => {
- aster::ty::TyBuilder::new().array(16).u8()
- }
- }
- }
-
- pub fn int_expr(val: i64) -> P<ast::Expr> {
- use std::i64;
- let expr = aster::AstBuilder::new().expr();
-
- // This is not representable as an i64 if it's negative, so we
- // special-case it.
- //
- // Fix in aster incoming.
- if val == i64::MIN {
- expr.neg().uint(1u64 << 63)
- } else {
- expr.int(val)
- }
- }
-}
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
deleted file mode 100755
index 8e04fd7c..00000000
--- a/src/codegen/mod.rs
+++ /dev/null
@@ -1,2121 +0,0 @@
-mod helpers;
-
-
-use aster;
-
-use ir::annotations::FieldAccessorKind;
-use ir::comp::{CompInfo, CompKind, Field, Method};
-use ir::context::{BindgenContext, ItemId};
-use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
-use ir::function::{Function, FunctionSig};
-use ir::int::IntKind;
-use ir::item::{Item, ItemCanonicalName, ItemCanonicalPath};
-use ir::item_kind::ItemKind;
-use ir::layout::Layout;
-use ir::module::Module;
-use ir::ty::{Type, TypeKind};
-use ir::type_collector::ItemSet;
-use ir::var::Var;
-use self::helpers::{BlobTyBuilder, attributes};
-
-use std::borrow::Cow;
-use std::collections::HashSet;
-use std::collections::hash_map::{Entry, HashMap};
-use std::fmt::Write;
-use std::mem;
-use std::ops;
-use syntax::abi::Abi;
-use syntax::ast;
-use syntax::codemap::{Span, respan};
-use syntax::ptr::P;
-
-fn root_import(ctx: &BindgenContext) -> P<ast::Item> {
- assert!(ctx.options().enable_cxx_namespaces, "Somebody messed it up");
- let root = ctx.root_module().canonical_name(ctx);
- let root_ident = ctx.rust_ident(&root);
- quote_item!(ctx.ext_cx(), use $root_ident;).unwrap()
-}
-
-struct CodegenResult {
- items: Vec<P<ast::Item>>,
- saw_union: bool,
- items_seen: HashSet<ItemId>,
- /// The set of generated function/var names, needed because in C/C++ is
- /// legal to do something like:
- ///
- /// ```c++
- /// extern "C" {
- /// void foo();
- /// extern int bar;
- /// }
- ///
- /// extern "C" {
- /// void foo();
- /// extern int bar;
- /// }
- /// ```
- ///
- /// Being these two different declarations.
- functions_seen: HashSet<String>,
- vars_seen: HashSet<String>,
-
- /// Used for making bindings to overloaded functions. Maps from a canonical
- /// function name to the number of overloads we have already codegen'd for
- /// that name. This lets us give each overload a unique suffix.
- overload_counters: HashMap<String, u32>,
-}
-
-impl CodegenResult {
- fn new() -> Self {
- CodegenResult {
- items: vec![],
- saw_union: false,
- items_seen: Default::default(),
- functions_seen: Default::default(),
- vars_seen: Default::default(),
- overload_counters: Default::default(),
- }
- }
-
- fn saw_union(&mut self) {
- self.saw_union = true;
- }
-
- fn seen(&self, item: ItemId) -> bool {
- self.items_seen.contains(&item)
- }
-
- fn set_seen(&mut self, item: ItemId) {
- self.items_seen.insert(item);
- }
-
- fn seen_function(&self, name: &str) -> bool {
- self.functions_seen.contains(name)
- }
-
- fn saw_function(&mut self, name: &str) {
- self.functions_seen.insert(name.into());
- }
-
- /// Get the overload number for the given function name. Increments the
- /// counter internally so the next time we ask for the overload for this
- /// name, we get the incremented value, and so on.
- fn overload_number(&mut self, name: &str) -> u32 {
- let mut counter =
- self.overload_counters.entry(name.into()).or_insert(0);
- let number = *counter;
- *counter += 1;
- number
- }
-
- fn seen_var(&self, name: &str) -> bool {
- self.vars_seen.contains(name)
- }
-
- fn saw_var(&mut self, name: &str) {
- self.vars_seen.insert(name.into());
- }
-
- fn inner<F>(&mut self, cb: F) -> Vec<P<ast::Item>>
- where F: FnOnce(&mut Self),
- {
- let mut new = Self::new();
-
- cb(&mut new);
-
- self.saw_union |= new.saw_union;
-
- new.items
- }
-}
-
-impl ops::Deref for CodegenResult {
- type Target = Vec<P<ast::Item>>;
-
- fn deref(&self) -> &Self::Target {
- &self.items
- }
-}
-
-impl ops::DerefMut for CodegenResult {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.items
- }
-}
-
-struct ForeignModBuilder {
- inner: ast::ForeignMod,
-}
-
-impl ForeignModBuilder {
- fn new(abi: Abi) -> Self {
- ForeignModBuilder {
- inner: ast::ForeignMod {
- abi: abi,
- items: vec![],
- },
- }
- }
-
- fn with_foreign_item(mut self, item: ast::ForeignItem) -> Self {
- self.inner.items.push(item);
- self
- }
-
- #[allow(dead_code)]
- fn with_foreign_items<I>(mut self, items: I) -> Self
- where I: IntoIterator<Item = ast::ForeignItem>,
- {
- self.inner.items.extend(items.into_iter());
- self
- }
-
- fn build(self, ctx: &BindgenContext) -> P<ast::Item> {
- use syntax::codemap::DUMMY_SP;
- P(ast::Item {
- ident: ctx.rust_ident(""),
- id: ast::DUMMY_NODE_ID,
- node: ast::ItemKind::ForeignMod(self.inner),
- vis: ast::Visibility::Public,
- attrs: vec![],
- span: DUMMY_SP,
- })
- }
-}
-
-/// A trait to convert a rust type into a pointer, optionally const, to the same
-/// type.
-///
-/// This is done due to aster's lack of pointer builder, I guess I should PR
-/// there.
-trait ToPtr {
- fn to_ptr(self, is_const: bool, span: Span) -> P<ast::Ty>;
-}
-
-impl ToPtr for P<ast::Ty> {
- fn to_ptr(self, is_const: bool, span: Span) -> Self {
- let ty = ast::TyKind::Ptr(ast::MutTy {
- ty: self,
- mutbl: if is_const {
- ast::Mutability::Immutable
- } else {
- ast::Mutability::Mutable
- },
- });
- P(ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ty,
- span: span,
- })
- }
-}
-
-trait CodeGenerator {
- /// Extra information from the caller.
- type Extra;
-
- fn codegen(&self,
- ctx: &BindgenContext,
- result: &mut CodegenResult,
- extra: &Self::Extra);
-}
-
-impl CodeGenerator for Item {
- type Extra = ();
-
- fn codegen(&self,
- ctx: &BindgenContext,
- result: &mut CodegenResult,
- _extra: &()) {
- if self.is_hidden(ctx) || result.seen(self.id()) {
- return;
- }
-
- result.set_seen(self.id());
-
- match *self.kind() {
- ItemKind::Module(ref module) => {
- if !ctx.options().enable_cxx_namespaces &&
- self.id() == ctx.root_module() {
- return;
- }
-
- module.codegen(ctx, result, self);
- }
- ItemKind::Function(ref fun) => {
- if !ctx.options().ignore_functions {
- fun.codegen(ctx, result, self);
- }
- }
- ItemKind::Var(ref var) => {
- var.codegen(ctx, result, self);
- }
- ItemKind::Type(ref ty) => {
- ty.codegen(ctx, result, self);
- }
- }
- }
-}
-
-impl CodeGenerator for Module {
- type Extra = Item;
-
- fn codegen(&self,
- ctx: &BindgenContext,
- result: &mut CodegenResult,
- item: &Item) {
- if !ctx.options().enable_cxx_namespaces {
- for child in self.children() {
- ctx.resolve_item(*child).codegen(ctx, result, &());
- }
- return;
- }
-
- let inner_items = result.inner(|result| {
- result.push(root_import(ctx));
- for child in self.children() {
- ctx.resolve_item(*child).codegen(ctx, result, &());
- }
- });
-
- let module = ast::ItemKind::Mod(ast::Mod {
- inner: ctx.span(),
- items: inner_items,
- });
-
- let name = item.canonical_name(ctx);
- let item = aster::AstBuilder::new()
- .item()
- .pub_()
- .build_item_kind(name, module);
-
- result.push(item);
- }
-}
-
-impl CodeGenerator for Var {
- type Extra = Item;
- fn codegen(&self,
- ctx: &BindgenContext,
- result: &mut CodegenResult,
- item: &Item) {
- let canonical_name = item.canonical_name(ctx);
-
- if result.seen_var(&canonical_name) {
- return;
- }
- result.saw_var(&canonical_name);
-
- let ty = self.ty().to_rust_ty(ctx);
-
- if let Some(val) = self.val() {
- let const_item = aster::AstBuilder::new()
- .item()
- .pub_()
- .const_(canonical_name)
- .expr()
- .build(helpers::ast_ty::int_expr(val))
- .build(ty);
- result.push(const_item)
- } else {
- let mut attrs = vec![];
- if let Some(mangled) = self.mangled_name() {
- attrs.push(attributes::link_name(mangled));
- } else if canonical_name != self.name() {
- attrs.push(attributes::link_name(self.name()));
- }
-
- let item = ast::ForeignItem {
- ident: ctx.rust_ident_raw(&canonical_name),
- attrs: attrs,
- node: ast::ForeignItemKind::Static(ty, !self.is_const()),
- id: ast::DUMMY_NODE_ID,
- span: ctx.span(),
- vis: ast::Visibility::Public,
- };
-
- let item = ForeignModBuilder::new(Abi::C)
- .with_foreign_item(item)
- .build(ctx);
- result.push(item);
- }
- }
-}
-
-impl CodeGenerator for Type {
- type Extra = Item;
-
- fn codegen(&self,
- ctx: &BindgenContext,
- result: &mut CodegenResult,
- item: &Item) {
- match *self.kind() {
- TypeKind::Void |
- TypeKind::NullPtr |
- TypeKind::Int(..) |
- TypeKind::Float(..) |
- TypeKind::Complex(..) |
- TypeKind::Array(..) |
- TypeKind::Pointer(..) |
- TypeKind::BlockPointer |
- TypeKind::Reference(..) |
- TypeKind::TemplateRef(..) |
- TypeKind::Function(..) |
- TypeKind::ResolvedTypeRef(..) |
- TypeKind::Named(..) => {
- // These items don't need code generation, they only need to be
- // converted to rust types in fields, arguments, and such.
- return;
- }
- TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
- TypeKind::TemplateAlias(inner, _) => {
- // NB: The inner Alias will pick the correct
- // applicable_template_args.
- let inner_item = ctx.resolve_item(inner);
- inner_item.expect_type().codegen(ctx, result, inner_item);
- }
- TypeKind::Alias(ref spelling, inner) => {
- let inner_item = ctx.resolve_item(inner);
- let name = item.canonical_name(ctx);
-
- // Try to catch the common pattern:
- //
- // typedef struct foo { ... } foo;
- //
- // here.
- //
- if inner_item.canonical_name(ctx) == name {
- return;
- }
-
- // If this is a known named type, disallow generating anything
- // for it too.
- if utils::type_from_named(ctx, spelling, inner).is_some() {
- return;
- }
-
- let mut applicable_template_args =
- item.applicable_template_args(ctx);
- let inner_rust_type = if item.is_opaque(ctx) {
- applicable_template_args.clear();
- // Pray if there's no layout.
- let layout = self.layout(ctx).unwrap_or_else(Layout::zero);
- BlobTyBuilder::new(layout).build()
- } else {
- inner_item.to_rust_ty(ctx)
- };
-
- let rust_name = ctx.rust_ident(&name);
- let mut typedef = aster::AstBuilder::new().item().pub_();
-
- if let Some(comment) = item.comment() {
- typedef = typedef.attr().doc(comment);
- }
-
- let mut generics = typedef.type_(rust_name).generics();
- for template_arg in applicable_template_args.iter() {
- let template_arg = ctx.resolve_type(*template_arg);
- if template_arg.is_named() {
- let name = template_arg.name().unwrap();
- if name.contains("typename ") {
- error!("Item contained `typename`'d template \
- parameter: {:?}", item);
- return;
- }
- generics =
- generics.ty_param_id(template_arg.name().unwrap());
- }
- }
-
- let typedef = generics.build().build_ty(inner_rust_type);
- result.push(typedef)
- }
- TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item),
- ref u @ TypeKind::UnresolvedTypeRef(..) => {
- unreachable!("Should have been resolved after parsing {:?}!", u)
- }
- }
- }
-}
-
-struct Vtable<'a> {
- item_id: ItemId,
- #[allow(dead_code)]
- methods: &'a [Method],
- #[allow(dead_code)]
- base_classes: &'a [ItemId],
-}
-
-impl<'a> Vtable<'a> {
- fn new(item_id: ItemId,
- methods: &'a [Method],
- base_classes: &'a [ItemId])
- -> Self {
- Vtable {
- item_id: item_id,
- methods: methods,
- base_classes: base_classes,
- }
- }
-}
-
-impl<'a> CodeGenerator for Vtable<'a> {
- type Extra = Item;
-
- fn codegen(&self,
- ctx: &BindgenContext,
- result: &mut CodegenResult,
- item: &Item) {
- assert_eq!(item.id(), self.item_id);
- // For now, generate an empty struct, later we should generate function
- // pointers and whatnot.
- let vtable = aster::AstBuilder::new()
- .item()
- .pub_()
- .with_attr(attributes::repr("C"))
- .struct_(self.canonical_name(ctx))
- .build();
- result.push(vtable);
- }
-}
-
-impl<'a> ItemCanonicalName for Vtable<'a> {
- fn canonical_name(&self, ctx: &BindgenContext) -> String {
- format!("{}__bindgen_vtable", self.item_id.canonical_name(ctx))
- }
-}
-
-impl<'a> ItemToRustTy for Vtable<'a> {
- fn to_rust_ty(&self, ctx: &BindgenContext) -> P<ast::Ty> {
- aster::ty::TyBuilder::new().id(self.canonical_name(ctx))
- }
-}
-
-struct Bitfield<'a> {
- index: usize,
- fields: Vec<&'a Field>,
-}
-
-impl<'a> Bitfield<'a> {
- fn new(index: usize, fields: Vec<&'a Field>) -> Self {
- Bitfield {
- index: index,
- fields: fields,
- }
- }
-
- fn codegen_fields(self,
- ctx: &BindgenContext,
- fields: &mut Vec<ast::StructField>,
- methods: &mut Vec<ast::ImplItem>) {
- use aster::struct_field::StructFieldBuilder;
- use std::cmp;
- let mut total_width = self.fields
- .iter()
- .fold(0u32, |acc, f| acc + f.bitfield().unwrap());
-
- if !total_width.is_power_of_two() || total_width < 8 {
- total_width = cmp::max(8, total_width.next_power_of_two());
- }
- debug_assert_eq!(total_width % 8, 0);
- let total_width_in_bytes = total_width as usize / 8;
-
- let bitfield_type =
- BlobTyBuilder::new(Layout::new(total_width_in_bytes,
- total_width_in_bytes))
- .build();
- let field_name = format!("_bitfield_{}", self.index);
- let field_ident = ctx.ext_cx().ident_of(&field_name);
- let field = StructFieldBuilder::named(&field_name)
- .pub_()
- .build_ty(bitfield_type.clone());
- fields.push(field);
-
-
- let mut offset = 0;
- for field in self.fields {
- let width = field.bitfield().unwrap();
- let field_name = field.name()
- .map(ToOwned::to_owned)
- .unwrap_or_else(|| format!("at_offset_{}", offset));
-
- let field_item = ctx.resolve_item(field.ty());
- let field_ty_layout = field_item.kind()
- .expect_type()
- .layout(ctx)
- .expect("Bitfield without layout? Gah!");
-
- let field_type = field_item.to_rust_ty(ctx);
- let int_type = BlobTyBuilder::new(field_ty_layout).build();
-
- let getter_name = ctx.ext_cx().ident_of(&field_name);
- let setter_name = ctx.ext_cx()
- .ident_of(&format!("set_{}", &field_name));
- let mask = ((1usize << width) - 1) << offset;
- let prefix = ctx.trait_prefix();
- // The transmute is unfortunate, but it's needed for enums in
- // bitfields.
- let item = quote_item!(ctx.ext_cx(),
- impl X {
- #[inline]
- pub fn $getter_name(&self) -> $field_type {
- unsafe {
- ::$prefix::mem::transmute(
- (
- (self.$field_ident &
- ($mask as $bitfield_type))
- >> $offset
- ) as $int_type
- )
- }
- }
-
- #[inline]
- pub fn $setter_name(&mut self, val: $field_type) {
- self.$field_ident &= !($mask as $bitfield_type);
- self.$field_ident |=
- (val as $int_type as $bitfield_type << $offset) &
- ($mask as $bitfield_type);
- }
- }
- )
- .unwrap();
-
- let items = match item.unwrap().node {
- ast::ItemKind::Impl(_, _, _, _, _, items) => items,
- _ => unreachable!(),
- };
-
- methods.extend(items.into_iter());
- offset += width;
- }
- }
-}
-
-impl CodeGenerator for CompInfo {
- type Extra = Item;
-
- fn codegen(&self,
- ctx: &BindgenContext,
- result: &mut CodegenResult,
- item: &Item) {
- use aster::struct_field::StructFieldBuilder;
- // Don't output classes with template parameters that aren't types, and
- // also don't output template specializations, neither total or partial.
- //
- // TODO: Generate layout tests for template specializations, yay!
- if self.has_non_type_template_params() ||
- self.is_template_specialization() {
- return;
- }
-
- let applicable_template_args = item.applicable_template_args(ctx);
-
- let mut attributes = vec![];
- let mut needs_clone_impl = false;
- if let Some(comment) = item.comment() {
- attributes.push(attributes::doc(comment));
- }
- if self.packed() {
- attributes.push(attributes::repr_list(&["C", "packed"]));
- } else {
- attributes.push(attributes::repr("C"));
- }
-
- let is_union = self.kind() == CompKind::Union;
- let mut derives = vec![];
- let ty = item.expect_type();
- if ty.can_derive_debug(ctx) {
- derives.push("Debug");
- }
-
- if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
- derives.push("Copy");
- if !applicable_template_args.is_empty() {
- // FIXME: This requires extra logic if you have a big array in a
- // templated struct. The reason for this is that the magic:
- // fn clone(&self) -> Self { *self }
- // doesn't work for templates.
- //
- // It's not hard to fix though.
- derives.push("Clone");
- } else {
- needs_clone_impl = true;
- }
- }
-
- if !derives.is_empty() {
- attributes.push(attributes::derives(&derives))
- }
-
- let mut template_args_used =
- vec![false; applicable_template_args.len()];
- let canonical_name = item.canonical_name(ctx);
- let builder = if is_union && ctx.options().unstable_rust {
- aster::AstBuilder::new()
- .item()
- .pub_()
- .with_attrs(attributes)
- .union_(&canonical_name)
- } else {
- aster::AstBuilder::new()
- .item()
- .pub_()
- .with_attrs(attributes)
- .struct_(&canonical_name)
- };
-
- // Generate the vtable from the method list if appropriate.
- //
- // TODO: I don't know how this could play with virtual methods that are
- // not in the list of methods found by us, we'll see. Also, could the
- // order of the vtable pointers vary?
- //
- // FIXME: Once we generate proper vtables, we need to codegen the
- // vtable, but *not* generate a field for it in the case that
- // needs_explicit_vtable is false but has_vtable is true.
- //
- // Also, we need to generate the vtable in such a way it "inherits" from
- // the parent too.
- let mut fields = vec![];
- if self.needs_explicit_vtable(ctx) {
- let vtable =
- Vtable::new(item.id(), self.methods(), self.base_members());
- vtable.codegen(ctx, result, item);
-
- let vtable_type = vtable.to_rust_ty(ctx).to_ptr(true, ctx.span());
-
- let vtable_field = StructFieldBuilder::named("vtable_")
- .pub_()
- .build_ty(vtable_type);
-
- fields.push(vtable_field);
- }
-
- for (i, base) in self.base_members().iter().enumerate() {
- let base_ty = ctx.resolve_type(*base);
- // NB: We won't include unsized types in our base chain because they
- // would contribute to our size given the dummy field we insert for
- // unsized types.
- //
- // NB: Canonical type is here because it could be inheriting from a
- // typedef, for example, and the lack of `unwrap()` is because we
- // can inherit from a template parameter, yes.
- if base_ty.is_unsized(ctx) {
- continue;
- }
-
- for (i, ty_id) in applicable_template_args.iter().enumerate() {
- let template_arg_ty = ctx.resolve_type(*ty_id);
- if base_ty.signature_contains_named_type(ctx, template_arg_ty) {
- template_args_used[i] = true;
- }
- }
-
- let inner = base.to_rust_ty(ctx);
- let field_name = if i == 0 {
- "_base".into()
- } else {
- format!("_base_{}", i)
- };
-
- let field = StructFieldBuilder::named(field_name)
- .pub_()
- .build_ty(inner);
- fields.push(field);
- }
- if is_union {
- result.saw_union();
- }
-
- let layout = item.kind().expect_type().layout(ctx);
-
- let mut current_bitfield_width = None;
- let mut current_bitfield_layout: Option<Layout> = None;
- let mut current_bitfield_fields = vec![];
- let mut bitfield_count = 0;
- let struct_fields = self.fields();
- let fields_should_be_private = item.annotations()
- .private_fields()
- .unwrap_or(false);
- let struct_accessor_kind = item.annotations()
- .accessor_kind()
- .unwrap_or(FieldAccessorKind::None);
-
- let mut methods = vec![];
- let mut anonymous_field_count = 0;
- for field in struct_fields {
- debug_assert_eq!(current_bitfield_width.is_some(),
- current_bitfield_layout.is_some());
- debug_assert_eq!(current_bitfield_width.is_some(),
- !current_bitfield_fields.is_empty());
-
- let field_ty = ctx.resolve_type(field.ty());
-
- // Try to catch a bitfield contination early.
- if let (Some(ref mut bitfield_width), Some(width)) =
- (current_bitfield_width, field.bitfield()) {
- let layout = current_bitfield_layout.unwrap();
- debug!("Testing bitfield continuation {} {} {:?}",
- *bitfield_width, width, layout);
- if *bitfield_width + width <= (layout.size * 8) as u32 {
- *bitfield_width += width;
- current_bitfield_fields.push(field);
- continue;
- }
- }
-
- // Flush the current bitfield.
- if current_bitfield_width.is_some() {
- debug_assert!(!current_bitfield_fields.is_empty());
- let bitfield_fields =
- mem::replace(&mut current_bitfield_fields, vec![]);
- bitfield_count += 1;
- Bitfield::new(bitfield_count, bitfield_fields)
- .codegen_fields(ctx, &mut fields, &mut methods);
- current_bitfield_width = None;
- current_bitfield_layout = None;
- }
- debug_assert!(current_bitfield_fields.is_empty());
-
- if let Some(width) = field.bitfield() {
- let layout = field_ty.layout(ctx)
- .expect("Bitfield type without layout?");
- current_bitfield_width = Some(width);
- current_bitfield_layout = Some(layout);
- current_bitfield_fields.push(field);
- continue;
- }
-
- for (i, ty_id) in applicable_template_args.iter().enumerate() {
- let template_arg = ctx.resolve_type(*ty_id);
- if field_ty.signature_contains_named_type(ctx, template_arg) {
- template_args_used[i] = true;
- }
- }
-
- let ty = field.ty().to_rust_ty(ctx);
-
- // NB: In unstable rust we use proper `union` types.
- let ty = if is_union && !ctx.options().unstable_rust {
- quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
- } else {
- ty
- };
-
- let mut attrs = vec![];
- if let Some(comment) = field.comment() {
- attrs.push(attributes::doc(comment));
- }
- let field_name = match field.name() {
- Some(name) => ctx.rust_mangle(name).into_owned(),
- None => {
- anonymous_field_count += 1;
- format!("__bindgen_anon_{}", anonymous_field_count)
- }
- };
-
- let is_private = field.annotations()
- .private_fields()
- .unwrap_or(fields_should_be_private);
-
- let accessor_kind = field.annotations()
- .accessor_kind()
- .unwrap_or(struct_accessor_kind);
-
- let mut field = StructFieldBuilder::named(&field_name);
-
- if !is_private {
- field = field.pub_();
- }
-
- let field = field.with_attrs(attrs)
- .build_ty(ty.clone());
-
- fields.push(field);
-
- // TODO: Factor the following code out, please!
- if accessor_kind == FieldAccessorKind::None {
- continue;
- }
-
- let getter_name =
- ctx.rust_ident_raw(&format!("get_{}", field_name));
- let mutable_getter_name =
- ctx.rust_ident_raw(&format!("get_{}_mut", field_name));
- let field_name = ctx.rust_ident_raw(&field_name);
-
- let accessor_methods_impl = match accessor_kind {
- FieldAccessorKind::None => unreachable!(),
- FieldAccessorKind::Regular => {
- quote_item!(ctx.ext_cx(),
- impl X {
- #[inline]
- pub fn $getter_name(&self) -> &$ty {
- &self.$field_name
- }
-
- #[inline]
- pub fn $mutable_getter_name(&mut self) -> &mut $ty {
- &mut self.$field_name
- }
- }
- )
- }
- FieldAccessorKind::Unsafe => {
- quote_item!(ctx.ext_cx(),
- impl X {
- #[inline]
- pub unsafe fn $getter_name(&self) -> &$ty {
- &self.$field_name
- }
-
- #[inline]
- pub unsafe fn $mutable_getter_name(&mut self)
- -> &mut $ty {
- &mut self.$field_name
- }
- }
- )
- }
- FieldAccessorKind::Immutable => {
- quote_item!(ctx.ext_cx(),
- impl X {
- #[inline]
- pub fn $getter_name(&self) -> &$ty {
- &self.$field_name
- }
- }
- )
- }
- };
-
- match accessor_methods_impl.unwrap().node {
- ast::ItemKind::Impl(_, _, _, _, _, ref items) => {
- methods.extend(items.clone())
- }
- _ => unreachable!(),
- }
- }
-
- // Flush the last bitfield if any.
- //
- // FIXME: Reduce duplication with the loop above.
- // FIXME: May need to pass current_bitfield_layout too.
- if current_bitfield_width.is_some() {
- debug_assert!(!current_bitfield_fields.is_empty());
- let bitfield_fields = mem::replace(&mut current_bitfield_fields,
- vec![]);
- bitfield_count += 1;
- Bitfield::new(bitfield_count, bitfield_fields)
- .codegen_fields(ctx, &mut fields, &mut methods);
- }
- debug_assert!(current_bitfield_fields.is_empty());
-
- if is_union && !ctx.options().unstable_rust {
- let layout = layout.expect("Unable to get layout information?");
- let ty = BlobTyBuilder::new(layout).build();
- let field = StructFieldBuilder::named("bindgen_union_field")
- .pub_()
- .build_ty(ty);
- fields.push(field);
- }
-
- // Yeah, sorry about that.
- if item.is_opaque(ctx) {
- fields.clear();
- methods.clear();
- for i in 0..template_args_used.len() {
- template_args_used[i] = false;
- }
-
- match layout {
- Some(l) => {
- let ty = BlobTyBuilder::new(l).build();
- let field =
- StructFieldBuilder::named("_bindgen_opaque_blob")
- .pub_()
- .build_ty(ty);
- fields.push(field);
- }
- None => {
- warn!("Opaque type without layout! Expect dragons!");
- }
- }
- }
-
- // C requires every struct to be addressable, so what C compilers do is
- // making the struct 1-byte sized.
- //
- // NOTE: This check is conveniently here to avoid the dummy fields we
- // may add for unused template parameters.
- if self.is_unsized(ctx) {
- let ty = BlobTyBuilder::new(Layout::new(1, 1)).build();
- let field = StructFieldBuilder::named("_address")
- .pub_()
- .build_ty(ty);
- fields.push(field);
- }
-
- // Append any extra template arguments that nobody has used so far.
- for (i, ty) in applicable_template_args.iter().enumerate() {
- if !template_args_used[i] {
- let name = ctx.resolve_type(*ty).name().unwrap();
- let ident = ctx.rust_ident(name);
- let prefix = ctx.trait_prefix();
- let phantom = quote_ty!(ctx.ext_cx(),
- ::$prefix::marker::PhantomData<$ident>);
- let field =
- StructFieldBuilder::named(format!("_phantom_{}", i))
- .pub_()
- .build_ty(phantom);
- fields.push(field)
- }
- }
-
-
- let mut generics = aster::AstBuilder::new().generics();
- for template_arg in applicable_template_args.iter() {
- // Take into account that here only arrive named types, not
- // template specialisations that would need to be
- // instantiated.
- //
- // TODO: Add template args from the parent, here and in
- // `to_rust_ty`!!
- let template_arg = ctx.resolve_type(*template_arg);
- generics = generics.ty_param_id(template_arg.name().unwrap());
- }
-
- let generics = generics.build();
-
- let rust_struct = builder.with_generics(generics.clone())
- .with_fields(fields)
- .build();
- result.push(rust_struct);
-
- // Generate the inner types and all that stuff.
- //
- // TODO: In the future we might want to be smart, and use nested
- // modules, and whatnot.
- for ty in self.inner_types() {
- let child_item = ctx.resolve_item(*ty);
- // assert_eq!(child_item.parent_id(), item.id());
- child_item.codegen(ctx, result, &());
- }
-
- // NOTE: Some unexposed attributes (like alignment attributes) may
- // affect layout, so we're bad and pray to the gods for avoid sending
- // all the tests to shit when parsing things like max_align_t.
- if self.found_unknown_attr() {
- warn!("Type {} has an unkown attribute that may affect layout",
- canonical_name);
- }
-
- if applicable_template_args.is_empty() && !self.found_unknown_attr() {
- for var in self.inner_vars() {
- ctx.resolve_item(*var).codegen(ctx, result, &());
- }
-
- if let Some(layout) = layout {
- let fn_name = format!("bindgen_test_layout_{}", canonical_name);
- let fn_name = ctx.rust_ident_raw(&fn_name);
- let ident = ctx.rust_ident_raw(&canonical_name);
- let prefix = ctx.trait_prefix();
- let size_of_expr = quote_expr!(ctx.ext_cx(),
- ::$prefix::mem::size_of::<$ident>());
- let align_of_expr = quote_expr!(ctx.ext_cx(),
- ::$prefix::mem::align_of::<$ident>());
- let size = layout.size;
- let align = layout.align;
- let item = quote_item!(ctx.ext_cx(),
- #[test]
- fn $fn_name() {
- assert_eq!($size_of_expr, $size);
- assert_eq!($align_of_expr, $align);
- })
- .unwrap();
- result.push(item);
- }
-
- let mut method_names = Default::default();
- for method in self.methods() {
- method.codegen_method(ctx,
- &mut methods,
- &mut method_names,
- result,
- item);
- }
- }
-
- // NB: We can't use to_rust_ty here since for opaque types this tries to
- // use the specialization knowledge to generate a blob field.
- let ty_for_impl =
- aster::AstBuilder::new().ty().path().id(&canonical_name).build();
- if needs_clone_impl {
- let impl_ = quote_item!(ctx.ext_cx(),
- impl X {
- fn clone(&self) -> Self { *self }
- }
- );
-
- let impl_ = match impl_.unwrap().node {
- ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(),
- _ => unreachable!(),
- };
-
- let clone_impl = aster::AstBuilder::new()
- .item()
- .impl_()
- .trait_()
- .id("Clone")
- .build()
- .with_generics(generics.clone())
- .with_items(impl_)
- .build_ty(ty_for_impl.clone());
-
- result.push(clone_impl);
- }
-
- if !methods.is_empty() {
- let methods = aster::AstBuilder::new()
- .item()
- .impl_()
- .with_generics(generics)
- .with_items(methods)
- .build_ty(ty_for_impl);
- result.push(methods);
- }
- }
-}
-
-trait MethodCodegen {
- fn codegen_method(&self,
- ctx: &BindgenContext,
- methods: &mut Vec<ast::ImplItem>,
- method_names: &mut HashMap<String, usize>,
- result: &mut CodegenResult,
- parent: &Item);
-}
-
-impl MethodCodegen for Method {
- fn codegen_method(&self,
- ctx: &BindgenContext,
- methods: &mut Vec<ast::ImplItem>,
- method_names: &mut HashMap<String, usize>,
- result: &mut CodegenResult,
- _parent: &Item) {
- if ctx.options().ignore_methods {
- return;
- }
-
- if self.is_virtual() {
- return; // FIXME
- }
- // First of all, output the actual function.
- ctx.resolve_item(self.signature()).codegen(ctx, result, &());
-
- let function_item = ctx.resolve_item(self.signature());
- let function = function_item.expect_function();
- let mut name = function.name().to_owned();
- let signature_item = ctx.resolve_item(function.signature());
- let signature = match *signature_item.expect_type().kind() {
- TypeKind::Function(ref sig) => sig,
- _ => panic!("How in the world?"),
- };
-
- let count = {
- let mut count = method_names.entry(name.clone())
- .or_insert(0);
- *count += 1;
- *count - 1
- };
-
- if count != 0 {
- name.push_str(&count.to_string());
- }
-
- let function_name = function_item.canonical_name(ctx);
- let mut fndecl = utils::rust_fndecl_from_signature(ctx, signature_item)
- .unwrap();
- if !self.is_static() {
- let mutability = if self.is_const() {
- ast::Mutability::Immutable
- } else {
- ast::Mutability::Mutable
- };
-
- assert!(!fndecl.inputs.is_empty());
-
- // FIXME: use aster here.
- fndecl.inputs[0] = ast::Arg {
- ty: P(ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ast::TyKind::Rptr(None, ast::MutTy {
- ty: P(ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: ast::TyKind::ImplicitSelf,
- span: ctx.span()
- }),
- mutbl: mutability,
- }),
- span: ctx.span(),
- }),
- pat: P(ast::Pat {
- id: ast::DUMMY_NODE_ID,
- node: ast::PatKind::Ident(
- ast::BindingMode::ByValue(ast::Mutability::Immutable),
- respan(ctx.span(), ctx.ext_cx().ident_of("self")),
- None
- ),
- span: ctx.span(),
- }),
- id: ast::DUMMY_NODE_ID,
- };
- }
-
- let sig = ast::MethodSig {
- unsafety: ast::Unsafety::Unsafe,
- abi: Abi::Rust,
- decl: P(fndecl.clone()),
- generics: ast::Generics::default(),
- constness: respan(ctx.span(), ast::Constness::NotConst),
- };
-
- // TODO: We need to keep in sync the argument names, so we should unify
- // this with the other loop that decides them.
- let mut unnamed_arguments = 0;
- let mut exprs = signature.argument_types()
- .iter()
- .map(|&(ref name, _ty)| {
- let arg_name = match *name {
- Some(ref name) => ctx.rust_mangle(name).into_owned(),
- None => {
- unnamed_arguments += 1;
- format!("arg{}", unnamed_arguments)
- }
- };
- aster::expr::ExprBuilder::new().id(arg_name)
- })
- .collect::<Vec<_>>();
-
- if !self.is_static() {
- assert!(!exprs.is_empty());
- exprs[0] = if self.is_const() {
- quote_expr!(ctx.ext_cx(), &*self)
- } else {
- quote_expr!(ctx.ext_cx(), &mut *self)
- };
- };
-
- let call = aster::expr::ExprBuilder::new()
- .call()
- .id(function_name)
- .with_args(exprs)
- .build();
-
- let block = ast::Block {
- stmts: vec![
- ast::Stmt {
- id: ast::DUMMY_NODE_ID,
- node: ast::StmtKind::Expr(call),
- span: ctx.span(),
- }
- ],
- id: ast::DUMMY_NODE_ID,
- rules: ast::BlockCheckMode::Default,
- span: ctx.span(),
- };
-
- let mut attrs = vec![];
- attrs.push(attributes::inline());
-
- let item = ast::ImplItem {
- id: ast::DUMMY_NODE_ID,
- ident: ctx.ext_cx().ident_of(&name),
- vis: ast::Visibility::Public,
- attrs: attrs,
- node: ast::ImplItemKind::Method(sig, P(block)),
- defaultness: ast::Defaultness::Final,
- span: ctx.span(),
- };
-
- methods.push(item);
- }
-}
-
-/// A helper type to construct enums, either bitfield ones or rust-style ones.
-enum EnumBuilder<'a> {
- Rust(aster::item::ItemEnumBuilder<aster::invoke::Identity>),
- Bitfield {
- canonical_name: &'a str,
- aster: P<ast::Item>,
- },
-}
-
-impl<'a> EnumBuilder<'a> {
- /// Create a new enum given an item builder, a canonical name, a name for
- /// the representation, and whether it should be represented as a rust enum.
- fn new(aster: aster::item::ItemBuilder<aster::invoke::Identity>,
- name: &'a str,
- repr_name: &str,
- is_rust: bool)
- -> Self {
- if is_rust {
- EnumBuilder::Rust(aster.enum_(name))
- } else {
- EnumBuilder::Bitfield {
- canonical_name: name,
- aster: aster.tuple_struct(name)
- .field()
- .pub_()
- .ty()
- .id(repr_name)
- .build(),
- }
- }
- }
-
- /// Add a variant to this enum.
- fn with_variant(self,
- ctx: &BindgenContext,
- variant: &EnumVariant,
- mangling_prefix: Option<&String>,
- rust_ty: P<ast::Ty>,
- result: &mut CodegenResult)
- -> Self {
- let variant_name = ctx.rust_mangle(variant.name());
- let expr = aster::AstBuilder::new().expr();
- let expr = match variant.val() {
- EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v),
- EnumVariantValue::Unsigned(v) => expr.uint(v),
- };
-
- match self {
- EnumBuilder::Rust(b) => {
- EnumBuilder::Rust(b.with_variant_(ast::Variant_ {
- name: ctx.rust_ident(&*variant_name),
- attrs: vec![],
- data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
- disr_expr: Some(expr),
- }))
- }
- EnumBuilder::Bitfield { canonical_name, .. } => {
- let constant_name = match mangling_prefix {
- Some(prefix) => {
- Cow::Owned(format!("{}_{}", prefix, variant_name))
- }
- None => variant_name,
- };
-
- let constant = aster::AstBuilder::new()
- .item()
- .pub_()
- .const_(&*constant_name)
- .expr()
- .call()
- .id(canonical_name)
- .arg()
- .build(expr)
- .build()
- .build(rust_ty);
- result.push(constant);
- self
- }
- }
- }
-
- fn build(self,
- ctx: &BindgenContext,
- rust_ty: P<ast::Ty>,
- result: &mut CodegenResult)
- -> P<ast::Item> {
- match self {
- EnumBuilder::Rust(b) => b.build(),
- EnumBuilder::Bitfield { canonical_name, aster } => {
- let rust_ty_name = ctx.rust_ident_raw(canonical_name);
- let prefix = ctx.trait_prefix();
-
- let impl_ = quote_item!(ctx.ext_cx(),
- impl ::$prefix::ops::BitOr<$rust_ty> for $rust_ty {
- type Output = Self;
-
- #[inline]
- fn bitor(self, other: Self) -> Self {
- $rust_ty_name(self.0 | other.0)
- }
- }
- )
- .unwrap();
-
- result.push(impl_);
- aster
- }
- }
- }
-}
-
-impl CodeGenerator for Enum {
- type Extra = Item;
-
- fn codegen(&self,
- ctx: &BindgenContext,
- result: &mut CodegenResult,
- item: &Item) {
- let name = item.canonical_name(ctx);
- let enum_ty = item.expect_type();
- let layout = enum_ty.layout(ctx);
-
- let repr = self.repr().map(|repr| ctx.resolve_type(repr));
- let repr = match repr {
- Some(repr) => {
- match *repr.canonical_type(ctx).kind() {
- TypeKind::Int(int_kind) => int_kind,
- _ => panic!("Unexpected type as enum repr"),
- }
- }
- None => {
- warn!("Guessing type of enum! Forward declarations of enums \
- shouldn't be legal!");
- IntKind::Int
- }
- };
-
- let signed = repr.is_signed();
- let size = layout.map(|l| l.size).unwrap_or(0);
- let repr_name = match (signed, size) {
- (true, 1) => "i8",
- (false, 1) => "u8",
- (true, 2) => "i16",
- (false, 2) => "u16",
- (true, 4) => "i32",
- (false, 4) => "u32",
- (true, 8) => "i64",
- (false, 8) => "u64",
- _ => {
- warn!("invalid enum decl: signed: {}, size: {}", signed, size);
- "i32"
- }
- };
-
- let mut builder = aster::AstBuilder::new().item().pub_();
-
- let is_bitfield = {
- ctx.options().bitfield_enums.matches(&name) ||
- (enum_ty.name().is_none() &&
- self.variants()
- .iter()
- .any(|v| ctx.options().bitfield_enums.matches(&v.name())))
- };
-
- let is_rust_enum = !is_bitfield;
-
- // FIXME: Rust forbids repr with empty enums. Remove this condition when
- // this is allowed.
- if is_rust_enum {
- if !self.variants().is_empty() {
- builder = builder.with_attr(attributes::repr(repr_name));
- }
- } else {
- builder = builder.with_attr(attributes::repr("C"));
- }
-
- if let Some(comment) = item.comment() {
- builder = builder.with_attr(attributes::doc(comment));
- }
-
- let derives = attributes::derives(&["Debug",
- "Copy",
- "Clone",
- "PartialEq",
- "Eq",
- "Hash"]);
-
- builder = builder.with_attr(derives);
-
- fn add_constant(enum_: &Type,
- // Only to avoid recomputing every time.
- enum_canonical_name: &str,
- // May be the same as "variant" if it's because the
- // enum is unnamed and we still haven't seen the value.
- variant_name: &str,
- referenced_name: &str,
- enum_rust_ty: P<ast::Ty>,
- result: &mut CodegenResult) {
- let constant_name = if enum_.name().is_some() {
- format!("{}_{}", enum_canonical_name, variant_name)
- } else {
- variant_name.into()
- };
-
- let constant = aster::AstBuilder::new()
- .item()
- .pub_()
- .const_(constant_name)
- .expr()
- .path()
- .ids(&[&*enum_canonical_name, referenced_name])
- .build()
- .build(enum_rust_ty);
- result.push(constant);
- }
-
- let mut builder =
- EnumBuilder::new(builder, &name, repr_name, is_rust_enum);
-
- // A map where we keep a value -> variant relation.
- let mut seen_values = HashMap::<_, String>::new();
- let enum_rust_ty = item.to_rust_ty(ctx);
- let is_toplevel = item.is_toplevel(ctx);
-
- // Used to mangle the constants we generate in the unnamed-enum case.
- let parent_canonical_name = if is_toplevel {
- None
- } else {
- Some(item.parent_id().canonical_name(ctx))
- };
-
- let constant_mangling_prefix = if enum_ty.name().is_none() {
- parent_canonical_name.as_ref().map(|n| &*n)
- } else {
- Some(&name)
- };
-
- for variant in self.variants().iter() {
- match seen_values.entry(variant.val()) {
- Entry::Occupied(ref entry) => {
- if is_rust_enum {
- let existing_variant_name = entry.get();
- let variant_name = ctx.rust_mangle(variant.name());
- add_constant(enum_ty,
- &name,
- &*variant_name,
- existing_variant_name,
- enum_rust_ty.clone(),
- result);
- } else {
- builder = builder.with_variant(ctx,
- variant,
- constant_mangling_prefix,
- enum_rust_ty.clone(),
- result);
- }
- }
- Entry::Vacant(entry) => {
- builder = builder.with_variant(ctx,
- variant,
- constant_mangling_prefix,
- enum_rust_ty.clone(),
- result);
-
- let variant_name = ctx.rust_mangle(variant.name());
-
- // If it's an unnamed enum, we also generate a constant so
- // it can be properly accessed.
- if is_rust_enum && enum_ty.name().is_none() {
- // NB: if we want to do this for other kind of nested
- // enums we can probably mangle the name.
- let mangled_name = if is_toplevel {
- variant_name.clone()
- } else {
- let parent_name = parent_canonical_name.as_ref()
- .unwrap();
-
- Cow::Owned(
- format!("{}_{}", parent_name, variant_name))
- };
-
- add_constant(enum_ty,
- &name,
- &mangled_name,
- &variant_name,
- enum_rust_ty.clone(),
- result);
- }
-
- entry.insert(variant_name.into_owned());
- }
- }
- }
-
- let enum_ = builder.build(ctx, enum_rust_ty, result);
- result.push(enum_);
- }
-}
-
-trait ToRustTy {
- type Extra;
-
- fn to_rust_ty(&self,
- ctx: &BindgenContext,
- extra: &Self::Extra)
- -> P<ast::Ty>;
-}
-
-trait ItemToRustTy {
- fn to_rust_ty(&self, ctx: &BindgenContext) -> P<ast::Ty>;
-}
-
-// Convenience implementation.
-impl ItemToRustTy for ItemId {
- fn to_rust_ty(&self, ctx: &BindgenContext) -> P<ast::Ty> {
- ctx.resolve_item(*self).to_rust_ty(ctx)
- }
-}
-
-impl ItemToRustTy for Item {
- fn to_rust_ty(&self, ctx: &BindgenContext) -> P<ast::Ty> {
- self.kind().expect_type().to_rust_ty(ctx, self)
- }
-}
-
-impl ToRustTy for Type {
- type Extra = Item;
-
- fn to_rust_ty(&self, ctx: &BindgenContext, item: &Item) -> P<ast::Ty> {
- use self::helpers::ast_ty::*;
-
- macro_rules! raw {
- ($ty: ident) => {
- raw_type(ctx, stringify!($ty))
- }
- }
- match *self.kind() {
- TypeKind::Void => raw!(c_void),
- // TODO: we should do something smart with nullptr, or maybe *const
- // c_void is enough?
- TypeKind::NullPtr => raw!(c_void).to_ptr(true, ctx.span()),
- TypeKind::Int(ik) => {
- match ik {
- IntKind::Bool => aster::ty::TyBuilder::new().bool(),
- IntKind::Char => raw!(c_char),
- IntKind::UChar => raw!(c_uchar),
- IntKind::Short => raw!(c_short),
- IntKind::UShort => raw!(c_ushort),
- IntKind::Int => raw!(c_int),
- IntKind::UInt => raw!(c_uint),
- IntKind::Long => raw!(c_long),
- IntKind::ULong => raw!(c_ulong),
- IntKind::LongLong => raw!(c_longlong),
- IntKind::ULongLong => raw!(c_ulonglong),
-
- IntKind::I8 => aster::ty::TyBuilder::new().i8(),
- IntKind::U8 => aster::ty::TyBuilder::new().u8(),
- IntKind::I16 => aster::ty::TyBuilder::new().i16(),
- IntKind::U16 => aster::ty::TyBuilder::new().u16(),
- IntKind::I32 => aster::ty::TyBuilder::new().i32(),
- IntKind::U32 => aster::ty::TyBuilder::new().u32(),
- IntKind::I64 => aster::ty::TyBuilder::new().i64(),
- IntKind::U64 => aster::ty::TyBuilder::new().u64(),
- IntKind::Custom { name, .. } => {
- let ident = ctx.rust_ident_raw(name);
- quote_ty!(ctx.ext_cx(), $ident)
- }
- // FIXME: This doesn't generate the proper alignment, but we
- // can't do better right now. We should be able to use
- // i128/u128 when they're available.
- IntKind::U128 | IntKind::I128 => {
- aster::ty::TyBuilder::new().array(2).u64()
- }
- }
- }
- TypeKind::Float(fk) => float_kind_rust_type(ctx, fk),
- TypeKind::Complex(fk) => {
- let float_path = float_kind_rust_type(ctx, fk);
-
- ctx.generated_bindegen_complex();
- quote_ty!(ctx.ext_cx(), __BindgenComplex<$float_path>)
- }
- TypeKind::Function(ref fs) => {
- let ty = fs.to_rust_ty(ctx, item);
- let prefix = ctx.trait_prefix();
- quote_ty!(ctx.ext_cx(), ::$prefix::option::Option<$ty>)
- }
- TypeKind::Array(item, len) => {
- let inner = item.to_rust_ty(ctx);
- aster::ty::TyBuilder::new().array(len).build(inner)
- }
- TypeKind::Enum(..) => {
- let path = item.canonical_path(ctx);
- aster::AstBuilder::new().ty().path().ids(path).build()
- }
- TypeKind::TemplateAlias(inner, ref template_args) |
- TypeKind::TemplateRef(inner, ref template_args) => {
- // PS: Sorry for the duplication here.
- let mut inner_ty = inner.to_rust_ty(ctx).unwrap();
-
- if let ast::TyKind::Path(_, ref mut path) = inner_ty.node {
- let template_args = template_args.iter()
- .map(|arg| arg.to_rust_ty(ctx))
- .collect();
-
- path.segments.last_mut().unwrap().parameters =
- ast::PathParameters::AngleBracketed(
- ast::AngleBracketedParameterData {
- lifetimes: vec![],
- types: P::from_vec(template_args),
- bindings: P::from_vec(vec![]),
- }
- );
- }
-
- P(inner_ty)
- }
- TypeKind::ResolvedTypeRef(inner) => inner.to_rust_ty(ctx),
- TypeKind::Alias(ref spelling, inner) => {
- if item.is_opaque(ctx) {
- // Pray if there's no available layout.
- let layout = self.layout(ctx).unwrap_or_else(Layout::zero);
- BlobTyBuilder::new(layout).build()
- } else if let Some(ty) = utils::type_from_named(ctx,
- spelling,
- inner) {
- ty
- } else {
- utils::build_templated_path(item, ctx, true)
- }
- }
- TypeKind::Comp(ref info) => {
- if item.is_opaque(ctx) || info.has_non_type_template_params() {
- return match self.layout(ctx) {
- Some(layout) => BlobTyBuilder::new(layout).build(),
- None => {
- warn!("Couldn't compute layout for a type with non \
- type template params or opaque, expect \
- dragons!");
- aster::AstBuilder::new().ty().unit()
- }
- };
- }
-
- utils::build_templated_path(item, ctx, false)
- }
- TypeKind::BlockPointer => {
- let void = raw!(c_void);
- void.to_ptr(/* is_const = */
- false,
- ctx.span())
- }
- TypeKind::Pointer(inner) |
- TypeKind::Reference(inner) => {
- let inner = ctx.resolve_item(inner);
- let inner_ty = inner.expect_type();
- let ty = inner.to_rust_ty(ctx);
-
- // Avoid the first function pointer level, since it's already
- // represented in Rust.
- if inner_ty.canonical_type(ctx).is_function() {
- ty
- } else {
- let is_const = self.is_const() ||
- inner.expect_type().is_const();
- ty.to_ptr(is_const, ctx.span())
- }
- }
- TypeKind::Named(..) => {
- let name = item.canonical_name(ctx);
- let ident = ctx.rust_ident(&name);
- quote_ty!(ctx.ext_cx(), $ident)
- }
- ref u @ TypeKind::UnresolvedTypeRef(..) => {
- unreachable!("Should have been resolved after parsing {:?}!", u)
- }
- }
- }
-}
-
-impl ToRustTy for FunctionSig {
- type Extra = Item;
-
- fn to_rust_ty(&self, ctx: &BindgenContext, _item: &Item) -> P<ast::Ty> {
- // TODO: we might want to consider ignoring the reference return value.
- let return_item = ctx.resolve_item(self.return_type());
- let ret =
- if let TypeKind::Void = *return_item.kind().expect_type().kind() {
- ast::FunctionRetTy::Default(ctx.span())
- } else {
- ast::FunctionRetTy::Ty(return_item.to_rust_ty(ctx))
- };
-
- let mut unnamed_arguments = 0;
- let arguments = self.argument_types().iter().map(|&(ref name, ty)| {
- let arg_item = ctx.resolve_item(ty);
- let arg_ty = arg_item.kind().expect_type();
-
- // From the C90 standard[1]:
- //
- // A declaration of a parameter as "array of type" shall be
- // adjusted to "qualified pointer to type", where the type
- // qualifiers (if any) are those specified within the [ and ] of
- // the array type derivation.
- //
- // [1]: http://c0x.coding-guidelines.com/6.7.5.3.html
- let arg_ty = if let TypeKind::Array(t, _) = *arg_ty.kind() {
- t.to_rust_ty(ctx).to_ptr(arg_ty.is_const(), ctx.span())
- } else {
- arg_item.to_rust_ty(ctx)
- };
-
- let arg_name = match *name {
- Some(ref name) => ctx.rust_mangle(name).into_owned(),
- None => {
- unnamed_arguments += 1;
- format!("arg{}", unnamed_arguments)
- }
- };
-
- assert!(!arg_name.is_empty());
-
- ast::Arg {
- ty: arg_ty,
- pat: aster::AstBuilder::new().pat().id(arg_name),
- id: ast::DUMMY_NODE_ID,
- }
- }).collect::<Vec<_>>();
-
- let decl = P(ast::FnDecl {
- inputs: arguments,
- output: ret,
- variadic: self.is_variadic(),
- });
-
- let fnty = ast::TyKind::BareFn(P(ast::BareFnTy {
- unsafety: ast::Unsafety::Unsafe,
- abi: self.abi(),
- lifetimes: vec![],
- decl: decl,
- }));
-
- P(ast::Ty {
- id: ast::DUMMY_NODE_ID,
- node: fnty,
- span: ctx.span(),
- })
- }
-}
-
-impl CodeGenerator for Function {
- type Extra = Item;
-
- fn codegen(&self,
- ctx: &BindgenContext,
- result: &mut CodegenResult,
- item: &Item) {
- let name = self.name();
- let mut canonical_name = item.canonical_name(ctx);
- let mangled_name = self.mangled_name();
-
- {
- let seen_symbol_name = mangled_name.unwrap_or(&canonical_name);
-
- // TODO: Maybe warn here if there's a type/argument mismatch, or
- // something?
- if result.seen_function(seen_symbol_name) {
- return;
- }
- result.saw_function(seen_symbol_name);
- }
-
- let signature_item = ctx.resolve_item(self.signature());
- let signature = signature_item.kind().expect_type();
- let signature = match *signature.kind() {
- TypeKind::Function(ref sig) => sig,
- _ => panic!("How?"),
- };
-
- let fndecl = utils::rust_fndecl_from_signature(ctx, signature_item);
-
- let mut attributes = vec![];
-
- if let Some(comment) = item.comment() {
- attributes.push(attributes::doc(comment));
- }
-
- if let Some(mangled) = mangled_name {
- attributes.push(attributes::link_name(mangled));
- } else if name != canonical_name {
- attributes.push(attributes::link_name(name));
- }
-
- let foreign_item_kind =
- ast::ForeignItemKind::Fn(fndecl, ast::Generics::default());
-
- // Handle overloaded functions by giving each overload its own unique
- // suffix.
- let times_seen = result.overload_number(&canonical_name);
- if times_seen > 0 {
- write!(&mut canonical_name, "{}", times_seen).unwrap();
- }
-
- let foreign_item = ast::ForeignItem {
- ident: ctx.rust_ident_raw(&canonical_name),
- attrs: attributes,
- node: foreign_item_kind,
- id: ast::DUMMY_NODE_ID,
- span: ctx.span(),
- vis: ast::Visibility::Public,
- };
-
- let item = ForeignModBuilder::new(signature.abi())
- .with_foreign_item(foreign_item)
- .build(ctx);
-
- result.push(item);
- }
-}
-
-// Return true if any of the ancestors of `id` are in the whitelisted items set,
-// false otherwise.
-fn ancestor_is_whitelisted(ctx: &BindgenContext,
- whitelisted_items: &ItemSet,
- id: ItemId)
- -> bool {
- let item = ctx.resolve_item(id);
- let mut last = id;
- let mut current = item.parent_id();
-
- while last != current {
- if whitelisted_items.contains(&current) {
- return true;
- }
- last = current;
- current = ctx.resolve_item(current).parent_id();
- }
-
- false
-}
-
-pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
- context.gen(|context| {
- let mut result = CodegenResult::new();
-
- debug!("codegen: {:?}", context.options());
-
- let whitelisted_items: ItemSet = context.whitelisted_items().collect();
-
- for &id in whitelisted_items.iter() {
- let item = context.resolve_item(id);
-
- // Non-toplevel items' parents are responsible one for generating
- // their children. However, if we find an orphaned reference to a
- // non-toplevel item whose parent is not in our whitelisted set, we
- // need to take responsibility for generating it.
- if item.is_toplevel(context) ||
- !ancestor_is_whitelisted(context, &whitelisted_items, id) {
- item.codegen(context, &mut result, &());
- }
- }
-
- let saw_union = result.saw_union;
- let mut result = result.items;
- if saw_union && !context.options().unstable_rust {
- utils::prepend_union_types(context, &mut result);
- }
- if context.need_bindegen_complex_type() {
- utils::prepend_complex_type(context, &mut result);
- }
- result
- })
-}
-
-mod utils {
- use aster;
- use ir::context::{BindgenContext, ItemId};
- use ir::item::{Item, ItemCanonicalPath};
- use ir::ty::TypeKind;
- use std::mem;
- use super::ItemToRustTy;
- use syntax::ast;
- use syntax::ptr::P;
-
- pub fn prepend_union_types(ctx: &BindgenContext,
- result: &mut Vec<P<ast::Item>>) {
- let prefix = ctx.trait_prefix();
-
- // TODO(emilio): The fmt::Debug impl could be way nicer with
- // std::intrinsics::type_name, but...
- let union_field_decl = quote_item!(ctx.ext_cx(),
- #[repr(C)]
- pub struct __BindgenUnionField<T>(
- ::$prefix::marker::PhantomData<T>);
- )
- .unwrap();
-
- let union_field_impl = quote_item!(&ctx.ext_cx(),
- impl<T> __BindgenUnionField<T> {
- #[inline]
- pub fn new() -> Self {
- __BindgenUnionField(::$prefix::marker::PhantomData)
- }
-
- #[inline]
- pub unsafe fn as_ref(&self) -> &T {
- ::$prefix::mem::transmute(self)
- }
-
- #[inline]
- pub unsafe fn as_mut(&mut self) -> &mut T {
- ::$prefix::mem::transmute(self)
- }
- }
- )
- .unwrap();
-
- let union_field_default_impl = quote_item!(&ctx.ext_cx(),
- impl<T> ::$prefix::default::Default for __BindgenUnionField<T> {
- #[inline]
- fn default() -> Self {
- Self::new()
- }
- }
- )
- .unwrap();
-
- let union_field_clone_impl = quote_item!(&ctx.ext_cx(),
- impl<T> ::$prefix::clone::Clone for __BindgenUnionField<T> {
- #[inline]
- fn clone(&self) -> Self {
- Self::new()
- }
- }
- )
- .unwrap();
-
- let union_field_copy_impl = quote_item!(&ctx.ext_cx(),
- impl<T> ::$prefix::marker::Copy for __BindgenUnionField<T> {}
- )
- .unwrap();
-
- let union_field_debug_impl = quote_item!(ctx.ext_cx(),
- impl<T> ::std::fmt::Debug for __BindgenUnionField<T> {
- fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
- -> ::std::fmt::Result {
- fmt.write_str("__BindgenUnionField")
- }
- }
- )
- .unwrap();
-
- let items = vec![
- union_field_decl, union_field_impl,
- union_field_default_impl,
- union_field_clone_impl,
- union_field_copy_impl,
- union_field_debug_impl,
- ];
-
- let old_items = mem::replace(result, items);
- result.extend(old_items.into_iter());
- }
-
- pub fn prepend_complex_type(ctx: &BindgenContext,
- result: &mut Vec<P<ast::Item>>) {
- let complex_type = quote_item!(ctx.ext_cx(),
- #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
- #[repr(C)]
- pub struct __BindgenComplex<T> {
- pub re: T,
- pub im: T
- }
- )
- .unwrap();
-
- let items = vec![complex_type];
- let old_items = mem::replace(result, items);
- result.extend(old_items.into_iter());
- }
-
- pub fn build_templated_path(item: &Item,
- ctx: &BindgenContext,
- only_named: bool)
- -> P<ast::Ty> {
- let path = item.canonical_path(ctx);
-
- let builder = aster::AstBuilder::new().ty().path();
- let template_args = if only_named {
- item.applicable_template_args(ctx)
- .iter()
- .filter(|arg| ctx.resolve_type(**arg).is_named())
- .map(|arg| arg.to_rust_ty(ctx))
- .collect::<Vec<_>>()
- } else {
- item.applicable_template_args(ctx)
- .iter()
- .map(|arg| arg.to_rust_ty(ctx))
- .collect::<Vec<_>>()
- };
-
- // XXX: I suck at aster.
- if path.len() == 1 {
- return builder.segment(&path[0])
- .with_tys(template_args)
- .build()
- .build();
- }
-
- let mut builder = builder.id(&path[0]);
- for (i, segment) in path.iter().skip(1).enumerate() {
- // Take into account the skip(1)
- builder = if i == path.len() - 2 {
- // XXX Extra clone courtesy of the borrow checker.
- builder.segment(&segment)
- .with_tys(template_args.clone())
- .build()
- } else {
- builder.segment(&segment).build()
- }
- }
-
- builder.build()
- }
-
- fn primitive_ty(ctx: &BindgenContext, name: &str) -> P<ast::Ty> {
- let ident = ctx.rust_ident_raw(&name);
- quote_ty!(ctx.ext_cx(), $ident)
- }
-
- pub fn type_from_named(ctx: &BindgenContext,
- name: &str,
- _inner: ItemId)
- -> Option<P<ast::Ty>> {
- // FIXME: We could use the inner item to check this is really a
- // primitive type but, who the heck overrides these anyway?
- macro_rules! ty {
- ($which:ident) => {{
- primitive_ty(ctx, stringify!($which))
- }}
- }
- Some(match name {
- "int8_t" => ty!(i8),
- "uint8_t" => ty!(u8),
- "int16_t" => ty!(i16),
- "uint16_t" => ty!(u16),
- "int32_t" => ty!(i32),
- "uint32_t" => ty!(u32),
- "int64_t" => ty!(i64),
- "uint64_t" => ty!(u64),
-
- "uintptr_t" | "size_t" => ty!(usize),
-
- "intptr_t" | "ptrdiff_t" | "ssize_t" => ty!(isize),
- _ => return None,
- })
- }
-
- pub fn rust_fndecl_from_signature(ctx: &BindgenContext,
- sig: &Item)
- -> P<ast::FnDecl> {
- use codegen::ToRustTy;
-
- let signature = sig.kind().expect_type();
- let signature = match *signature.kind() {
- TypeKind::Function(ref sig) => sig,
- _ => panic!("How?"),
- };
-
- let decl_ty = signature.to_rust_ty(ctx, sig);
- match decl_ty.unwrap().node {
- ast::TyKind::BareFn(bare_fn) => bare_fn.unwrap().decl,
- _ => panic!("How did this happen exactly?"),
- }
- }
-}
diff --git a/src/ir/annotations.rs b/src/ir/annotations.rs
deleted file mode 100644
index 58308d6d..00000000
--- a/src/ir/annotations.rs
+++ /dev/null
@@ -1,157 +0,0 @@
-//! 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,
-}
-
-/// Annotations for a given item, or a field.
-#[derive(Clone, PartialEq, Debug)]
-pub struct Annotations {
- /// Whether this item is marked as opaque. Only applies to types.
- opaque: bool,
- /// Whether this item should be hidden from the output. Only applies to
- /// types.
- hide: bool,
- /// Whether this type should be replaced by another. The name must be the
- /// canonical name that that type would get.
- use_instead_of: Option<String>,
- /// Manually disable deriving copy/clone on this type. Only applies to
- /// struct or union types.
- disallow_copy: bool,
- /// Whether fields should be marked as private or not. You can set this on
- /// structs (it will apply to all the fields), or individual fields.
- private_fields: Option<bool>,
- /// The kind of accessor this field will have. Also can be applied to
- /// structs so all the fields inside share it by default.
- accessor_kind: Option<FieldAccessorKind>,
-}
-
-fn parse_accessor(s: &str) -> FieldAccessorKind {
- match s {
- "false" => FieldAccessorKind::None,
- "unsafe" => FieldAccessorKind::Unsafe,
- "immutable" => FieldAccessorKind::Immutable,
- _ => FieldAccessorKind::Regular,
- }
-}
-
-impl Default for Annotations {
- fn default() -> Self {
- Annotations {
- opaque: false,
- hide: false,
- use_instead_of: None,
- disallow_copy: false,
- private_fields: None,
- accessor_kind: None,
- }
- }
-}
-
-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;
- anno.parse(&cursor.comment(), &mut matched_one);
-
- if matched_one { Some(anno) } else { None }
- }
-
- /// Should this type be hidden?
- pub fn hide(&self) -> bool {
- self.hide
- }
-
- /// Should this type be opaque?
- pub fn opaque(&self) -> bool {
- self.opaque
- }
-
- /// For a given type, indicates the type it should replace.
- ///
- /// For example, in the following code:
- ///
- /// ```cpp
- ///
- /// /** <div rustbindgen replaces="Bar"></div> */
- /// struct Foo { int x; };
- ///
- /// struct Bar { char foo; };
- /// ```
- ///
- /// the generated code would look something like:
- ///
- /// ```
- /// /** <div rustbindgen replaces="Bar"></div> */
- /// struct Bar {
- /// x: ::std::os::raw::c_int,
- /// };
- /// ```
- ///
- /// That is, code for `Foo` is used to generate `Bar`.
- pub fn use_instead_of(&self) -> Option<&str> {
- 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
- }
-
- fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) {
- use clangll::CXComment_HTMLStartTag;
- if comment.kind() == CXComment_HTMLStartTag &&
- comment.get_tag_name() == "div" &&
- comment.get_tag_attrs()
- .next()
- .map_or(false, |attr| attr.name == "rustbindgen") {
- *matched = true;
- for attr in comment.get_tag_attrs() {
- match attr.name.as_str() {
- "opaque" => self.opaque = true,
- "hide" => self.hide = true,
- "nocopy" => self.disallow_copy = true,
- "replaces" => self.use_instead_of = Some(attr.value),
- "private" => {
- self.private_fields = Some(attr.value != "false")
- }
- "accessor" => {
- self.accessor_kind = Some(parse_accessor(&attr.value))
- }
- _ => {}
- }
- }
- }
-
- for child in comment.get_children() {
- self.parse(&child, matched);
- }
- }
-}
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
deleted file mode 100644
index d19d1209..00000000
--- a/src/ir/comp.rs
+++ /dev/null
@@ -1,871 +0,0 @@
-//! Compound types (unions and structs) in our intermediate representation.
-
-use clang;
-use parse::{ClangItemParser, ParseError};
-use std::cell::Cell;
-use std::cmp;
-use super::annotations::Annotations;
-use super::context::{BindgenContext, ItemId};
-use super::item::Item;
-use super::layout::Layout;
-use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type};
-use super::type_collector::{ItemSet, TypeCollector};
-
-/// 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,
-}
-
-/// A struct representing a C++ method, either static, normal, or virtual.
-#[derive(Debug)]
-pub struct Method {
- kind: MethodKind,
- /// The signature of the method. Take into account this is not a `Type`
- /// item, but a `Function` one.
- ///
- /// This is tricky and probably this field should be renamed.
- signature: ItemId,
- is_const: bool,
-}
-
-impl Method {
- /// Construct a new `Method`.
- fn new(kind: MethodKind, signature: ItemId, is_const: bool) -> Self {
- Method {
- kind: kind,
- signature: signature,
- is_const: is_const,
- }
- }
-
- /// 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
- }
-}
-
-/// A struct representing a C++ field.
-#[derive(Clone, Debug)]
-pub struct Field {
- /// The name of the field, empty if it's an unnamed bitfield width.
- name: Option<String>,
- /// The inner type.
- ty: ItemId,
- /// The doc comment on the field if any.
- comment: Option<String>,
- /// Annotations for this field, or the default.
- annotations: Annotations,
- /// If this field is a bitfield, and how many bits does it contain if it is.
- bitfield: Option<u32>,
- /// If the C++ field is marked as `mutable`
- mutable: bool,
-}
-
-impl Field {
- /// Construct a new `Field`.
- pub fn new(name: Option<String>,
- ty: ItemId,
- comment: Option<String>,
- annotations: Option<Annotations>,
- bitfield: Option<u32>,
- mutable: bool)
- -> Field {
- Field {
- name: name,
- ty: ty,
- comment: comment,
- annotations: annotations.unwrap_or_default(),
- bitfield: bitfield,
- mutable: mutable,
- }
- }
-
- /// 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 {
- /// typedef int FooTy;
- /// struct Bar {
- /// int baz;
- /// };
- /// }
- ///
- /// 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.
- ///
- /// 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,
- fields: vec![],
- template_args: vec![],
- methods: vec![],
- base_members: vec![],
- ref_template: None,
- inner_types: vec![],
- inner_vars: vec![],
- has_vtable: false,
- has_destructor: false,
- has_nonempty_base: false,
- has_non_type_template_params: false,
- packed: false,
- is_anonymous: false,
- found_unknown_attr: false,
- detect_derive_debug_cycle: Cell::new(false),
- detect_has_destructor_cycle: Cell::new(false),
- }
- }
-
- /// 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.
- if self.detect_derive_debug_cycle.get() {
- warn!("Derive debug cycle detected!");
- return true;
- }
-
- if self.kind == CompKind::Union {
- if ctx.options().unstable_rust {
- return false;
- }
-
- let layout = layout.unwrap_or_else(Layout::zero);
- let size_divisor = cmp::max(1, layout.align);
- return layout.size / size_divisor <= RUST_DERIVE_IN_ARRAY_LIMIT;
- }
-
- self.detect_derive_debug_cycle.set(true);
-
- let can_derive_debug = {
- self.base_members
- .iter()
- .all(|ty| ctx.resolve_type(*ty).can_derive_debug(ctx)) &&
- self.template_args
- .iter()
- .all(|ty| ctx.resolve_type(*ty).can_derive_debug(ctx)) &&
- self.fields
- .iter()
- .all(|f| ctx.resolve_type(f.ty).can_derive_debug(ctx)) &&
- self.ref_template.map_or(true, |template| {
- ctx.resolve_type(template).can_derive_debug(ctx)
- })
- };
-
- self.detect_derive_debug_cycle.set(false);
-
- 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| {
- ctx.resolve_type(*base).canonical_type(ctx).is_unsized(ctx)
- }) &&
- self.ref_template
- .map_or(true, |template| ctx.resolve_type(template).is_unsized(ctx))
- }
-
- /// 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");
- // Assume no destructor, since we don't have an explicit one.
- return false;
- }
-
- self.detect_has_destructor_cycle.set(true);
-
- let has_destructor = self.has_destructor ||
- match self.kind {
- CompKind::Union => false,
- CompKind::Struct => {
- // NB: We can't rely on a type with type parameters
- // not having destructor.
- //
- // This is unfortunate, but...
- self.ref_template.as_ref().map_or(false, |t| {
- ctx.resolve_type(*t).has_destructor(ctx)
- }) ||
- self.template_args
- .iter()
- .any(|t| ctx.resolve_type(*t).has_destructor(ctx)) ||
- self.base_members
- .iter()
- .any(|t| ctx.resolve_type(*t).has_destructor(ctx)) ||
- self.fields.iter().any(|field| {
- ctx.resolve_type(field.ty)
- .has_destructor(ctx)
- })
- }
- };
-
- self.detect_has_destructor_cycle.set(false);
-
- 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
- // defer this check just for the union case.
- if self.has_destructor(ctx) {
- return false;
- }
-
- if self.kind == CompKind::Union {
- if !ctx.options().unstable_rust {
- return true;
- }
-
- // https://github.com/rust-lang/rust/issues/36640
- if !self.template_args.is_empty() || self.ref_template.is_some() ||
- !item.applicable_template_args(ctx).is_empty() {
- return false;
- }
- }
-
- // With template args, use a safe subset of the types,
- // since copyability depends on the types itself.
- self.ref_template
- .as_ref()
- .map_or(true, |t| ctx.resolve_item(*t).can_derive_copy(ctx)) &&
- self.base_members
- .iter()
- .all(|t| ctx.resolve_item(*t).can_derive_copy(ctx)) &&
- self.fields.iter().all(|field| {
- ctx.resolve_item(field.ty)
- .can_derive_copy(ctx)
- })
- }
-
- /// 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
- }
-
- /// 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;
-
- // We can't do better than clang here, sorry.
- if self.kind == CompKind::Struct {
- return None;
- }
-
- let mut max_size = 0;
- let mut max_align = 0;
- for field in &self.fields {
- let field_layout = ctx.resolve_type(field.ty)
- .layout(ctx);
-
- if let Some(layout) = field_layout {
- max_size = cmp::max(max_size, layout.size);
- max_align = cmp::max(max_align, layout.align);
- }
- }
-
- 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.resolve_type(*base)
- .has_vtable(ctx)
- }) ||
- self.ref_template.map_or(false, |template| {
- ctx.resolve_type(template).has_vtable(ctx)
- })
- }
-
- /// 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>,
- ctx: &mut BindgenContext)
- -> Result<Self, ParseError> {
- use clangll::*;
- // Sigh... For class templates we want the location, for
- // specialisations, we want the declaration... So just try both.
- //
- // TODO: Yeah, this code reads really bad.
- let mut cursor = ty.declaration();
- let mut kind = Self::kind_from_cursor(&cursor);
- if kind.is_err() {
- if let Some(location) = location {
- kind = Self::kind_from_cursor(&location);
- cursor = location;
- }
- }
-
- let kind = try!(kind);
-
- debug!("CompInfo::from_ty({:?}, {:?})", kind, cursor);
-
- let mut ci = CompInfo::new(kind);
- ci.is_anonymous = cursor.is_anonymous();
- ci.template_args = match ty.template_args() {
- // In forward declarations and not specializations,
- // etc, they are in
- // the ast, we'll meet them in
- // CXCursor_TemplateTypeParameter
- None => vec![],
- Some(arg_types) => {
- let num_arg_types = arg_types.len();
-
- let args = arg_types.filter(|t| t.kind() != CXType_Invalid)
- .map(|t| Item::from_ty_or_ref(t, None, None, ctx))
- .collect::<Vec<_>>();
-
- if args.len() != num_arg_types {
- ci.has_non_type_template_params = true;
- warn!("warning: Template parameter is not a type");
- }
-
- args
- }
- };
-
- ci.ref_template = cursor.specialized()
- .and_then(|c| Item::parse(c, None, ctx).ok());
-
- let mut maybe_anonymous_struct_field = None;
- cursor.visit(|cur| {
- if cur.kind() != CXCursor_FieldDecl {
- if let Some((ty, _)) = maybe_anonymous_struct_field {
- let field = Field::new(None, ty, None, None, None, false);
- ci.fields.push(field);
- }
- maybe_anonymous_struct_field = None;
- }
-
- match cur.kind() {
- CXCursor_FieldDecl => {
- match maybe_anonymous_struct_field.take() {
- Some((ty, clang_ty)) => {
- let mut used = false;
- cur.visit(|child| {
- if child.cur_type() == clang_ty {
- used = true;
- }
- CXChildVisit_Continue
- });
- if !used {
- let field = Field::new(None,
- ty,
- None,
- None,
- None,
- false);
- ci.fields.push(field);
- }
- }
- None => {}
- }
-
- let bit_width = cur.bit_width();
- let field_type = Item::from_ty_or_ref(cur.cur_type(),
- Some(cur),
- Some(potential_id),
- ctx);
-
- let comment = cur.raw_comment();
- let annotations = Annotations::new(&cur);
- let name = cur.spelling();
- let is_mutable = cursor.is_mutable_field();
-
- // Name can be empty if there are bitfields, for example,
- // see tests/headers/struct_with_bitfields.h
- assert!(!name.is_empty() || bit_width.is_some(),
- "Empty field name?");
-
- let name = if name.is_empty() { None } else { Some(name) };
-
- let field = Field::new(name,
- field_type,
- comment,
- annotations,
- bit_width,
- is_mutable);
- ci.fields.push(field);
-
- // No we look for things like attributes and stuff.
- cur.visit(|cur| {
- if cur.kind() == CXCursor_UnexposedAttr {
- ci.found_unknown_attr = true;
- }
- CXChildVisit_Continue
- });
-
- }
- CXCursor_UnexposedAttr => {
- ci.found_unknown_attr = true;
- }
- CXCursor_EnumDecl |
- CXCursor_TypeAliasDecl |
- CXCursor_TypedefDecl |
- CXCursor_StructDecl |
- CXCursor_UnionDecl |
- CXCursor_ClassTemplate |
- CXCursor_ClassDecl => {
- let inner = Item::parse(cur, Some(potential_id), ctx)
- .expect("Inner ClassDecl");
- if !ci.inner_types.contains(&inner) {
- ci.inner_types.push(inner);
- }
- // A declaration of an union or a struct without name could
- // also be an unnamed field, unfortunately.
- if cur.spelling().is_empty() &&
- cur.kind() != CXCursor_EnumDecl {
- let ty = cur.cur_type();
- maybe_anonymous_struct_field = Some((inner, ty));
- }
- }
- CXCursor_PackedAttr => {
- ci.packed = true;
- }
- CXCursor_TemplateTypeParameter => {
- // Yes! You can arrive here with an empty template parameter
- // name! Awesome, isn't it?
- //
- // see tests/headers/empty_template_param_name.hpp
- if cur.spelling().is_empty() {
- return CXChildVisit_Continue;
- }
-
- let default_type = Item::from_ty(&cur.cur_type(),
- Some(cur),
- Some(potential_id),
- ctx)
- .ok();
- let param = Item::named_type(cur.spelling(),
- default_type,
- potential_id,
- ctx);
- ci.template_args.push(param);
- }
- CXCursor_CXXBaseSpecifier => {
- if !ci.has_vtable {
- ci.has_vtable = cur.is_virtual_base();
- }
- let type_id =
- Item::from_ty(&cur.cur_type(), Some(cur), None, ctx)
- .expect("BaseSpecifier");
- ci.base_members.push(type_id);
- }
- CXCursor_CXXMethod => {
- let is_virtual = cur.method_is_virtual();
- let is_static = cur.method_is_static();
- debug_assert!(!(is_static && is_virtual), "How?");
-
- if !ci.has_vtable {
- ci.has_vtable = is_virtual;
- }
-
- let linkage = cur.linkage();
- if linkage != CXLinkage_External {
- return CXChildVisit_Continue;
- }
-
- if cur.access_specifier() == CX_CXXPrivate {
- return CXChildVisit_Continue;
- }
-
- let visibility = cur.visibility();
- if visibility != CXVisibility_Default {
- return CXChildVisit_Continue;
- }
-
- if cur.is_inlined_function() {
- return CXChildVisit_Continue;
- }
-
- let spelling = cur.spelling();
- if spelling.starts_with("operator") {
- return CXChildVisit_Continue;
- }
-
- // This used to not be here, but then I tried generating
- // stylo bindings with this (without path filters), and
- // cried a lot with a method in gfx/Point.h
- // (ToUnknownPoint), that somehow was causing the same type
- // to be inserted in the map two times.
- //
- // I couldn't make a reduced test case, but anyway...
- // Methods of template functions not only use to be inlined,
- // but also instantiated, and we wouldn't be able to call
- // them, so just bail out.
- if !ci.template_args.is_empty() {
- return CXChildVisit_Continue;
- }
-
- // NB: This gets us an owned `Function`, not a
- // `FunctionSig`.
- let method_signature =
- Item::parse(cur, Some(potential_id), ctx)
- .expect("CXXMethod");
-
- let is_const = cur.method_is_const();
- let method_kind = if is_static {
- MethodKind::Static
- } else if is_virtual {
- MethodKind::Virtual
- } else {
- MethodKind::Normal
- };
-
- let method =
- Method::new(method_kind, method_signature, is_const);
-
- ci.methods.push(method);
- }
- CXCursor_Destructor => {
- if cur.method_is_virtual() {
- // FIXME: Push to the method list?
- ci.has_vtable = true;
- }
- ci.has_destructor = true;
- }
- CXCursor_NonTypeTemplateParameter => {
- ci.has_non_type_template_params = true;
- }
- CXCursor_VarDecl => {
- let linkage = cur.linkage();
- if linkage != CXLinkage_External &&
- linkage != CXLinkage_UniqueExternal {
- return CXChildVisit_Continue;
- }
-
- let visibility = cur.visibility();
- if visibility != CXVisibility_Default {
- return CXChildVisit_Continue;
- }
-
- let item = Item::parse(cur, Some(potential_id), ctx)
- .expect("VarDecl");
- ci.inner_vars.push(item);
- }
- // Intentionally not handled
- CXCursor_CXXAccessSpecifier |
- CXCursor_CXXFinalAttr |
- CXCursor_Constructor |
- CXCursor_FunctionTemplate |
- CXCursor_ConversionFunction => {}
- _ => {
- warn!("unhandled comp member `{}` (kind {}) in `{}` ({})",
- cur.spelling(),
- cur.kind(),
- cursor.spelling(),
- cur.location());
- }
- }
- CXChildVisit_Continue
- });
-
- if let Some((ty, _)) = maybe_anonymous_struct_field {
- let field = Field::new(None, ty, None, None, None, false);
- ci.fields.push(field);
- }
-
- Ok(ci)
- }
-
- fn kind_from_cursor(cursor: &clang::Cursor)
- -> Result<CompKind, ParseError> {
- use clangll::*;
- Ok(match cursor.kind() {
- CXCursor_UnionDecl => CompKind::Union,
- CXCursor_ClassDecl |
- CXCursor_StructDecl => CompKind::Struct,
- CXCursor_CXXBaseSpecifier |
- CXCursor_ClassTemplatePartialSpecialization |
- CXCursor_ClassTemplate => {
- match cursor.template_kind() {
- CXCursor_UnionDecl => CompKind::Union,
- _ => CompKind::Struct,
- }
- }
- _ => {
- warn!("Unknown kind for comp type: {:?}", cursor);
- return Err(ParseError::Continue);
- }
- })
- }
-
- /// 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 {
- // We don't generate these, so rather don't make the codegen step to
- // think we got it covered.
- if self.has_non_type_template_params() {
- return false;
- }
- self.template_args.iter().any(|arg| {
- ctx.resolve_type(*arg)
- .signature_contains_named_type(ctx, ty)
- })
- }
-
- /// 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
- }
-
- /// Returns whether this type needs an explicit vtable because it has
- /// virtual methods and none of its base classes has already a vtable.
- pub fn needs_explicit_vtable(&self, ctx: &BindgenContext) -> bool {
- self.has_vtable(ctx) &&
- !self.base_members.iter().any(|base| {
- // NB: Ideally, we could rely in all these types being `comp`, and
- // life would be beautiful.
- //
- // Unfortunately, given the way we implement --match-pat, and also
- // that you can inherit from templated types, we need to handle
- // other cases here too.
- ctx.resolve_type(*base)
- .canonical_type(ctx)
- .as_comp()
- .map_or(false, |ci| ci.has_vtable(ctx))
- })
- }
-}
-
-impl TypeCollector for CompInfo {
- type Extra = Item;
-
- fn collect_types(&self,
- context: &BindgenContext,
- types: &mut ItemSet,
- item: &Item) {
- if let Some(template) = self.specialized_template() {
- types.insert(template);
- }
-
- let applicable_template_args = item.applicable_template_args(context);
- for arg in applicable_template_args {
- types.insert(arg);
- }
-
- for &base in self.base_members() {
- types.insert(base);
- }
-
- for field in self.fields() {
- types.insert(field.ty());
- }
-
- for &ty in self.inner_types() {
- types.insert(ty);
- }
-
- // FIXME(emilio): Methods, VTable?
- }
-}
diff --git a/src/ir/context.rs b/src/ir/context.rs
deleted file mode 100644
index 85721978..00000000
--- a/src/ir/context.rs
+++ /dev/null
@@ -1,1055 +0,0 @@
-//! Common context that is passed around during parsing and codegen.
-
-use BindgenOptions;
-use cexpr;
-use clang::{self, Cursor};
-use parse::ClangItemParser;
-use std::borrow::Cow;
-use std::cell::Cell;
-use std::collections::{HashMap, hash_map};
-use std::collections::btree_map::{self, BTreeMap};
-use std::fmt;
-use super::int::IntKind;
-use super::item::{Item, ItemCanonicalName};
-use super::item_kind::ItemKind;
-use super::module::Module;
-use super::ty::{FloatKind, Type, TypeKind};
-use super::type_collector::{ItemSet, TypeCollector};
-use syntax::ast::Ident;
-use syntax::codemap::{DUMMY_SP, Span};
-use syntax::ext::base::ExtCtxt;
-
-/// A single identifier for an item.
-///
-/// TODO: Build stronger abstractions on top of this, like TypeId(ItemId)?
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct ItemId(usize);
-
-impl ItemId {
- /// Get a numeric representation of this id.
- pub fn as_usize(&self) -> usize {
- self.0
- }
-}
-
-/// A key used to index a resolved type, so we only process it once.
-///
-/// This is almost always a USR string (an unique identifier generated by
-/// clang), but it can also be the canonical declaration if the type is unnamed,
-/// in which case clang may generate the same USR for multiple nested unnamed
-/// types.
-#[derive(Eq, PartialEq, Hash, Debug)]
-enum TypeKey {
- USR(String),
- Declaration(Cursor),
-}
-
-// This is just convenience to avoid creating a manual debug impl for the
-// context.
-struct GenContext<'ctx>(ExtCtxt<'ctx>);
-
-impl<'ctx> fmt::Debug for GenContext<'ctx> {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- write!(fmt, "GenContext {{ ... }}")
- }
-}
-
-/// A context used during parsing and generation of structs.
-#[derive(Debug)]
-pub struct BindgenContext<'ctx> {
- /// The map of all the items parsed so far.
- ///
- /// It's a BTreeMap because we want the keys to be sorted to have consistent
- /// output.
- items: BTreeMap<ItemId, Item>,
-
- /// The next item id to use during this bindings regeneration.
- next_item_id: ItemId,
-
- /// Clang USR to type map. This is needed to be able to associate types with
- /// item ids during parsing.
- types: HashMap<TypeKey, ItemId>,
-
- /// A cursor to module map. Similar reason than above.
- modules: HashMap<Cursor, ItemId>,
-
- /// The root module, this is guaranteed to be an item of kind Module.
- root_module: ItemId,
-
- /// Current module being traversed.
- current_module: ItemId,
-
- /// A stack with the current type declarations and types we're parsing. This
- /// is needed to avoid infinite recursion when parsing a type like:
- ///
- /// struct c { struct c* next; };
- ///
- /// This means effectively, that a type has a potential ID before knowing if
- /// it's a correct type. But that's not important in practice.
- ///
- /// We could also use the `types` HashMap, but my intention with it is that
- /// only valid types and declarations end up there, and this could
- /// potentially break that assumption.
- ///
- /// FIXME: Should not be public, though... meh.
- pub currently_parsed_types: Vec<(Cursor, ItemId)>,
-
- /// A HashSet with all the already parsed macro names. This is done to avoid
- /// hard errors while parsing duplicated macros, as well to allow macro
- /// expression parsing.
- parsed_macros: HashMap<Vec<u8>, cexpr::expr::EvalResult>,
-
- /// The active replacements collected from replaces="xxx" annotations.
- replacements: HashMap<String, ItemId>,
-
- collected_typerefs: bool,
-
- /// Dummy structures for code generation.
- gen_ctx: Option<&'ctx GenContext<'ctx>>,
- span: Span,
-
- /// The clang index for parsing.
- index: clang::Index,
-
- /// The translation unit for parsing.
- translation_unit: clang::TranslationUnit,
-
- /// The options given by the user via cli or other medium.
- options: BindgenOptions,
-
- /// Whether a bindgen complex was generated
- generated_bindegen_complex: Cell<bool>,
-}
-
-impl<'ctx> BindgenContext<'ctx> {
- /// Construct the context for the given `options`.
- pub fn new(options: BindgenOptions) -> Self {
- use clangll;
-
- let index = clang::Index::new(false, true);
-
- let parse_options =
- clangll::CXTranslationUnit_DetailedPreprocessingRecord;
- let translation_unit =
- clang::TranslationUnit::parse(&index,
- "",
- &options.clang_args,
- &[],
- parse_options)
- .expect("TranslationUnit::parse");
-
- let root_module = Self::build_root_module(ItemId(0));
- let mut me = BindgenContext {
- items: Default::default(),
- types: Default::default(),
- modules: Default::default(),
- next_item_id: ItemId(1),
- root_module: root_module.id(),
- current_module: root_module.id(),
- currently_parsed_types: vec![],
- parsed_macros: Default::default(),
- replacements: Default::default(),
- collected_typerefs: false,
- gen_ctx: None,
- span: DUMMY_SP,
- index: index,
- translation_unit: translation_unit,
- options: options,
- generated_bindegen_complex: Cell::new(false),
- };
-
- me.add_item(root_module, None, None);
-
- 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>,
- location: Option<Cursor>) {
- use clangll::{CXCursor_ClassTemplate,
- CXCursor_ClassTemplatePartialSpecialization};
- debug!("BindgenContext::add_item({:?}, declaration: {:?}, loc: {:?}",
- item,
- declaration,
- location);
- debug_assert!(declaration.is_some() || !item.kind().is_type() ||
- item.kind().expect_type().is_builtin_or_named(),
- "Adding a type without declaration?");
-
- let id = item.id();
- let is_type = item.kind().is_type();
- let is_unnamed = is_type && item.expect_type().name().is_none();
- let old_item = self.items.insert(id, item);
- assert!(old_item.is_none(), "Inserted type twice?");
-
- // Unnamed items can have an USR, but they can't be referenced from
- // other sites explicitly and the USR can match if the unnamed items are
- // nested, so don't bother tracking them.
- if is_type && declaration.is_some() {
- let mut declaration = declaration.unwrap();
- if !declaration.is_valid() {
- if let Some(location) = location {
- if location.kind() == CXCursor_ClassTemplate ||
- location.kind() ==
- CXCursor_ClassTemplatePartialSpecialization {
- declaration = location;
- }
- }
- }
- declaration = declaration.canonical();
- if !declaration.is_valid() {
- // This could happen, for example, with types like `int*` or
- // similar.
- //
- // Fortunately, we don't care about those types being
- // duplicated, so we can just ignore them.
- debug!("Invalid declaration {:?} found for type {:?}",
- declaration,
- self.items.get(&id).unwrap().kind().expect_type());
- return;
- }
-
- let key = if is_unnamed {
- TypeKey::Declaration(declaration)
- } else if let Some(usr) = declaration.usr() {
- TypeKey::USR(usr)
- } else {
- error!("Valid declaration with no USR: {:?}, {:?}",
- declaration,
- location);
- return;
- };
-
- let old = self.types.insert(key, id);
- debug_assert_eq!(old, None);
- }
- }
-
- // 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
- }
-
- /// Mangles a name so it doesn't conflict with any keyword.
- pub fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
- use syntax::parse::token;
- let ident = self.rust_ident_raw(name);
- let token = token::Ident(ident);
- if token.is_any_keyword() || name.contains("@") ||
- name.contains("?") || name.contains("$") ||
- "bool" == name {
- let mut s = name.to_owned();
- s = s.replace("@", "_");
- s = s.replace("?", "_");
- s = s.replace("$", "_");
- s.push_str("_");
- return Cow::Owned(s);
- }
- Cow::Borrowed(name)
- }
-
- /// Returns a mangled name as a rust identifier.
- pub fn rust_ident(&self, name: &str) -> Ident {
- self.rust_ident_raw(&self.rust_mangle(name))
- }
-
- /// Returns a mangled name as a rust identifier.
- pub fn rust_ident_raw(&self, name: &str) -> Ident {
- self.ext_cx().ident_of(name)
- }
-
- /// 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;
- let mut typerefs = vec![];
- for (id, ref mut item) in &mut self.items {
- let kind = item.kind();
- let ty = match kind.as_type() {
- Some(ty) => ty,
- None => continue,
- };
-
- match *ty.kind() {
- TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) => {
- typerefs.push((*id, ty.clone(), loc, parent_id));
- }
- _ => {}
- };
- }
- typerefs
- }
-
- /// Collect all of our unresolved type references and resolve them.
- fn resolve_typerefs(&mut self) {
- let typerefs = self.collect_typerefs();
-
- for (id, ty, loc, parent_id) in typerefs {
- let _resolved = {
- let resolved = Item::from_ty(&ty, loc, parent_id, self)
- .expect("What happened?");
- let mut item = self.items.get_mut(&id).unwrap();
-
- *item.kind_mut().as_type_mut().unwrap().kind_mut() =
- TypeKind::ResolvedTypeRef(resolved);
- resolved
- };
-
- // Something in the STL is trolling me. I don't need this assertion
- // right now, but worth investigating properly once this lands.
- //
- // debug_assert!(self.items.get(&resolved).is_some(), "How?");
- }
- }
-
- /// 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() {
- debug!("No replacements to process");
- return;
- }
-
- // FIXME: This is linear, but the replaces="xxx" annotation was already
- // there, and for better or worse it's useful, sigh...
- //
- // We leverage the ResolvedTypeRef thing, though, which is cool :P.
-
- let mut replacements = vec![];
-
- for (id, item) in self.items.iter() {
- // Calls to `canonical_name` are expensive, so eagerly filter out
- // items that cannot be replaced.
- let ty = match item.kind().as_type() {
- Some(ty) => ty,
- None => continue,
- };
-
- match *ty.kind() {
- TypeKind::Comp(ref ci) if !ci.is_template_specialization() => {}
- TypeKind::TemplateAlias(_, _) |
- TypeKind::Alias(_, _) => {}
- _ => continue,
- }
-
- let name = item.real_canonical_name(self,
- self.options()
- .enable_cxx_namespaces,
- true);
- let replacement = self.replacements.get(&name);
-
- if let Some(replacement) = replacement {
- if replacement != id {
- // We set this just after parsing the annotation. It's
- // very unlikely, but this can happen.
- if self.items.get(replacement).is_some() {
- replacements.push((*id, *replacement));
- }
- }
- }
- }
-
- for (id, replacement) in replacements {
- debug!("Replacing {:?} with {:?}", id, replacement);
-
- let mut item = self.items.get_mut(&id).unwrap();
- *item.kind_mut().as_type_mut().unwrap().kind_mut() =
- TypeKind::ResolvedTypeRef(replacement);
- }
- }
-
- /// 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,
- {
- use syntax::ext::expand::ExpansionConfig;
- use syntax::codemap::{ExpnInfo, MacroBang, NameAndSpan};
- use syntax::ext::base;
- use syntax::parse;
- use std::mem;
-
- let cfg = ExpansionConfig::default("xxx".to_owned());
- let sess = parse::ParseSess::new();
- let mut loader = base::DummyResolver;
- let mut ctx =
- GenContext(base::ExtCtxt::new(&sess, vec![], cfg, &mut loader));
-
- ctx.0.bt_push(ExpnInfo {
- call_site: self.span,
- callee: NameAndSpan {
- format: MacroBang(parse::token::intern("")),
- allow_internal_unstable: false,
- span: None,
- },
- });
-
- // FIXME: This is evil, we should move code generation to use a wrapper
- // of BindgenContext instead, I guess. Even though we know it's fine
- // because we remove it before the end of this function.
- self.gen_ctx = Some(unsafe { mem::transmute(&ctx) });
-
- if !self.collected_typerefs() {
- self.resolve_typerefs();
- self.process_replacements();
- }
-
- let ret = cb(self);
- self.gen_ctx = None;
- ret
- }
-
- // This deserves a comment. Builtin types don't get a valid declaration, so
- // we can't add it to the cursor->type map.
- //
- // That being said, they're not generated anyway, and are few, so the
- // duplication and special-casing is fine.
- //
- // If at some point we care about the memory here, probably a map TypeKind
- // -> builtin type ItemId would be the best to improve that.
- fn add_builtin_item(&mut self, item: Item) {
- debug!("add_builtin_item: item = {:?}", item);
- debug_assert!(item.kind().is_type());
- let id = item.id();
- let old_item = self.items.insert(id, item);
- assert!(old_item.is_none(), "Inserted type twice?");
- }
-
- fn build_root_module(id: ItemId) -> Item {
- let module = Module::new(Some("root".into()));
- 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,
- None => panic!("Not an item: {:?}", item_id),
- }
- }
-
- /// Get the current module.
- pub fn current_module(&self) -> ItemId {
- self.current_module
- }
-
- /// This is one of the hackiest methods in all the parsing code. This method
- /// is used to allow having templates with another argument names instead of
- /// the canonical ones.
- ///
- /// This is surprisingly difficult to do with libclang, due to the fact that
- /// partial template specializations don't provide explicit template
- /// argument information.
- ///
- /// The only way to do this as far as I know, is inspecting manually the
- /// AST, looking for TypeRefs inside. This, unfortunately, doesn't work for
- /// more complex cases, see the comment on the assertion below.
- ///
- /// To see an example of what this handles:
- ///
- /// ```c++
- /// template<typename T>
- /// class Incomplete {
- /// T p;
- /// };
- ///
- /// template<typename U>
- /// class Foo {
- /// Incomplete<U> bar;
- /// };
- /// ```
- fn build_template_wrapper(&mut self,
- with_id: ItemId,
- wrapping: ItemId,
- parent_id: ItemId,
- ty: &clang::Type,
- location: clang::Cursor,
- declaration: clang::Cursor)
- -> ItemId {
- use clangll::*;
- let mut args = vec![];
- location.visit(|c| {
- if c.kind() == CXCursor_TypeRef {
- // The `with_id` id will potentially end up unused if we give up
- // on this type (for example, its a tricky partial template
- // specialization), so if we pass `with_id` as the parent, it is
- // potentially a dangling reference. Instead, use the canonical
- // template declaration as the parent. It is already parsed and
- // has a known-resolvable `ItemId`.
- let new_ty = Item::from_ty_or_ref(c.cur_type(),
- Some(c),
- Some(wrapping),
- self);
- args.push(new_ty);
- }
- CXChildVisit_Continue
- });
-
- let item = {
- let wrapping_type = self.resolve_type(wrapping);
- if let TypeKind::Comp(ref ci) = *wrapping_type.kind() {
- let old_args = ci.template_args();
-
- // The following assertion actually fails with partial template
- // specialization. But as far as I know there's no way at all to
- // grab the specialized types from neither the AST or libclang,
- // which sucks. The same happens for specialized type alias
- // template declarations, where we have that ugly hack up there.
- //
- // This flaw was already on the old parser, but I now think it
- // has no clear solution (apart from patching libclang to
- // somehow expose them, of course).
- //
- // For an easy example in which there's no way at all of getting
- // the `int` type, except manually parsing the spelling:
- //
- // template<typename T, typename U>
- // class Incomplete {
- // T d;
- // U p;
- // };
- //
- // template<typename U>
- // class Foo {
- // Incomplete<U, int> bar;
- // };
- //
- // debug_assert_eq!(old_args.len(), args.len());
- //
- // That being said, this is not so common, so just error! and
- // hope for the best, returning the previous type, who knows.
- if old_args.len() != args.len() {
- error!("Found partial template specialization, \
- expect dragons!");
- return wrapping;
- }
- } else {
- assert_eq!(declaration.kind(),
- ::clangll::CXCursor_TypeAliasTemplateDecl,
- "Expected wrappable type");
- }
-
- let type_kind = TypeKind::TemplateRef(wrapping, args);
- let name = ty.spelling();
- let name = if name.is_empty() { None } else { Some(name) };
- let ty = Type::new(name,
- ty.fallible_layout().ok(),
- type_kind,
- ty.is_const());
- Item::new(with_id, None, None, parent_id, ItemKind::Type(ty))
- };
-
- // Bypass all the validations in add_item explicitly.
- debug!("build_template_wrapper: inserting item: {:?}", item);
- debug_assert!(with_id == item.id());
- self.items.insert(with_id, item);
- with_id
- }
-
- /// Looks up for an already resolved type, either because it's builtin, or
- /// because we already have it in the map.
- pub fn builtin_or_resolved_ty(&mut self,
- with_id: ItemId,
- parent_id: Option<ItemId>,
- ty: &clang::Type,
- location: Option<clang::Cursor>)
- -> Option<ItemId> {
- use clangll::{CXCursor_ClassTemplate,
- CXCursor_ClassTemplatePartialSpecialization,
- CXCursor_TypeAliasTemplateDecl,
- CXCursor_TypeRef};
- debug!("builtin_or_resolved_ty: {:?}, {:?}, {:?}",
- ty,
- location,
- parent_id);
- let mut declaration = ty.declaration();
- if !declaration.is_valid() {
- if let Some(location) = location {
- if location.kind() == CXCursor_ClassTemplate ||
- location.kind() ==
- CXCursor_ClassTemplatePartialSpecialization {
- declaration = location;
- }
- }
- }
- let canonical_declaration = declaration.canonical();
- if canonical_declaration.is_valid() {
- let id = self.types
- .get(&TypeKey::Declaration(canonical_declaration))
- .map(|id| *id)
- .or_else(|| {
- canonical_declaration.usr()
- .and_then(|usr| self.types.get(&TypeKey::USR(usr)))
- .map(|id| *id)
- });
- if let Some(id) = id {
- debug!("Already resolved ty {:?}, {:?}, {:?} {:?}",
- id,
- declaration,
- ty,
- location);
-
- // If the declaration existed, we *might* be done, but it's not
- // the case for class templates, where the template arguments
- // may vary.
- //
- // In this case, we create a TemplateRef with the new template
- // arguments, pointing to the canonical template.
- //
- // Note that we only do it if parent_id is some, and we have a
- // location for building the new arguments, the template
- // argument names don't matter in the global context.
- if (declaration.kind() == CXCursor_ClassTemplate ||
- declaration.kind() ==
- CXCursor_ClassTemplatePartialSpecialization ||
- declaration.kind() == CXCursor_TypeAliasTemplateDecl) &&
- *ty != canonical_declaration.cur_type() &&
- location.is_some() &&
- parent_id.is_some() {
- // For specialized type aliases, there's no way to get the
- // template parameters as of this writing (for a struct
- // specialization we wouldn't be in this branch anyway).
- //
- // Explicitly return `None` if there aren't any
- // unspecialized parameters (contains any `TypeRef`) so we
- // resolve the canonical type if there is one and it's
- // exposed.
- //
- // This is _tricky_, I know :(
- if declaration.kind() == CXCursor_TypeAliasTemplateDecl &&
- !location.unwrap().contains_cursor(CXCursor_TypeRef) &&
- ty.canonical_type().is_valid_and_exposed() {
- return None;
- }
-
- return Some(self.build_template_wrapper(with_id,
- id,
- parent_id.unwrap(),
- ty,
- location.unwrap(),
- declaration));
- }
-
- return Some(self.build_ty_wrapper(with_id, id, parent_id, ty));
- }
- }
-
- debug!("Not resolved, maybe builtin?");
-
- // Else, build it.
- self.build_builtin_ty(ty, declaration)
- }
-
- // This is unfortunately a lot of bloat, but is needed to properly track
- // constness et. al.
- //
- // We should probably make the constness tracking separate, so it doesn't
- // bloat that much, but hey, we already bloat the heck out of builtin types.
- fn build_ty_wrapper(&mut self,
- with_id: ItemId,
- wrapped_id: ItemId,
- parent_id: Option<ItemId>,
- ty: &clang::Type)
- -> ItemId {
- let spelling = ty.spelling();
- let is_const = ty.is_const();
- let layout = ty.fallible_layout().ok();
- let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
- let ty = Type::new(Some(spelling), layout, type_kind, is_const);
- let item = Item::new(with_id,
- None,
- None,
- parent_id.unwrap_or(self.current_module),
- ItemKind::Type(ty));
- self.add_builtin_item(item);
- with_id
- }
-
- /// Returns the next item id to be used for an item.
- pub fn next_item_id(&mut self) -> ItemId {
- let ret = self.next_item_id;
- self.next_item_id = ItemId(self.next_item_id.0 + 1);
- ret
- }
-
- fn build_builtin_ty(&mut self,
- ty: &clang::Type,
- _declaration: Cursor)
- -> Option<ItemId> {
- use clangll::*;
- let type_kind = match ty.kind() {
- CXType_NullPtr => TypeKind::NullPtr,
- CXType_Void => TypeKind::Void,
- CXType_Bool => TypeKind::Int(IntKind::Bool),
- CXType_Int => TypeKind::Int(IntKind::Int),
- CXType_UInt => TypeKind::Int(IntKind::UInt),
- CXType_SChar | CXType_Char_S => TypeKind::Int(IntKind::Char),
- CXType_UChar | CXType_Char_U => TypeKind::Int(IntKind::UChar),
- CXType_Short => TypeKind::Int(IntKind::Short),
- CXType_UShort => TypeKind::Int(IntKind::UShort),
- CXType_WChar | CXType_Char16 => TypeKind::Int(IntKind::U16),
- CXType_Char32 => TypeKind::Int(IntKind::U32),
- CXType_Long => TypeKind::Int(IntKind::Long),
- CXType_ULong => TypeKind::Int(IntKind::ULong),
- CXType_LongLong => TypeKind::Int(IntKind::LongLong),
- CXType_ULongLong => TypeKind::Int(IntKind::ULongLong),
- CXType_Int128 => TypeKind::Int(IntKind::I128),
- CXType_UInt128 => TypeKind::Int(IntKind::U128),
- CXType_Float => TypeKind::Float(FloatKind::Float),
- CXType_Double => TypeKind::Float(FloatKind::Double),
- CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
- CXType_Float128 => TypeKind::Float(FloatKind::Float128),
- CXType_Complex => {
- let float_type = ty.elem_type()
- .expect("Not able to resolve complex type?");
- let float_kind = match float_type.kind() {
- CXType_Float => FloatKind::Float,
- CXType_Double => FloatKind::Double,
- CXType_LongDouble => FloatKind::LongDouble,
- _ => panic!("Non floating-type complex?"),
- };
- TypeKind::Complex(float_kind)
- }
- _ => return None,
- };
-
- let spelling = ty.spelling();
- let is_const = ty.is_const();
- let layout = ty.fallible_layout().ok();
- let ty = Type::new(Some(spelling), layout, type_kind, is_const);
- let id = self.next_item_id();
- let item =
- Item::new(id, None, None, self.root_module, ItemKind::Type(ty));
- self.add_builtin_item(item);
- 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: &[u8]) -> bool {
- self.parsed_macros.contains_key(macro_name)
- }
-
- /// Get the currently parsed macros.
- pub fn parsed_macros(&self) -> &HashMap<Vec<u8>, cexpr::expr::EvalResult> {
- debug_assert!(!self.in_codegen_phase());
- &self.parsed_macros
- }
-
- /// Mark the macro named `macro_name` as parsed.
- pub fn note_parsed_macro(&mut self,
- id: Vec<u8>,
- value: cexpr::expr::EvalResult) {
- self.parsed_macros.insert(id, value);
- }
-
- /// Are we in the codegen phase?
- pub fn in_codegen_phase(&self) -> bool {
- self.gen_ctx.is_some()
- }
-
- /// 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) {
- match self.replacements.entry(name.into()) {
- hash_map::Entry::Vacant(entry) => {
- debug!("Defining replacement for {} as {:?}",
- name,
- potential_ty);
- entry.insert(potential_ty);
- }
- hash_map::Entry::Occupied(occupied) => {
- warn!("Replacement for {} already defined as {:?}; \
- ignoring duplicate replacement definition as {:?}}}",
- name,
- occupied.get(),
- 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");
- self.options.hidden_types.contains(name) ||
- 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,
- _ => false,
- }
- }
-
- /// 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
- }
-
- /// Given a CXCursor_Namespace cursor, return the item id of the
- /// corresponding module, or create one on the fly.
- pub fn module(&mut self, cursor: clang::Cursor) -> ItemId {
- use clangll::*;
- assert!(cursor.kind() == CXCursor_Namespace, "Be a nice person");
- let cursor = cursor.canonical();
- if let Some(id) = self.modules.get(&cursor) {
- return *id;
- }
-
- let module_id = self.next_item_id();
- let module_name = self.translation_unit
- .tokens(&cursor)
- .and_then(|tokens| {
- if tokens.len() <= 1 {
- None
- } else {
- match &*tokens[1].spelling {
- "{" => None,
- s => Some(s.to_owned()),
- }
- }
- });
-
- let module = Module::new(module_name);
- let module = Item::new(module_id,
- None,
- None,
- self.current_module,
- ItemKind::Module(module));
-
- self.add_item(module, None, None);
-
- 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>),
- {
- debug_assert!(self.resolve_item(module_id).kind().is_module(), "Wat");
-
- let previous_id = self.current_module;
- self.current_module = module_id;
-
- let mut children = vec![];
- cb(self, &mut children);
-
- self.items
- .get_mut(&module_id)
- .unwrap()
- .as_module_mut()
- .expect("Not a module?")
- .children_mut()
- .extend(children.into_iter());
-
- self.current_module = previous_id;
- }
-
- /// Iterate over all (explicitly or transitively) whitelisted items.
- ///
- /// If no items are explicitly whitelisted, then all items are considered
- /// whitelisted.
- pub fn whitelisted_items<'me>(&'me self)
- -> WhitelistedItemsIter<'me, 'ctx> {
- assert!(self.in_codegen_phase());
- assert!(self.current_module == self.root_module);
-
- let roots = self.items()
- .filter(|&(_, item)| {
- // If nothing is explicitly whitelisted, then everything is fair
- // game.
- if self.options().whitelisted_types.is_empty() &&
- self.options().whitelisted_functions.is_empty() &&
- self.options().whitelisted_vars.is_empty() {
- return true;
- }
-
- let name = item.canonical_name(self);
- match *item.kind() {
- ItemKind::Module(..) => false,
- ItemKind::Function(_) => {
- self.options().whitelisted_functions.matches(&name)
- }
- ItemKind::Var(_) => {
- self.options().whitelisted_vars.matches(&name)
- }
- ItemKind::Type(ref ty) => {
- if self.options().whitelisted_types.matches(&name) {
- return true;
- }
-
- // Unnamed top-level enums are special and we whitelist
- // them via the `whitelisted_vars` filter, since they're
- // effectively top-level constants, and there's no way
- // for them to be referenced consistently.
- if let TypeKind::Enum(ref enum_) = *ty.kind() {
- if ty.name().is_none() &&
- enum_.variants().iter().any(|variant| {
- self.options()
- .whitelisted_vars
- .matches(&variant.name())
- }) {
- return true;
- }
- }
-
- false
- }
- }
- })
- .map(|(&id, _)| id);
-
- let seen: ItemSet = roots.collect();
-
- // The .rev() preserves the expected ordering traversal, resulting in
- // more stable-ish bindgen-generated names for anonymous types (like
- // unions).
- let to_iterate = seen.iter().cloned().rev().collect();
-
- WhitelistedItemsIter {
- ctx: self,
- seen: seen,
- to_iterate: to_iterate,
- }
- }
-
- /// Convenient method for getting the prefix to use for most traits in
- /// codegen depending on the `use_core` option.
- pub fn trait_prefix(&self) -> Ident {
- if self.options().use_core {
- self.rust_ident_raw("core")
- } else {
- self.rust_ident_raw("std")
- }
- }
-
- /// Call if a binden complex is generated
- pub fn generated_bindegen_complex(&self) {
- self.generated_bindegen_complex.set(true)
- }
-
- /// Whether we need to generate the binden complex type
- pub fn need_bindegen_complex_type(&self) -> bool {
- self.generated_bindegen_complex.get()
- }
-}
-
-/// An iterator over whitelisted items.
-///
-/// See `BindgenContext::whitelisted_items` for more information.
-pub struct WhitelistedItemsIter<'ctx, 'gen>
- where 'gen: 'ctx,
-{
- ctx: &'ctx BindgenContext<'gen>,
-
- // The set of whitelisted items we have seen. If you think of traversing
- // whitelisted items like GC tracing, this is the mark bits, and contains
- // both black and gray items.
- seen: ItemSet,
-
- // The set of whitelisted items that we have seen but have yet to iterate
- // over and collect transitive references from. To return to the GC analogy,
- // this is the mark stack, containing the set of gray items which we have
- // not finished tracing yet.
- to_iterate: Vec<ItemId>,
-}
-
-impl<'ctx, 'gen> Iterator for WhitelistedItemsIter<'ctx, 'gen>
- where 'gen: 'ctx,
-{
- type Item = ItemId;
-
- fn next(&mut self) -> Option<Self::Item> {
- let id = match self.to_iterate.pop() {
- None => return None,
- Some(id) => id,
- };
-
- debug_assert!(self.seen.contains(&id));
- debug_assert!(self.ctx.items.contains_key(&id));
-
- let mut sub_types = ItemSet::new();
- id.collect_types(self.ctx, &mut sub_types, &());
-
- for id in sub_types {
- if self.seen.insert(id) {
- self.to_iterate.push(id);
- }
- }
-
- Some(id)
- }
-}
diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs
deleted file mode 100644
index 6085833d..00000000
--- a/src/ir/enum_ty.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-//! Intermediate representation for C/C++ enumerations.
-
-use clang;
-use parse::{ClangItemParser, ParseError};
-use super::context::{BindgenContext, ItemId};
-use super::item::Item;
-use super::ty::TypeKind;
-
-/// A C/C++ enumeration.
-#[derive(Debug)]
-pub struct Enum {
- /// 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`.
- 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,
- variants: variants,
- }
- }
-
- /// 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::*;
- if ty.kind() != CXType_Enum {
- return Err(ParseError::Continue);
- }
-
- let declaration = ty.declaration().canonical();
- let repr = Item::from_ty(&declaration.enum_type(), None, None, ctx)
- .ok();
- let mut variants = vec![];
-
- let is_signed = match repr {
- Some(repr) => {
- let repr_type = ctx.resolve_type(repr);
- match *repr_type.canonical_type(ctx).kind() {
- TypeKind::Int(ref int_kind) => int_kind.is_signed(),
- ref other => {
- panic!("Since when enums can be non-integers? {:?}",
- other)
- }
- }
- }
- // Assume signedness since the default type by the C
- // standard is an
- // int.
- None => true,
- };
-
- declaration.visit(|cursor| {
- if cursor.kind() == CXCursor_EnumConstantDecl {
- let value = if is_signed {
- cursor.enum_val_signed().map(EnumVariantValue::Signed)
- } else {
- cursor.enum_val_unsigned().map(EnumVariantValue::Unsigned)
- };
- if let Some(val) = value {
- let name = cursor.spelling();
- let comment = cursor.raw_comment();
- variants.push(EnumVariant::new(name, comment, val));
- }
- }
- CXChildVisit_Continue
- });
- Ok(Enum::new(repr, variants))
- }
-}
-
-/// A single enum variant, to be contained only in an enum.
-#[derive(Debug)]
-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,
- comment: comment,
- val: val,
- }
- }
-
- /// 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
deleted file mode 100644
index eacb6c0e..00000000
--- a/src/ir/function.rs
+++ /dev/null
@@ -1,282 +0,0 @@
-//! Intermediate representation for C/C++ functions and methods.
-
-use clang;
-use clangll::Enum_CXCallingConv;
-use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
-use super::context::{BindgenContext, ItemId};
-use super::item::Item;
-use super::ty::TypeKind;
-use super::type_collector::{ItemSet, TypeCollector};
-use syntax::abi;
-
-/// 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,
- comment: Option<String>)
- -> Self {
- Function {
- name: name,
- mangled_name: mangled_name,
- signature: sig,
- comment: comment,
- }
- }
-
- /// 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
- }
-}
-
-/// A function signature.
-#[derive(Debug)]
-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.
- abi: abi::Abi,
-}
-
-fn get_abi(cc: Enum_CXCallingConv) -> abi::Abi {
- use clangll::*;
- match cc {
- CXCallingConv_Default => abi::Abi::C,
- CXCallingConv_C => abi::Abi::C,
- CXCallingConv_X86StdCall => abi::Abi::Stdcall,
- CXCallingConv_X86FastCall => abi::Abi::Fastcall,
- CXCallingConv_AAPCS => abi::Abi::Aapcs,
- CXCallingConv_X86_64Win64 => abi::Abi::Win64,
- other => panic!("unsupported calling convention: {}", other),
- }
-}
-
-/// 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.
- // See servo/rust-bindgen#67.
- if cursor.is_in_non_fully_specialized_template() {
- return None;
- }
-
- let mut mangling = cursor.mangling();
- if mangling.is_empty() {
- return None;
- }
-
- // Try to undo backend linkage munging (prepended _, generally)
- if cfg!(target_os = "macos") {
- mangling.remove(0);
- }
-
- Some(mangling)
-}
-
-impl FunctionSig {
- /// Construct a new function signature.
- pub fn new(return_type: ItemId,
- arguments: Vec<(Option<String>, ItemId)>,
- is_variadic: bool,
- abi: abi::Abi)
- -> Self {
- FunctionSig {
- return_type: return_type,
- argument_types: arguments,
- is_variadic: is_variadic,
- abi: abi,
- }
- }
-
- /// 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> {
- use clangll::*;
- debug!("FunctionSig::from_ty {:?} {:?}", ty, cursor);
-
- // Don't parse operatorxx functions in C++
- let spelling = cursor.spelling();
- if spelling.starts_with("operator") {
- return Err(ParseError::Continue);
- }
-
- let cursor = if cursor.is_valid() {
- *cursor
- } else {
- ty.declaration()
- };
- let mut args: Vec<_> = match cursor.kind() {
- CXCursor_FunctionDecl |
- CXCursor_CXXMethod => {
- // For CXCursor_FunctionDecl, cursor.args() is the reliable way
- // to get parameter names and types.
- cursor.args()
- .iter()
- .map(|arg| {
- let arg_ty = arg.cur_type();
- let name = arg.spelling();
- let name =
- if name.is_empty() { None } else { Some(name) };
- let ty = Item::from_ty(&arg_ty, Some(*arg), None, ctx)
- .expect("Argument?");
- (name, ty)
- })
- .collect()
- }
- _ => {
- // For non-CXCursor_FunctionDecl, visiting the cursor's children
- // is the only reliable way to get parameter names.
- let mut args = vec![];
- cursor.visit(|c| {
- if c.kind() == CXCursor_ParmDecl {
- let ty =
- Item::from_ty(&c.cur_type(), Some(c), None, ctx)
- .expect("ParmDecl?");
- let name = c.spelling();
- let name =
- if name.is_empty() { None } else { Some(name) };
- args.push((name, ty));
- }
- CXChildVisit_Continue
- });
- args
- }
- };
-
- if cursor.kind() == CXCursor_CXXMethod {
- let is_const = cursor.method_is_const();
- let is_virtual = cursor.method_is_virtual();
- let is_static = cursor.method_is_static();
- if !is_static && !is_virtual {
- let class = Item::parse(cursor.semantic_parent(), None, ctx)
- .expect("Expected to parse the class");
- let ptr =
- Item::builtin_type(TypeKind::Pointer(class), is_const, ctx);
- args.insert(0, (Some("this".into()), ptr));
- } else if is_virtual {
- let void = Item::builtin_type(TypeKind::Void, false, ctx);
- let ptr =
- Item::builtin_type(TypeKind::Pointer(void), false, ctx);
- args.insert(0, (Some("this".into()), ptr));
- }
- }
-
- let ty_ret_type = try!(ty.ret_type().ok_or(ParseError::Continue));
- let ret = try!(Item::from_ty(&ty_ret_type, None, None, ctx));
- let abi = get_abi(ty.call_conv());
-
- 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
- // variadic functions without an initial argument.
- self.is_variadic && !self.argument_types.is_empty()
- }
-}
-
-impl ClangSubItemParser for Function {
- fn parse(cursor: clang::Cursor,
- context: &mut BindgenContext)
- -> Result<ParseResult<Self>, ParseError> {
- use clangll::*;
- match cursor.kind() {
- CXCursor_FunctionDecl |
- CXCursor_CXXMethod => {}
- _ => return Err(ParseError::Continue),
- };
-
- debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());
-
- // Grab the signature using Item::from_ty.
- let sig = try!(Item::from_ty(&cursor.cur_type(),
- Some(cursor),
- None,
- context));
-
- let name = cursor.spelling();
- assert!(!name.is_empty(), "Empty function name?");
-
- let mut mangled_name = cursor_mangling(&cursor);
- if mangled_name.as_ref() == Some(&name) {
- mangled_name = None;
- }
-
- let comment = cursor.raw_comment();
-
- let function = Self::new(name, mangled_name, sig, comment);
- Ok(ParseResult::New(function, Some(cursor)))
- }
-}
-
-impl TypeCollector for FunctionSig {
- type Extra = Item;
-
- fn collect_types(&self,
- _context: &BindgenContext,
- types: &mut ItemSet,
- _item: &Item) {
- types.insert(self.return_type());
-
- for &(_, ty) in self.argument_types() {
- types.insert(ty);
- }
- }
-}
diff --git a/src/ir/int.rs b/src/ir/int.rs
deleted file mode 100644
index 2d85db83..00000000
--- a/src/ir/int.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-//! 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,
-
- /// A 8-bit signed integer.
- I8,
-
- /// A 8-bit unsigned integer.
- U8,
-
- /// A 16-bit signed integer.
- I16,
-
- /// Either a `char16_t` or a `wchar_t`.
- U16,
-
- /// A 32-bit signed integer.
- I32,
-
- /// A 32-bit unsigned integer.
- U32,
-
- /// A 64-bit signed integer.
- I64,
-
- /// A 64-bit unsigned integer.
- U64,
-
- /// An `int128_t`
- I128,
-
- /// A `uint128_t`.
- U128,
-
- /// A custom integer type, used to allow custom macro types depending on
- /// range.
- Custom {
- /// The name of the type, which would be used without modification.
- name: &'static str,
- /// Whether the type is signed or not.
- is_signed: bool,
- },
-}
-
-impl IntKind {
- /// Is this integral type signed?
- pub fn is_signed(&self) -> bool {
- use self::IntKind::*;
- match *self {
- Bool | UChar | UShort | UInt | ULong | ULongLong | U8 | U16 |
- U32 | U64 | U128 => false,
-
- Char | Short | Int | Long | LongLong | I8 | I16 | I32 | I64 |
- I128 => true,
-
- Custom { is_signed, .. } => is_signed,
- }
- }
-}
diff --git a/src/ir/item.rs b/src/ir/item.rs
deleted file mode 100644
index 1f05f92f..00000000
--- a/src/ir/item.rs
+++ /dev/null
@@ -1,1172 +0,0 @@
-//! Bindgen's core intermediate representation type.
-
-use clang;
-use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
-use regex::Regex;
-use std::cell::{Cell, RefCell};
-use super::annotations::Annotations;
-use super::context::{BindgenContext, ItemId};
-use super::function::Function;
-use super::item_kind::ItemKind;
-use super::module::Module;
-use super::ty::{Type, TypeKind};
-use super::type_collector::{ItemSet, TypeCollector};
-
-/// A trait to get the canonical name from an item.
-///
-/// This is the trait that will eventually isolate all the logic related to name
-/// mangling and that kind of stuff.
-///
-/// This assumes no nested paths, at some point I'll have to make it a more
-/// complex thing.
-///
-/// 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;
-}
-
-/// The same, but specifies the path that needs to be followed to reach an item.
-///
-/// To contrast with canonical_name, here's an example:
-///
-/// ```c++
-/// namespace foo {
-/// const BAR = 3;
-/// }
-/// ```
-///
-/// For bar, the canonical path is `vec!["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>;
-}
-
-/// A trait for iterating over an item and its parents and up its ancestor chain
-/// up to (but not including) the implicit root module.
-pub trait ItemAncestors {
- /// Get an iterable over this item's ancestors.
- fn ancestors<'a, 'b>(&self,
- ctx: &'a BindgenContext<'b>)
- -> ItemAncestorsIter<'a, 'b>;
-}
-
-/// An iterator over an item and its ancestors.
-pub struct ItemAncestorsIter<'a, 'b>
- where 'b: 'a,
-{
- item: ItemId,
- ctx: &'a BindgenContext<'b>,
-}
-
-impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b>
- where 'b: 'a,
-{
- type Item = ItemId;
-
- fn next(&mut self) -> Option<Self::Item> {
- let item = self.ctx.resolve_item(self.item);
- if item.parent_id() == self.item {
- None
- } else {
- self.item = item.parent_id();
- Some(item.id())
- }
- }
-}
-
-// Pure convenience
-impl ItemCanonicalName for ItemId {
- fn canonical_name(&self, ctx: &BindgenContext) -> String {
- debug_assert!(ctx.in_codegen_phase(),
- "You're not supposed to call this yet");
- ctx.resolve_item(*self).canonical_name(ctx)
- }
-}
-
-impl ItemCanonicalPath for ItemId {
- fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
- debug_assert!(ctx.in_codegen_phase(),
- "You're not supposed to call this yet");
- ctx.resolve_item(*self).canonical_path(ctx)
- }
-}
-
-impl ItemAncestors for ItemId {
- fn ancestors<'a, 'b>(&self,
- ctx: &'a BindgenContext<'b>)
- -> ItemAncestorsIter<'a, 'b> {
- ItemAncestorsIter {
- item: *self,
- ctx: ctx,
- }
- }
-}
-
-impl ItemAncestors for Item {
- fn ancestors<'a, 'b>(&self,
- ctx: &'a BindgenContext<'b>)
- -> ItemAncestorsIter<'a, 'b> {
- self.id().ancestors(ctx)
- }
-}
-
-impl TypeCollector for ItemId {
- type Extra = ();
-
- fn collect_types(&self,
- ctx: &BindgenContext,
- types: &mut ItemSet,
- extra: &()) {
- ctx.resolve_item(*self).collect_types(ctx, types, extra);
- }
-}
-
-impl TypeCollector for Item {
- type Extra = ();
-
- fn collect_types(&self,
- ctx: &BindgenContext,
- types: &mut ItemSet,
- _extra: &()) {
- if self.is_hidden(ctx) || types.contains(&self.id()) {
- return;
- }
-
- match *self.kind() {
- ItemKind::Type(ref ty) => {
- if !self.is_opaque(ctx) {
- ty.collect_types(ctx, types, self);
- }
- }
- _ => {} // FIXME.
- }
- }
-}
-
-/// An item is the base of the bindgen representation, it can be either a
-/// module, a type, a function, or a variable (see `ItemKind` for more
-/// information).
-///
-/// 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 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).
-///
-/// Note that even though we parse all the types of annotations in comments, not
-/// all of them apply to every item. Those rules are described in the
-/// `annotations` module.
-#[derive(Debug)]
-pub struct Item {
- /// This item's id.
- id: ItemId,
-
- /// The item's local id, unique only amongst its siblings. Only used for
- /// anonymous items.
- ///
- /// Lazily initialized in local_id().
- ///
- /// Note that only structs, unions, and enums get a local type id. In any
- /// case this is an implementation detail.
- local_id: Cell<Option<usize>>,
-
- /// The next local id to use for a child..
- next_child_local_id: Cell<usize>,
-
- /// A cached copy of the canonical name, as returned by `canonical_name`.
- ///
- /// This is a fairly used operation during codegen so this makes bindgen
- /// considerably faster in those cases.
- canonical_name_cache: RefCell<Option<String>>,
-
- /// A doc comment over the item, if any.
- comment: Option<String>,
- /// Annotations extracted from the doc comment, or the default ones
- /// otherwise.
- annotations: Annotations,
- /// An item's parent id. This will most likely be a class where this item
- /// was declared, or a module, etc.
- ///
- /// All the items have a parent, except the root module, in which case the
- /// parent id is its own id.
- parent_id: ItemId,
- /// The item kind.
- kind: ItemKind,
-}
-
-impl Item {
- /// Construct a new `Item`.
- pub fn new(id: ItemId,
- comment: Option<String>,
- annotations: Option<Annotations>,
- parent_id: ItemId,
- kind: ItemKind)
- -> Self {
- debug_assert!(id != parent_id || kind.is_module());
- Item {
- id: id,
- local_id: Cell::new(None),
- next_child_local_id: Cell::new(1),
- canonical_name_cache: RefCell::new(None),
- parent_id: parent_id,
- comment: comment,
- annotations: annotations.unwrap_or_default(),
- kind: kind,
- }
- }
-
- /// 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);
- let local_id = parent.next_child_local_id.get();
- parent.next_child_local_id.set(local_id + 1);
- self.local_id.set(Some(local_id));
- }
- self.local_id.get().unwrap()
- }
-
- /// Returns whether this item is a top-level item, from the point of view of
- /// bindgen.
- ///
- /// This point of view changes depending on whether namespaces are enabled
- /// or not. That way, in the following example:
- ///
- /// ```c++
- /// namespace foo {
- /// static int var;
- /// }
- /// ```
- ///
- /// `var` would be a toplevel item if namespaces are disabled, but won't if
- /// they aren't.
- ///
- /// This function is used to determine when the codegen phase should call
- /// `codegen` on an item, since any item that is not top-level will be
- /// generated by its parent.
- pub fn is_toplevel(&self, ctx: &BindgenContext) -> bool {
- // FIXME: Workaround for some types falling behind when parsing weird
- // stl classes, for example.
- if ctx.options().enable_cxx_namespaces && self.kind().is_module() &&
- self.id() != ctx.root_module() {
- return false;
- }
-
- let mut parent = self.parent_id;
- loop {
- let parent_item = match ctx.resolve_item_fallible(parent) {
- Some(item) => item,
- None => return false,
- };
-
- if parent_item.id() == ctx.root_module() {
- return true;
- } else if ctx.options().enable_cxx_namespaces ||
- !parent_item.kind().is_module() {
- return false;
- }
-
- parent = parent_item.parent_id();
- }
- }
-
- /// 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 `Type`, or `None` if this is
- /// some other kind of item.
- pub fn as_type(&self) -> Option<&Type> {
- self.kind().as_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()
- }
-
- /// Checks whether an item contains in its "type signature" some named type.
- ///
- /// 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.
- ///
- /// For example, in code like the following:
- ///
- /// ```c++
- /// template<typename T, typename U>
- /// struct Foo {
- /// T bar;
- ///
- /// struct Baz {
- /// U bas;
- /// };
- /// };
- /// ```
- ///
- /// Both `Foo` and `Baz` contain both `T` and `U` template parameters in
- /// their signature:
- ///
- /// * `Foo<T, U>`
- /// * `Bar<T, U>`
- ///
- /// But the Rust structure for `Foo` would look like:
- ///
- /// ```rust
- /// struct Foo<T, U> {
- /// bar: T,
- /// _phantom0: ::std::marker::PhantomData<U>,
- /// }
- /// ```
- ///
- /// 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.
- ///
- /// Note that this is somewhat similar to `applicable_template_args`, but
- /// this also takes into account other kind of types, like arrays,
- /// (`[T; 40]`), pointers: `*mut T`, etc...
- ///
- /// Normally we could do this check just in the `Type` kind, but we also
- /// need to check the `applicable_template_args` more generally, since we
- /// could need a type transitively from our parent, see the test added in
- /// commit 2a3f93074dd2898669dbbce6e97e5cc4405d7cb1.
- ///
- /// It's kind of unfortunate (in the sense that it's a sort of complex
- /// process), but I think it should get all the cases.
- fn signature_contains_named_type(&self,
- ctx: &BindgenContext,
- ty: &Type)
- -> bool {
- debug_assert!(ty.is_named());
- self.expect_type().signature_contains_named_type(ctx, ty) ||
- self.applicable_template_args(ctx).iter().any(|template| {
- ctx.resolve_type(*template).signature_contains_named_type(ctx, ty)
- })
- }
-
- /// Returns the template arguments that apply to a struct. This is a concept
- /// needed because of type declarations inside templates, for example:
- ///
- /// ```c++
- /// template<typename T>
- /// class Foo {
- /// typedef T element_type;
- /// typedef int Bar;
- ///
- /// template<typename U>
- /// class Baz {
- /// };
- /// };
- /// ```
- ///
- /// In this case, the applicable template arguments for the different types
- /// would be:
- ///
- /// * `Foo`: [`T`]
- /// * `Foo::element_type`: [`T`]
- /// * `Foo::Bar`: [`T`]
- /// * `Foo::Baz`: [`T`, `U`]
- ///
- /// You might notice that we can't generate something like:
- ///
- /// ```rust,ignore
- /// type Foo_Bar<T> = ::std::os::raw::c_int;
- /// ```
- ///
- /// since that would be invalid Rust. Still, conceptually, `Bar` *could* use
- /// the template parameter type `T`, and that's exactly what this method
- /// represents. The unused template parameters get stripped in the
- /// `signature_contains_named_type` check.
- pub fn applicable_template_args(&self,
- ctx: &BindgenContext)
- -> Vec<ItemId> {
- let ty = match *self.kind() {
- ItemKind::Type(ref ty) => ty,
- _ => return vec![],
- };
-
- fn parent_contains(ctx: &BindgenContext,
- parent_template_args: &[ItemId],
- item: ItemId)
- -> bool {
- let item_ty = ctx.resolve_type(item);
- parent_template_args.iter().any(|parent_item| {
- let parent_ty = ctx.resolve_type(*parent_item);
- match (parent_ty.kind(), item_ty.kind()) {
- (&TypeKind::Named(ref n, _),
- &TypeKind::Named(ref i, _)) => n == i,
- _ => false,
- }
- })
- }
-
- match *ty.kind() {
- TypeKind::Named(..) => vec![self.id()],
- TypeKind::Array(inner, _) |
- TypeKind::Pointer(inner) |
- TypeKind::Reference(inner) |
- TypeKind::ResolvedTypeRef(inner) => {
- ctx.resolve_item(inner).applicable_template_args(ctx)
- }
- TypeKind::Alias(_, inner) => {
- let parent_args = ctx.resolve_item(self.parent_id())
- .applicable_template_args(ctx);
- let inner = ctx.resolve_item(inner);
-
- // Avoid unused type parameters, sigh.
- parent_args.iter()
- .cloned()
- .filter(|arg| {
- let arg = ctx.resolve_type(*arg);
- arg.is_named() &&
- inner.signature_contains_named_type(ctx, arg)
- })
- .collect()
- }
- // XXX Is this completely correct? Partial template specialization
- // is hard anyways, sigh...
- TypeKind::TemplateAlias(_, ref args) |
- TypeKind::TemplateRef(_, ref args) => args.clone(),
- // In a template specialization we've got all we want.
- TypeKind::Comp(ref ci) if ci.is_template_specialization() => {
- ci.template_args().iter().cloned().collect()
- }
- TypeKind::Comp(ref ci) => {
- let mut parent_template_args =
- ctx.resolve_item(self.parent_id())
- .applicable_template_args(ctx);
-
- for ty in ci.template_args() {
- if !parent_contains(ctx, &parent_template_args, *ty) {
- parent_template_args.push(*ty);
- }
- }
-
- parent_template_args
- }
- _ => vec![],
- }
- }
-
- fn is_module(&self) -> bool {
- match self.kind {
- ItemKind::Module(..) => true,
- _ => false,
- }
- }
-
- /// Get this item's annotations.
- pub fn annotations(&self) -> &Annotations {
- &self.annotations
- }
-
- /// 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");
- self.annotations.hide() ||
- 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");
- self.annotations.opaque() ||
- ctx.opaque_by_name(&self.real_canonical_name(ctx, false, true))
- }
-
- /// Is this a reference to another type?
- pub fn is_type_ref(&self) -> bool {
- self.as_type().map_or(false, |ty| ty.is_type_ref())
- }
-
- /// Get the canonical name without taking into account the replaces
- /// annotation.
- ///
- /// This is the base logic used to implement hiding and replacing via
- /// annotations, and also to implement proper name mangling.
- ///
- /// The idea is that each generated type in the same "level" (read: module
- /// or namespace) has a unique canonical name.
- ///
- /// This name should be derived from the immutable state contained in the
- /// type and the parent chain, since it should be consistent.
- pub fn real_canonical_name(&self,
- ctx: &BindgenContext,
- count_namespaces: bool,
- for_name_checking: bool)
- -> String {
- let base_name = match *self.kind() {
- ItemKind::Type(ref ty) => {
- match *ty.kind() {
- // If we're a template specialization, our name is our
- // parent's.
- TypeKind::Comp(ref ci)
- if ci.is_template_specialization() => {
- return ci.specialized_template().unwrap()
- .canonical_name(ctx);
- },
- // Same as above
- TypeKind::ResolvedTypeRef(inner) |
- TypeKind::TemplateRef(inner, _) => {
- return inner.canonical_name(ctx);
- }
- // If we're a named type, we don't need to mangle it, and we
- // should be able to assert we're not top level.
- TypeKind::Named(ref name, _) => {
- return name.to_owned();
- }
- // We call codegen on the inner type, but we do not want
- // this alias's name to appear in the canonical name just
- // because it is in the inner type's parent chain, so we use
- // an empty base name.
- //
- // Note that this would be incorrect if this type could be
- // referenced from, let's say, a member variable, but in
- // that case the referenced type is the inner alias, so
- // we're good there. If we wouldn't, a more complex solution
- // would be needed.
- TypeKind::TemplateAlias(inner, _) => {
- if for_name_checking {
- return ctx.resolve_item(inner)
- .real_canonical_name(ctx,
- count_namespaces,
- false);
- }
- Some("")
- }
- // Else use the proper name, or fallback to a name with an
- // id.
- _ => {
- ty.name()
- }
- }.map(ToOwned::to_owned)
- }
- ItemKind::Function(ref fun) => {
- let mut base = fun.name().to_owned();
-
- // We might need to deduplicate if we're a method.
- let parent = ctx.resolve_item(self.parent_id());
- if let ItemKind::Type(ref ty) = *parent.kind() {
- if let TypeKind::Comp(ref ci) = *ty.kind() {
- let mut count = 0;
- let mut found = false;
- for method in ci.methods() {
- if method.signature() == self.id() {
- found = true;
- break;
- }
- let fun = ctx.resolve_item(method.signature())
- .expect_function();
- if fun.name() == base {
- count += 1;
- }
- }
-
- assert!(found, "Method not found?");
- if count != 0 {
- base.push_str(&count.to_string());
- }
- }
- }
- Some(base)
- }
- ItemKind::Var(ref var) => Some(var.name().to_owned()),
- ItemKind::Module(ref module) => {
- module.name().map(ToOwned::to_owned)
- }
- };
-
- let parent = ctx.resolve_item(self.parent_id());
- let parent_is_namespace = parent.is_module();
-
- if self.is_toplevel(ctx) || (parent_is_namespace && count_namespaces) {
- let base_name = self.make_exposed_name(None, base_name, ctx);
- return ctx.rust_mangle(&base_name).into_owned();
- }
-
- // TODO: allow modification of the mangling functions, maybe even per
- // item type?
- let parent_name = parent.canonical_name(ctx);
- self.make_exposed_name(Some(parent_name), base_name, ctx)
- }
-
- fn exposed_id(&self, ctx: &BindgenContext) -> String {
- // Only use local ids for enums, classes, structs and union types. All
- // other items use their global id.
- let ty_kind = self.kind().as_type().map(|t| t.kind());
- if let Some(ty_kind) = ty_kind {
- match *ty_kind {
- TypeKind::Comp(..) |
- TypeKind::Enum(..) => return self.local_id(ctx).to_string(),
- _ => {}
- }
- }
-
- // Note that this `id_` prefix prevents (really unlikely) collisions
- // between the global id and the local id of an item with the same
- // parent.
- format!("id_{}", self.id().as_usize())
- }
-
- fn make_exposed_name(&self,
- parent_name: Option<String>,
- base_name: Option<String>,
- ctx: &BindgenContext)
- -> String {
- lazy_static! {
- 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),
- (Some(parent), None) => {
- if re.is_match(parent.as_str()) {
- format!("{}_{}", parent, self.exposed_id(ctx))
- } else {
- format!("{}__bindgen_{}_{}",
- parent,
- kind,
- self.exposed_id(ctx))
- }
- }
- (None, Some(base)) => base,
- (None, None) => {
- format!("_bindgen_{}_{}", kind, self.exposed_id(ctx))
- }
- }
- }
-
- /// 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),
- _ => None,
- }
- }
-
- /// 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)
- }
-}
-
-impl ClangItemParser for Item {
- fn builtin_type(kind: TypeKind,
- is_const: bool,
- ctx: &mut BindgenContext)
- -> ItemId {
- // Feel free to add more here, I'm just lazy.
- match kind {
- TypeKind::Void |
- TypeKind::Int(..) |
- TypeKind::Pointer(..) |
- TypeKind::Float(..) => {}
- _ => panic!("Unsupported builtin type"),
- }
-
- let ty = Type::new(None, None, kind, is_const);
- let id = ctx.next_item_id();
- let module = ctx.root_module();
- ctx.add_item(Item::new(id, None, None, module, ItemKind::Type(ty)),
- None,
- None);
- id
- }
-
-
- fn parse(cursor: clang::Cursor,
- parent_id: Option<ItemId>,
- ctx: &mut BindgenContext)
- -> Result<ItemId, ParseError> {
- use ir::function::Function;
- use ir::module::Module;
- use ir::var::Var;
- use clangll::*;
-
- if !cursor.is_valid() {
- return Err(ParseError::Continue);
- }
-
- let comment = cursor.raw_comment();
- let annotations = Annotations::new(&cursor);
-
- let current_module = ctx.current_module();
- let relevant_parent_id = parent_id.unwrap_or(current_module);
-
- macro_rules! try_parse {
- ($what:ident) => {
- match $what::parse(cursor, ctx) {
- Ok(ParseResult::New(item, declaration)) => {
- let id = ctx.next_item_id();
-
- ctx.add_item(Item::new(id, comment, annotations,
- relevant_parent_id,
- ItemKind::$what(item)),
- declaration,
- Some(cursor));
- return Ok(id);
- }
- Ok(ParseResult::AlreadyResolved(id)) => {
- return Ok(id);
- }
- Err(ParseError::Recurse) => return Err(ParseError::Recurse),
- Err(ParseError::Continue) => {},
- }
- }
- }
-
- try_parse!(Module);
-
- // NOTE: Is extremely important to parse functions and vars **before**
- // types. Otherwise we can parse a function declaration as a type
- // (which is legal), and lose functions to generate.
- //
- // In general, I'm not totally confident this split between
- // ItemKind::Function and TypeKind::FunctionSig is totally worth it, but
- // I guess we can try.
- try_parse!(Function);
- try_parse!(Var);
-
- // Types are sort of special, so to avoid parsing template classes
- // twice, handle them separately.
- {
- let applicable_cursor = cursor.definition().unwrap_or(cursor);
- match Self::from_ty(&applicable_cursor.cur_type(),
- Some(applicable_cursor),
- parent_id,
- ctx) {
- Ok(ty) => return Ok(ty),
- Err(ParseError::Recurse) => return Err(ParseError::Recurse),
- Err(ParseError::Continue) => {}
- }
- }
-
- // Guess how does clang treat extern "C" blocks?
- if cursor.kind() == CXCursor_UnexposedDecl {
- Err(ParseError::Recurse)
- } else {
- // We whitelist cursors here known to be unhandled, to prevent being
- // too noisy about this.
- match cursor.kind() {
- CXCursor_MacroDefinition |
- CXCursor_MacroExpansion |
- CXCursor_UsingDeclaration |
- CXCursor_StaticAssert |
- CXCursor_InclusionDirective => {
- debug!("Unhandled cursor kind {:?}: {:?}",
- cursor.kind(),
- cursor);
- }
- _ => {
- error!("Unhandled cursor kind {:?}: {:?}",
- cursor.kind(),
- cursor);
- }
- }
-
- Err(ParseError::Continue)
- }
- }
-
- fn from_ty_or_ref(ty: clang::Type,
- location: Option<clang::Cursor>,
- parent_id: Option<ItemId>,
- ctx: &mut BindgenContext)
- -> ItemId {
- let id = ctx.next_item_id();
- Self::from_ty_or_ref_with_id(id,
- ty,
- location,
- parent_id,
- ctx)
- }
-
- /// Parse a C++ type. If we find a reference to a type that has not been
- /// defined yet, use `UnresolvedTypeRef` as a placeholder.
- ///
- /// This logic is needed to avoid parsing items with the incorrect parent
- /// and it's sort of complex to explain, so I'll just point to
- /// `tests/headers/typeref.hpp` to see the kind of constructs that forced
- /// this.
- ///
- /// Typerefs are resolved once parsing is completely done, see
- /// `BindgenContext::resolve_typerefs`.
- fn from_ty_or_ref_with_id(potential_id: ItemId,
- ty: clang::Type,
- location: Option<clang::Cursor>,
- parent_id: Option<ItemId>,
- ctx: &mut BindgenContext)
- -> ItemId {
- debug!("from_ty_or_ref_with_id: {:?} {:?}, {:?}, {:?}",
- potential_id,
- ty,
- location,
- parent_id);
-
- if ctx.collected_typerefs() {
- debug!("refs already collected, resolving directly");
- return Self::from_ty_with_id(potential_id,
- &ty,
- location,
- parent_id,
- ctx)
- .expect("Unable to resolve type");
- }
-
- if let Some(ty) = ctx.builtin_or_resolved_ty(potential_id,
- parent_id, &ty,
- location) {
- debug!("{:?} already resolved: {:?}", ty, location);
- return ty;
- }
-
- debug!("New unresolved type reference: {:?}, {:?}", ty, location);
-
- let is_const = ty.is_const();
- let kind = TypeKind::UnresolvedTypeRef(ty, location, parent_id);
- let current_module = ctx.current_module();
- ctx.add_item(Item::new(potential_id,
- None,
- None,
- parent_id.unwrap_or(current_module),
- ItemKind::Type(Type::new(None,
- None,
- kind,
- is_const))),
- Some(clang::Cursor::null()),
- None);
- potential_id
- }
-
-
- fn from_ty(ty: &clang::Type,
- location: Option<clang::Cursor>,
- parent_id: Option<ItemId>,
- ctx: &mut BindgenContext)
- -> Result<ItemId, ParseError> {
- let id = ctx.next_item_id();
- Self::from_ty_with_id(id, ty, location, parent_id, ctx)
- }
-
- /// This is one of the trickiest methods you'll find (probably along with
- /// some of the ones that handle templates in `BindgenContext`).
- ///
- /// This method parses a type, given the potential id of that type (if
- /// parsing it was correct), an optional location we're scanning, which is
- /// critical some times to obtain information, an optional parent item id,
- /// that will, if it's `None`, become the current module id, and the
- /// context.
- fn from_ty_with_id(id: ItemId,
- ty: &clang::Type,
- location: Option<clang::Cursor>,
- parent_id: Option<ItemId>,
- ctx: &mut BindgenContext)
- -> Result<ItemId, ParseError> {
- use clangll::*;
-
- let decl = {
- let decl = ty.declaration();
- decl.definition().unwrap_or(decl)
- };
-
- let comment = decl.raw_comment()
- .or_else(|| location.as_ref().and_then(|l| l.raw_comment()));
- let annotations = Annotations::new(&decl)
- .or_else(|| location.as_ref().and_then(|l| Annotations::new(l)));
-
- if let Some(ref annotations) = annotations {
- if let Some(ref replaced) = annotations.use_instead_of() {
- ctx.replace(replaced, id);
- }
- }
-
- if let Some(ty) =
- ctx.builtin_or_resolved_ty(id, parent_id, ty, location) {
- return Ok(ty);
- }
-
- // First, check we're not recursing.
- let mut valid_decl = decl.kind() != CXCursor_NoDeclFound;
- let declaration_to_look_for = if valid_decl {
- decl.canonical()
- } else if location.is_some() &&
- location.unwrap().kind() ==
- CXCursor_ClassTemplate {
- valid_decl = true;
- location.unwrap()
- } else {
- decl
- };
-
- if valid_decl {
- if let Some(&(_, item_id)) = ctx.currently_parsed_types
- .iter()
- .find(|&&(d, _)| d == declaration_to_look_for) {
- debug!("Avoiding recursion parsing type: {:?}", ty);
- return Ok(item_id);
- }
- }
-
- let current_module = ctx.current_module();
- if valid_decl {
- ctx.currently_parsed_types.push((declaration_to_look_for, id));
- }
-
- let result = Type::from_clang_ty(id, ty, location, parent_id, ctx);
- let relevant_parent_id = parent_id.unwrap_or(current_module);
- let ret = match result {
- Ok(ParseResult::AlreadyResolved(ty)) => Ok(ty),
- Ok(ParseResult::New(item, declaration)) => {
- ctx.add_item(Item::new(id,
- comment,
- annotations,
- relevant_parent_id,
- ItemKind::Type(item)),
- declaration,
- location);
- Ok(id)
- }
- Err(ParseError::Continue) => Err(ParseError::Continue),
- Err(ParseError::Recurse) => {
- debug!("Item::from_ty recursing in the ast");
- let mut result = Err(ParseError::Recurse);
- if let Some(ref location) = location {
- // Need to pop here, otherwise we'll get stuck.
- //
- // TODO: Find a nicer interface, really. Also, the
- // declaration_to_look_for suspiciously shares a lot of
- // logic with ir::context, so we should refactor that.
- if valid_decl {
- let (popped_decl, _) =
- ctx.currently_parsed_types.pop().unwrap();
- assert_eq!(popped_decl, declaration_to_look_for);
- }
-
- location.visit(|cur| {
- use clangll::*;
- result = Item::from_ty_with_id(id,
- ty,
- Some(cur),
- parent_id,
- ctx);
- match result {
- Ok(..) => CXChildVisit_Break,
- Err(ParseError::Recurse) => CXChildVisit_Recurse,
- Err(ParseError::Continue) => CXChildVisit_Continue,
- }
- });
-
- if valid_decl {
- ctx.currently_parsed_types
- .push((declaration_to_look_for, id));
- }
- }
- // If we have recursed into the AST all we know, and we still
- // haven't found what we've got, let's just make a named type.
- //
- // This is what happens with some template members, for example.
- //
- // FIXME: Maybe we should restrict this to things with parent?
- // It's harmless, but if we restrict that, then
- // tests/headers/nsStyleAutoArray.hpp crashes.
- if let Err(ParseError::Recurse) = result {
- warn!("Unknown type, assuming named template type: id = {:?}; spelling = {}",
- id,
- ty.spelling());
- Ok(Self::named_type_with_id(id,
- ty.spelling(),
- None,
- relevant_parent_id,
- ctx))
- } else {
- result
- }
- }
- };
-
- if valid_decl {
- let (popped_decl, _) = ctx.currently_parsed_types.pop().unwrap();
- assert_eq!(popped_decl, declaration_to_look_for);
- }
-
- ret
- }
-
- /// A named type is a template parameter, e.g., the "T" in Foo<T>. They're
- /// always local so it's the only exception when there's no declaration for
- /// a type.
- ///
- /// It must have an id, and must not be the current module id. Ideally we
- /// could assert the parent id is a Comp(..) type, but that info isn't
- /// available yet.
- fn named_type_with_id<S>(id: ItemId,
- name: S,
- default: Option<ItemId>,
- parent_id: ItemId,
- ctx: &mut BindgenContext)
- -> ItemId
- where S: Into<String>,
- {
- // see tests/headers/const_tparam.hpp
- // and tests/headers/variadic_tname.hpp
- let name = name.into().replace("const ", "").replace(".", "");
-
- ctx.add_item(Item::new(id,
- None,
- None,
- parent_id,
- ItemKind::Type(Type::named(name, default))),
- None,
- None);
-
- id
- }
-
- fn named_type<S>(name: S,
- default: Option<ItemId>,
- parent_id: ItemId,
- ctx: &mut BindgenContext)
- -> ItemId
- where S: Into<String>,
- {
- let id = ctx.next_item_id();
- Self::named_type_with_id(id, name, default, parent_id, ctx)
- }
-}
-
-impl ItemCanonicalName for Item {
- fn canonical_name(&self, ctx: &BindgenContext) -> String {
- debug_assert!(ctx.in_codegen_phase(),
- "You're not supposed to call this yet");
- if let Some(other_canon_type) = self.annotations.use_instead_of() {
- return other_canon_type.to_owned();
- }
- if self.canonical_name_cache.borrow().is_none() {
- *self.canonical_name_cache.borrow_mut() =
- Some(self.real_canonical_name(ctx,
- ctx.options()
- .enable_cxx_namespaces,
- false));
- }
- return self.canonical_name_cache.borrow().as_ref().unwrap().clone();
- }
-}
-
-impl ItemCanonicalPath for Item {
- fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
- if !ctx.options().enable_cxx_namespaces {
- return vec![self.canonical_name(ctx)];
- }
-
- if self.id() == ctx.root_module() {
- match self.kind {
- ItemKind::Module(ref module) => {
- return vec![module.name().unwrap().into()]
- }
- _ => panic!("Something has wrong horribly wrong"),
- }
- }
-
- // TODO: This duplicates too much logic with real_canonical_name.
- if let ItemKind::Type(ref ty) = *self.kind() {
- match *ty.kind() {
- TypeKind::Comp(ref ci) if ci.is_template_specialization() => {
- return ci.specialized_template()
- .unwrap()
- .canonical_path(ctx);
- }
- TypeKind::ResolvedTypeRef(inner) |
- TypeKind::TemplateRef(inner, _) => {
- return inner.canonical_path(ctx);
- }
- TypeKind::Named(ref name, _) => {
- return vec![name.clone()];
- }
- _ => {}
- }
- }
-
- let mut parent_path = self.parent_id().canonical_path(&ctx);
- if parent_path.last()
- .map_or(false, |parent_name| parent_name.is_empty()) {
- // This only happens (or should only happen) when we're an alias,
- // and our parent is a templated alias, in which case the last
- // component of the path will be empty.
- let is_alias = match *self.expect_type().kind() {
- TypeKind::Alias(..) => true,
- _ => false,
- };
- debug_assert!(is_alias, "How can this ever happen?");
- parent_path.pop().unwrap();
- }
- parent_path.push(self.real_canonical_name(ctx, true, false));
-
- parent_path
- }
-}
diff --git a/src/ir/item_kind.rs b/src/ir/item_kind.rs
deleted file mode 100644
index d9e4690c..00000000
--- a/src/ir/item_kind.rs
+++ /dev/null
@@ -1,114 +0,0 @@
-//! Different variants of an `Item` in our intermediate representation.
-
-use super::function::Function;
-use super::module::Module;
-use super::ty::Type;
-use super::var::Var;
-
-/// A item we parse and translate.
-#[derive(Debug)]
-pub enum ItemKind {
- /// A module, created implicitly once (the root module), or via C++
- /// namespaces.
- Module(Module),
-
- /// A type declared in any of the multiple ways it can be declared.
- Type(Type),
-
- /// A function or method declaration.
- Function(Function),
-
- /// A variable declaration, most likely a static.
- Var(Var),
-}
-
-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),
- _ => None,
- }
- }
-
- /// 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),
- _ => None,
- }
- }
-
- /// 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),
- _ => None,
- }
- }
-
- /// 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),
- _ => None,
- }
- }
-
- /// 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),
- _ => None,
- }
- }
-
- /// 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
deleted file mode 100644
index 3ac4a5f4..00000000
--- a/src/ir/layout.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//! 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,
- align: align,
- packed: false,
- }
- }
-
- /// 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/mod.rs b/src/ir/mod.rs
deleted file mode 100644
index 3c658a4a..00000000
--- a/src/ir/mod.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//! The ir module defines bindgen's intermediate representation.
-//!
-//! Parsing C/C++ generates the IR, while code generation outputs Rust code from
-//! the IR.
-
-pub mod annotations;
-pub mod comp;
-pub mod context;
-pub mod enum_ty;
-pub mod function;
-pub mod int;
-pub mod item;
-pub mod item_kind;
-pub mod layout;
-pub mod module;
-pub mod ty;
-pub mod type_collector;
-pub mod var;
diff --git a/src/ir/module.rs b/src/ir/module.rs
deleted file mode 100644
index c5d8cfa7..00000000
--- a/src/ir/module.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-//! Intermediate representation for modules (AKA C++ namespaces).
-
-use clang;
-use parse::{ClangSubItemParser, ParseError, ParseResult};
-use parse_one;
-use super::context::{BindgenContext, ItemId};
-
-/// A module, as in, a C++ namespace.
-#[derive(Clone, Debug)]
-pub struct Module {
- /// The name of the module, or none if it's anonymous.
- name: Option<String>,
- /// The children of this module, just here for convenience.
- children_ids: Vec<ItemId>,
-}
-
-impl Module {
- /// Construct a new `Module`.
- pub fn new(name: Option<String>) -> Self {
- Module {
- name: name,
- children_ids: vec![],
- }
- }
-
- /// 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
- }
-}
-
-impl ClangSubItemParser for Module {
- fn parse(cursor: clang::Cursor,
- ctx: &mut BindgenContext)
- -> Result<ParseResult<Self>, ParseError> {
- use clangll::*;
- match cursor.kind() {
- CXCursor_Namespace => {
- let module_id = ctx.module(cursor);
- ctx.with_module(module_id, |ctx, children| {
- cursor.visit(|cursor| {
- parse_one(ctx, cursor, Some(module_id), children)
- })
- });
-
- Ok(ParseResult::AlreadyResolved(module_id))
- }
- _ => Err(ParseError::Continue),
- }
- }
-}
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
deleted file mode 100644
index 34af2db5..00000000
--- a/src/ir/ty.rs
+++ /dev/null
@@ -1,869 +0,0 @@
-//! Everything related to types in our intermediate representation.
-
-use clang::{self, Cursor};
-use parse::{ClangItemParser, ParseError, ParseResult};
-use super::comp::CompInfo;
-use super::context::{BindgenContext, ItemId};
-use super::enum_ty::Enum;
-use super::function::FunctionSig;
-use super::int::IntKind;
-use super::item::Item;
-use super::layout::Layout;
-use super::type_collector::{ItemSet, TypeCollector};
-
-/// The base representation of a type in bindgen.
-///
-/// A type has an optional name, which if present cannot be empty, a `layout`
-/// (size, alignment and packedness) if known, a `Kind`, which determines which
-/// kind of type it is, and whether the type is const.
-#[derive(Debug)]
-pub struct Type {
- /// The name of the type, or None if it was an unnamed struct or union.
- name: Option<String>,
- /// The layout of the type, if known.
- layout: Option<Layout>,
- /// The inner kind of the type
- kind: TypeKind,
- /// Whether this type is const-qualified.
- is_const: bool,
-}
-
-/// 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),
- _ => None,
- }
- }
-
- /// Construct a new `Type`.
- pub fn new(name: Option<String>,
- layout: Option<Layout>,
- kind: TypeKind,
- is_const: bool)
- -> Self {
- Type {
- name: name,
- layout: layout,
- kind: kind,
- is_const: is_const,
- }
- }
-
- /// 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,
- _ => false,
- }
- }
-
- /// Is this a named type?
- pub fn is_named(&self) -> bool {
- match self.kind {
- TypeKind::Named(..) => true,
- _ => false,
- }
- }
-
- /// Is this a function type?
- pub fn is_function(&self) -> bool {
- match self.kind {
- TypeKind::Function(..) => true,
- _ => false,
- }
- }
-
- /// Is this either a builtin or named type?
- pub fn is_builtin_or_named(&self) -> bool {
- match self.kind {
- TypeKind::Void |
- TypeKind::NullPtr |
- TypeKind::Function(..) |
- TypeKind::Array(..) |
- TypeKind::Reference(..) |
- TypeKind::Pointer(..) |
- TypeKind::BlockPointer |
- TypeKind::Int(..) |
- TypeKind::Float(..) |
- TypeKind::Named(..) => true,
- _ => false,
- }
- }
-
- /// Creates a new named type, with name `name`.
- pub fn named(name: String, default: Option<ItemId>) -> Self {
- assert!(!name.is_empty());
- // TODO: stop duplicating the name, it's stupid.
- let kind = TypeKind::Named(name.clone(), default);
- Self::new(Some(name), None, kind, false)
- }
-
- /// Is this an integer type?
- pub fn is_integer(&self) -> bool {
- match self.kind {
- TypeKind::Int(..) => true,
- _ => false,
- }
- }
-
- /// Is this a `const` qualified type?
- pub fn is_const(&self) -> bool {
- self.is_const
- }
-
- /// Is this a reference to another type?
- pub fn is_type_ref(&self) -> bool {
- match self.kind {
- TypeKind::ResolvedTypeRef(_) |
- TypeKind::UnresolvedTypeRef(_, _, _) => true,
- _ => false,
- }
- }
-
- /// What is the layout of this type?
- pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
- use std::mem;
-
- self.layout.or_else(|| {
- match self.kind {
- TypeKind::Comp(ref ci) => ci.layout(ctx),
- // FIXME(emilio): This is a hack for anonymous union templates.
- // Use the actual pointer size!
- TypeKind::Pointer(..) |
- TypeKind::BlockPointer => {
- Some(Layout::new(mem::size_of::<*mut ()>(),
- mem::align_of::<*mut ()>()))
- }
- TypeKind::ResolvedTypeRef(inner) => {
- ctx.resolve_type(inner).layout(ctx)
- }
- _ => None,
- }
- })
- }
-
- /// Wether we can derive rust's `Debug` annotation in Rust. This should
- /// ideally be a no-op that just returns `true`, but instead needs to be a
- /// recursive method that checks whether all the proper members can derive
- /// debug or not, because of the limit rust has on 32 items as max in the
- /// array.
- pub fn can_derive_debug(&self, ctx: &BindgenContext) -> bool {
- match self.kind {
- TypeKind::Array(t, len) => {
- len <= RUST_DERIVE_IN_ARRAY_LIMIT &&
- ctx.resolve_type(t).can_derive_debug(ctx)
- }
- TypeKind::ResolvedTypeRef(t) |
- TypeKind::TemplateAlias(t, _) |
- TypeKind::Alias(_, t) => ctx.resolve_type(t).can_derive_debug(ctx),
- TypeKind::Comp(ref info) => {
- info.can_derive_debug(ctx, self.layout(ctx))
- }
- _ => true,
- }
- }
-
- /// For some reason, deriving copies of an array of a type that is not known
- /// to be copy is a compile error. e.g.:
- ///
- /// ```rust
- /// #[derive(Copy, Clone)]
- /// struct A<T> {
- /// member: T,
- /// }
- /// ```
- ///
- /// is fine, while:
- ///
- /// ```rust,ignore
- /// #[derive(Copy, Clone)]
- /// struct A<T> {
- /// member: [T; 1],
- /// }
- /// ```
- ///
- /// is an error.
- ///
- /// That's the whole point of the existence of `can_derive_copy_in_array`.
- pub fn can_derive_copy_in_array(&self,
- ctx: &BindgenContext,
- item: &Item)
- -> bool {
- match self.kind {
- TypeKind::ResolvedTypeRef(t) |
- TypeKind::TemplateAlias(t, _) |
- TypeKind::Alias(_, t) |
- TypeKind::Array(t, _) => {
- ctx.resolve_item(t)
- .can_derive_copy_in_array(ctx)
- }
- TypeKind::Named(..) => false,
- _ => self.can_derive_copy(ctx, item),
- }
- }
-
- /// Wether we'd be able to derive the `Copy` trait in Rust or not. Same
- /// rationale than `can_derive_debug`.
- pub fn can_derive_copy(&self, ctx: &BindgenContext, item: &Item) -> bool {
- match self.kind {
- TypeKind::Array(t, len) => {
- len <= RUST_DERIVE_IN_ARRAY_LIMIT &&
- ctx.resolve_item(t).can_derive_copy_in_array(ctx)
- }
- TypeKind::ResolvedTypeRef(t) |
- TypeKind::TemplateAlias(t, _) |
- TypeKind::TemplateRef(t, _) |
- TypeKind::Alias(_, t) => ctx.resolve_item(t).can_derive_copy(ctx),
- TypeKind::Comp(ref info) => info.can_derive_copy(ctx, item),
- _ => true,
- }
- }
-
- /// Whether this type has a vtable.
- pub fn has_vtable(&self, ctx: &BindgenContext) -> bool {
- // FIXME: Can we do something about template parameters? Huh...
- match self.kind {
- TypeKind::TemplateRef(t, _) |
- TypeKind::TemplateAlias(t, _) |
- TypeKind::Alias(_, t) |
- TypeKind::ResolvedTypeRef(t) => ctx.resolve_type(t).has_vtable(ctx),
- TypeKind::Comp(ref info) => info.has_vtable(ctx),
- _ => false,
- }
-
- }
-
- /// Returns whether this type has a destructor.
- pub fn has_destructor(&self, ctx: &BindgenContext) -> bool {
- match self.kind {
- TypeKind::TemplateRef(t, _) |
- TypeKind::TemplateAlias(t, _) |
- TypeKind::Alias(_, t) |
- TypeKind::ResolvedTypeRef(t) => {
- ctx.resolve_type(t).has_destructor(ctx)
- }
- TypeKind::Comp(ref info) => info.has_destructor(ctx),
- _ => false,
- }
- }
-
- /// See the comment in `Item::signature_contains_named_type`.
- pub fn signature_contains_named_type(&self,
- ctx: &BindgenContext,
- ty: &Type)
- -> bool {
- debug_assert!(ty.is_named());
- let name = match *ty.kind() {
- TypeKind::Named(ref name, _) => name,
- _ => unreachable!(),
- };
-
- match self.kind {
- TypeKind::Named(ref this_name, _) => this_name == name,
- TypeKind::ResolvedTypeRef(t) |
- TypeKind::Array(t, _) |
- TypeKind::Pointer(t) |
- TypeKind::Alias(_, t) => {
- ctx.resolve_type(t)
- .signature_contains_named_type(ctx, ty)
- }
- TypeKind::Function(ref sig) => {
- sig.argument_types().iter().any(|&(_, arg)| {
- ctx.resolve_type(arg)
- .signature_contains_named_type(ctx, ty)
- }) ||
- ctx.resolve_type(sig.return_type())
- .signature_contains_named_type(ctx, ty)
- }
- TypeKind::TemplateAlias(_, ref template_args) |
- TypeKind::TemplateRef(_, ref template_args) => {
- template_args.iter().any(|arg| {
- ctx.resolve_type(*arg)
- .signature_contains_named_type(ctx, ty)
- })
- }
- TypeKind::Comp(ref ci) => ci.signature_contains_named_type(ctx, ty),
- _ => false,
- }
- }
-
- /// See safe_canonical_type.
- pub fn canonical_type<'tr>(&'tr self,
- ctx: &'tr BindgenContext)
- -> &'tr Type {
- self.safe_canonical_type(ctx)
- .expect("Should have been resolved after parsing!")
- }
-
- /// Returns the canonical type of this type, that is, the "inner type".
- ///
- /// For example, for a `typedef`, the canonical type would be the
- /// `typedef`ed type, for a template specialization, would be the template
- /// its specializing, and so on. Return None if the type is unresolved.
- pub fn safe_canonical_type<'tr>(&'tr self,
- ctx: &'tr BindgenContext)
- -> Option<&'tr Type> {
- match self.kind {
- TypeKind::Named(..) |
- TypeKind::Array(..) |
- TypeKind::Comp(..) |
- TypeKind::Int(..) |
- TypeKind::Float(..) |
- TypeKind::Complex(..) |
- TypeKind::Function(..) |
- TypeKind::Enum(..) |
- TypeKind::Reference(..) |
- TypeKind::Void |
- TypeKind::NullPtr |
- TypeKind::BlockPointer |
- TypeKind::Pointer(..) => Some(self),
-
- TypeKind::ResolvedTypeRef(inner) |
- TypeKind::Alias(_, inner) |
- TypeKind::TemplateAlias(inner, _) |
- TypeKind::TemplateRef(inner, _) => {
- ctx.resolve_type(inner).safe_canonical_type(ctx)
- }
-
- TypeKind::UnresolvedTypeRef(..) => None,
- }
- }
-}
-
-/// 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,
- /// A `__float128`.
- Float128,
-}
-
-/// The different kinds of types that we can parse.
-#[derive(Debug)]
-pub enum TypeKind {
- /// The void type.
- Void,
-
- /// 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 complex floating point type.
- Complex(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
- /// 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.
- 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`.
- TemplateRef(ItemId, Vec<ItemId>),
-
- /// A reference to a yet-to-resolve type. This stores the clang cursor
- /// itself, and postpones its resolution.
- ///
- /// These are gone in a phase after parsing where these are mapped to
- /// already known types, and are converted to ResolvedTypeRef.
- ///
- /// 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
- /// type.
- Named(String, Option<ItemId>),
-}
-
-impl Type {
- /// Whether this type is unsized, that is, has no members. This is used to
- /// derive whether we should generate a dummy `_address` field for structs,
- /// to comply to the C and C++ layouts, that specify that every type needs
- /// to be addressable.
- pub fn is_unsized(&self, ctx: &BindgenContext) -> bool {
- debug_assert!(ctx.in_codegen_phase(), "Not yet");
-
- match self.kind {
- TypeKind::Void => true,
- TypeKind::Comp(ref ci) => ci.is_unsized(ctx),
- TypeKind::Array(inner, size) => {
- size == 0 || ctx.resolve_type(inner).is_unsized(ctx)
- }
- TypeKind::ResolvedTypeRef(inner) |
- TypeKind::Alias(_, inner) |
- TypeKind::TemplateAlias(inner, _) |
- TypeKind::TemplateRef(inner, _) => {
- ctx.resolve_type(inner).is_unsized(ctx)
- }
- TypeKind::Named(..) |
- TypeKind::Int(..) |
- TypeKind::Float(..) |
- TypeKind::Complex(..) |
- TypeKind::Function(..) |
- TypeKind::Enum(..) |
- TypeKind::Reference(..) |
- TypeKind::NullPtr |
- TypeKind::BlockPointer |
- TypeKind::Pointer(..) => false,
-
- TypeKind::UnresolvedTypeRef(..) => {
- unreachable!("Should have been resolved after parsing!");
- }
- }
- }
-
- /// This is another of the nasty methods. This one is the one that takes
- /// care of the core logic of converting a clang type to a `Type`.
- ///
- /// It's sort of nasty and full of special-casing, but hopefully the
- /// comments in every special case justify why they're there.
- pub fn from_clang_ty(potential_id: ItemId,
- ty: &clang::Type,
- location: Option<Cursor>,
- parent_id: Option<ItemId>,
- ctx: &mut BindgenContext)
- -> Result<ParseResult<Self>, ParseError> {
- use clangll::*;
- {
- let already_resolved =
- ctx.builtin_or_resolved_ty(potential_id,
- parent_id,
- ty,
- location);
- if let Some(ty) = already_resolved {
- debug!("{:?} already resolved: {:?}", ty, location);
- return Ok(ParseResult::AlreadyResolved(ty));
- }
- }
-
- let layout = ty.fallible_layout().ok();
- let cursor = ty.declaration();
- let mut name = cursor.spelling();
-
- debug!("from_clang_ty: {:?}, ty: {:?}, loc: {:?}",
- potential_id,
- ty,
- location);
- debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types);
-
- let canonical_ty = ty.canonical_type();
- let kind = match ty.kind() {
- CXType_Unexposed if *ty != canonical_ty &&
- canonical_ty.kind() != CXType_Invalid => {
- debug!("Looking for canonical type: {:?}", canonical_ty);
- return Self::from_clang_ty(potential_id,
- &canonical_ty,
- location,
- parent_id,
- ctx);
- }
- CXType_Unexposed | CXType_Invalid => {
- // For some reason Clang doesn't give us any hint in some
- // situations where we should generate a function pointer (see
- // tests/headers/func_ptr_in_struct.h), so we do a guess here
- // trying to see if it has a valid return type.
- if ty.ret_type().is_some() {
- let signature = try!(FunctionSig::from_ty(ty,
- &location.unwrap_or(cursor),
- ctx));
- TypeKind::Function(signature)
- // Same here, with template specialisations we can safely
- // assume this is a Comp(..)
- } else if ty.template_args().map_or(false, |x| x.len() > 0) {
- debug!("Template specialization: {:?}", ty);
- let complex =
- CompInfo::from_ty(potential_id, ty, location, ctx)
- .expect("C'mon");
- TypeKind::Comp(complex)
- } else if let Some(location) = location {
- match location.kind() {
- CXCursor_ClassTemplatePartialSpecialization |
- CXCursor_CXXBaseSpecifier |
- CXCursor_ClassTemplate => {
- if location.kind() == CXCursor_CXXBaseSpecifier {
- // In the case we're parsing a base specifier
- // inside an unexposed or invalid type, it means
- // that we're parsing one of two things:
- //
- // * A template parameter.
- // * A complex class that isn't exposed.
- //
- // This means, unfortunately, that there's no
- // good way to differentiate between them.
- //
- // Probably we could try to look at the
- // declaration and complicate more this logic,
- // but we'll keep it simple... if it's a valid
- // C++ identifier, we'll consider it as a
- // template parameter.
- //
- // This is because:
- //
- // * We expect every other base that is a
- // proper identifier (that is, a simple
- // struct/union declaration), to be exposed,
- // so this path can't be reached in that
- // case.
- //
- // * Quite conveniently, complex base
- // specifiers preserve their full names (that
- // is: Foo<T> instead of Foo). We can take
- // advantage of this.
- //
- // If we find some edge case where this doesn't
- // work (which I guess is unlikely, see the
- // different test cases[1][2][3][4]), we'd need
- // to find more creative ways of differentiating
- // these two cases.
- //
- // [1]: inherit_named.hpp
- // [2]: forward-inherit-struct-with-fields.hpp
- // [3]: forward-inherit-struct.hpp
- // [4]: inherit-namespaced.hpp
- if location.spelling()
- .chars()
- .all(|c| c.is_alphanumeric() || c == '_') {
- return Err(ParseError::Recurse);
- }
- } else {
- name = location.spelling();
- }
- let complex = CompInfo::from_ty(potential_id,
- ty,
- Some(location),
- ctx)
- .expect("C'mon");
- TypeKind::Comp(complex)
- }
- CXCursor_TypeAliasTemplateDecl => {
- debug!("TypeAliasTemplateDecl");
-
- // We need to manually unwind this one.
- let mut inner = Err(ParseError::Continue);
- let mut args = vec![];
-
- location.visit(|cur| {
- match cur.kind() {
- CXCursor_TypeAliasDecl => {
- debug_assert!(cur.cur_type().kind() ==
- CXType_Typedef);
- inner =
- Item::from_ty(&cur.cur_type(),
- Some(cur),
- Some(potential_id),
- ctx);
- }
- CXCursor_TemplateTypeParameter => {
- // See the comment in src/ir/comp.rs
- // about the same situation.
- if cur.spelling().is_empty() {
- return CXChildVisit_Continue;
- }
-
- let default_type =
- Item::from_ty(&cur.cur_type(),
- Some(cur),
- Some(potential_id),
- ctx)
- .ok();
- let param =
- Item::named_type(cur.spelling(),
- default_type,
- potential_id,
- ctx);
- args.push(param);
- }
- _ => {}
- }
- CXChildVisit_Continue
- });
-
- if inner.is_err() {
- error!("Failed to parse templated alias {:?}",
- location);
- return Err(ParseError::Continue);
- }
-
- // NB: `args` may be empty here (if for example the
- // template parameters are constants).
- //
- // We can't reject it here then because inner points
- // to `potential_id` now, so either we remove
- // `inner` and return an error, or carry on.
- //
- // In this case, we just carry on, since it seems
- // easier if than removing every possible reference
- // to `item` from `ctx`, and it doesn't give any
- // problems that we didn't have anyway.
- TypeKind::TemplateAlias(inner.unwrap(), args)
- }
- CXCursor_TemplateRef => {
- let referenced = location.referenced().expect("expected value, got none");
- let referenced_ty = referenced.cur_type();
- let referenced_declaration =
- Some(referenced_ty.declaration());
-
- return Self::from_clang_ty(potential_id,
- &referenced_ty,
- referenced_declaration,
- parent_id,
- ctx);
- }
- CXCursor_TypeRef => {
- let referenced = location.referenced().expect("expected value, got none");
- let referenced_ty = referenced.cur_type();
- let referenced_declaration =
- Some(referenced_ty.declaration());
-
- let item =
- Item::from_ty_or_ref_with_id(
- potential_id,
- referenced_ty,
- referenced_declaration,
- parent_id,
- ctx);
- return Ok(ParseResult::AlreadyResolved(item));
- }
- _ => {
- if ty.kind() == CXType_Unexposed {
- warn!("Unexposed type {:?}, recursing inside, \
- loc: {:?}",
- ty,
- location);
- return Err(ParseError::Recurse);
- }
-
- // If the type name is empty we're probably
- // over-recursing to find a template parameter name
- // or something like that, so just don't be too
- // noisy with it since it causes confusion, see for
- // example the discussion in:
- //
- // https://github.com/jamesmunns/teensy3-rs/issues/9
- if !ty.spelling().is_empty() {
- error!("invalid type {:?}", ty);
- } else {
- warn!("invalid type {:?}", ty);
- }
- return Err(ParseError::Continue);
- }
- }
- } else {
- // TODO: Don't duplicate this!
- if ty.kind() == CXType_Unexposed {
- warn!("Unexposed type {:?}, recursing inside", ty);
- return Err(ParseError::Recurse);
- }
-
- if !ty.spelling().is_empty() {
- error!("invalid type {:?}", ty);
- } else {
- warn!("invalid type {:?}", ty);
- }
- return Err(ParseError::Continue);
- }
- }
- // NOTE: We don't resolve pointers eagerly because the pointee type
- // might not have been parsed, and if it contains templates or
- // something else we might get confused, see the comment inside
- // TypeRef.
- //
- // We might need to, though, if the context is already in the
- // process of resolving them.
- CXType_MemberPointer |
- CXType_Pointer => {
- let inner = Item::from_ty_or_ref(ty.pointee_type().unwrap(),
- location,
- parent_id,
- ctx);
- TypeKind::Pointer(inner)
- }
- CXType_BlockPointer => TypeKind::BlockPointer,
- // XXX: RValueReference is most likely wrong, but I don't think we
- // can even add bindings for that, so huh.
- CXType_RValueReference |
- CXType_LValueReference => {
- let inner = Item::from_ty_or_ref(ty.pointee_type().unwrap(),
- location,
- parent_id,
- ctx);
- TypeKind::Reference(inner)
- }
- // XXX DependentSizedArray is wrong
- CXType_VariableArray |
- CXType_DependentSizedArray |
- CXType_IncompleteArray => {
- let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(),
- location,
- parent_id,
- ctx)
- .expect("Not able to resolve array element?");
- TypeKind::Pointer(inner)
- }
- CXType_FunctionNoProto |
- CXType_FunctionProto => {
- let signature = try!(FunctionSig::from_ty(ty,
- &location.unwrap_or(cursor),
- ctx));
- TypeKind::Function(signature)
- }
- CXType_Typedef => {
- let inner = cursor.typedef_type();
- let inner =
- Item::from_ty_or_ref(inner, location, parent_id, ctx);
- TypeKind::Alias(ty.spelling(), inner)
- }
- CXType_Enum => {
- let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?");
- TypeKind::Enum(enum_)
- }
- CXType_Record => {
- let complex =
- CompInfo::from_ty(potential_id, ty, location, ctx)
- .expect("Not a complex type?");
- TypeKind::Comp(complex)
- }
- // FIXME: We stub vectors as arrays since in 99% of the cases the
- // layout is going to be correct, and there's no way we can generate
- // vector types properly in Rust for now.
- //
- // That being said, that should be fixed eventually.
- CXType_Vector |
- CXType_ConstantArray => {
- let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(),
- location,
- parent_id,
- ctx)
- .expect("Not able to resolve array element?");
- TypeKind::Array(inner, ty.num_elements().unwrap())
- }
- #[cfg(not(feature="llvm_stable"))]
- CXType_Elaborated => {
- return Self::from_clang_ty(potential_id,
- &ty.named(),
- location,
- parent_id,
- ctx);
- }
- _ => {
- error!("unsupported type: kind = {:?}; ty = {:?}; at {:?}",
- ty.kind(),
- ty,
- location);
- return Err(ParseError::Continue);
- }
- };
-
- let name = if name.is_empty() { None } else { Some(name) };
- let is_const = ty.is_const();
-
- let ty = Type::new(name, layout, kind, is_const);
- // TODO: maybe declaration.canonical()?
- Ok(ParseResult::New(ty, Some(cursor.canonical())))
- }
-}
-
-impl TypeCollector for Type {
- type Extra = Item;
-
- fn collect_types(&self,
- context: &BindgenContext,
- types: &mut ItemSet,
- item: &Item) {
- match *self.kind() {
- TypeKind::Pointer(inner) |
- TypeKind::Reference(inner) |
- TypeKind::Array(inner, _) |
- TypeKind::TemplateAlias(inner, _) |
- TypeKind::Alias(_, inner) |
- TypeKind::Named(_, Some(inner)) |
- TypeKind::ResolvedTypeRef(inner) => {
- types.insert(inner);
- }
-
- TypeKind::TemplateRef(inner, ref template_args) => {
- types.insert(inner);
- for &item in template_args {
- types.insert(item);
- }
- }
- TypeKind::Comp(ref ci) => ci.collect_types(context, types, item),
- TypeKind::Function(ref sig) => {
- sig.collect_types(context, types, item)
- }
- // FIXME: Pending types!
- ref other @ _ => {
- debug!("<Type as TypeCollector>::collect_types: Ignoring: {:?}", other);
- }
- }
- }
-}
diff --git a/src/ir/type_collector.rs b/src/ir/type_collector.rs
deleted file mode 100644
index 0f10152d..00000000
--- a/src/ir/type_collector.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//! Collecting type items.
-
-use std::collections::BTreeSet;
-use super::context::{BindgenContext, ItemId};
-
-/// A set of items.
-pub type ItemSet = BTreeSet<ItemId>;
-
-/// Collect all the type items referenced by this item.
-pub trait TypeCollector {
- /// If a particular type needs extra information beyond what it has in
- /// `self` and `context` to find its referenced type items, its
- /// implementation can define this associated type, forcing callers to pass
- /// the needed information through.
- type Extra;
-
- /// Add each type item referenced by `self` into the `types` set.
- fn collect_types(&self,
- context: &BindgenContext,
- types: &mut ItemSet,
- extra: &Self::Extra);
-}
diff --git a/src/ir/var.rs b/src/ir/var.rs
deleted file mode 100644
index d0c4d9ca..00000000
--- a/src/ir/var.rs
+++ /dev/null
@@ -1,246 +0,0 @@
-//! Intermediate representation of variables.
-
-use cexpr;
-use clang;
-use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
-use std::num::Wrapping;
-use super::context::{BindgenContext, ItemId};
-use super::function::cursor_mangling;
-use super::int::IntKind;
-use super::item::Item;
-use super::ty::TypeKind;
-
-/// A `Var` is our intermediate representation of a variable.
-#[derive(Debug)]
-pub struct Var {
- /// The name of the variable.
- name: String,
- /// The mangled name of the variable.
- mangled_name: Option<String>,
- /// The type of the variable.
- ty: ItemId,
- /// TODO: support non-integer constants?
- /// The integer value of the variable.
- val: Option<i64>,
- /// Whether this variable is const.
- is_const: bool,
-}
-
-impl Var {
- /// Construct a new `Var`.
- pub fn new(name: String,
- mangled: Option<String>,
- ty: ItemId,
- val: Option<i64>,
- is_const: bool)
- -> Var {
- assert!(!name.is_empty());
- Var {
- name: name,
- mangled_name: mangled,
- ty: ty,
- val: val,
- is_const: is_const,
- }
- }
-
- /// 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)
- }
-}
-
-impl ClangSubItemParser for Var {
- fn parse(cursor: clang::Cursor,
- ctx: &mut BindgenContext)
- -> Result<ParseResult<Self>, ParseError> {
- use clangll::*;
- use cexpr::expr::EvalResult;
- match cursor.kind() {
- CXCursor_MacroDefinition => {
- let value = parse_macro(ctx, &cursor, ctx.translation_unit());
-
- let (id, value) = match value {
- Some(v) => v,
- None => return Err(ParseError::Continue),
- };
-
- assert!(!id.is_empty(), "Empty macro name?");
-
- let previously_defined = ctx.parsed_macro(&id);
-
- // NB: It's important to "note" the macro even if the result is
- // not an integer, otherwise we might loose other kind of
- // derived macros.
- ctx.note_parsed_macro(id.clone(), value.clone());
-
- if previously_defined {
- let name = String::from_utf8(id).unwrap();
- warn!("Duplicated macro definition: {}", name);
- return Err(ParseError::Continue);
- }
-
- // NOTE: Unwrapping, here and above, is safe, because the
- // identifier of a token comes straight from clang, and we
- // enforce utf8 there, so we should have already panicked at
- // this point.
- let name = String::from_utf8(id).unwrap();
- let (int_kind, val) = match value {
- // TODO(emilio): Handle the non-invalid ones!
- EvalResult::Float(..) |
- EvalResult::Char(..) |
- EvalResult::Str(..) |
- EvalResult::Invalid => return Err(ParseError::Continue),
-
- EvalResult::Int(Wrapping(value)) => {
- let kind = ctx.options()
- .type_chooser
- .as_ref()
- .and_then(|c| c.int_macro(&name, value))
- .unwrap_or_else(|| {
- if value < 0 {
- if value < i32::min_value() as i64 {
- IntKind::LongLong
- } else {
- IntKind::Int
- }
- } else if value > u32::max_value() as i64 {
- IntKind::ULongLong
- } else {
- IntKind::UInt
- }
- });
-
- (kind, value)
- }
- };
-
- let ty = Item::builtin_type(TypeKind::Int(int_kind), true, ctx);
-
- Ok(ParseResult::New(Var::new(name, None, ty, Some(val), true),
- Some(cursor)))
- }
- CXCursor_VarDecl => {
- let name = cursor.spelling();
- if name.is_empty() {
- warn!("Empty constant name?");
- return Err(ParseError::Continue);
- }
-
- let ty = cursor.cur_type();
-
- // XXX this is redundant, remove!
- let is_const = ty.is_const();
-
- let ty = Item::from_ty(&ty, Some(cursor), None, ctx)
- .expect("Unable to resolve constant type?");
-
- // Note: Ty might not be totally resolved yet, see
- // tests/headers/inner_const.hpp
- //
- // That's fine because in that case we know it's not a literal.
- let value = ctx.safe_resolve_type(ty)
- .and_then(|t| t.safe_canonical_type(ctx))
- .and_then(|t| if t.is_integer() { Some(t) } else { None })
- .and_then(|_| {
- get_integer_literal_from_cursor(&cursor,
- ctx.translation_unit())
- });
-
- let mangling = cursor_mangling(&cursor);
-
- let var = Var::new(name, mangling, ty, value, is_const);
- Ok(ParseResult::New(var, Some(cursor)))
-
- }
- _ => {
- /* TODO */
- Err(ParseError::Continue)
- }
- }
- }
-}
-
-/// Try and parse a macro using all the macros parsed until now.
-fn parse_macro(ctx: &BindgenContext,
- cursor: &clang::Cursor,
- unit: &clang::TranslationUnit)
- -> Option<(Vec<u8>, cexpr::expr::EvalResult)> {
- use cexpr::{expr, nom};
-
- let cexpr_tokens = match unit.cexpr_tokens(cursor) {
- None => return None,
- Some(tokens) => tokens,
- };
-
- let parser = expr::IdentifierParser::new(ctx.parsed_macros());
- let result = parser.macro_definition(&cexpr_tokens);
-
- match result {
- nom::IResult::Done(_, (id, val)) => Some((id.into(), val)),
- _ => None,
- }
-}
-
-fn parse_int_literal_tokens(cursor: &clang::Cursor,
- unit: &clang::TranslationUnit)
- -> Option<i64> {
- use cexpr::{expr, nom};
- use cexpr::expr::EvalResult;
-
- let cexpr_tokens = match unit.cexpr_tokens(cursor) {
- None => return None,
- Some(tokens) => tokens,
- };
-
- // TODO(emilio): We can try to parse other kinds of literals.
- match expr::expr(&cexpr_tokens) {
- nom::IResult::Done(_, EvalResult::Int(Wrapping(val))) => Some(val),
- _ => None,
- }
-}
-
-fn get_integer_literal_from_cursor(cursor: &clang::Cursor,
- unit: &clang::TranslationUnit)
- -> Option<i64> {
- use clangll::*;
- let mut value = None;
- cursor.visit(|c| {
- match c.kind() {
- CXCursor_IntegerLiteral |
- CXCursor_UnaryOperator => {
- value = parse_int_literal_tokens(&c, unit);
- }
- CXCursor_UnexposedExpr => {
- value = get_integer_literal_from_cursor(&c, unit);
- }
- _ => (),
- }
- if value.is_some() {
- CXChildVisit_Break
- } else {
- CXChildVisit_Continue
- }
- });
- value
-}
diff --git a/src/lib.rs b/src/lib.rs
deleted file mode 100755
index b56cb468..00000000
--- a/src/lib.rs
+++ /dev/null
@@ -1,614 +0,0 @@
-//! Generate Rust bindings for C and C++ libraries.
-//!
-//! Provide a C/C++ header file, receive Rust FFI code to call into C/C++
-//! functions and use types defined in the header.
-//!
-//! See the [Builder](./struct.Builder.html) struct for usage.
-
-#![crate_name = "bindgen"]
-#![crate_type = "dylib"]
-
-#![cfg_attr(feature = "clippy", feature(plugin))]
-#![cfg_attr(feature = "clippy", plugin(clippy))]
-
-#![deny(missing_docs)]
-#![deny(warnings)]
-
-// We internally use the deprecated BindgenOptions all over the place. Once we
-// remove its `pub` declaration, we can un-deprecate it and remove this pragma.
-#![allow(deprecated)]
-
-// To avoid rather annoying warnings when matching with CXCursor_xxx as a
-// constant.
-#![allow(non_upper_case_globals)]
-
-#[macro_use]
-extern crate cfg_if;
-extern crate cexpr;
-extern crate syntex_syntax as syntax;
-extern crate aster;
-extern crate quasi;
-extern crate clang_sys;
-extern crate libc;
-extern crate regex;
-#[macro_use]
-extern crate log;
-#[macro_use]
-extern crate lazy_static;
-
-// A macro to declare an internal module for which we *must* provide
-// documentation for. If we are building with the "_docs" feature, then the
-// module is declared public, and our `#![deny(missing_docs)]` pragma applies to
-// it. This feature is used in CI, so we won't let anything slip by
-// undocumented. Normal builds, however, will leave the module private, so that
-// we don't expose internals to library consumers.
-macro_rules! doc_mod {
- ($m:ident, $doc_mod_name:ident) => {
- cfg_if! {
- if #[cfg(feature = "_docs")] {
- pub mod $doc_mod_name {
- //! Autogenerated documentation module.
- pub use super::$m::*;
- }
- } else {
- }
- }
- };
-}
-
-mod clangll;
-mod clang;
-mod ir;
-mod parse;
-mod regex_set;
-mod uses;
-
-pub mod chooser;
-
-#[cfg(rustfmt)]
-mod codegen;
-
-doc_mod!(clang, clang_docs);
-doc_mod!(ir, ir_docs);
-doc_mod!(parse, parse_docs);
-doc_mod!(regex_set, regex_set_docs);
-doc_mod!(uses, uses_docs);
-
-mod codegen {
- include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
-}
-
-use ir::context::{BindgenContext, ItemId};
-use ir::item::Item;
-use parse::{ClangItemParser, ParseError};
-use regex_set::RegexSet;
-
-use std::borrow::Borrow;
-use std::collections::HashSet;
-use std::fs::OpenOptions;
-use std::io::{self, Write};
-use std::path::Path;
-
-use syntax::ast;
-use syntax::codemap::{DUMMY_SP, Span};
-use syntax::print::pp::eof;
-use syntax::print::pprust;
-use syntax::ptr::P;
-
-/// Configure and generate Rust bindings for a C/C++ header.
-///
-/// This is the main entry point to the library.
-///
-/// ```ignore
-/// use bindgen::builder;
-///
-/// // Configure and generate bindings.
-/// let bindings = try!(builder().header("path/to/input/header")
-/// .whitelisted_type("SomeCoolClass")
-/// .whitelisted_function("do_some_cool_thing")
-/// .generate());
-///
-/// // Write the generated bindings to an output file.
-/// try!(bindings.write_to_file("path/to/output.rs"));
-/// ```
-#[derive(Debug,Default)]
-pub struct Builder {
- options: BindgenOptions,
-}
-
-/// Construct a new [`Builder`](./struct.Builder.html).
-pub fn builder() -> Builder {
- Default::default()
-}
-
-impl Builder {
- /// Set the input C/C++ header.
- pub fn header<T: Into<String>>(mut self, header: T) -> Builder {
- let header = header.into();
- self.options.input_header = Some(header.clone());
- self.clang_arg(header)
- }
-
- /// Generate a C/C++ file that includes the header and has dummy uses of
- /// every type defined in the header.
- pub fn dummy_uses<T: Into<String>>(mut self, dummy_uses: T) -> Builder {
- self.options.dummy_uses = Some(dummy_uses.into());
- self
- }
-
- /// Hide the given type from the generated bindings.
- pub fn hide_type<T: Into<String>>(mut self, arg: T) -> Builder {
- self.options.hidden_types.insert(arg.into());
- self
- }
-
- /// Treat the given type as opaque in the generated bindings.
- pub fn opaque_type<T: Into<String>>(mut self, arg: T) -> Builder {
- self.options.opaque_types.insert(arg.into());
- self
- }
-
- /// Whitelist the given type so that it (and all types that it transitively
- /// refers to) appears in the generated bindings.
- pub fn whitelisted_type<T: Borrow<str>>(mut self, arg: T) -> Builder {
- self.options.whitelisted_types.insert(&arg);
- self
- }
-
- /// Whitelist the given function so that it (and all types that it
- /// transitively refers to) appears in the generated bindings.
- pub fn whitelisted_function<T: Borrow<str>>(mut self, arg: T) -> Builder {
- self.options.whitelisted_functions.insert(&arg);
- self
- }
-
- /// Whitelist the given variable so that it (and all types that it
- /// transitively refers to) appears in the generated bindings.
- pub fn whitelisted_var<T: Borrow<str>>(mut self, arg: T) -> Builder {
- self.options.whitelisted_vars.insert(&arg);
- self
- }
-
- /// Mark the given enum (or set of enums, if using a pattern) as being
- /// bitfield-like.
- ///
- /// This makes bindgen generate a type that isn't a rust `enum`.
- pub fn bitfield_enum<T: Borrow<str>>(mut self, arg: T) -> Builder {
- self.options.bitfield_enums.insert(&arg);
- self
- }
-
- /// Add a string to prepend to the generated bindings. The string is passed
- /// through without any modification.
- pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Builder {
- self.options.raw_lines.push(arg.into());
- self
- }
-
- /// Add an argument to be passed straight through to clang.
- pub fn clang_arg<T: Into<String>>(mut self, arg: T) -> Builder {
- self.options.clang_args.push(arg.into());
- self
- }
-
- /// Make the generated bindings link the given shared library.
- pub fn link<T: Into<String>>(mut self, library: T) -> Builder {
- self.options.links.push((library.into(), LinkType::Default));
- self
- }
-
- /// Make the generated bindings link the given static library.
- pub fn link_static<T: Into<String>>(mut self, library: T) -> Builder {
- self.options.links.push((library.into(), LinkType::Static));
- self
- }
-
- /// Make the generated bindings link the given framework.
- pub fn link_framework<T: Into<String>>(mut self, library: T) -> Builder {
- self.options.links.push((library.into(), LinkType::Framework));
- self
- }
-
- /// Emit bindings for builtin definitions (for example `__builtin_va_list`)
- /// in the generated Rust.
- pub fn emit_builtins(mut self) -> Builder {
- self.options.builtins = true;
- self
- }
-
- /// Avoid converting floats to f32/f64 by default.
- pub fn no_convert_floats(mut self) -> Self {
- self.options.convert_floats = false;
- self
- }
-
- /// Emit Clang AST.
- pub fn emit_clang_ast(mut self) -> Builder {
- self.options.emit_ast = true;
- self
- }
-
- /// Enable C++ namespaces.
- pub fn enable_cxx_namespaces(mut self) -> Builder {
- self.options.enable_cxx_namespaces = true;
- self
- }
-
- /// Ignore functions.
- pub fn ignore_functions(mut self) -> Builder {
- self.options.ignore_functions = true;
- self
- }
-
- /// Ignore methods.
- pub fn ignore_methods(mut self) -> Builder {
- self.options.ignore_methods = true;
- self
- }
-
- /// Avoid generating any unstable Rust in the generated bindings.
- pub fn no_unstable_rust(mut self) -> Builder {
- self.options.unstable_rust = false;
- self
- }
-
- /// Use core instead of libstd in the generated bindings.
- pub fn use_core(mut self) -> Builder {
- self.options.use_core = true;
- self
- }
-
- /// Use the given prefix for the raw types instead of `::std::os::raw`.
- pub fn ctypes_prefix<T: Into<String>>(mut self, prefix: T) -> Builder {
- self.options.ctypes_prefix = Some(prefix.into());
- self
- }
-
- /// Allows configuring types in different situations, see the `TypeChooser`
- /// documentation.
- pub fn type_chooser(mut self, cb: Box<chooser::TypeChooser>) -> Self {
- self.options.type_chooser = Some(cb);
- self
- }
-
- /// Generate the Rust bindings using the options built up thus far.
- pub fn generate<'ctx>(self) -> Result<Bindings<'ctx>, ()> {
- Bindings::generate(self.options, None)
- }
-}
-
-/// Configuration options for generated bindings.
-///
-/// Deprecated: use a `Builder` instead.
-#[derive(Debug)]
-#[deprecated]
-pub struct BindgenOptions {
- /// The set of types that have been blacklisted and should not appear
- /// anywhere in the generated code.
- pub hidden_types: HashSet<String>,
-
- /// The set of types that should be treated as opaque structures in the
- /// generated code.
- pub opaque_types: HashSet<String>,
-
- /// The set of types that we should have bindings for in the generated
- /// code.
- ///
- /// This includes all types transitively reachable from any type in this
- /// set. One might think of whitelisted types/vars/functions as GC roots,
- /// and the generated Rust code as including everything that gets marked.
- pub whitelisted_types: RegexSet,
-
- /// Whitelisted functions. See docs for `whitelisted_types` for more.
- pub whitelisted_functions: RegexSet,
-
- /// Whitelisted variables. See docs for `whitelisted_types` for more.
- pub whitelisted_vars: RegexSet,
-
- /// The enum patterns to mark an enum as bitfield.
- pub bitfield_enums: RegexSet,
-
- /// Whether we should generate builtins or not.
- pub builtins: bool,
-
- /// The set of libraries we should link in the generated Rust code.
- pub links: Vec<(String, LinkType)>,
-
- /// True if we should dump the Clang AST for debugging purposes.
- pub emit_ast: bool,
-
- /// True if we should ignore functions and only generate bindings for
- /// structures, types, and methods.
- pub ignore_functions: bool,
-
- /// True if we should avoid generating bindings for methods, and instead
- /// just generate code for structures and types.
- pub ignore_methods: bool,
-
- /// True if we should emulate C++ namespaces with Rust modules in the
- /// generated bindings.
- pub enable_cxx_namespaces: bool,
-
- /// True if we shold derive Debug trait implementations for C/C++ structures
- /// and types.
- pub derive_debug: bool,
-
- /// True if we can use unstable Rust code in the bindings, false if we
- /// cannot.
- pub unstable_rust: bool,
-
- /// True if we should avoid using libstd to use libcore instead.
- pub use_core: bool,
-
- /// An optional prefix for the "raw" types, like `c_int`, `c_void`...
- pub ctypes_prefix: Option<String>,
-
- /// True if we should generate constant names that are **directly** under
- /// namespaces.
- pub namespaced_constants: bool,
-
- /// True if we should use MSVC name mangling rules.
- pub msvc_mangling: bool,
-
- /// Whether we should convert float types to f32/f64 types.
- pub convert_floats: bool,
-
- /// The set of raw lines to prepend to the generated Rust code.
- pub raw_lines: Vec<String>,
-
- /// The set of arguments to pass straight through to Clang.
- pub clang_args: Vec<String>,
-
- /// The input header file.
- pub input_header: Option<String>,
-
- /// Generate a dummy C/C++ file that includes the header and has dummy uses
- /// of all types defined therein. See the `uses` module for more.
- pub dummy_uses: Option<String>,
-
- /// A user-provided type chooser to allow customizing different kinds of
- /// situations.
- pub type_chooser: Option<Box<chooser::TypeChooser>>,
-}
-
-impl Default for BindgenOptions {
- fn default() -> BindgenOptions {
- BindgenOptions {
- hidden_types: Default::default(),
- opaque_types: Default::default(),
- whitelisted_types: Default::default(),
- whitelisted_functions: Default::default(),
- whitelisted_vars: Default::default(),
- bitfield_enums: Default::default(),
- builtins: false,
- links: vec![],
- emit_ast: false,
- ignore_functions: false,
- ignore_methods: false,
- derive_debug: true,
- enable_cxx_namespaces: false,
- unstable_rust: true,
- use_core: false,
- ctypes_prefix: None,
- namespaced_constants: true,
- msvc_mangling: false,
- convert_floats: true,
- raw_lines: vec![],
- clang_args: vec![],
- input_header: None,
- dummy_uses: None,
- type_chooser: None,
- }
- }
-}
-
-/// The linking type to use with a given library.
-///
-/// TODO: #104: This is ignored at the moment, but shouldn't be.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub enum LinkType {
- /// Use shared library linking. This is the default.
- Default,
- /// Use static linking.
- Static,
- /// The library is an OSX framework.
- Framework,
-}
-
-/// Generated Rust bindings.
-#[derive(Debug)]
-pub struct Bindings<'ctx> {
- context: BindgenContext<'ctx>,
- module: ast::Mod,
-}
-
-impl<'ctx> Bindings<'ctx> {
- /// Generate bindings for the given options.
- ///
- /// Deprecated - use a `Builder` instead
- #[deprecated]
- pub fn generate(options: BindgenOptions,
- span: Option<Span>)
- -> Result<Bindings<'ctx>, ()> {
- let span = span.unwrap_or(DUMMY_SP);
-
- let mut context = BindgenContext::new(options);
- parse(&mut context);
-
- let module = ast::Mod {
- inner: span,
- items: codegen::codegen(&mut context),
- };
-
- Ok(Bindings {
- context: context,
- module: module,
- })
- }
-
- /// Convert these bindings into a Rust AST.
- pub fn into_ast(self) -> Vec<P<ast::Item>> {
- self.module.items
- }
-
- /// Convert these bindings into source text (with raw lines prepended).
- pub fn to_string(&self) -> String {
- let mut mod_str = vec![];
- {
- let ref_writer = Box::new(mod_str.by_ref()) as Box<Write>;
- self.write(ref_writer).expect("Could not write bindings to string");
- }
- String::from_utf8(mod_str).unwrap()
- }
-
- /// Write these bindings as source text to a file.
- pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
- let file = try!(OpenOptions::new()
- .write(true)
- .truncate(true)
- .create(true)
- .open(path));
- self.write(Box::new(file))
- }
-
- /// Write these bindings as source text to the given `Write`able.
- // https://github.com/Manishearth/rust-clippy/issues/740
- #[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
- pub fn write<'a>(&self, mut writer: Box<Write + 'a>) -> io::Result<()> {
- try!(writer.write("/* automatically generated by rust-bindgen */\n\n"
- .as_bytes()));
-
- for line in self.context.options().raw_lines.iter() {
- try!(writer.write(line.as_bytes()));
- try!(writer.write("\n".as_bytes()));
- }
- if !self.context.options().raw_lines.is_empty() {
- try!(writer.write("\n".as_bytes()));
- }
-
- let mut ps = pprust::rust_printer(writer);
- try!(ps.print_mod(&self.module, &[]));
- try!(ps.print_remaining_comments());
- try!(eof(&mut ps.s));
- ps.s.out.flush()
- }
-
- /// Generate and write dummy uses of all the types we parsed, if we've been
- /// requested to do so in the options.
- ///
- /// See the `uses` module for more information.
- pub fn write_dummy_uses(&mut self) -> io::Result<()> {
- let file =
- if let Some(ref dummy_path) = self.context.options().dummy_uses {
- Some(try!(OpenOptions::new()
- .write(true)
- .truncate(true)
- .create(true)
- .open(dummy_path)))
- } else {
- None
- };
-
- if let Some(file) = file {
- try!(uses::generate_dummy_uses(&mut self.context, file));
- }
-
- Ok(())
- }
-}
-
-/// Determines whether the given cursor is in any of the files matched by the
-/// options.
-fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
- let (file, _, _, _) = cursor.location().location();
-
- match file.name() {
- None => ctx.options().builtins,
- Some(..) => true,
- }
-}
-
-/// Parse one `Item` from the Clang cursor.
-pub fn parse_one(ctx: &mut BindgenContext,
- cursor: clang::Cursor,
- parent: Option<ItemId>,
- children: &mut Vec<ItemId>)
- -> clangll::Enum_CXVisitorResult {
- if !filter_builtins(ctx, &cursor) {
- return CXChildVisit_Continue;
- }
-
- use clangll::CXChildVisit_Continue;
- match Item::parse(cursor, parent, ctx) {
- Ok(id) => children.push(id),
- Err(ParseError::Continue) => {}
- Err(ParseError::Recurse) => {
- cursor.visit(|child| parse_one(ctx, child, parent, children));
- }
- }
- CXChildVisit_Continue
-}
-
-/// Parse the Clang AST into our `Item` internal representation.
-fn parse(context: &mut BindgenContext) {
- use clang::Diagnostic;
- use clangll::*;
-
- for d in context.translation_unit().diags().iter() {
- let msg = d.format(Diagnostic::default_opts());
- let is_err = d.severity() >= CXDiagnostic_Error;
- println!("{}, err: {}", msg, is_err);
- }
-
- let cursor = context.translation_unit().cursor();
- if context.options().emit_ast {
- cursor.visit(|cur| clang::ast_dump(&cur, 0));
- }
-
- let root = context.root_module();
- context.with_module(root, |context, children| {
- cursor.visit(|cursor| parse_one(context, cursor, None, children))
- });
-
- assert!(context.current_module() == context.root_module(),
- "How did this happen?");
-}
-
-/// Extracted Clang version data
-#[derive(Debug)]
-pub struct ClangVersion {
- /// Major and minor semvar, if parsing was successful
- pub parsed: Option<(u32, u32)>,
- /// full version string
- pub full: String,
-}
-
-/// Get the major and the minor semvar numbers of Clang's version
-pub fn clang_version() -> ClangVersion {
- let raw_v: String = clang::extract_clang_version();
- let split_v: Option<Vec<&str>> = raw_v.split_whitespace()
- .nth(2)
- .map(|v| v.split('.').collect());
- match split_v {
- Some(v) => {
- if v.len() >= 2 {
- let maybe_major = v[0].parse::<u32>();
- let maybe_minor = v[1].parse::<u32>();
- match (maybe_major, maybe_minor) {
- (Ok(major), Ok(minor)) => {
- return ClangVersion {
- parsed: Some((major, minor)),
- full: raw_v.clone(),
- }
- }
- _ => {}
- }
- }
- }
- None => {}
- };
- ClangVersion {
- parsed: None,
- full: raw_v.clone(),
- }
-}
diff --git a/src/bin/bindgen.rs b/src/main.rs
index 14e882bc..8cbff63b 100755..100644
--- a/src/bin/bindgen.rs
+++ b/src/main.rs
@@ -1,7 +1,4 @@
-#![crate_name = "bindgen"]
-#![crate_type = "bin"]
-
-extern crate bindgen;
+extern crate libbindgen;
extern crate env_logger;
#[macro_use]
extern crate log;
@@ -9,7 +6,7 @@ extern crate clang_sys;
extern crate clap;
extern crate rustc_serialize;
-use bindgen::clang_version;
+use libbindgen::clang_version;
use std::env;
mod options;
diff --git a/src/bin/options.rs b/src/options.rs
index 9f746fd0..c3c6a1f2 100644
--- a/src/bin/options.rs
+++ b/src/options.rs
@@ -1,8 +1,5 @@
-
-
-use bindgen::{Builder, builder};
-
use clap::{App, Arg};
+use libbindgen::{Builder, builder};
use std::fs::File;
use std::io::{self, Error, ErrorKind};
diff --git a/src/parse.rs b/src/parse.rs
deleted file mode 100644
index 28e65759..00000000
--- a/src/parse.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-//! Common traits and types related to parsing our IR from Clang cursors.
-
-use clang;
-use ir::context::{BindgenContext, ItemId};
-use ir::ty::TypeKind;
-
-/// Not so much an error in the traditional sense, but a control flow message
-/// when walking over Clang's AST with a cursor.
-#[derive(Debug)]
-pub enum ParseError {
- /// Recurse down the current AST node's children.
- Recurse,
- /// Continue on to the next sibling AST node, or back up to the parent's
- /// siblings if we've exhausted all of this node's siblings (and so on).
- Continue,
-}
-
-/// The result of parsing a Clang AST node.
-#[derive(Debug)]
-pub enum ParseResult<T> {
- /// We've already resolved this item before, here is the extant `ItemId` for
- /// it.
- AlreadyResolved(ItemId),
-
- /// This is a newly parsed item. If the cursor is `Some`, it points to the
- /// AST node where the new `T` was declared.
- New(T, Option<clang::Cursor>),
-}
-
-/// An intermediate representation "sub-item" (i.e. one of the types contained
-/// inside an `ItemKind` variant) that can be parsed from a Clang cursor.
-pub trait ClangSubItemParser: Sized {
- /// Attempt to parse this type from the given cursor.
- ///
- /// 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>;
-}
-
-/// An intermediate representation item that can be parsed from a Clang cursor.
-pub trait ClangItemParser: Sized {
- /// Parse this item from the given Clang cursor.
- fn parse(cursor: clang::Cursor,
- parent: Option<ItemId>,
- context: &mut BindgenContext)
- -> Result<ItemId, ParseError>;
-
- /// Parse this item from the given Clang type.
- fn from_ty(ty: &clang::Type,
- location: Option<clang::Cursor>,
- parent: Option<ItemId>,
- ctx: &mut BindgenContext)
- -> Result<ItemId, ParseError>;
-
- /// Identical to `from_ty`, but use the given `id` as the `ItemId` for the
- /// newly parsed item.
- fn from_ty_with_id(id: ItemId,
- ty: &clang::Type,
- location: Option<clang::Cursor>,
- parent: Option<ItemId>,
- ctx: &mut BindgenContext)
- -> Result<ItemId, ParseError>;
-
- /// Parse this item from the given Clang type, or if we haven't resolved all
- /// the other items this one depends on, an unresolved reference.
- fn from_ty_or_ref(ty: clang::Type,
- location: Option<clang::Cursor>,
- parent_id: Option<ItemId>,
- context: &mut BindgenContext)
- -> ItemId;
-
- /// Identical to `from_ty_or_ref`, but use the given `potential_id` as the
- /// `ItemId` for the newly parsed item.
- fn from_ty_or_ref_with_id(potential_id: ItemId,
- ty: clang::Type,
- location: Option<clang::Cursor>,
- parent_id: Option<ItemId>,
- context: &mut BindgenContext)
- -> ItemId;
-
- /// Create a named template type.
- fn named_type<S>(name: S,
- default: Option<ItemId>,
- parent: ItemId,
- context: &mut BindgenContext)
- -> ItemId
- where S: Into<String>;
-
- /// Identical to `named_type`, but use `id` as the resulting item's
- /// `ItemId`.
- fn named_type_with_id<S>(id: ItemId,
- name: S,
- default: Option<ItemId>,
- parent: ItemId,
- context: &mut BindgenContext)
- -> ItemId
- where S: Into<String>;
-
- /// Create a builtin type.
- fn builtin_type(kind: TypeKind,
- is_const: bool,
- context: &mut BindgenContext)
- -> ItemId;
-}
diff --git a/src/regex_set.rs b/src/regex_set.rs
deleted file mode 100644
index 93130590..00000000
--- a/src/regex_set.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-//! A type that represents the union of a set of regular expressions.
-
-use regex::Regex;
-use std::borrow::Borrow;
-
-// Yeah, I'm aware this is sorta crappy, should be cheaper to compile a regex
-// ORing all the patterns, I guess...
-
-/// A dynamic set of regular expressions.
-#[derive(Debug)]
-pub struct RegexSet {
- items: Vec<Regex>,
-}
-
-impl RegexSet {
- /// Is this set empty?
- pub fn is_empty(&self) -> bool {
- self.items.is_empty()
- }
-
- /// Extend this set with every regex in the iterator.
- pub fn extend<I>(&mut self, iter: I)
- where I: IntoIterator<Item = String>,
- {
- for s in iter.into_iter() {
- self.insert(&s)
- }
- }
-
- /// Insert a new regex into this set.
- pub fn insert<S>(&mut self, string: &S)
- where S: Borrow<str>,
- {
- let s = string.borrow();
- match Regex::new(&format!("^{}$", s)) {
- Ok(r) => {
- self.items.push(r);
- }
- Err(err) => {
- error!("Invalid pattern provided: {}, {:?}", s, err);
- }
- }
- }
-
- /// Does the given `string` match any of the regexes in this set?
- pub fn matches<S>(&self, string: &S) -> bool
- where S: Borrow<str>,
- {
- let s = string.borrow();
- for r in &self.items {
- if r.is_match(s) {
- return true;
- }
- }
-
- false
- }
-}
-
-impl Default for RegexSet {
- fn default() -> Self {
- RegexSet {
- items: vec![],
- }
- }
-}
diff --git a/src/uses.rs b/src/uses.rs
deleted file mode 100644
index 47f72da6..00000000
--- a/src/uses.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-//! Take in our IR and output a C/C++ file with dummy uses of each IR type.
-//!
-//! Say that we had this C++ header, `header.hpp`:
-//!
-//! ```c++
-//! class Point {
-//! int x;
-//! int y;
-//! }
-//!
-//! enum Bar {
-//! THIS,
-//! THAT,
-//! OTHER
-//! }
-//! ```
-//!
-//! If we generated dummy uses for this header, we would get a `.cpp` file like
-//! this:
-//!
-//! ```c++
-//! #include "header.hpp"
-//!
-//! void dummy(Point*) {}
-//! void dummy(Bar*) {}
-//! ```
-//!
-//! This is useful because we can compile this `.cpp` file into an object file,
-//! and then compare its debugging information to the debugging information
-//! generated for our Rust bindings. These two sets of debugging information had
-//! better agree on the C/C++ types' physical layout, or else our bindings are
-//! incorrect!
-//!
-//! "But you still haven't explained why we have to generate the dummy uses" you
-//! complain. Well if the types are never used, then they are elided when the
-//! C/C++ compiler generates debugging information.
-
-use ir::context::BindgenContext;
-use ir::item::{Item, ItemAncestors, ItemCanonicalName};
-use std::io;
-
-// Like `canonical_path`, except we always take namespaces into account, ignore
-// the generated names of anonymous items, and return a `String`.
-//
-// TODO: Would it be easier to try and demangle the USR?
-fn namespaced_name(ctx: &BindgenContext, item: &Item) -> String {
- let mut names: Vec<_> = item.ancestors(ctx)
- .map(|id| ctx.resolve_item(id).canonical_name(ctx))
- .filter(|name| !name.starts_with("_bindgen_"))
- .collect();
- names.reverse();
- names.join("::")
-}
-
-/// Generate the dummy uses for all the items in the given context, and write
-/// the dummy uses to `dest`.
-pub fn generate_dummy_uses<W>(ctx: &mut BindgenContext,
- mut dest: W)
- -> io::Result<()>
- where W: io::Write,
-{
- ctx.gen(|ctx| {
- let input_header = ctx.options()
- .input_header
- .as_ref()
- .expect("Should not generate dummy uses without an input header");
-
- try!(writeln!(dest, "/* automatically generated by rust-bindgen */"));
- try!(writeln!(dest, ""));
- try!(writeln!(dest, "#include \"{}\"", input_header));
- try!(writeln!(dest, ""));
-
- let type_items = ctx.whitelisted_items()
- .map(|id| ctx.resolve_item(id))
- .filter(|item| {
- // We only want type items.
- if let Some(ty) = item.kind().as_type() {
- // However, we don't want anonymous types, as we can't
- // generate dummy uses for them.
- ty.name().is_some() &&
- // Nor do we want builtin types or named template type
- // arguments. Again, we can't generate dummy uses for
- // these.
- !ty.is_builtin_or_named() &&
- // And finally, we won't be creating any dummy
- // specializations, so ignore template declarations and
- // partial specializations.
- item.applicable_template_args(ctx).is_empty()
- } else {
- false
- }
- })
- .map(|item| namespaced_name(ctx, item))
- .enumerate();
-
- for (idx, name) in type_items {
- try!(writeln!(dest, "void dummy{}({}*) {{ }}", idx, name));
- }
-
- Ok(())
- })
-}