diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2022-08-08 08:48:26 +0200 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2022-08-08 09:07:54 +0200 |
commit | 084f959076c10d54bdb5c80cad10a0aac5756ea4 (patch) | |
tree | fb8a7e1ce1374e130fbe882fdbfcca5d8c575e88 /gcc/rust | |
parent | 7beea479c5a1e7e415223f3fbd4e16c20c3214ec (diff) | |
download | gcc-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.cc | 46 |
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 ¶m : function.get_function_params ()) + param.get_type ()->accept_vis (*this); + function.get_definition ()->accept_vis (*this); if (const_fn) |