summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <me@emiliocobos.me>2016-05-04 19:29:45 +0200
committerEmilio Cobos Álvarez <me@emiliocobos.me>2016-05-04 19:31:11 +0200
commitf40e3686917c393990d24f395f4d140e3a8e2ad5 (patch)
treeba44545e14abcf99e6b6a8c32648309b43c1bd8e /src
parent0ea208b7e6ef54fa1f40efb7912d7040cf2e4fa9 (diff)
c++: Detect an inner class declaration with the same name in a composite
Diffstat (limited to 'src')
-rw-r--r--src/clang.rs6
-rw-r--r--src/lib.rs1
-rw-r--r--src/parser.rs45
-rw-r--r--src/types.rs20
4 files changed, 67 insertions, 5 deletions
diff --git a/src/clang.rs b/src/clang.rs
index b7d6b5c7..1d738def 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -43,6 +43,12 @@ impl Cursor {
mangling
}
+ pub fn lexical_parent(&self) -> Cursor {
+ unsafe {
+ Cursor { x: clang_getCursorLexicalParent(self.x) }
+ }
+ }
+
pub fn semantic_parent(&self) -> Cursor {
unsafe {
Cursor { x: clang_getCursorSemanticParent(self.x) }
diff --git a/src/lib.rs b/src/lib.rs
index 0934a772..a42fa2ae 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,7 @@
#![crate_name = "bindgen"]
#![crate_type = "dylib"]
#![feature(quote)]
+#![feature(borrow_state)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
diff --git a/src/parser.rs b/src/parser.rs
index 774ebbbb..86240eb2 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -124,6 +124,7 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
};
let mut ci = CompInfo::new(spelling, ctx.current_module_id, filename, comment, kind, vec![], layout);
+ ci.parser_cursor = Some(cursor);
// If it's an instantiation of another template,
// find the canonical declaration to find the module
@@ -367,18 +368,18 @@ fn conv_decl_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
// it's important not to override
if !args.is_empty() {
ci.borrow_mut().args = args;
+
// XXX: This is a super-dumb way to get the spesialisation,
// but it seems to be the only one that'd work here...
cursor.visit(|c, _: &Cursor| {
if c.kind() == CXCursor_TemplateRef {
- let decl = decl_name(ctx, &c.referenced());
+ let decl = decl_name(ctx, &c.referenced());
ci.borrow_mut().ref_template = Some(decl.to_type());
}
CXChildVisit_Continue
});
}
-
TComp(ci)
}
CXCursor_EnumDecl => {
@@ -458,7 +459,9 @@ fn conv_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
CXType_Pointer => conv_ptr_ty_resolving_typedefs(ctx, &ty.pointee_type(), cursor, false, layout, resolve_typedefs),
CXType_LValueReference => conv_ptr_ty_resolving_typedefs(ctx, &ty.pointee_type(), cursor, true, layout, resolve_typedefs),
// XXX DependentSizedArray is wrong
- CXType_VariableArray | CXType_DependentSizedArray | CXType_IncompleteArray => {
+ CXType_VariableArray |
+ CXType_DependentSizedArray |
+ CXType_IncompleteArray => {
conv_ptr_ty_resolving_typedefs(ctx, &ty.elem_type(), cursor, false, layout, resolve_typedefs)
}
CXType_FunctionProto => TFuncProto(mk_fn_sig(ctx, ty, cursor)),
@@ -537,6 +540,7 @@ impl Annotations {
fn visit_composite(cursor: &Cursor, parent: &Cursor,
ctx: &mut ClangParserCtx,
ci: &mut CompInfo) -> Enum_CXVisitorResult {
+ assert!(ci.parser_cursor.is_some());
fn is_bitfield_continuation(field: &il::FieldInfo, _ty: &il::Type, width: u32) -> bool {
match (&field.bitfields, field.ty.layout()) {
(&Some(ref bitfields), Some(layout)) => {
@@ -560,8 +564,41 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
let is_class_typedef = cursor.cur_type().sanitized_spelling_in(&ci.typedefs);
let mutable = cursor.is_mutable_field();
+ let cursor_ty = cursor.cur_type();
+
// NB: Overwritten in the case of non-integer bitfield
- let mut ty = conv_ty_resolving_typedefs(ctx, &cursor.cur_type(), cursor, is_class_typedef);
+ let mut ty = conv_ty_resolving_typedefs(ctx,
+ &cursor.cur_type(),
+ cursor,
+ is_class_typedef);
+
+ use std::cell::BorrowState;
+ if let Some(child_ci) = ty.get_outermost_composite() {
+ if let BorrowState::Unused = child_ci.borrow_state() {
+ let mut child_ci = child_ci.borrow_mut();
+ let child_cursor = child_ci.parser_cursor.unwrap();
+
+ // TODO: This is lame, ideally we should use cursors.
+ // The problem this is trying to solve is
+ // tests/headers/inner_template_self.hpp.
+ //
+ // The problem with this is that clang treats the *prev*
+ // field as a Class Declaration instead of a Class Template,
+ // so we have to check now for the name and the module id.
+ //
+ // Ideally, some method like `semantic_parent` or
+ // `lexical_parent` should return the reference to the
+ // class, but I've tried everything I could think about and
+ // failed miserably.
+ if child_cursor.kind() == CXCursor_ClassDecl &&
+ child_ci.args.is_empty() &&
+ child_ci.name == ci.name &&
+ child_ci.module_id == ci.module_id {
+ child_ci.args = ci.args.clone();
+ }
+ }
+ }
+
let comment = cursor.raw_comment();
let (name, bitfields) = match (cursor.bit_width(), ci.members.last_mut()) {
diff --git a/src/types.rs b/src/types.rs
index c7b9e530..c0180cd6 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -10,6 +10,7 @@ pub use self::Global::*;
pub use self::Type::*;
pub use self::IKind::*;
pub use self::FKind::*;
+use clang::Cursor;
static NEXT_MODULE_ID: AtomicUsize = ATOMIC_USIZE_INIT;
@@ -200,6 +201,15 @@ impl Type {
}
}
+ pub fn get_outermost_composite(&self) -> Option<Rc<RefCell<CompInfo>>> {
+ match *self {
+ TComp(ref ci) => Some(ci.clone()),
+ TArray(ref t, _, _) => t.get_outermost_composite(),
+ TPtr(ref t, _, _, _) => t.get_outermost_composite(),
+ _ => None,
+ }
+ }
+
pub fn size(&self) -> usize {
self.layout().map(|l| l.size).unwrap_or(0)
}
@@ -401,6 +411,7 @@ pub struct CompInfo {
pub has_destructor: bool,
pub has_nonempty_base: bool,
pub hide: bool,
+ pub parser_cursor: Option<Cursor>,
/// If this struct should be replaced by an opaque blob.
///
/// This is useful if for some reason we can't generate
@@ -431,7 +442,13 @@ fn unnamed_name(name: String, filename: &String) -> String {
}
impl CompInfo {
- pub fn new(name: String, module_id: ModuleId, filename: String, comment: String, kind: CompKind, members: Vec<CompMember>, layout: Layout) -> CompInfo {
+ pub fn new(name: String,
+ module_id: ModuleId,
+ filename: String,
+ comment: String,
+ kind: CompKind,
+ members: Vec<CompMember>,
+ layout: Layout) -> CompInfo {
let was_unnamed = name.is_empty();
CompInfo {
kind: kind,
@@ -448,6 +465,7 @@ impl CompInfo {
has_destructor: false,
has_nonempty_base: false,
hide: false,
+ parser_cursor: None,
opaque: false,
base_members: 0,
layout: layout,