Fix handling of `const SomeStruct&` when generating thunk impls.
Before this CL, `format_cc_type` would error out when trying to format a const-ref:
panicked at 'called `Result::unwrap()` on an `Err` value: Type not
yet supported: CcType { name: Some("&"), is_const: false, type_args:
[CcType { name: None, is_const: true, type_args: [], decl_id:
Some(DeclId(95208605585584)) }], decl_id: None }',
Additionally, the `const` qualifier could be lost.
PiperOrigin-RevId: 419833272
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index 64bbb79..4e05033 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -684,6 +684,13 @@
let nested_type = format_cc_type(&ty.type_args[0], ir)?;
Ok(quote! {#nested_type * #const_fragment})
}
+ "&" => {
+ if ty.type_args.len() != 1 {
+ bail!("Invalid reference type (need exactly 1 type argument): {:?}", ty);
+ }
+ let nested_type = format_cc_type(&ty.type_args[0], ir)?;
+ Ok(quote! {#nested_type &})
+ }
ident => {
if !ty.type_args.is_empty() {
bail!("Type not yet supported: {:?}", ty);
@@ -700,7 +707,7 @@
.identifier
.as_str(),
);
- Ok(quote! {#ident})
+ Ok(quote! {#const_fragment #ident})
}
}
@@ -1018,6 +1025,36 @@
}
#[test]
+ fn test_ref_to_struct_in_thunk_impls() -> Result<()> {
+ let ir = ir_from_cc("struct S{}; inline void foo(S& s) {} ")?;
+ let rs_api_impl = generate_rs_api_impl(&ir)?;
+ assert_cc_matches!(
+ rs_api_impl,
+ quote! {
+ extern "C" void __rust_thunk___Z3fooR1S(S& s) {
+ foo(s);
+ }
+ }
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn test_const_ref_to_struct_in_thunk_impls() -> Result<()> {
+ let ir = ir_from_cc("struct S{}; inline void foo(const S& s) {} ")?;
+ let rs_api_impl = generate_rs_api_impl(&ir)?;
+ assert_cc_matches!(
+ rs_api_impl,
+ quote! {
+ extern "C" void __rust_thunk___Z3fooRK1S(const S& s) {
+ foo(s);
+ }
+ }
+ );
+ Ok(())
+ }
+
+ #[test]
fn test_record_static_methods_qualify_call_in_thunk() -> Result<()> {
let ir = ir_from_cc(&tokens_to_string(quote! {
struct SomeStruct {
diff --git a/rs_bindings_from_cc/test/function/inline/hello_world.h b/rs_bindings_from_cc/test/function/inline/hello_world.h
index 84e7c07..e3bdd63 100644
--- a/rs_bindings_from_cc/test/function/inline/hello_world.h
+++ b/rs_bindings_from_cc/test/function/inline/hello_world.h
@@ -7,4 +7,11 @@
inline int hello_world_inline() { return 42; }
+// This testcase helps verify that thunks correctly work with const-ref
+// parameters. Using an 'inline' method forces generation of a C++ thunk.
+struct SomeStruct {
+ int int_field;
+};
+inline int take_struct_by_const_ref(const SomeStruct& s) { return s.int_field; }
+
#endif // CRUBIT_RS_BINDINGS_FROM_CC_TEST_FUNCTION_INLINE_HELLO_WORLD_H_
diff --git a/rs_bindings_from_cc/test/function/inline/test.rs b/rs_bindings_from_cc/test/function/inline/test.rs
index 9eefb3a..7074d7b 100644
--- a/rs_bindings_from_cc/test/function/inline/test.rs
+++ b/rs_bindings_from_cc/test/function/inline/test.rs
@@ -4,10 +4,16 @@
#[cfg(test)]
mod tests {
- use hello_world::hello_world_inline;
+ use hello_world::*;
#[test]
fn test_hello_world() {
assert_eq!(hello_world_inline(), 42);
}
+
+ #[test]
+ fn test_take_struct_by_const_ref() {
+ let s = SomeStruct { int_field: 789 };
+ assert_eq!(789, take_struct_by_const_ref(&s));
+ }
}