summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <ecoal95@gmail.com>2016-03-20 20:58:20 +0100
committerEmilio Cobos Álvarez <ecoal95@gmail.com>2016-03-20 21:08:09 +0100
commit923323598f7e1baf2d59b4355367de67a7dfa597 (patch)
treefc9dcffef427b03f9b90debbbc68d68d7cd0b45b
parent5166b22773df329b20d24b32246d1621aa085b65 (diff)
Resolve class typedefs eagerly
-rw-r--r--src/gen.rs1
-rw-r--r--src/parser.rs66
-rw-r--r--src/types.rs3
-rw-r--r--tests/headers/class_with_typedef.hpp8
4 files changed, 67 insertions, 11 deletions
diff --git a/src/gen.rs b/src/gen.rs
index ab1e5fce..1376e806 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -944,6 +944,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
has_destructor = true;
}
if !cty_is_translatable(&f.ty) {
+ println!("{} not translatable, void: {}", f.name, f.ty == TVoid);
continue;
}
let f_name = match f.bitfields {
diff --git a/src/parser.rs b/src/parser.rs
index 5fe83942..a6264778 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -52,6 +52,10 @@ impl<'a> ClangParserCtx<'a> {
fn current_module_mut(&mut self) -> &mut Module {
self.module_map.get_mut(&self.current_module_id).expect("Module not found!")
}
+
+ fn module_mut(&mut self, id: &ModuleId) -> &mut Module {
+ self.module_map.get_mut(id).expect("Module not found!")
+ }
}
fn match_pattern(ctx: &mut ClangParserCtx, cursor: &Cursor) -> bool {
@@ -289,7 +293,16 @@ fn mk_fn_sig(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor) -> il::Fu
}
}
-fn conv_decl_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor) -> il::Type {
+fn conv_decl_ty(ctx: &mut ClangParserCtx,
+ ty: &cx::Type,
+ cursor: &Cursor) -> il::Type {
+ conv_decl_ty_resolving_typedefs(ctx, ty, cursor, false)
+}
+
+fn conv_decl_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
+ ty: &cx::Type,
+ cursor: &Cursor,
+ resolve_typedefs: bool) -> il::Type {
let ty_decl = &ty.declaration();
return match ty_decl.kind() {
CXCursor_StructDecl |
@@ -328,6 +341,10 @@ fn conv_decl_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor) -> il:
TEnum(ei)
}
CXCursor_TypedefDecl => {
+ if resolve_typedefs {
+ return conv_ty_resolving_typedefs(ctx, &ty_decl.typedef_type(), &ty_decl.typedef_type().declaration(), resolve_typedefs);
+ }
+
let decl = decl_name(ctx, ty_decl);
let ti = decl.typeinfo();
TNamed(ti)
@@ -349,10 +366,28 @@ fn conv_decl_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor) -> il:
};
}
-fn conv_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor) -> il::Type {
+fn conv_ty(ctx: &mut ClangParserCtx,
+ ty: &cx::Type,
+ cursor: &Cursor) -> il::Type {
+ conv_ty_resolving_typedefs(ctx, ty, cursor, false)
+}
+
+fn conv_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
+ ty: &cx::Type,
+ cursor: &Cursor,
+ resolve_typedefs: bool) -> il::Type {
let layout = Layout::new(ty.size(), ty.align());
match ty.kind() {
- CXType_Void | CXType_Invalid => TVoid,
+ CXType_Void => TVoid,
+ CXType_Invalid => {
+ log_err_warn(ctx,
+ &format!("invalid type `{}` ({})",
+ type_to_str(ty.kind()), cursor.location()
+ ),
+ false
+ );
+ TVoid
+ }
CXType_Bool => TInt(IBool, layout),
CXType_SChar |
CXType_Char_S => TInt(ISChar, layout),
@@ -380,7 +415,7 @@ fn conv_ty(ctx: &mut ClangParserCtx, ty: &cx::Type, cursor: &Cursor) -> il::Type
CXType_Record |
CXType_Typedef |
CXType_Unexposed |
- CXType_Enum => conv_decl_ty(ctx, ty, cursor),
+ CXType_Enum => conv_decl_ty_resolving_typedefs(ctx, ty, cursor, resolve_typedefs),
CXType_ConstantArray => TArray(Box::new(conv_ty(ctx, &ty.elem_type(), cursor)), ty.array_size(), layout),
_ => {
let fail = ctx.options.fail_on_unknown_type;
@@ -471,12 +506,21 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
}
match cursor.kind() {
+ CXCursor_TypedefDecl => {
+ ci.typedefs.push(cursor.spelling().to_owned());
+ }
CXCursor_FieldDecl => {
let anno = Annotations::new(cursor);
if anno.hide {
return CXChildVisit_Continue;
}
- let ty = conv_ty(ctx, &cursor.cur_type(), cursor);
+
+ let type_spelling = cursor.cur_type().spelling();
+ let is_class_typedef = ci.typedefs.iter().any(|spelling| *spelling == *type_spelling);
+
+ // println!("{} is ctd: {}", type_spelling, is_class_typedef);
+
+ let ty = conv_ty_resolving_typedefs(ctx, &cursor.cur_type(), cursor, is_class_typedef);
let comment = cursor.raw_comment();
let (name, bitfields) = match (cursor.bit_width(), ci.members.last_mut()) {
@@ -704,15 +748,15 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
CXCursor_Destructor => {
ci.has_destructor = true;
}
+ CXCursor_CXXAccessSpecifier => {}
_ => {
// XXX: Some kind of warning would be nice, but this produces far
// too many.
- //log_err_warn(ctx,
- // &format!("unhandled composite member `{}` (kind {}) in `{}` ({})",
- // cursor.spelling(), cursor.kind(), parent.spelling(), cursor.location()
- // )[..],
- // false
- //);
+ log_err_warn(ctx,
+ &format!("unhandled composite member `{}` (kind {}) in `{}` ({})",
+ cursor.spelling(), cursor.kind(), parent.spelling(), cursor.location()
+ ),
+ false);
}
}
CXChildVisit_Continue
diff --git a/src/types.rs b/src/types.rs
index 3377b1b6..c9a7f0fd 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -272,6 +272,8 @@ pub struct CompInfo {
pub hide: bool,
pub base_members: usize,
pub layout: Layout,
+ /// Typedef'd types names, that we'll resolve early to avoid name conflicts
+ pub typedefs: Vec<String>,
}
static mut UNNAMED_COUNTER: u32 = 0;
@@ -303,6 +305,7 @@ impl CompInfo {
hide: false,
base_members: 0,
layout: layout,
+ typedefs: vec!(),
}
}
}
diff --git a/tests/headers/class_with_typedef.hpp b/tests/headers/class_with_typedef.hpp
new file mode 100644
index 00000000..6d97dae4
--- /dev/null
+++ b/tests/headers/class_with_typedef.hpp
@@ -0,0 +1,8 @@
+typedef int AnotherInt;
+
+class C {
+public:
+ typedef int MyInt;
+ MyInt c;
+ AnotherInt d;
+};