diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/checks/errors/rust-unsafe-checker.cc | 57 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/unsafe10.rs | 12 |
2 files changed, 66 insertions, 3 deletions
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index d9ef551..e3f3253 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -90,6 +90,50 @@ check_unsafe_call (HIR::Function *fn, Location locus, const std::string &kind) kind.c_str ()); } +static bool +is_safe_intrinsic (const std::string &fn_name) +{ + static const std::unordered_set<std::string> safe_intrinsics = { + "abort", + "size_of", + "min_align_of", + "needs_drop", + "caller_location", + "add_with_overflow", + "sub_with_overflow", + "mul_with_overflow", + "wrapping_add", + "wrapping_sub", + "wrapping_mul", + "saturating_add", + "saturating_sub", + "rotate_left", + "rotate_right", + "ctpop", + "ctlz", + "cttz", + "bswap", + "bitreverse", + "discriminant_value", + "type_id", + "likely", + "unlikely", + "ptr_guaranteed_eq", + "ptr_guaranteed_ne", + "minnumf32", + "minnumf64", + "maxnumf32", + "rustc_peek", + "maxnumf64", + "type_name", + "forget", + "black_box", + "variant_count", + }; + + return safe_intrinsics.find (fn_name) != safe_intrinsics.end (); +} + static void check_extern_call (HIR::ExternalItem *maybe_fn, HIR::ExternBlock *parent_block, Location locus) @@ -103,9 +147,16 @@ check_extern_call (HIR::ExternalItem *maybe_fn, HIR::ExternBlock *parent_block, // hand, any function defined in a block with a specific ABI (even `extern // "Rust"` blocks) is unsafe to call - if (maybe_fn->get_extern_kind () == ExternalItem::ExternKind::Function) - rust_error_at (locus, - "call to extern function requires unsafe function or block"); + if (maybe_fn->get_extern_kind () != ExternalItem::ExternKind::Function) + return; + + // Some intrinsics are safe to call + if (parent_block->get_abi () == Rust::ABI::INTRINSIC + && is_safe_intrinsic (maybe_fn->get_item_name ())) + return; + + rust_error_at (locus, + "call to extern function requires unsafe function or block"); } void diff --git a/gcc/testsuite/rust/compile/unsafe10.rs b/gcc/testsuite/rust/compile/unsafe10.rs new file mode 100644 index 0000000..6b6be06 --- /dev/null +++ b/gcc/testsuite/rust/compile/unsafe10.rs @@ -0,0 +1,12 @@ +extern "rust-intrinsic" { + pub fn rotate_left<T>(l: T, r: T) -> T; +} + +fn main() -> i32 { + let a = 15; + let b = 15; + + let _ = rotate_left(a, b); + + 0 +} |