-
Notifications
You must be signed in to change notification settings - Fork 748
Add support for 'unsafe fields' #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -122,6 +122,7 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global { | |
CXCursor_ClassTemplate | | ||
CXCursor_ClassDecl | | ||
CXCursor_StructDecl => { | ||
let anno = Annotations::new(&cursor); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm... This is for nested structs right? Can you add a test for this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, this is for annotating the entire struct with something. See the test. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm... I'm pretty sure we parse that at another place. huh. I'll take a look. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's visit_top, which AFAICT is only called for toplevel decls. decl_name otoh is called for all decls There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only thing So I'm fine with moving it here, but there's no point in parsing it twice, that's what I wanted to say. Nontheless, I think that would bring a bit of churn here right? I'd be satisfied if you file an issue so I can refactor that when I have the time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Filed #26 |
||
let kind = if cursor.kind() == CXCursor_UnionDecl { | ||
CompKind::Union | ||
} else { | ||
|
@@ -159,7 +160,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); | ||
let mut ci = CompInfo::new(spelling, ctx.current_module_id, filename, comment, kind, vec![], layout, anno); | ||
ci.parser_cursor = Some(cursor); | ||
|
||
// If it's an instantiation of another template, | ||
|
@@ -538,12 +539,34 @@ fn opaque_ty(ctx: &mut ClangParserCtx, ty: &cx::Type) { | |
} | ||
} | ||
|
||
struct Annotations { | ||
#[derive(Copy, PartialEq, Clone, Debug)] | ||
pub enum Accessor { | ||
None, | ||
Regular, | ||
Unsafe, | ||
Immutable, | ||
} | ||
|
||
#[derive(Clone, PartialEq, Debug)] | ||
pub struct Annotations { | ||
opaque: bool, | ||
hide: bool, | ||
use_as: Option<String>, | ||
/// Disable deriving copy/clone on this struct. | ||
no_copy: bool, | ||
// In the None case we fall back to the value specified | ||
// in the enclosing decl | ||
private: Option<bool>, | ||
accessor: Option<Accessor>, | ||
} | ||
|
||
fn parse_accessor(s: &str) -> Accessor { | ||
match s { | ||
"false" => Accessor::None, | ||
"unsafe" => Accessor::Unsafe, | ||
"immutable" => Accessor::Immutable, | ||
_ => Accessor::Regular, | ||
} | ||
} | ||
|
||
impl Annotations { | ||
|
@@ -553,6 +576,8 @@ impl Annotations { | |
hide: false, | ||
use_as: None, | ||
no_copy: false, | ||
private: None, | ||
accessor: None | ||
}; | ||
|
||
anno.parse(&cursor.comment()); | ||
|
@@ -571,6 +596,10 @@ impl Annotations { | |
"hide" => self.hide = true, | ||
"replaces" => self.use_as = Some(comment.get_tag_attr_value(i)), | ||
"nocopy" => self.no_copy = true, | ||
"private" => self.private = Some(comment.get_tag_attr_value(i) != "false"), | ||
"accessor" => { | ||
self.accessor = Some(parse_accessor(&comment.get_tag_attr_value(i))) | ||
}, | ||
_ => (), | ||
} | ||
} | ||
|
@@ -792,12 +821,16 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, | |
|
||
if should_replace { | ||
*info = FieldInfo::new(name, ty, comment, bitfields, mutable); | ||
info.private = anno.private.unwrap_or(ci.anno.private.unwrap_or(false)); | ||
info.accessor = anno.accessor.unwrap_or(ci.anno.accessor.unwrap_or(Accessor::None)); | ||
return CXChildVisit_Continue; | ||
} | ||
} | ||
} | ||
|
||
let field = FieldInfo::new(name, ty, comment, bitfields, mutable); | ||
let mut field = FieldInfo::new(name, ty, comment, bitfields, mutable); | ||
field.private = anno.private.unwrap_or(ci.anno.private.unwrap_or(false)); | ||
field.accessor = anno.accessor.unwrap_or(ci.anno.accessor.unwrap_or(Accessor::None)); | ||
ci.members.push(CompMember::Field(field)); | ||
} | ||
CXCursor_StructDecl | | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,8 @@ pub use self::IKind::*; | |
pub use self::FKind::*; | ||
use clang::Cursor; | ||
|
||
use parser::{Annotations, Accessor}; | ||
|
||
static NEXT_MODULE_ID: AtomicUsize = ATOMIC_USIZE_INIT; | ||
|
||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] | ||
|
@@ -446,6 +448,9 @@ pub struct CompInfo { | |
/// Used to detect if we've run in a has_destructor cycle while cycling | ||
/// around the template arguments. | ||
detect_has_destructor_cycle: Cell<bool>, | ||
|
||
/// Annotations on the decl | ||
pub anno: Annotations, | ||
} | ||
|
||
static mut UNNAMED_COUNTER: u32 = 0; | ||
|
@@ -466,7 +471,8 @@ impl CompInfo { | |
comment: String, | ||
kind: CompKind, | ||
members: Vec<CompMember>, | ||
layout: Layout) -> CompInfo { | ||
layout: Layout, | ||
anno: Annotations) -> CompInfo { | ||
let was_unnamed = name.is_empty(); | ||
CompInfo { | ||
kind: kind, | ||
|
@@ -494,6 +500,7 @@ impl CompInfo { | |
was_unnamed: was_unnamed, | ||
detect_derive_debug_cycle: Cell::new(false), | ||
detect_has_destructor_cycle: Cell::new(false), | ||
anno: anno, | ||
} | ||
} | ||
|
||
|
@@ -640,6 +647,12 @@ pub struct FieldInfo { | |
pub bitfields: Option<Vec<(String, u32)>>, | ||
/// If the C++ field is marked as `mutable` | ||
pub mutable: bool, | ||
/// True when field or enclosing struct | ||
/// has a `<div rust-bindgen private>` annotation | ||
pub private: bool, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a doc comment here saying when this can be true (right now only explicitly via annotations right?) |
||
/// Set by the `<div rust-bindgen accessor="..">` | ||
/// annotation on a field or enclosing struct | ||
pub accessor: Accessor, | ||
} | ||
|
||
impl FieldInfo { | ||
|
@@ -654,6 +667,8 @@ impl FieldInfo { | |
comment: comment, | ||
bitfields: bitfields, | ||
mutable: mutable, | ||
private: false, | ||
accessor: Accessor::None, | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can do the same removing the --quiet here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, git diff-index only gives an error on empty diffs if run with --quiet.
(It also outputs object ids, not diffs)