diff --git a/cc_bindings_from_rs/generate_bindings/lib.rs b/cc_bindings_from_rs/generate_bindings/lib.rs index 35c852972..6dfbfe6dc 100644 --- a/cc_bindings_from_rs/generate_bindings/lib.rs +++ b/cc_bindings_from_rs/generate_bindings/lib.rs @@ -719,7 +719,6 @@ fn generate_using( let tcx = db.tcx(); match tcx.def_kind(def_id) { DefKind::Fn => { - // TODO(b/350772554): Support exporting private functions. let mut prereqs = match db.generate_function(def_id) { Ok(snippet) => snippet.main_api.prereqs, Err(err) => { @@ -733,15 +732,14 @@ fn generate_using( let main_api_fn_name = format_cc_ident(db, fully_qualified_fn_name.unqualified.cpp_name.as_str()) .context("Error formatting function name")?; - let using_name = + let using_name_ident = format_cc_ident(db, using_name.as_str()).context("Error formatting using name")?; prereqs.defs.insert(def_id); - let tokens = if format!("{}", using_name) == format!("{}", main_api_fn_name) { + let tokens = if using_name_ident.to_string() == main_api_fn_name.to_string() { quote! { using #formatted_fully_qualified_fn_name; } } else { - // TODO(b/350772554): Support function alias. - bail!("Unsupported function alias"); + quote! { constexpr auto #using_name_ident = #formatted_fully_qualified_fn_name; } }; Ok(CcSnippet { prereqs, tokens }) } diff --git a/cc_bindings_from_rs/test/uses/uses.rs b/cc_bindings_from_rs/test/uses/uses.rs index f08301512..e5ee23a9e 100644 --- a/cc_bindings_from_rs/test/uses/uses.rs +++ b/cc_bindings_from_rs/test/uses/uses.rs @@ -2,11 +2,15 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// Put before the real definition to make sure that the generarated C++ bindings -// is not affected by the order of the imports. +use crubit_annotate::must_bind; + +// Used before the real definition to make sure that the generarated C++ bindings +// are not affected by the order of the imports. +#[must_bind] pub use test_mod::f; pub mod test_mod { + #[crubit_annotate::must_bind] pub fn f() -> i32 { 42 } @@ -29,8 +33,11 @@ mod private_mod { } } +#[must_bind] pub use private_mod::private_fn; +#[must_bind] pub use private_mod::ReexportedStruct as ExportedStruct; +#[must_bind] pub use private_mod::ReexportedStruct as AliasOfExportedStruct; mod gg { @@ -38,27 +45,45 @@ mod gg { pub use extern_crate::X; } -// TODO(b/350772554): `use extern_crate::*`. +pub use extern_crate::X as XFromExternCrate; +#[must_bind] pub use gg::X; + +#[must_bind] pub fn return_x() -> X { X { field: 42 } } -#[crubit_annotate::must_bind] +#[must_bind] pub fn return_y() -> ::extern_crate::Y { ::extern_crate::Y { field: 42 } } -#[crubit_annotate::must_bind] +#[must_bind] pub struct Original { pub field: i32, } -#[crubit_annotate::must_bind] +#[must_bind] pub type Alias = Original; +#[must_bind] pub use Alias as Alias2; +mod private_for_renaming { + pub struct NonPublicName(pub i32); + pub fn non_public_name() {} +} +#[must_bind] +pub use private_for_renaming::non_public_name as public_name; +#[must_bind] +pub use private_for_renaming::NonPublicName as PublicName; + +#[must_bind] +pub use private_for_renaming::non_public_name as other_public_name; +#[must_bind] +pub use private_for_renaming::NonPublicName as OtherPublicName; + pub mod doc_hidden_test { mod private_mod { #[crubit_annotate::must_bind] diff --git a/cc_bindings_from_rs/test/uses/uses_cc_api.h b/cc_bindings_from_rs/test/uses/uses_cc_api.h index c0a1077ca..350ed2f86 100644 --- a/cc_bindings_from_rs/test/uses/uses_cc_api.h +++ b/cc_bindings_from_rs/test/uses/uses_cc_api.h @@ -25,7 +25,7 @@ namespace uses { // CRUBIT_ANNOTATE: must_bind= // // Generated from: -// cc_bindings_from_rs/test/uses/uses.rs;l=53 +// cc_bindings_from_rs/test/uses/uses.rs;l=63 struct CRUBIT_INTERNAL_RUST_TYPE(":: uses_golden :: Original") alignas(4) [[clang::trivial_abi]] Original final { public: @@ -45,7 +45,7 @@ struct CRUBIT_INTERNAL_RUST_TYPE(":: uses_golden :: Original") alignas(4) } union { // Generated from: - // cc_bindings_from_rs/test/uses/uses.rs;l=54 + // cc_bindings_from_rs/test/uses/uses.rs;l=64 std::int32_t field; }; @@ -58,7 +58,7 @@ namespace a::c { // CRUBIT_ANNOTATE: must_bind= // // Generated from: -// cc_bindings_from_rs/test/uses/uses.rs;l=84 +// cc_bindings_from_rs/test/uses/uses.rs;l=109 std::int32_t private_middle_path(); } // namespace a::c @@ -68,15 +68,52 @@ namespace doc_hidden_test::visible { // CRUBIT_ANNOTATE: must_bind= // // Generated from: -// cc_bindings_from_rs/test/uses/uses.rs;l=65 +// cc_bindings_from_rs/test/uses/uses.rs;l=90 std::int32_t private_fn(); } // namespace doc_hidden_test::visible +// Generated from: +// cc_bindings_from_rs/test/uses/uses.rs;l=74 +struct CRUBIT_INTERNAL_RUST_TYPE(":: uses_golden :: OtherPublicName") alignas(4) + [[clang::trivial_abi]] OtherPublicName final { + public: + // `uses_golden::OtherPublicName` doesn't implement the `Default` trait + OtherPublicName() = delete; + + // Synthesized tuple constructor + explicit OtherPublicName(std::int32_t __field0) + : __field0(std::move(__field0)) {} + + // No custom `Drop` impl and no custom "drop glue" required + ~OtherPublicName() = default; + OtherPublicName(OtherPublicName&&) = default; + OtherPublicName& operator=(OtherPublicName&&) = default; + + // `uses_golden::OtherPublicName` doesn't implement the `Clone` trait + OtherPublicName(const OtherPublicName&) = delete; + OtherPublicName& operator=(const OtherPublicName&) = delete; + OtherPublicName(::crubit::UnsafeRelocateTag, OtherPublicName&& value) { + memcpy(this, &value, sizeof(value)); + } + union { + // Generated from: + // cc_bindings_from_rs/test/uses/uses.rs;l=74 + std::int32_t __field0; + }; + + private: + static void __crubit_field_offset_assertions(); +}; + +// Generated from: +// cc_bindings_from_rs/test/uses/uses.rs;l=75 +void other_public_name(); + // CRUBIT_ANNOTATE: must_bind= // // Generated from: -// cc_bindings_from_rs/test/uses/uses.rs;l=17 +// cc_bindings_from_rs/test/uses/uses.rs;l=21 struct CRUBIT_INTERNAL_RUST_TYPE( ":: uses_golden :: AliasOfExportedStruct") alignas(4) [[clang::trivial_abi]] AliasOfExportedStruct final { @@ -98,12 +135,12 @@ AliasOfExportedStruct final { } // Generated from: - // cc_bindings_from_rs/test/uses/uses.rs;l=22 + // cc_bindings_from_rs/test/uses/uses.rs;l=26 static ::uses::AliasOfExportedStruct create(std::int32_t field); union { // Generated from: - // cc_bindings_from_rs/test/uses/uses.rs;l=18 + // cc_bindings_from_rs/test/uses/uses.rs;l=22 std::int32_t field; }; @@ -112,21 +149,25 @@ AliasOfExportedStruct final { }; // Generated from: -// cc_bindings_from_rs/test/uses/uses.rs;l=27 +// cc_bindings_from_rs/test/uses/uses.rs;l=31 std::int32_t private_fn(); +// CRUBIT_ANNOTATE: must_bind= +// // Generated from: -// cc_bindings_from_rs/test/uses/uses.rs;l=43 +// cc_bindings_from_rs/test/uses/uses.rs;l=53 ::extern_crate::X return_x(); // CRUBIT_ANNOTATE: must_bind= // // Generated from: -// cc_bindings_from_rs/test/uses/uses.rs;l=48 +// cc_bindings_from_rs/test/uses/uses.rs;l=58 ::extern_crate::Y return_y(); +// CRUBIT_ANNOTATE: must_bind= +// // Generated from: -// cc_bindings_from_rs/test/uses/uses.rs;l=10 +// cc_bindings_from_rs/test/uses/uses.rs;l=14 std::int32_t f(); using Alias CRUBIT_INTERNAL_RUST_TYPE(":: uses_golden :: Original") = @@ -173,6 +214,30 @@ inline std::int32_t private_fn() { } // namespace doc_hidden_test::visible using X CRUBIT_INTERNAL_RUST_TYPE(":: extern_crate :: X") = ::extern_crate::X; +using XFromExternCrate CRUBIT_INTERNAL_RUST_TYPE(":: extern_crate :: X") = + ::extern_crate::X; + +using PublicName CRUBIT_INTERNAL_RUST_TYPE( + ":: uses_golden :: OtherPublicName") = ::uses::OtherPublicName; +static_assert( + sizeof(OtherPublicName) == 4, + "Verify that ADT layout didn't change since this header got generated"); +static_assert( + alignof(OtherPublicName) == 4, + "Verify that ADT layout didn't change since this header got generated"); +static_assert(std::is_trivially_destructible_v); +static_assert(std::is_trivially_move_constructible_v); +static_assert(std::is_trivially_move_assignable_v); +inline void OtherPublicName::__crubit_field_offset_assertions() { + static_assert(0 == offsetof(OtherPublicName, __field0)); +} +constexpr auto public_name = ::uses::other_public_name; +namespace __crubit_internal { +extern "C" void __crubit_thunk_other_upublic_uname(); +} +inline void other_public_name() { + return __crubit_internal::__crubit_thunk_other_upublic_uname(); +} using ExportedStruct CRUBIT_INTERNAL_RUST_TYPE( ":: uses_golden :: AliasOfExportedStruct") = ::uses::AliasOfExportedStruct; diff --git a/cc_bindings_from_rs/test/uses/uses_cc_api_impl.rs b/cc_bindings_from_rs/test/uses/uses_cc_api_impl.rs index 6a8faa1d8..327c3ea34 100644 --- a/cc_bindings_from_rs/test/uses/uses_cc_api_impl.rs +++ b/cc_bindings_from_rs/test/uses/uses_cc_api_impl.rs @@ -21,6 +21,13 @@ unsafe extern "C" fn __crubit_thunk_private_umiddle_upath() -> i32 { unsafe extern "C" fn __crubit_thunk_private_ufn() -> i32 { unsafe { ::uses_golden::doc_hidden_test::visible::private_fn() } } +const _: () = assert!(::std::mem::size_of::<::uses_golden::OtherPublicName>() == 4); +const _: () = assert!(::std::mem::align_of::<::uses_golden::OtherPublicName>() == 4); +const _: () = assert!(::core::mem::offset_of!(::uses_golden::OtherPublicName, 0) == 0); +#[unsafe(no_mangle)] +unsafe extern "C" fn __crubit_thunk_other_upublic_uname() -> () { + unsafe { ::uses_golden::other_public_name() } +} const _: () = assert!(::std::mem::size_of::<::uses_golden::AliasOfExportedStruct>() == 4); const _: () = assert!(::std::mem::align_of::<::uses_golden::AliasOfExportedStruct>() == 4); #[unsafe(no_mangle)] diff --git a/cc_bindings_from_rs/test/uses/uses_test.cc b/cc_bindings_from_rs/test/uses/uses_test.cc index e8d499350..d3daac4e9 100644 --- a/cc_bindings_from_rs/test/uses/uses_test.cc +++ b/cc_bindings_from_rs/test/uses/uses_test.cc @@ -45,5 +45,10 @@ TEST(UsesTest, PrivateModuleInMiddleOfPath) { EXPECT_EQ(uses::a::c::private_middle_path(), 742); } +TEST(UsesTest, FunctionWithMultipleAliases) { + uses::public_name(); + uses::other_public_name(); +} + } // namespace } // namespace crubit \ No newline at end of file