diff options
-rw-r--r-- | src/parser.rs | 29 | ||||
-rw-r--r-- | src/types.rs | 8 | ||||
-rw-r--r-- | tests/headers/class_with_inner_struct.hpp | 6 |
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 { |