Skip to content

Commit 61cdc00

Browse files
committed
Report C++ visibility and other details.
This change reports extra C++ information about items: * Whether methods are virtual or pure virtual or neither * Whether a method is a "special member", e.g. a move constructor * Whether a method is defaulted or deleted * C++ visibility (for structs, enums, unions and methods) It builds on top of #3145. A follow up PR should enhance the tests once #3139 is merged. Part of google/autocxx#124
1 parent bf438d1 commit 61cdc00

File tree

9 files changed

+315
-12
lines changed

9 files changed

+315
-12
lines changed

bindgen-tests/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp

+10
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,15 @@
22

33
class SomeClass {
44
public:
5+
SomeClass() = delete;
6+
SomeClass(const SomeClass&) = default;
7+
SomeClass(SomeClass&&);
58
void named_method();
9+
virtual void virtual_method();
10+
virtual void pure_virtual_method() = 0;
11+
private:
12+
void private_method();
13+
protected:
14+
void protected_method();
15+
616
};

bindgen-tests/tests/parse_callbacks/item_discovery_callback/mod.rs

+87-5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use regex::Regex;
77

88
use bindgen::callbacks::{
99
DiscoveredItem, DiscoveredItemId, ParseCallbacks, SourceLocation,
10+
SpecialMemberKind, Visibility,
1011
};
1112
use bindgen::Builder;
1213

