Lukasz Anforowicz | 41e578a | 2022-10-21 07:53:38 -0700 | [diff] [blame] | 1 | // Part of the Crubit project, under the Apache License v2.0 with LLVM |
| 2 | // Exceptions. See /LICENSE for license information. |
| 3 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 4 | |
| 5 | //! This crate is used as a test input for `cc_bindings_from_rs` and the |
| 6 | //! generated C++ bindings are then tested via `functions_test.cc`. |
| 7 | |
Lukasz Anforowicz | f0f37dd | 2023-01-05 11:22:06 -0800 | [diff] [blame] | 8 | /// APIs for testing various function calling conventions and linking options: |
| 9 | /// - `#[no_mangle]` |
| 10 | /// - `#[export_name = ...]` |
| 11 | /// - `extern "C"` vs default/Rust ABI |
| 12 | /// - etc. |
| 13 | pub mod fn_abi_tests { |
Lukasz Anforowicz | f04bc52 | 2022-11-04 09:19:51 -0700 | [diff] [blame] | 14 | |
Lukasz Anforowicz | f0f37dd | 2023-01-05 11:22:06 -0800 | [diff] [blame] | 15 | /// Testing one of simpler function bindings: |
| 16 | /// - `extern "C"` means that no thunk is required |
| 17 | /// - `#[no_mangle]` means that the function is already exposed with the |
| 18 | /// desired, public name (and just needs to be redeclared in C++). |
| 19 | #[no_mangle] |
| 20 | pub extern "C" fn get_42_as_f64_via_no_mangle_extern_c() -> f64 { |
| 21 | 42.0 |
| 22 | } |
| 23 | |
| 24 | /// Testing `#[export_name = ...]` - the generated bindings need to |
| 25 | /// forward/proxy the call into a function with a different name. |
| 26 | #[export_name = "custom_export_name_for_add_i32"] |
| 27 | pub extern "C" fn add_i32_via_extern_c_with_export_name(x: i32, y: i32) -> i32 { |
| 28 | x + y |
| 29 | } |
| 30 | |
| 31 | /// Testing bindings for an `extern "C"` function (no thunk required) with a |
| 32 | /// mangled name. This test verifies that: |
| 33 | /// * `cc_bindings_from_rs` can correctly discover mangled names that |
| 34 | /// `rustc` produces |
| 35 | /// * Bazel support for `cc_bindings_from_rs` invokes it with the same |
| 36 | /// command line flags as the ones used when invoking `rustc` when |
| 37 | /// building the `functions` crate. |
| 38 | /// |
| 39 | /// TODO(b/262904507): Bazel integration is currently broken and the |
| 40 | /// coresponding test is commented out in `functions_test.cc`. |
| 41 | pub extern "C" fn add_i32_via_extern_c_with_mangling(x: i32, y: i32) -> i32 { |
| 42 | x + y |
| 43 | } |
| 44 | |
| 45 | /// Testing the default / Rust ABI (one used in absence of `extern "C"`). |
| 46 | pub fn add_i32_via_rust_abi(x: i32, y: i32) -> i32 { |
| 47 | x + y |
| 48 | } |
Lukasz Anforowicz | 41e578a | 2022-10-21 07:53:38 -0700 | [diff] [blame] | 49 | } |
Lukasz Anforowicz | 903fc63 | 2022-10-25 08:55:33 -0700 | [diff] [blame] | 50 | |
Lukasz Anforowicz | f0f37dd | 2023-01-05 11:22:06 -0800 | [diff] [blame] | 51 | /// APIs for testing various kinds of function parameter types. |
| 52 | pub mod fn_param_ty_tests { |
| 53 | /// Testing a type that maps to a built-in C++ type (spelled with a |
| 54 | /// keyword). `float` is one such example. |
| 55 | pub fn add_f64(x: f64, y: f64) -> f64 { |
| 56 | x + y |
| 57 | } |
| 58 | |
| 59 | /// Testing a type that requires `#include`ing a standard C++ header. |
| 60 | /// `std::int32_t` is one such example - it requires `#include <cstdint>`. |
| 61 | pub fn add_i32(x: i32, y: i32) -> i32 { |
| 62 | x + y |
| 63 | } |
Lukasz Anforowicz | eb58a49 | 2023-01-07 08:25:48 -0800 | [diff] [blame] | 64 | |
| 65 | pub fn add_i32_via_ptr(x: *const i32, y: *const i32, sum: *mut i32) { |
| 66 | #![allow(clippy::not_unsafe_ptr_arg_deref)] |
| 67 | unsafe { |
| 68 | *sum = *x + *y; |
| 69 | } |
| 70 | } |
Lukasz Anforowicz | a782bda | 2023-01-17 14:04:50 -0800 | [diff] [blame] | 71 | |
Lukasz Anforowicz | b06e081 | 2023-03-02 15:54:32 -0800 | [diff] [blame] | 72 | pub fn char_to_ascii_lowercase(c: char) -> char { |
| 73 | // This function used to return unmodified `c` value, but (as we learned when |
| 74 | // authoring `rs_bindings_from_cc/test/struct/abi_class` tests) making |
| 75 | // some simple calculations below helps to exercise the ABI |
| 76 | // compatibility between Rust `char` and C++ `rs_std::rs_char`. |
| 77 | c.to_ascii_lowercase() |
Lukasz Anforowicz | a782bda | 2023-01-17 14:04:50 -0800 | [diff] [blame] | 78 | } |
Lukasz Anforowicz | 5c1b3ad | 2023-04-13 17:05:00 -0700 | [diff] [blame] | 79 | |
| 80 | pub fn apply_binary_i32_op(x: i32, y: i32, f: extern "C" fn(i32, i32) -> i32) -> i32 { |
| 81 | f(x, y) |
| 82 | } |
Lukasz Anforowicz | aa2de7e | 2023-06-15 11:32:05 -0700 | [diff] [blame] | 83 | |
| 84 | pub fn get_ref_to_smaller_int<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { |
| 85 | if *x < *y { x } else { y } |
| 86 | } |
| 87 | |
| 88 | pub fn get_identical_ref_with_inferred_lifetime(x: &'_ i32) -> &'_ i32 { |
| 89 | x |
| 90 | } |
| 91 | |
| 92 | pub fn set_mut_ref_to_sum_of_ints(sum: &mut i32, x: i32, y: i32) { |
| 93 | *sum = x + y; |
| 94 | } |
Lukasz Anforowicz | 903fc63 | 2022-10-25 08:55:33 -0700 | [diff] [blame] | 95 | } |
Lukasz Anforowicz | ed17d05 | 2022-11-02 12:07:28 -0700 | [diff] [blame] | 96 | |
Lukasz Anforowicz | f0f37dd | 2023-01-05 11:22:06 -0800 | [diff] [blame] | 97 | /// APIs for testing functions that return the unit / `()` / `void` type. |
| 98 | pub mod unit_ret_ty_tests { |
| 99 | use std::sync::Mutex; |
| 100 | |
| 101 | static G_I32: Mutex<i32> = Mutex::new(0); |
| 102 | |
| 103 | // Presence of the API below tests how bindings handle functions returning |
| 104 | // `void`. |
| 105 | #[export_name = "custom_export_name_for_get_global_i32"] |
| 106 | pub extern "C" fn set_global_i32_via_extern_c_with_export_name(x: i32) { |
| 107 | *G_I32.lock().unwrap() = x; |
| 108 | } |
| 109 | |
| 110 | #[no_mangle] |
| 111 | pub extern "C" fn get_global_i32_via_extern_c_with_export_name() -> i32 { |
| 112 | *G_I32.lock().unwrap() |
| 113 | } |
Lukasz Anforowicz | ed17d05 | 2022-11-02 12:07:28 -0700 | [diff] [blame] | 114 | } |
Lukasz Anforowicz | f04bc52 | 2022-11-04 09:19:51 -0700 | [diff] [blame] | 115 | |
Lukasz Anforowicz | f0f37dd | 2023-01-05 11:22:06 -0800 | [diff] [blame] | 116 | pub mod other_fn_param_tests { |
| 117 | pub fn add_i32_via_rust_abi_with_duplicated_param_names(x: i32, y: i32, _: i32, _: i32) -> i32 { |
| 118 | x + y |
| 119 | } |
Lukasz Anforowicz | f04bc52 | 2022-11-04 09:19:51 -0700 | [diff] [blame] | 120 | } |
Devin Jeanpierre | d63080a | 2023-12-20 17:59:22 -0800 | [diff] [blame] | 121 | |
Googler | 6b39531 | 2024-04-22 17:09:02 -0700 | [diff] [blame] | 122 | pub mod fn_attribute_tests { |
| 123 | #[deprecated(since = "1.2.3", note = "★ Deprecated note for add_i32 ★")] |
| 124 | pub fn add_i32(x: i32, y: i32) -> i32 { |
| 125 | x + y |
| 126 | } |
| 127 | } |
| 128 | |
Devin Jeanpierre | d63080a | 2023-12-20 17:59:22 -0800 | [diff] [blame] | 129 | pub mod unsafe_fn_tests { |
| 130 | /// # Safety |
| 131 | /// |
| 132 | /// This function has no safety requirements - it is only marked as `unsafe` |
| 133 | /// to facilitate minimal testing of bindings generated for such functions. |
| 134 | pub unsafe fn unsafe_add(x: i32, y: i32) -> i32 { |
| 135 | x + y |
| 136 | } |
| 137 | } |
Googler | 208c1ad | 2024-04-22 15:39:30 -0700 | [diff] [blame] | 138 | |
| 139 | // Tests the use of the #[must_use] attribute |
| 140 | pub mod fn_must_use_tests { |
| 141 | #[must_use] |
| 142 | pub fn no_msg_add(x: i32, y: i32) -> i32 { |
| 143 | x + y |
| 144 | } |
| 145 | |
| 146 | #[must_use = "woohoo"] |
| 147 | pub fn msg_add(x: i32, y: i32) -> i32 { |
| 148 | x + y |
| 149 | } |
| 150 | } |