diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-08-09 13:48:52 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-09 13:48:52 +0000 |
commit | 17b625cbd612f05359c3199a3253f42e4cf25120 (patch) | |
tree | 36d03056fb9747a4394c56f78c29e13f1d6df82b /gcc/rust | |
parent | 8749b66879f3ef78182d7712e5da981cc55f747a (diff) | |
parent | 4ffd884a69396d828049d4a14d17e6d3f6c8d61f (diff) | |
download | gcc-17b625cbd612f05359c3199a3253f42e4cf25120.zip gcc-17b625cbd612f05359c3199a3253f42e4cf25120.tar.gz gcc-17b625cbd612f05359c3199a3253f42e4cf25120.tar.bz2 |
Merge #1444
1444: Handle `rustc_const_{un}stable` properly for intrinsics r=CohenArthur a=CohenArthur
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.
Closes #1440
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Diffstat (limited to 'gcc/rust')
-rw-r--r-- | gcc/rust/checks/errors/rust-const-checker.cc | 51 | ||||
-rw-r--r-- | gcc/rust/checks/errors/rust-const-checker.h | 7 |
2 files changed, 55 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..ad0a2cf 100644 --- a/gcc/rust/checks/errors/rust-const-checker.cc +++ b/gcc/rust/checks/errors/rust-const-checker.cc @@ -37,6 +37,21 @@ ConstChecker::go (HIR::Crate &crate) item->accept_vis (*this); } +bool +ConstChecker::is_const_extern_fn (HIR::ExternalFunctionItem &fn) +{ + // 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 std::any_of ( + fn.get_outer_attrs ().begin (), fn.get_outer_attrs ().end (), + [] (const AST::Attribute &attr) { + // `starts_with` in C++11... + return attr.get_path ().as_string ().rfind ("rustc_const_", 0) == 0; + }); +} + void ConstChecker::visit (IdentifierExpr &ident_expr) {} @@ -235,11 +250,38 @@ 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); + if (!is_const_extern_fn (*fn)) + 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 +564,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) diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h index a474fc8..608ea3e 100644 --- a/gcc/rust/checks/errors/rust-const-checker.h +++ b/gcc/rust/checks/errors/rust-const-checker.h @@ -33,6 +33,13 @@ public: void go (HIR::Crate &crate); + /** + * Check if an item is a const extern item or not + * TODO: Move this to a const compilation context class or an attribute + * checking class + */ + static bool is_const_extern_fn (HIR::ExternalFunctionItem &fn); + private: /** * Check that only const functions are called in const contexts |