Add getters for `no_unique_address` fields, and use them in a test.
PiperOrigin-RevId: 428594290
diff --git a/rs_bindings_from_cc/src_code_gen.rs b/rs_bindings_from_cc/src_code_gen.rs
index 889ba5a..2f10a0d 100644
--- a/rs_bindings_from_cc/src_code_gen.rs
+++ b/rs_bindings_from_cc/src_code_gen.rs
@@ -780,6 +780,7 @@
quote! {}
};
+ let no_unique_address_accessors = cc_struct_no_unique_address_impl(record, ir)?;
let base_class_into = cc_struct_upcast_impl(record, ir)?;
let record_tokens = quote! {
@@ -792,6 +793,8 @@
#empty_struct_placeholder_field
}
+ #no_unique_address_accessors
+
#base_class_into
#unpin_impl
@@ -1418,6 +1421,36 @@
}
}
+// Returns the accessor functions for no_unique_address member variables.
+fn cc_struct_no_unique_address_impl(record: &Record, ir: &IR) -> Result<TokenStream> {
+ let mut fields = vec![];
+ let mut types = vec![];
+ for field in &record.fields {
+ if field.access != AccessSpecifier::Public || !field.is_no_unique_address {
+ continue;
+ }
+ fields.push(make_rs_ident(&field.identifier.identifier));
+ types.push(format_rs_type(&field.type_.rs_type, ir, &HashMap::new()).with_context(
+ || format!("Failed to format type for field {:?} on record {:?}", field, record),
+ )?)
+ }
+
+ if fields.is_empty() {
+ return Ok(quote! {});
+ }
+
+ let ident = make_rs_ident(&record.identifier.identifier);
+ Ok(quote! {
+ impl #ident {
+ #(
+ pub fn #fields(&self) -> &#types {
+ unsafe {&* (&self.#fields as *const _ as *const #types)}
+ }
+ )*
+ }
+ })
+}
+
/// Returns the implementation of base class conversions, for converting a type
/// to its unambiguous public base classes.
///
@@ -2198,6 +2231,15 @@
field2: [std::mem::MaybeUninit<u8>; 2],
pub z: i16,
}
+
+ impl Struct {
+ pub fn field1(&self) -> &Field1 {
+ unsafe {&* (&self.field1 as *const _ as *const Field1)}
+ }
+ pub fn field2(&self) -> &Field2 {
+ unsafe {&* (&self.field2 as *const _ as *const Field2)}
+ }
+ }
}
);
Ok(())
diff --git a/rs_bindings_from_cc/test/struct/no_unique_address/no_unique_address.h b/rs_bindings_from_cc/test/struct/no_unique_address/no_unique_address.h
new file mode 100644
index 0000000..4ed5081
--- /dev/null
+++ b/rs_bindings_from_cc/test/struct/no_unique_address/no_unique_address.h
@@ -0,0 +1,17 @@
+// Part of the Crubit project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#ifndef CRUBIT_RS_BINDINGS_FROM_CC_TEST_STRUCT_NO_UNIQUE_ADDRESS_NO_UNIQUE_ADDRESS_H_
+#define CRUBIT_RS_BINDINGS_FROM_CC_TEST_STRUCT_NO_UNIQUE_ADDRESS_NO_UNIQUE_ADDRESS_H_
+#pragma clang lifetime_elision
+
+struct Struct final {
+ static Struct Make(int f1, char f2) { return Struct{f1, f2}; }
+ // Nobody would ever use a no_unique_address int/char field, this is just
+ // enough to test that the transmute is correct.
+ [[no_unique_address]] int field1 = 1;
+ [[no_unique_address]] char field2 = 2;
+};
+
+#endif // CRUBIT_RS_BINDINGS_FROM_CC_TEST_STRUCT_NO_UNIQUE_ADDRESS_NO_UNIQUE_ADDRESS_H_
diff --git a/rs_bindings_from_cc/test/struct/no_unique_address/no_unique_address_test.rs b/rs_bindings_from_cc/test/struct/no_unique_address/no_unique_address_test.rs
new file mode 100644
index 0000000..eeccd58
--- /dev/null
+++ b/rs_bindings_from_cc/test/struct/no_unique_address/no_unique_address_test.rs
@@ -0,0 +1,15 @@
+// Part of the Crubit project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#[cfg(test)]
+mod tests {
+ use no_unique_address::*;
+
+ #[test]
+ fn test_get() {
+ let s = Struct::Make(1, 2);
+ assert_eq!(s.field1(), &1);
+ assert_eq!(s.field2(), &2);
+ }
+}