Skip to content

Commit 25432ba

Browse files
committed
Options to generate uncallable C++ functions.
Downstream code generators may need to know about the existence of certain C++ functions even if those functions can't be called. This is counterintuitive but: * A type can't even be allocated if it contains pure virtual functions or if its constructor is private. * A type may not be relocatable if it contains a deleted move constructor. This PR provides command line options to reveal the existence of these functions. Subsequent PRs will announce their special status using the ParseCallbacks mechanism. Part of google/autocxx#124.
1 parent 61603fc commit 25432ba

File tree

6 files changed

+142
-10
lines changed

6 files changed

+142
-10
lines changed

bindgen-tests/tests/expectations/tests/uncallable_functions.rs

Lines changed: 46 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// bindgen-flags: --generate-deleted-functions --generate-private-functions --generate-pure-virtual-functions --generate-inline-functions -- -x c++ -std=c++14
2+
3+
class Test {
4+
public:
5+
virtual void a() = 0;
6+
void b() = delete;
7+
private:
8+
void c() {}
9+
};

bindgen/codegen/mod.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4564,14 +4564,20 @@ impl CodeGenerator for Function {
45644564
}
45654565
}
45664566

4567-
// Pure virtual methods have no actual symbol, so we can't generate
4568-
// something meaningful for them.
4569-
let is_dynamic_function = match self.kind() {
4570-
FunctionKind::Method(ref method_kind)
4571-
if method_kind.is_pure_virtual() =>
4572-
{
4573-
return None;
4567+
let is_pure_virtual = match self.kind() {
4568+
FunctionKind::Method(ref method_kind) => {
4569+
method_kind.is_pure_virtual()
45744570
}
4571+
_ => false,
4572+
};
4573+
if is_pure_virtual && !ctx.options().generate_pure_virtual_functions {
4574+
// Pure virtual methods have no actual symbol, so we can't generate
4575+
// something meaningful for them. Downstream code postprocessors
4576+
// might want to find out about them.
4577+
return None;
4578+
}
4579+
4580+
let is_dynamic_function = match self.kind() {
45754581
FunctionKind::Function => {
45764582
ctx.options().dynamic_library_name.is_some()
45774583
}

bindgen/ir/function.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -731,8 +731,7 @@ impl ClangSubItemParser for Function {
731731
if visibility != CXVisibility_Default {
732732
return Err(ParseError::Continue);
733733
}
734-
735-
if cursor.access_specifier() == CX_CXXPrivate {
734+
if cursor.access_specifier() == CX_CXXPrivate && !context.options().generate_private_functions {
736735
return Err(ParseError::Continue);
737736
}
738737

@@ -752,7 +751,7 @@ impl ClangSubItemParser for Function {
752751
return Err(ParseError::Continue);
753752
}
754753

755-
if cursor.is_deleted_function() {
754+
if cursor.is_deleted_function() && !context.options().generate_deleted_functions {
756755
return Err(ParseError::Continue);
757756
}
758757

bindgen/options/cli.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,18 @@ struct BindgenCommand {
507507
/// bitfields. This flag is ignored if the `--respect-cxx-access-specs` flag is used.
508508
#[arg(long, value_name = "VISIBILITY")]
509509
default_visibility: Option<FieldVisibilityKind>,
510+
/// Whether to generate C++ functions marked with "=delete" even though they
511+
/// can't be called.
512+
#[arg(long)]
513+
generate_deleted_functions: bool,
514+
/// Whether to generate C++ "pure virtual" functions even though they can't
515+
/// be called.
516+
#[arg(long)]
517+
generate_pure_virtual_functions: bool,
518+
/// Whether to generate C++ private functions even though they can't
519+
/// be called.
520+
#[arg(long)]
521+
generate_private_functions: bool,
510522
/// Whether to emit diagnostics or not.
511523
#[cfg(feature = "experimental")]
512524
#[arg(long, requires = "experimental")]
@@ -653,6 +665,9 @@ where
653665
wrap_static_fns_path,
654666
wrap_static_fns_suffix,
655667
default_visibility,
668+
generate_deleted_functions,
669+
generate_pure_virtual_functions,
670+
generate_private_functions,
656671
#[cfg(feature = "experimental")]
657672
emit_diagnostics,
658673
generate_shell_completions,
@@ -943,6 +958,9 @@ where
943958
wrap_static_fns_path,
944959
wrap_static_fns_suffix,
945960
default_visibility,
961+
generate_deleted_functions,
962+
generate_pure_virtual_functions,
963+
generate_private_functions,
946964
}
947965
);
948966

bindgen/options/mod.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2193,4 +2193,58 @@ options! {
21932193
},
21942194
as_args: "--clang-macro-fallback-build-dir",
21952195
}
2196+
/// Whether to always report C++ "deleted" functions.
2197+
generate_deleted_functions: bool {
2198+
methods: {
2199+
/// Set whether to generate C++ functions even marked "=deleted"
2200+
///
2201+
/// Although not useful to call these functions, downstream code
2202+
/// generators may need to know whether they've been deleted in
2203+
/// order to determine the relocatability of a C++ type
2204+
/// (specifically by virtue of which constructors exist.)
2205+
pub fn generate_deleted_functions(mut self, doit: bool) -> Self {
2206+
self.options.generate_deleted_functions = doit;
2207+
self
2208+
}
2209+
2210+
},
2211+
as_args: "--generate-deleted-functions",
2212+
},
2213+
/// Whether to always report C++ "pure virtual" functions.
2214+
generate_pure_virtual_functions: bool {
2215+
methods: {
2216+
/// Set whether to generate C++ functions that are pure virtual.
2217+
///
2218+
/// These functions can't be called, so the only reason
2219+
/// to generate them is if downstream postprocessors
2220+
/// need to know of their existence. This is necessary,
2221+
/// for instance, to determine whether a type itself is
2222+
/// pure virtual and thus can't be allocated.
2223+
/// Downstream code generators may choose to make code to
2224+
/// allow types to be allocated but need to avoid doing so
2225+
/// if the type contains pure virtual functions.
2226+
pub fn generate_pure_virtual_functions(mut self, doit: bool) -> Self {
2227+
self.options.generate_pure_virtual_functions = doit;
2228+
self
2229+
}
2230+
2231+
},
2232+
as_args: "--generate-pure-virtual-functions",
2233+
},
2234+
/// Whether to always report C++ "private" functions.
2235+
generate_private_functions: bool {
2236+
methods: {
2237+
/// Set whether to generate C++ functions that are private.
2238+
///
2239+
/// These functions can't be called, so the only reason
2240+
/// to generate them is if downstream postprocessors
2241+
/// need to know of their existence.
2242+
pub fn generate_private_functions(mut self, doit: bool) -> Self {
2243+
self.options.generate_private_functions = doit;
2244+
self
2245+
}
2246+
2247+
},
2248+
as_args: "--generate-private-functions",
2249+
},
21962250
}

0 commit comments

Comments
 (0)