summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parser.rs29
-rw-r--r--src/types.rs8
-rw-r--r--tests/headers/class_with_inner_struct.hpp6
3 files changed, 32 insertions, 11 deletions
diff --git a/src/parser.rs b/src/parser.rs
index 6188cb62..cdbe80ea 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -618,16 +618,19 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
// _ => false
//};
- let field = FieldInfo::new(name, ty.clone(), comment, bitfields);
- //if is_composite {
- // if let Some(CompMember::Comp(c)) = ci.members.pop() {
- // ci.members.push(CompMember::CompField(c, field));
- // } else {
- // unreachable!(); // Checks in is_composite make this unreachable.
- // }
- //} else {
+ // If it's a field from an unnamed union we only have to update the name
+ if let Some(&mut CompMember::Field(ref mut info)) = ci.members.last_mut() {
+ if let (&TComp(ref field_ty_ci), &TComp(ref ci)) = (&info.ty, &ty) {
+ if field_ty_ci.borrow().was_unnamed && ci.borrow().was_unnamed &&
+ field_ty_ci.borrow().name == ci.borrow().name {
+ info.name = name;
+ return CXChildVisit_Continue;
+ }
+ }
+ }
+
+ let field = FieldInfo::new(name, ty, comment, bitfields);
ci.members.push(CompMember::Field(field));
- //}
}
CXCursor_StructDecl | CXCursor_UnionDecl => {
fwd_decl(ctx, cursor, |ctx_| {
@@ -640,7 +643,15 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
let mut ci_ = ci2.borrow_mut();
visit_composite(c, p, ctx_, &mut ci_)
});
+
ci.members.push(CompMember::Comp(decl.compinfo()));
+
+ // Anonymous structs are legal in both C++ and C11
+ if ci2.borrow().kind == CompKind::Union && ci2.borrow().was_unnamed {
+ let ci2b = ci2.borrow();
+ let field = FieldInfo::new(ci2b.name.clone(), TComp(ci2.clone()), ci2b.comment.clone(), None);
+ ci.members.push(CompMember::Field(field));
+ }
});
}
CXCursor_PackedAttr => {
diff --git a/src/types.rs b/src/types.rs
index a5aa4188..03a9ef3a 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -319,21 +319,24 @@ pub struct CompInfo {
pub typedefs: Vec<String>,
/// If this type has a template parameter which is not a type (e.g.: a size_t)
pub has_non_type_template_params: bool,
+ /// If this type was unnamed when parsed
+ pub was_unnamed: bool,
}
static mut UNNAMED_COUNTER: u32 = 0;
fn unnamed_name(name: String, filename: &String) -> String {
- return if name.is_empty() {
+ if name.is_empty() {
let n = unsafe { UNNAMED_COUNTER += 1; UNNAMED_COUNTER };
format!("{}_unnamed_{}", filename, n)
} else {
name
- };
+ }
}
impl 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,
module_id: module_id,
@@ -353,6 +356,7 @@ impl CompInfo {
layout: layout,
typedefs: vec!(),
has_non_type_template_params: false,
+ was_unnamed: was_unnamed,
}
}
}
diff --git a/tests/headers/class_with_inner_struct.hpp b/tests/headers/class_with_inner_struct.hpp
index 40199ccc..5f57a1c0 100644
--- a/tests/headers/class_with_inner_struct.hpp
+++ b/tests/headers/class_with_inner_struct.hpp
@@ -1,6 +1,12 @@
class A {
unsigned c;
struct Segment { int begin, end; };
+ union {
+ int f;
+ } named_union;
+ union {
+ int d;
+ };
};
class B {