Skip to content

Commit f40e368

Browse files
committed
c++: Detect an inner class declaration with the same name in a composite
1 parent 0ea208b commit f40e368

File tree

6 files changed

+104
-5
lines changed

6 files changed

+104
-5
lines changed

src/clang.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ impl Cursor {
4343
mangling
4444
}
4545

46+
pub fn lexical_parent(&self) -> Cursor {
47+
unsafe {
48+
Cursor { x: clang_getCursorLexicalParent(self.x) }
49+
}
50+
}
51+
4652
pub fn semantic_parent(&self) -> Cursor {
4753
unsafe {
4854
Cursor { x: clang_getCursorSemanticParent(self.x) }

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![crate_name = "bindgen"]
22
#![crate_type = "dylib"]
33
#![feature(quote)]
4+
#![feature(borrow_state)]
45

56
#![cfg_attr(feature = "clippy", feature(plugin))]
67
#![cfg_attr(feature = "clippy", plugin(clippy))]

src/parser.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global {
124124
};
125125

126126
let mut ci = CompInfo::new(spelling, ctx.current_module_id, filename, comment, kind, vec![], layout);
127+
ci.parser_cursor = Some(cursor);
127128

128129
// If it's an instantiation of another template,
129130
// find the canonical declaration to find the module
@@ -367,18 +368,18 @@ fn conv_decl_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
367368
// it's important not to override
368369
if !args.is_empty() {
369370
ci.borrow_mut().args = args;
371+
370372
// XXX: This is a super-dumb way to get the spesialisation,
371373
// but it seems to be the only one that'd work here...
372374
cursor.visit(|c, _: &Cursor| {
373375
if c.kind() == CXCursor_TemplateRef {
374-
let decl = decl_name(ctx, &c.referenced());
376+
let decl = decl_name(ctx, &c.referenced());
375377
ci.borrow_mut().ref_template = Some(decl.to_type());
376378
}
377379
CXChildVisit_Continue
378380
});
379381
}
380382

381-
382383
TComp(ci)
383384
}
384385
CXCursor_EnumDecl => {
@@ -458,7 +459,9 @@ fn conv_ty_resolving_typedefs(ctx: &mut ClangParserCtx,
458459
CXType_Pointer => conv_ptr_ty_resolving_typedefs(ctx, &ty.pointee_type(), cursor, false, layout, resolve_typedefs),
459460
CXType_LValueReference => conv_ptr_ty_resolving_typedefs(ctx, &ty.pointee_type(), cursor, true, layout, resolve_typedefs),
460461
// XXX DependentSizedArray is wrong
461-
CXType_VariableArray | CXType_DependentSizedArray | CXType_IncompleteArray => {
462+
CXType_VariableArray |
463+
CXType_DependentSizedArray |
464+
CXType_IncompleteArray => {
462465
conv_ptr_ty_resolving_typedefs(ctx, &ty.elem_type(), cursor, false, layout, resolve_typedefs)
463466
}
464467
CXType_FunctionProto => TFuncProto(mk_fn_sig(ctx, ty, cursor)),
@@ -537,6 +540,7 @@ impl Annotations {
537540
fn visit_composite(cursor: &Cursor, parent: &Cursor,
538541
ctx: &mut ClangParserCtx,
539542
ci: &mut CompInfo) -> Enum_CXVisitorResult {
543+
assert!(ci.parser_cursor.is_some());
540544
fn is_bitfield_continuation(field: &il::FieldInfo, _ty: &il::Type, width: u32) -> bool {
541545
match (&field.bitfields, field.ty.layout()) {
542546
(&Some(ref bitfields), Some(layout)) => {
@@ -560,8 +564,41 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
560564
let is_class_typedef = cursor.cur_type().sanitized_spelling_in(&ci.typedefs);
561565
let mutable = cursor.is_mutable_field();
562566

567+
let cursor_ty = cursor.cur_type();
568+
563569
// NB: Overwritten in the case of non-integer bitfield
564-
let mut ty = conv_ty_resolving_typedefs(ctx, &cursor.cur_type(), cursor, is_class_typedef);
570+
let mut ty = conv_ty_resolving_typedefs(ctx,
571+
&cursor.cur_type(),
572+
cursor,
573+
is_class_typedef);
574+
575+
use std::cell::BorrowState;
576+
if let Some(child_ci) = ty.get_outermost_composite() {
577+
if let BorrowState::Unused = child_ci.borrow_state() {
578+
let mut child_ci = child_ci.borrow_mut();
579+
let child_cursor = child_ci.parser_cursor.unwrap();
580+
581+
// TODO: This is lame, ideally we should use cursors.
582+
// The problem this is trying to solve is
583+
// tests/headers/inner_template_self.hpp.
584+
//
585+
// The problem with this is that clang treats the *prev*
586+
// field as a Class Declaration instead of a Class Template,
587+
// so we have to check now for the name and the module id.
588+
//
589+
// Ideally, some method like `semantic_parent` or
590+
// `lexical_parent` should return the reference to the
591+
// class, but I've tried everything I could think about and
592+
// failed miserably.
593+
if child_cursor.kind() == CXCursor_ClassDecl &&
594+
child_ci.args.is_empty() &&
595+
child_ci.name == ci.name &&
596+
child_ci.module_id == ci.module_id {
597+
child_ci.args = ci.args.clone();
598+
}
599+
}
600+
}
601+
565602
let comment = cursor.raw_comment();
566603

567604
let (name, bitfields) = match (cursor.bit_width(), ci.members.last_mut()) {

src/types.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub use self::Global::*;
1010
pub use self::Type::*;
1111
pub use self::IKind::*;
1212
pub use self::FKind::*;
13+
use clang::Cursor;
1314

1415
static NEXT_MODULE_ID: AtomicUsize = ATOMIC_USIZE_INIT;
1516

@@ -200,6 +201,15 @@ impl Type {
200201
}
201202
}
202203

204+
pub fn get_outermost_composite(&self) -> Option<Rc<RefCell<CompInfo>>> {
205+
match *self {
206+
TComp(ref ci) => Some(ci.clone()),
207+
TArray(ref t, _, _) => t.get_outermost_composite(),
208+
TPtr(ref t, _, _, _) => t.get_outermost_composite(),
209+
_ => None,
210+
}
211+
}
212+
203213
pub fn size(&self) -> usize {
204214
self.layout().map(|l| l.size).unwrap_or(0)
205215
}
@@ -401,6 +411,7 @@ pub struct CompInfo {
401411
pub has_destructor: bool,
402412
pub has_nonempty_base: bool,
403413
pub hide: bool,
414+
pub parser_cursor: Option<Cursor>,
404415
/// If this struct should be replaced by an opaque blob.
405416
///
406417
/// This is useful if for some reason we can't generate
@@ -431,7 +442,13 @@ fn unnamed_name(name: String, filename: &String) -> String {
431442
}
432443

433444
impl CompInfo {
434-
pub fn new(name: String, module_id: ModuleId, filename: String, comment: String, kind: CompKind, members: Vec<CompMember>, layout: Layout) -> CompInfo {
445+
pub fn new(name: String,
446+
module_id: ModuleId,
447+
filename: String,
448+
comment: String,
449+
kind: CompKind,
450+
members: Vec<CompMember>,
451+
layout: Layout) -> CompInfo {
435452
let was_unnamed = name.is_empty();
436453
CompInfo {
437454
kind: kind,
@@ -448,6 +465,7 @@ impl CompInfo {
448465
has_destructor: false,
449466
has_nonempty_base: false,
450467
hide: false,
468+
parser_cursor: None,
451469
opaque: false,
452470
base_members: 0,
453471
layout: layout,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![feature(const_fn)]
5+
#![allow(non_snake_case)]
6+
7+
8+
#[repr(C)]
9+
#[derive(Debug, Copy, Clone)]
10+
pub struct Struct_LinkedList<T> {
11+
pub next: *mut Struct_LinkedList<T>,
12+
pub prev: *mut Struct_LinkedList<T>,
13+
pub _phantom0: ::std::marker::PhantomData<T>,
14+
}
15+
#[repr(C)]
16+
#[derive(Debug, Copy)]
17+
pub struct Struct_InstantiateIt {
18+
pub m_list: Struct_LinkedList<::std::os::raw::c_int>,
19+
}
20+
impl ::std::clone::Clone for Struct_InstantiateIt {
21+
fn clone(&self) -> Self { *self }
22+
}
23+
#[test]
24+
fn bindgen_test_layout_Struct_InstantiateIt() {
25+
assert_eq!(::std::mem::size_of::<Struct_InstantiateIt>() , 16usize);
26+
assert_eq!(::std::mem::align_of::<Struct_InstantiateIt>() , 8usize);
27+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
template <typename T>
3+
class LinkedList {
4+
LinkedList<T>* next;
5+
LinkedList* prev;
6+
};
7+
8+
class InstantiateIt {
9+
LinkedList<int> m_list;
10+
};

0 commit comments

Comments
 (0)