Skip to content

Commit e16a8de

Browse files
adetayloremilio
authored andcommitted
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 bf91987 commit e16a8de

File tree

6 files changed

+142
-10
lines changed

6 files changed

+142
-10
lines changed

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

+46
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
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

+13-7
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

+2-3
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,7 @@ impl ClangSubItemParser for Function {
734734
if visibility != CXVisibility_Default {
735735
return Err(ParseError::Continue);
736736
}
737-
738-
if cursor.access_specifier() == CX_CXXPrivate {
737+
if cursor.access_specifier() == CX_CXXPrivate && !context.options().generate_private_functions {
739738
return Err(ParseError::Continue);
740739
}
741740

@@ -755,7 +754,7 @@ impl ClangSubItemParser for Function {
755754
return Err(ParseError::Continue);
756755
}
757756

758-
if cursor.is_deleted_function() {
757+
if cursor.is_deleted_function() && !context.options().generate_deleted_functions {
759758
return Err(ParseError::Continue);
760759
}
761760

bindgen/options/cli.rs

+18
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,18 @@ struct BindgenCommand {
510510
/// bitfields. This flag is ignored if the `--respect-cxx-access-specs` flag is used.
511511
#[arg(long, value_name = "VISIBILITY")]
512512
default_visibility: Option<FieldVisibilityKind>,
513+
/// Whether to generate C++ functions marked with "=delete" even though they
514+
/// can't be called.
515+
#[arg(long)]
516+
generate_deleted_functions: bool,
517+
/// Whether to generate C++ "pure virtual" functions even though they can't
518+
/// be called.
519+
#[arg(long)]
520+
generate_pure_virtual_functions: bool,
521+
/// Whether to generate C++ private functions even though they can't
522+
/// be called.
523+
#[arg(long)]
524+
generate_private_functions: bool,
513525
/// Whether to emit diagnostics or not.
514526
#[cfg(feature = "experimental")]
515527
#[arg(long, requires = "experimental")]
@@ -657,6 +669,9 @@ where
657669
wrap_static_fns_path,
658670
wrap_static_fns_suffix,
659671
default_visibility,
672+
generate_deleted_functions,
673+
generate_pure_virtual_functions,
674+
generate_private_functions,
660675
#[cfg(feature = "experimental")]
661676
emit_diagnostics,
662677
generate_shell_completions,
@@ -948,6 +963,9 @@ where
948963
wrap_static_fns_path,
949964
wrap_static_fns_suffix,
950965
default_visibility,
966+
generate_deleted_functions,
967+
generate_pure_virtual_functions,
968+
generate_private_functions,
951969
}
952970
);
953971

bindgen/options/mod.rs

+54
Original file line numberDiff line numberDiff line change
@@ -2211,4 +2211,58 @@ options! {
22112211
},
22122212
as_args: "--clang-macro-fallback-build-dir",
22132213
}
2214+
/// Whether to always report C++ "deleted" functions.
2215+
generate_deleted_functions: bool {
2216+
methods: {
2217+
/// Set whether to generate C++ functions even marked "=deleted"
2218+
///
2219+
/// Although not useful to call these functions, downstream code
2220+
/// generators may need to know whether they've been deleted in
2221+
/// order to determine the relocatability of a C++ type
2222+
/// (specifically by virtue of which constructors exist.)
2223+
pub fn generate_deleted_functions(mut self, doit: bool) -> Self {
2224+
self.options.generate_deleted_functions = doit;
2225+
self
2226+
}
2227+
2228+
},
2229+
as_args: "--generate-deleted-functions",
2230+
},
2231+
/// Whether to always report C++ "pure virtual" functions.
2232+
generate_pure_virtual_functions: bool {
2233+
methods: {
2234+
/// Set whether to generate C++ functions that are pure virtual.
2235+
///
2236+
/// These functions can't be called, so the only reason
2237+
/// to generate them is if downstream postprocessors
2238+
/// need to know of their existence. This is necessary,
2239+
/// for instance, to determine whether a type itself is
2240+
/// pure virtual and thus can't be allocated.
2241+
/// Downstream code generators may choose to make code to
2242+
/// allow types to be allocated but need to avoid doing so
2243+
/// if the type contains pure virtual functions.
2244+
pub fn generate_pure_virtual_functions(mut self, doit: bool) -> Self {
2245+
self.options.generate_pure_virtual_functions = doit;
2246+
self
2247+
}
2248+
2249+
},
2250+
as_args: "--generate-pure-virtual-functions",
2251+
},
2252+
/// Whether to always report C++ "private" functions.
2253+
generate_private_functions: bool {
2254+
methods: {
2255+
/// Set whether to generate C++ functions that are private.
2256+
///
2257+
/// These functions can't be called, so the only reason
2258+
/// to generate them is if downstream postprocessors
2259+
/// need to know of their existence.
2260+
pub fn generate_private_functions(mut self, doit: bool) -> Self {
2261+
self.options.generate_private_functions = doit;
2262+
self
2263+
}
2264+
2265+
},
2266+
as_args: "--generate-private-functions",
2267+
},
22142268
}

0 commit comments

Comments
 (0)