aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2022-08-08 08:48:26 +0200
committerArthur Cohen <arthur.cohen@embecosm.com>2022-08-08 09:07:54 +0200
commit084f959076c10d54bdb5c80cad10a0aac5756ea4 (patch)
treefb8a7e1ce1374e130fbe882fdbfcca5d8c575e88 /gcc/rust
parent7beea479c5a1e7e415223f3fbd4e16c20c3214ec (diff)
downloadgcc-084f959076c10d54bdb5c80cad10a0aac5756ea4.zip
gcc-084f959076c10d54bdb5c80cad10a0aac5756ea4.tar.gz
gcc-084f959076c10d54bdb5c80cad10a0aac5756ea4.tar.bz2
attr: Handle `rustc_const_{un}stable` properly
Since extern functions cannot be marked as const (they take no qualifiers) but some intrinsics are const, while still being `extern "rust-intrinsic", we need to be able to handle the `#[rustc_const_stable]` and `#[rustc_const_unstable]` attribute. Technically, this simply indicates that a certain intrinsic is constant and can be used in const contexts, such as `size_of` or `offset`. We also need to mark all const intrinsics with `rustc_const_stable` in the testsuite.
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.cc46
1 files changed, 43 insertions, 3 deletions
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index bb6ae10..bd4c7f1 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -235,11 +235,48 @@ ConstChecker::check_function_call (HirId fn_id, Location locus)
return;
auto maybe_fn = mappings.lookup_hir_item (fn_id);
- if (!maybe_fn || maybe_fn->get_item_kind () != Item::ItemKind::Function)
+ if (maybe_fn && maybe_fn->get_item_kind () != Item::ItemKind::Function)
return;
- auto fn = static_cast<Function *> (maybe_fn);
- if (!fn->get_qualifiers ().is_const ())
+ // There are const extern functions (intrinsics)
+ // TODO: Should we check the ABI is only "rust intrinsics"? Is that handled
+ // elsewhere?
+ HirId parent_block;
+ auto maybe_extern_item
+ = mappings.lookup_hir_extern_item (fn_id, &parent_block);
+ if (maybe_extern_item
+ && maybe_extern_item->get_extern_kind ()
+ != ExternalItem::ExternKind::Function)
+ return;
+
+ auto is_error = false;
+ if (maybe_fn)
+ {
+ auto fn = static_cast<Function *> (maybe_fn);
+ if (!fn->get_qualifiers ().is_const ())
+ is_error = true;
+ }
+
+ if (maybe_extern_item)
+ {
+ {
+ auto fn = static_cast<ExternalFunctionItem *> (maybe_extern_item);
+ auto is_const_extern = std::any_of (
+ fn->get_outer_attrs ().begin (), fn->get_outer_attrs ().end (),
+ [] (const AST::Attribute &attr) {
+ // `starts_with` in C++11...
+ // FIXME: Is it really how we want to handle `rustc_const_stable`
+ // and `rustc_const_unstable`?
+ // TODO: Add these attributes to the attribute check and handle
+ // `stable` and `unstable` as well
+ return attr.get_path ().as_string ().rfind ("rustc_const_", 0) == 0;
+ });
+ if (!is_const_extern)
+ is_error = true;
+ }
+ }
+
+ if (is_error)
rust_error_at (locus, "only functions marked as %<const%> are allowed to "
"be called from constant contexts");
}
@@ -522,6 +559,9 @@ ConstChecker::visit (Function &function)
if (const_fn)
const_context.enter (function.get_mappings ().get_hirid ());
+ for (auto &param : function.get_function_params ())
+ param.get_type ()->accept_vis (*this);
+
function.get_definition ()->accept_vis (*this);
if (const_fn)