aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.cc57
-rw-r--r--gcc/testsuite/rust/compile/unsafe10.rs12
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
+}