Skip to content

Commit 55b608f

Browse files
authored
Merge pull request rust-lang#3 from martinboehme/special-member-attribute
Add attribute for C++ special members
2 parents b1f017e + 388d43a commit 55b608f

17 files changed

+169
-3
lines changed

src/clang.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,21 @@ impl Cursor {
683683
unsafe { clang_isVirtualBase(self.x) != 0 }
684684
}
685685

686+
// Is this cursor's referent a default constructor?
687+
pub fn is_default_constructor(&self) -> bool {
688+
unsafe { clang_CXXConstructor_isDefaultConstructor(self.x) != 0 }
689+
}
690+
691+
// Is this cursor's referent a copy constructor?
692+
pub fn is_copy_constructor(&self) -> bool {
693+
unsafe { clang_CXXConstructor_isCopyConstructor(self.x) != 0 }
694+
}
695+
696+
// Is this cursor's referent a move constructor?
697+
pub fn is_move_constructor(&self) -> bool {
698+
unsafe { clang_CXXConstructor_isMoveConstructor(self.x) != 0 }
699+
}
700+
686701
/// Try to evaluate this cursor.
687702
pub fn evaluate(&self) -> Option<EvalResult> {
688703
EvalResult::new(*self)

src/codegen/helpers.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use proc_macro2::{Ident, Span, TokenStream};
66
use quote::TokenStreamExt;
77

88
pub mod attributes {
9+
use crate::ir::comp::SpecialMemberKind;
910
use proc_macro2::{Ident, Span, TokenStream};
1011
use std::str::FromStr;
1112

@@ -104,6 +105,18 @@ pub mod attributes {
104105
#[bindgen_unused_template_param]
105106
}
106107
}
108+
109+
pub fn special_member(kind: SpecialMemberKind) -> TokenStream {
110+
let kind_str = match kind {
111+
SpecialMemberKind::DefaultConstructor => "default_ctor",
112+
SpecialMemberKind::CopyConstructor => "copy_ctor",
113+
SpecialMemberKind::MoveConstructor => "move_ctor",
114+
SpecialMemberKind::Destructor => "dtor",
115+
};
116+
quote! {
117+
#[bindgen_special_member(#kind_str)]
118+
}
119+
}
107120
}
108121

109122
/// Generates a proper type for a field or type with a given `Layout`, that is,

src/codegen/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3982,6 +3982,10 @@ impl CodeGenerator for Function {
39823982
attributes.push(attributes::original_name(self.name()));
39833983
}
39843984

3985+
if let Some(special_member_kind) = self.special_member() {
3986+
attributes.push(attributes::special_member(special_member_kind));
3987+
}
3988+
39853989
let link_name = mangled_name.unwrap_or(name);
39863990
if !utils::names_will_be_identical_after_mangling(
39873991
&canonical_name,

src/ir/comp.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,17 @@ impl MethodKind {
7373
}
7474
}
7575

