Skip to content

Commit 4faaf9a

Browse files
committed
codegen: Deal with overloads in method code generation.
Fixes #2019
1 parent b21086c commit 4faaf9a

File tree

3 files changed

+151
-31
lines changed

3 files changed

+151
-31
lines changed

src/codegen/mod.rs

Lines changed: 68 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -422,37 +422,36 @@ trait CodeGenerator {
422422
/// Extra information from the caller.
423423
type Extra;
424424

425+
/// Extra information returned to the caller.
426+
type Return;
427+
425428
fn codegen<'a>(
426429
&self,
427430
ctx: &BindgenContext,
428431
result: &mut CodegenResult<'a>,
429432
extra: &Self::Extra,
430-
);
433+
) -> Self::Return;
431434
}
432435

433-
impl CodeGenerator for Item {
434-
type Extra = ();
435-
436-
fn codegen<'a>(
436+
impl Item {
437+
fn process_before_codegen(
437438
&self,
438439
ctx: &BindgenContext,
439-
result: &mut CodegenResult<'a>,
440-
_extra: &(),
441-
) {
440+
result: &mut CodegenResult,
441+
) -> bool {
442442
if !self.is_enabled_for_codegen(ctx) {
443-
return;
443+
return false;
444444
}
445445

446446
if self.is_blocklisted(ctx) || result.seen(self.id()) {
447447
debug!(
448-
"<Item as CodeGenerator>::codegen: Ignoring hidden or seen: \
448+
"<Item as CodeGenerator>::process_before_codegen: Ignoring hidden or seen: \
449449
self = {:?}",
450450
self
451451
);
452-
return;
452+
return false;
453453
}
454454

455-
debug!("<Item as CodeGenerator>::codegen: self = {:?}", self);
456455
if !ctx.codegen_items().contains(&self.id()) {
457456
// TODO(emilio, #453): Figure out what to do when this happens
458457
// legitimately, we could track the opaque stuff and disable the
@@ -461,6 +460,24 @@ impl CodeGenerator for Item {
461460
}
462461

463462
result.set_seen(self.id());
463+
true
464+
}
465+
}
466+
467+
impl CodeGenerator for Item {
468+
type Extra = ();
469+
type Return = ();
470+
471+
fn codegen<'a>(
472+
&self,
473+
ctx: &BindgenContext,
474+
result: &mut CodegenResult<'a>,
475+
_extra: &(),
476+
) {
477+
debug!("<Item as CodeGenerator>::codegen: self = {:?}", self);
478+
if !self.process_before_codegen(ctx, result) {
479+
return;
480+
}
464481

465482
match *self.kind() {
466483
ItemKind::Module(ref module) => {
@@ -481,6 +498,7 @@ impl CodeGenerator for Item {
481498

482499
impl CodeGenerator for Module {
483500
type Extra = Item;
501+
type Return = ();
484502

485503
fn codegen<'a>(
486504
&self,
@@ -572,6 +590,8 @@ impl CodeGenerator for Module {
572590

573591
impl CodeGenerator for Var {
574592
type Extra = Item;
593+
type Return = ();
594+
575595
fn codegen<'a>(
576596
&self,
577597
ctx: &BindgenContext,
@@ -698,6 +718,7 @@ impl CodeGenerator for Var {
698718

699719
impl CodeGenerator for Type {
700720
type Extra = Item;
721+
type Return = ();
701722

702723
fn codegen<'a>(
703724
&self,
@@ -1004,6 +1025,7 @@ impl<'a> Vtable<'a> {
10041025

10051026
impl<'a> CodeGenerator for Vtable<'a> {
10061027
type Extra = Item;
1028+
type Return = ();
10071029

10081030
fn codegen<'b>(
10091031
&self,
@@ -1048,6 +1070,7 @@ impl<'a> TryToRustTy for Vtable<'a> {
10481070

10491071
impl CodeGenerator for TemplateInstantiation {
10501072
type Extra = Item;
1073+
type Return = ();
10511074

10521075
fn codegen<'a>(
10531076
&self,
@@ -1664,6 +1687,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
16641687

16651688
impl CodeGenerator for CompInfo {
16661689
type Extra = Item;
1690+
type Return = ();
16671691

16681692
fn codegen<'a>(
16691693
&self,
@@ -2261,13 +2285,15 @@ impl MethodCodegen for Method {
22612285

22622286
// First of all, output the actual function.
22632287
let function_item = ctx.resolve_item(self.signature());
2264-
if function_item.is_blocklisted(ctx) {
2265-
// We shouldn't emit a method declaration if the function is blocklisted
2288+
if !function_item.process_before_codegen(ctx, result) {
22662289
return;
22672290
}
2268-
function_item.codegen(ctx, result, &());
2269-
22702291
let function = function_item.expect_function();
2292+
let times_seen = function.codegen(ctx, result, &function_item);
2293+
let times_seen = match times_seen {
2294+
Some(seen) => seen,
2295+
None => return,
2296+
};
22712297
let signature_item = ctx.resolve_item(function.signature());
22722298
let mut name = match self.kind() {
22732299
MethodKind::Constructor => "new".into(),
@@ -2302,7 +2328,11 @@ impl MethodCodegen for Method {
23022328
name.push_str(&count.to_string());
23032329
}
23042330

2305-
let function_name = ctx.rust_ident(function_item.canonical_name(ctx));
2331+
let mut function_name = function_item.canonical_name(ctx);
2332+
if times_seen > 0 {
2333+
write!(&mut function_name, "{}", times_seen).unwrap();
2334+
}
2335+
let function_name = ctx.rust_ident(function_name);
23062336
let mut args = utils::fnsig_arguments(ctx, signature);
23072337
let mut ret = utils::fnsig_return_ty(ctx, signature);
23082338

@@ -2808,6 +2838,7 @@ impl<'a> EnumBuilder<'a> {
28082838

28092839
impl CodeGenerator for Enum {
28102840
type Extra = Item;
2841+
type Return = ();
28112842

28122843
fn codegen<'a>(
28132844
&self,
@@ -3731,19 +3762,23 @@ impl TryToRustTy for FunctionSig {
37313762
impl CodeGenerator for Function {
37323763
type Extra = Item;
37333764

3765+
/// If we've actually generated the symbol, the number of times we've seen
3766+
/// it.
3767+
type Return = Option<u32>;
3768+
37343769
fn codegen<'a>(
37353770
&self,
37363771
ctx: &BindgenContext,
37373772
result: &mut CodegenResult<'a>,
37383773
item: &Item,
3739-
) {
3774+
) -> Self::Return {
37403775
debug!("<Function as CodeGenerator>::codegen: item = {:?}", item);
37413776
debug_assert!(item.is_enabled_for_codegen(ctx));
37423777

37433778
// We can't currently do anything with Internal functions so just
37443779
// avoid generating anything for them.
37453780
match self.linkage() {
3746-
Linkage::Internal => return,
3781+
Linkage::Internal => return None,
37473782
Linkage::External => {}
37483783
}
37493784

@@ -3753,7 +3788,7 @@ impl CodeGenerator for Function {
37533788
FunctionKind::Method(ref method_kind)
37543789
if method_kind.is_pure_virtual() =>
37553790
{
3756-
return;
3791+
return None;
37573792
}
37583793
_ => {}
37593794
}
@@ -3763,7 +3798,7 @@ impl CodeGenerator for Function {
37633798
// instantiations is open ended and we have no way of knowing which
37643799
// monomorphizations actually exist.
37653800
if !item.all_template_params(ctx).is_empty() {
3766-
return;
3801+
return None;
37673802
}
37683803

37693804
let name = self.name();
@@ -3776,7 +3811,7 @@ impl CodeGenerator for Function {
37763811
// TODO: Maybe warn here if there's a type/argument mismatch, or
37773812
// something?
37783813
if result.seen_function(seen_symbol_name) {
3779-
return;
3814+
return None;
37803815
}
37813816
result.saw_function(seen_symbol_name);
37823817
}
@@ -3803,21 +3838,14 @@ impl CodeGenerator for Function {
38033838
attributes.push(attributes::doc(comment));
38043839
}
38053840

3806-
// Handle overloaded functions by giving each overload its own unique
3807-
// suffix.
3808-
let times_seen = result.overload_number(&canonical_name);
3809-
if times_seen > 0 {
3810-
write!(&mut canonical_name, "{}", times_seen).unwrap();
3811-
}
3812-
38133841
let abi = match signature.abi() {
38143842
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
38153843
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
3816-
return;
3844+
return None;
38173845
}
38183846
Abi::Win64 if signature.is_variadic() => {
38193847
warn!("Skipping variadic function with Win64 ABI that isn't supported");
3820-
return;
3848+
return None;
38213849
}
38223850
Abi::Unknown(unknown_abi) => {
38233851
panic!(
@@ -3828,6 +3856,13 @@ impl CodeGenerator for Function {
38283856
abi => abi,
38293857
};
38303858

3859+
// Handle overloaded functions by giving each overload its own unique
3860+
// suffix.
3861+
let times_seen = result.overload_number(&canonical_name);
3862+
if times_seen > 0 {
3863+
write!(&mut canonical_name, "{}", times_seen).unwrap();
3864+
}
3865+
38313866
let link_name = mangled_name.unwrap_or(name);
38323867
if !utils::names_will_be_identical_after_mangling(
38333868
&canonical_name,
@@ -3878,6 +3913,7 @@ impl CodeGenerator for Function {
38783913
} else {
38793914
result.push(tokens);
38803915
}
3916+
Some(times_seen)
38813917
}
38823918
}
38833919

@@ -3933,6 +3969,7 @@ fn objc_method_codegen(
39333969

39343970
impl CodeGenerator for ObjCInterface {
39353971
type Extra = Item;
3972+
type Return = ();
39363973

39373974
fn codegen<'a>(
39383975
&self,
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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, Copy, Clone)]
10+
pub struct A {
11+
pub a: ::std::os::raw::c_int,
12+
}
13+
#[test]
14+
fn bindgen_test_layout_A() {
15+
assert_eq!(
16+
::std::mem::size_of::<A>(),
17+
4usize,
18+
concat!("Size of: ", stringify!(A))
19+
);
20+
assert_eq!(
21+
::std::mem::align_of::<A>(),
22+
4usize,
23+
concat!("Alignment of ", stringify!(A))
24+
);
25+
assert_eq!(
26+
unsafe { &(*(::std::ptr::null::<A>())).a as *const _ as usize },
27+
0usize,
28+
concat!("Offset of field: ", stringify!(A), "::", stringify!(a))
29+
);
30+
}
31+
extern "C" {
32+
#[link_name = "\u{1}_ZN1A4makeEv"]
33+
pub fn make() -> A;
34+
}
35+
impl A {
36+
#[inline]
37+
pub unsafe fn make() -> A {
38+
make()
39+
}
40+
}
41+
#[repr(C)]
42+
#[derive(Debug, Default, Copy, Clone)]
43+
pub struct B {
44+
pub b: ::std::os::raw::c_int,
45+
}
46+
#[test]
47+
fn bindgen_test_layout_B() {
48+
assert_eq!(
49+
::std::mem::size_of::<B>(),
50+
4usize,
51+
concat!("Size of: ", stringify!(B))
52+
);
53+
assert_eq!(
54+
::std::mem::align_of::<B>(),
55+
4usize,
56+
concat!("Alignment of ", stringify!(B))
57+
);
58+
assert_eq!(
59+
unsafe { &(*(::std::ptr::null::<B>())).b as *const _ as usize },
60+
0usize,
61+
concat!("Offset of field: ", stringify!(B), "::", stringify!(b))
62+
);
63+
}
64+
extern "C" {
65+
#[link_name = "\u{1}_ZN1B4makeEv"]
66+
pub fn make1() -> B;
67+
}
68+
impl B {
69+
#[inline]
70+
pub unsafe fn make() -> B {
71+
make1()
72+
}
73+
}

tests/headers/issue-2019.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// bindgen-flags: --disable-nested-struct-naming
2+
3+
struct A {
4+
static A make();
5+
int a;
6+
};
7+
struct B {
8+
static B make();
9+
int b;
10+
};

0 commit comments

Comments
 (0)