@@ -101,6 +102,7 @@ fn test_item_discovery_callback_c() {
101102
DiscoveredItem::Struct {
102103
original_name: Some("NamedStruct".to_string()),
103104
final_name: "NamedStruct".to_string(),
105+
cpp_visibility: Visibility::Public,
104106
},
105107
4,
106108
8,
@@ -127,6 +129,7 @@ fn test_item_discovery_callback_c() {
127129
DiscoveredItem::Union {
128130
original_name: Some("NamedUnion".to_string()),
129131
final_name: "NamedUnion".to_string(),
132+
cpp_visibility: Visibility::Public,
130133
},
131134
13,
132135
7,
@@ -165,6 +168,7 @@ fn test_item_discovery_callback_c() {
165168
ItemExpectations::new(
166169
DiscoveredItem::Enum {
167170
final_name: "NamedEnum".to_string(),
171+
cpp_visibility: Visibility::Public,
168172
},
169173
24,
170174
6,
@@ -178,6 +182,7 @@ fn test_item_discovery_callback_c() {
178182
DiscoveredItem::Struct {
179183
original_name: None,
180184
final_name: "_bindgen_ty_*".to_string(),
185+
cpp_visibility: Visibility::Public,
181186
},
182187
2,
183188
38,
@@ -191,6 +196,7 @@ fn test_item_discovery_callback_c() {
191196
DiscoveredItem::Union {
192197
original_name: None,
193198
final_name: "_bindgen_ty_*".to_string(),
199+
cpp_visibility: Visibility::Public,
194200
},
195201
11,
196202
37,
@@ -216,14 +222,15 @@ fn test_item_discovery_callback_c() {
216222
}
217223

218224
#[test]
219-
fn test_item_discovery_callback_cpp() {
225+
fn test_item_discovery_callback_cpp_features() {
220226
let expected = ExpectationMap::from([
221227
(
222228
DiscoveredItemId::new(1),
223229
ItemExpectations::new(
224230
DiscoveredItem::Struct {
225231
original_name: Some("SomeClass".to_string()),
226232
final_name: "SomeClass".to_string(),
233+
cpp_visibility: Visibility::Public,
227234
},
228235
3,
229236
7,
@@ -237,16 +244,57 @@ fn test_item_discovery_callback_cpp() {
237244
DiscoveredItem::Method {
238245
final_name: "named_method".to_string(),
239246
parent: DiscoveredItemId::new(1),
247+
cpp_visibility: Visibility::Public,
248+
cpp_special_member: None,
249+
cpp_virtual: None,
250+
cpp_explicit: None,
240251
},
241-
5,
252+
8,
242253
10,
243-
47,
254+
144,
255+
None,
256+
),
257+
),
258+
(
259+
DiscoveredItemId::new(48),
260+
ItemExpectations::new(
261+
DiscoveredItem::Method {
262+
final_name: "protected_method".to_string(),
263+
parent: DiscoveredItemId::new(1),
264+
cpp_visibility: Visibility::Protected,
265+
cpp_special_member: None,
266+
cpp_virtual: None,
267+
cpp_explicit: None,
268+
},
269+
14,
270+
10,
271+
295,
272+
None,
273+
),
274+
),
275+
(
276+
DiscoveredItemId::new(19),
277+
ItemExpectations::new(
278+
DiscoveredItem::Method {
279+
final_name: "new".to_string(),
280+
parent: DiscoveredItemId::new(1),
281+
cpp_visibility: Visibility::Public,
282+
cpp_special_member: Some(
283+
SpecialMemberKind::MoveConstructor,
284+
),
285+
cpp_virtual: None,
286+
cpp_explicit: None,
287+
},
288+
7,
289+
5,
290+
111,
244291
None,
245292
),
246293
),
247294
]);
295+
248296
test_item_discovery_callback(
249-
"/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp", expected, identity);
297+
"/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp", expected, |b| b.clang_arg("--std=c++11"));
250298
}
251299

252300
/// Returns the expectations corresponding to header_item_discovery_with_namespaces.hpp,
@@ -361,6 +409,7 @@ fn cpp_expectation_map() -> ExpectationMap {
361409
DiscoveredItem::Struct {
362410
final_name: "L".to_string(),
363411
original_name: Some("L".to_string()),
412+
cpp_visibility: Visibility::Public,
364413
},
365414
25,
366415
12,
@@ -374,6 +423,7 @@ fn cpp_expectation_map() -> ExpectationMap {
374423
DiscoveredItem::Struct {
375424
final_name: "L_M".to_string(),
376425
original_name: Some("M".to_string()),
426+
cpp_visibility: Visibility::Public,
377427
},
378428
26,
379429
16,
@@ -597,6 +647,7 @@ pub fn compare_struct_info(
597647
let DiscoveredItem::Struct {
598648
original_name: expected_original_name,
599649
final_name: expected_final_name,
650+
cpp_visibility: expected_cpp_visibility,
600651
} = expected_item
601652
else {
602653
unreachable!()
@@ -605,6 +656,7 @@ pub fn compare_struct_info(
605656
let DiscoveredItem::Struct {
606657
original_name: generated_original_name,
607658
final_name: generated_final_name,
659+
cpp_visibility: generated_cpp_visibility,
608660
} = generated_item
609661
else {
610662
unreachable!()
@@ -614,6 +666,10 @@ pub fn compare_struct_info(
614666
return false;
615667
}
616668

669+
if expected_cpp_visibility != generated_cpp_visibility {
670+
return false;
671+
}
672+
617673
match (expected_original_name, generated_original_name) {
618674
(None, None) => true,
619675
(Some(expected_original_name), Some(generated_original_name)) => {
@@ -630,6 +686,7 @@ pub fn compare_union_info(
630686
let DiscoveredItem::Union {
631687
original_name: expected_original_name,
632688
final_name: expected_final_name,
689+
cpp_visibility: expected_cpp_visibility,
633690
} = expected_item
634691
else {
635692
unreachable!()
@@ -638,6 +695,7 @@ pub fn compare_union_info(
638695
let DiscoveredItem::Union {
639696
original_name: generated_original_name,
640697
final_name: generated_final_name,
698+
cpp_visibility: generated_cpp_visibility,
641699
} = generated_item
642700
else {
643701
unreachable!()
@@ -647,6 +705,10 @@ pub fn compare_union_info(
647705
return false;
648706
}
649707

708+
if expected_cpp_visibility != generated_cpp_visibility {
709+
return false;
710+
}
711+
650712
match (expected_original_name, generated_original_name) {
651713
(None, None) => true,
652714
(Some(expected_original_name), Some(generated_original_name)) => {
@@ -662,13 +724,15 @@ pub fn compare_enum_info(
662724
) -> bool {
663725
let DiscoveredItem::Enum {
664726
final_name: expected_final_name,
727+
cpp_visibility: expected_cpp_visibility,
665728
} = expected_item
666729
else {
667730
unreachable!()
668731
};
669732

670733
let DiscoveredItem::Enum {
671734
final_name: generated_final_name,
735+
cpp_visibility: generated_cpp_visibility,
672736
} = generated_item
673737
else {
674738
unreachable!()
@@ -677,6 +741,11 @@ pub fn compare_enum_info(
677741
if !compare_names(expected_final_name, generated_final_name) {
678742
return false;
679743
}
744+
745+
if expected_cpp_visibility != generated_cpp_visibility {
746+
return false;
747+
}
748+
680749
true
681750
}
682751

@@ -755,6 +824,10 @@ pub fn compare_method_info(
755824
let DiscoveredItem::Method {
756825
final_name: expected_final_name,
757826
parent: expected_parent,
827+
cpp_visibility: expected_cpp_visibility,
828+
cpp_special_member: expected_cpp_special_member,
829+
cpp_virtual: expected_cpp_virtual,
830+
cpp_explicit: expected_cpp_explicit,
758831
} = expected_item
759832
else {
760833
unreachable!()
@@ -763,12 +836,21 @@ pub fn compare_method_info(
763836
let DiscoveredItem::Method {
764837
final_name: generated_final_name,
765838
parent: generated_parent,
839+
cpp_visibility: generated_cpp_visibility,
840+
cpp_special_member: generated_cpp_special_member,
841+
cpp_virtual: generated_cpp_virtual,
842+
cpp_explicit: generated_cpp_explicit,
766843
} = generated_item
767844
else {
768845
unreachable!()
769846
};
770847

771-
if expected_parent != generated_parent {
848+
if expected_parent != generated_parent
849+
|| expected_cpp_explicit != generated_cpp_explicit
850+
|| expected_cpp_special_member != generated_cpp_special_member
851+
|| expected_cpp_virtual != generated_cpp_virtual
852+
|| expected_cpp_visibility != generated_cpp_visibility
853+
{
772854
return false;
773855
}
774856

bindgen/callbacks.rs

+38
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
//! A public API for more fine-grained customization of bindgen behavior.
22
33
pub use crate::ir::analysis::DeriveTrait;
4+
pub use crate::ir::comp::SpecialMemberKind;
45
pub use crate::ir::derive::CanDerive as ImplementsTrait;
56
pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue};
7+
pub use crate::ir::function::Explicitness;
8+
pub use crate::ir::function::Visibility;
69
pub use crate::ir::int::IntKind;
710
use std::fmt;
811

@@ -208,6 +211,10 @@ pub enum DiscoveredItem {
208211

209212
/// The name of the generated binding
210213
final_name: String,
214+
215+
/// Its C++ visibility. [`Visibility::Public`] unless this is nested
216+
/// in another type.
217+
cpp_visibility: Visibility,
211218
},
212219

213220
/// Represents a union with its original name in C and its generated binding name
@@ -218,6 +225,10 @@ pub enum DiscoveredItem {
218225

219226
/// The name of the generated binding
220227
final_name: String,
228+
229+
/// Its C++ visibility. [`Visibility::Public`] unless this is nested
230+
/// in another type.
231+
cpp_visibility: Visibility,
221232
},
222233

223234
/// Represents an alias like a typedef
@@ -239,6 +250,10 @@ pub enum DiscoveredItem {
239250
Enum {
240251
/// The final name of the generated binding
241252
final_name: String,
253+
254+
/// Its C++ visibility. [`Visibility::Public`] unless this is nested
255+
/// in another type.
256+
cpp_visibility: Visibility,
242257
},
243258

244259
/// A module, representing a C++ namespace.
@@ -269,6 +284,20 @@ pub enum DiscoveredItem {
269284

270285
/// Type to which this method belongs.
271286
parent: DiscoveredItemId,
287+
288+
/// Its C++ visibility.
289+
cpp_visibility: Visibility,
290+
291+
/// Whether this is a C++ "special member".
292+
cpp_special_member: Option<SpecialMemberKind>,
293+
294+
/// Whether this is a C++ virtual function.
295+
cpp_virtual: Option<Virtualness>,
296+
297+
/// Whether this is a C++ function which has been marked
298+
/// `=default` or `=deleted`. Note that deleted functions aren't
299+
/// normally generated without special bindgen options.
300+
cpp_explicit: Option<Explicitness>,
272301
},
273302
}
274303

@@ -336,6 +365,15 @@ pub struct FieldInfo<'a> {
336365
pub field_type_name: Option<&'a str>,
337366
}
338367

368+
/// Whether a method is virtual or pure virtual.
369+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
370+
pub enum Virtualness {
371+
/// Not pure virtual.
372+
Virtual,
373+
/// Pure virtual.
374+
PureVirtual,
375+
}
376+
339377
/// Location in the source code. Roughly equivalent to the same type
340378
/// within `clang_sys`.
341379
#[derive(Clone, Debug, PartialEq, Eq)]

bindgen/clang.rs

+15
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,21 @@ impl Cursor {
927927
unsafe { clang_isVirtualBase(self.x) != 0 }
928928
}
929929

930+
// Is this cursor's referent a default constructor?
931+
pub fn is_default_constructor(&self) -> bool {
932+
unsafe { clang_CXXConstructor_isDefaultConstructor(self.x) != 0 }
933+
}
934+
935+
// Is this cursor's referent a copy constructor?
936+
pub fn is_copy_constructor(&self) -> bool {
937+
unsafe { clang_CXXConstructor_isCopyConstructor(self.x) != 0 }
938+
}
939+
940+
// Is this cursor's referent a move constructor?
941+
pub fn is_move_constructor(&self) -> bool {
942+
unsafe { clang_CXXConstructor_isMoveConstructor(self.x) != 0 }
943+
}
944+
930945
/// Try to evaluate this cursor.
931946
pub(crate) fn evaluate(&self) -> Option<EvalResult> {
932947
EvalResult::new(*self)

0 commit comments

Comments
 (0)