76+
// The kind of C++ special member.
77+
// TODO: We don't currently cover copy assignment or move assignment operator
78+
// because libclang doesn't provide a way to query for them.
79+
#[derive(Debug, Copy, Clone, PartialEq)]
80+
pub enum SpecialMemberKind {
81+
DefaultConstructor,
82+
CopyConstructor,
83+
MoveConstructor,
84+
Destructor,
85+
}
86+
7687
/// A struct representing a C++ method, either static, normal, or virtual.
7788
#[derive(Debug)]
7889
pub struct Method {

src/ir/function.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Intermediate representation for C/C++ functions and methods.
22
3-
use super::comp::MethodKind;
3+
use super::comp::{MethodKind, SpecialMemberKind};
44
use super::context::{BindgenContext, TypeId};
55
use super::dot::DotAttributes;
66
use super::item::Item;
@@ -92,6 +92,9 @@ pub struct Function {
9292

9393
/// The linkage of the function.
9494
linkage: Linkage,
95+
96+
/// C++ special member kind, if any.
97+
special_member: Option<SpecialMemberKind>,
9598
}
9699

97100
impl Function {
@@ -103,6 +106,7 @@ impl Function {
103106
comment: Option<String>,
104107
kind: FunctionKind,
105108
linkage: Linkage,
109+
special_member: Option<SpecialMemberKind>,
106110
) -> Self {
107111
Function {
108112
name,
@@ -111,6 +115,7 @@ impl Function {
111115
comment,
112116
kind,
113117
linkage,
118+
special_member,
114119
}
115120
}
116121

@@ -138,6 +143,11 @@ impl Function {
138143
pub fn linkage(&self) -> Linkage {
139144
self.linkage
140145
}
146+
147+
/// Get this function's C++ special member kind.
148+
pub fn special_member(&self) -> Option<SpecialMemberKind> {
149+
self.special_member
150+
}
141151
}
142152

143153
impl DotAttributes for Function {
@@ -631,8 +641,27 @@ impl ClangSubItemParser for Function {
631641
let mangled_name = cursor_mangling(context, &cursor);
632642
let comment = cursor.raw_comment();
633643

634-
let function =
635-
Self::new(name, mangled_name, sig, comment, kind, linkage);
644+
let special_member = if cursor.is_default_constructor() {
645+
Some(SpecialMemberKind::DefaultConstructor)
646+
} else if cursor.is_copy_constructor() {
647+
Some(SpecialMemberKind::CopyConstructor)
648+
} else if cursor.is_move_constructor() {
649+
Some(SpecialMemberKind::MoveConstructor)
650+
} else if cursor.kind() == clang_sys::CXCursor_Destructor {
651+
Some(SpecialMemberKind::Destructor)
652+
} else {
653+
None
654+
};
655+
656+
let function = Self::new(
657+
name,
658+
mangled_name,
659+
sig,
660+
comment,
661+
kind,
662+
linkage,
663+
special_member,
664+
);
636665
Ok(ParseResult::New(function, Some(cursor)))
637666
}
638667
}

tests/expectations/tests/constructor-tp.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ fn bindgen_test_layout_Bar() {
3030
}
3131
extern "C" {
3232
#[bindgen_original_name("Bar")]
33+
#[bindgen_special_member("default_ctor")]
3334
#[link_name = "\u{1}_ZN3BarC1Ev"]
3435
pub fn Bar_Bar(this: *mut Bar);
3536
}

tests/expectations/tests/constructors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ fn bindgen_test_layout_TestPublicNoArgs() {
7070
}
7171
extern "C" {
7272
#[bindgen_original_name("TestPublicNoArgs")]
73+
#[bindgen_special_member("default_ctor")]
7374
#[link_name = "\u{1}_ZN16TestPublicNoArgsC1Ev"]
7475
pub fn TestPublicNoArgs_TestPublicNoArgs(this: *mut TestPublicNoArgs);
7576
}

tests/expectations/tests/constructors_1_33.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ fn bindgen_test_layout_TestPublicNoArgs() {
7272
}
7373
extern "C" {
7474
#[bindgen_original_name("TestPublicNoArgs")]
75+
#[bindgen_special_member("default_ctor")]
7576
#[link_name = "\u{1}_ZN16TestPublicNoArgsC1Ev"]
7677
pub fn TestPublicNoArgs_TestPublicNoArgs(this: *mut TestPublicNoArgs);
7778
}

tests/expectations/tests/gen-destructors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ fn bindgen_test_layout_Foo() {
3030
}
3131
extern "C" {
3232
#[bindgen_original_name("Foo_destructor")]
33+
#[bindgen_special_member("dtor")]
3334
#[link_name = "\u{1}_ZN3FooD1Ev"]
3435
pub fn Foo_Foo_destructor(this: *mut Foo);
3536
}

tests/expectations/tests/issue-1197-pure-virtual-stuff.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern "C" {
3939
extern "C" {
4040
#[bindgen_pure_virtual]
4141
#[bindgen_original_name("Foo_destructor")]
42+
#[bindgen_special_member("dtor")]
4243
#[link_name = "\u{1}_ZN3FooD1Ev"]
4344
pub fn Foo_Foo_destructor(this: *mut Foo);
4445
}

tests/expectations/tests/packed-vtable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ impl Default for PackedVtable {
3333
}
3434
extern "C" {
3535
#[bindgen_original_name("PackedVtable_destructor")]
36+
#[bindgen_special_member("dtor")]
3637
#[link_name = "\u{1}_ZN12PackedVtableD1Ev"]
3738
pub fn PackedVtable_PackedVtable_destructor(this: *mut PackedVtable);
3839
}

tests/expectations/tests/public-dtor.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ fn bindgen_test_layout_cv_String() {
2525
}
2626
extern "C" {
2727
#[bindgen_original_name("String_destructor")]
28+
#[bindgen_special_member("dtor")]
2829
#[link_name = "\u{1}_ZN2cv6StringD1Ev"]
2930
pub fn cv_String_String_destructor(this: *mut cv_String);
3031
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#![allow(
2+
dead_code,
3+
non_snake_case,
4+
non_camel_case_types,
5+
non_upper_case_globals
6+
)]
7+
8+
#[repr(C)]
9+
#[derive(Debug, Default)]
10+
pub struct A {
11+
pub _address: u8,
12+
}
13+
#[test]
14+
fn bindgen_test_layout_A() {
15+
assert_eq!(
16+
::std::mem::size_of::<A>(),
17+
1usize,
18+
concat!("Size of: ", stringify!(A))
19+
);
20+
assert_eq!(
21+
::std::mem::align_of::<A>(),
22+
1usize,
23+
concat!("Alignment of ", stringify!(A))
24+
);
25+
}
26+
extern "C" {
27+
#[bindgen_original_name("A")]
28+
#[bindgen_special_member("default_ctor")]
29+
#[link_name = "\u{1}_ZN1AC1Ev"]
30+
pub fn A_A(this: *mut A);
31+
}
32+
extern "C" {
33+
#[bindgen_arg_type_reference(arg1)]
34+
#[bindgen_original_name("A")]
35+
#[bindgen_special_member("copy_ctor")]
36+
#[link_name = "\u{1}_ZN1AC1ERS_"]
37+
pub fn A_A1(this: *mut A, arg1: *mut A);
38+
}
39+
extern "C" {
40+
#[bindgen_arg_type_reference(arg1)]
41+
#[bindgen_original_name("A")]
42+
#[bindgen_special_member("move_ctor")]
43+
#[link_name = "\u{1}_ZN1AC1EOS_"]
44+
pub fn A_A2(this: *mut A, arg1: *mut A);
45+
}
46+
extern "C" {
47+
#[bindgen_original_name("A_destructor")]
48+
#[bindgen_special_member("dtor")]
49+
#[link_name = "\u{1}_ZN1AD1Ev"]
50+
pub fn A_A_destructor(this: *mut A);
51+
}
52+
impl A {
53+
#[inline]
54+
pub unsafe fn new() -> Self {
55+
let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit();
56+
A_A(__bindgen_tmp.as_mut_ptr());
57+
__bindgen_tmp.assume_init()
58+
}
59+
#[bindgen_arg_type_reference(arg1)]
60+
#[inline]
61+
pub unsafe fn new1(arg1: *mut A) -> Self {
62+
let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit();
63+
A_A1(__bindgen_tmp.as_mut_ptr(), arg1);
64+
__bindgen_tmp.assume_init()
65+
}
66+
#[bindgen_arg_type_reference(arg1)]
67+
#[inline]
68+
pub unsafe fn new2(arg1: *mut A) -> Self {
69+
let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit();
70+
A_A2(__bindgen_tmp.as_mut_ptr(), arg1);
71+
__bindgen_tmp.assume_init()
72+
}
73+
#[inline]
74+
pub unsafe fn destruct(&mut self) {
75+
A_A_destructor(self)
76+
}
77+
}

tests/expectations/tests/union_dtor.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ fn bindgen_test_layout_UnionWithDtor() {
4949
}
5050
extern "C" {
5151
#[bindgen_original_name("UnionWithDtor_destructor")]
52+
#[bindgen_special_member("dtor")]
5253
#[link_name = "\u{1}_ZN13UnionWithDtorD1Ev"]
5354
pub fn UnionWithDtor_UnionWithDtor_destructor(this: *mut UnionWithDtor);
5455
}

tests/expectations/tests/union_dtor_1_0.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ fn bindgen_test_layout_UnionWithDtor() {
9494
}
9595
extern "C" {
9696
#[bindgen_original_name("UnionWithDtor_destructor")]
97+
#[bindgen_special_member("dtor")]
9798
#[link_name = "\u{1}_ZN13UnionWithDtorD1Ev"]
9899
pub fn UnionWithDtor_UnionWithDtor_destructor(this: *mut UnionWithDtor);
99100
}

tests/expectations/tests/virtual_dtor.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ impl Default for nsSlots {
3232
}
3333
extern "C" {
3434
#[bindgen_original_name("nsSlots_destructor")]
35+
#[bindgen_special_member("dtor")]
3536
#[link_name = "\u{1}_ZN7nsSlotsD1Ev"]
3637
pub fn nsSlots_nsSlots_destructor(this: *mut nsSlots);
3738
}

tests/headers/special-members.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class A {
2+
public:
3+
A();
4+
A(A&);
5+
A(A&&);
6+
~A();
7+
};

0 commit comments

Comments
 (0)