Skip to content

Commit f5bf67a

Browse files
committed
Use NonNull for C++ references
- Make feature disabled by default until usability concerns are resolved. - Add test for --nonnull-references argument Signed-off-by: Tin Švagelj <[email protected]>
1 parent 1cf0a1f commit f5bf67a

File tree

5 files changed

+107
-0
lines changed

5 files changed

+107
-0
lines changed

bindgen-tests/tests/expectations/tests/references.rs

Lines changed: 61 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// bindgen-flags: --nonnull-references
2+
3+
struct Container {
4+
int *normalPointer;
5+
const int *constPointer;
6+
int &normalRef;
7+
const int &constRef;
8+
int *&pointerRef;
9+
const int *&constPointerRef;
10+
};
11+
12+
int &refReturningFunction();
13+
14+
void functionConsumingRef(int &someRef, float normalArgument,
15+
const int &constRef);
16+
17+
void functionConsumingPointerRef(int* &pointerRef);

bindgen/codegen/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4384,6 +4384,10 @@ impl TryToRustTy for Type {
43844384
if inner_ty.canonical_type(ctx).is_function() || is_objc_pointer
43854385
{
43864386
Ok(ty)
4387+
} else if ctx.options().generate_cxx_nonnull_references && matches!(self.kind(), TypeKind::Reference(_)) {
4388+
// It's UB to pass null values in place of C++ references
4389+
let prefix = ctx.trait_prefix();
4390+
Ok(syn::parse_quote! { ::#prefix::ptr::NonNull<#ty> })
43874391
} else {
43884392
Ok(ty.to_ptr(is_const))
43894393
}

bindgen/options/cli.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ struct BindgenCommand {
258258
/// Use extern crate instead of use for objc.
259259
#[arg(long)]
260260
objc_extern_crate: bool,
261+
/// Use `NonNull` in place of raw pointer for C++ references.
262+
#[arg(long)]
263+
nonnull_references: bool,
261264
/// Generate block signatures instead of void pointers.
262265
#[arg(long)]
263266
generate_block: bool,
@@ -590,6 +593,7 @@ where
590593
no_doc_comments,
591594
no_recursive_allowlist,
592595
objc_extern_crate,
596+
nonnull_references,
593597
generate_block,
594598
generate_cstr,
595599
block_extern_crate,
@@ -921,6 +925,7 @@ where
921925
no_doc_comments => |b, _| b.generate_comments(false),
922926
no_recursive_allowlist => |b, _| b.allowlist_recursively(false),
923927
objc_extern_crate,
928+
nonnull_references => |b, _| b.generate_cxx_nonnull_references(true),
924929
generate_block,
925930
generate_cstr,
926931
block_extern_crate,

bindgen/options/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,6 +1474,26 @@ options! {
14741474
},
14751475
as_args: |value, args| (!value).as_args(args, "--no-doc-comments"),
14761476
},
1477+
/// Whether to generate [`NonNull`] pointers for C++ references.
1478+
///
1479+
/// [`NonNull`]: core::ptr::NonNull
1480+
generate_cxx_nonnull_references: bool {
1481+
default: false,
1482+
methods: {
1483+
/// Generate `NonNull` pointers in place of raw pointers for C++
1484+
/// references.
1485+
///
1486+
/// This option is disabled by default:
1487+
///
1488+
/// Enabling it erases information about constness in generated
1489+
/// code, and `NonNull` is more cumbersome to use than raw pointers.
1490+
pub fn generate_cxx_nonnull_references(mut self, doit: bool) -> Self {
1491+
self.options.generate_cxx_nonnull_references = doit;
1492+
self
1493+
}
1494+
},
1495+
as_args: |value, args| value.as_args(args, "--nonnull-references"),
1496+
},
14771497
/// Whether to generate inline functions.
14781498
generate_inline_functions: bool {
14791499
methods: {

0 commit comments

Comments
 (0)