https://gcc.gnu.org/g:847d8287d372b0f7b3e46272a051adab1bf85f55
commit r17-2259-g847d8287d372b0f7b3e46272a051adab1bf85f55 Author: Lucas Ly Ba <[email protected]> Date: Sun Jun 28 18:04:29 2026 +0200 gccrs: add missing_abi lint Warn on an `extern` block written without an explicit ABI string, such as a bare `extern { ... }`, which silently defaults to the C ABI. Rust deprecates this in favour of spelling the ABI out, e.g. `extern "C"`. The HIR `ExternBlock` only stored the resolved ABI enum, which always collapses a missing ABI to the C default, so it could not tell a bare `extern` from `extern "C"`. Carry the AST's `has_abi` flag through lowering so the lint can distinguish the two. gcc/rust/ChangeLog: * hir/tree/rust-hir-item.h (ExternBlock): Track whether the ABI was explicit and expose it through has_abi. * hir/tree/rust-hir-item.cc (ExternBlock::ExternBlock): Likewise. (ExternBlock::operator=): Likewise. * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_extern_block): Forward the AST has_abi flag to the HIR node. * checks/lints/unused/rust-unused-checker.cc (UnusedChecker::visit): New. * checks/lints/unused/rust-unused-checker.h (UnusedChecker::visit): New. gcc/testsuite/ChangeLog: * rust/compile/missing-abi_0.rs: New test. Signed-off-by: Lucas Ly Ba <[email protected]> Diff: --- gcc/rust/checks/lints/unused/rust-unused-checker.cc | 10 ++++++++++ gcc/rust/checks/lints/unused/rust-unused-checker.h | 1 + gcc/rust/hir/rust-ast-lower-base.cc | 5 +++-- gcc/rust/hir/tree/rust-hir-item.cc | 8 +++++--- gcc/rust/hir/tree/rust-hir-item.h | 6 +++++- gcc/testsuite/rust/compile/missing-abi_0.rs | 12 ++++++++++++ 6 files changed, 36 insertions(+), 6 deletions(-) diff --git a/gcc/rust/checks/lints/unused/rust-unused-checker.cc b/gcc/rust/checks/lints/unused/rust-unused-checker.cc index 30fb37cfb99b..643d262d2d5f 100644 --- a/gcc/rust/checks/lints/unused/rust-unused-checker.cc +++ b/gcc/rust/checks/lints/unused/rust-unused-checker.cc @@ -188,6 +188,16 @@ UnusedChecker::visit (HIR::LifetimeParam &lft) walk (lft); } +void +UnusedChecker::visit (HIR::ExternBlock &block) +{ + if (!block.has_abi ()) + rust_warning_at (block.get_locus (), OPT_Wunused_variable, + "extern declarations without an explicit ABI are " + "deprecated"); + walk (block); +} + void UnusedChecker::visit_loop_label (HIR::LoopLabel &label) { diff --git a/gcc/rust/checks/lints/unused/rust-unused-checker.h b/gcc/rust/checks/lints/unused/rust-unused-checker.h index c8a272041a9d..2f2557ce3d89 100644 --- a/gcc/rust/checks/lints/unused/rust-unused-checker.h +++ b/gcc/rust/checks/lints/unused/rust-unused-checker.h @@ -50,6 +50,7 @@ private: virtual void visit (HIR::LifetimeParam &lft) override; virtual void visit (HIR::StructPatternFieldIdentPat &field) override; virtual void visit (HIR::MatchExpr &expr) override; + virtual void visit (HIR::ExternBlock &block) override; virtual void visit_loop_label (HIR::LoopLabel &label) override; }; } // namespace Analysis diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index a1f84c9f0779..ffa7a0f39db5 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -1071,8 +1071,9 @@ ASTLoweringBase::lower_extern_block (AST::ExternBlock &extern_block) } HIR::ExternBlock *hir_extern_block - = new HIR::ExternBlock (mapping, abi, std::move (extern_items), - std::move (vis), extern_block.get_inner_attrs (), + = new HIR::ExternBlock (mapping, abi, extern_block.has_abi (), + std::move (extern_items), std::move (vis), + extern_block.get_inner_attrs (), extern_block.get_outer_attrs (), extern_block.get_locus ()); diff --git a/gcc/rust/hir/tree/rust-hir-item.cc b/gcc/rust/hir/tree/rust-hir-item.cc index 309118cff434..d5c9ad154c8d 100644 --- a/gcc/rust/hir/tree/rust-hir-item.cc +++ b/gcc/rust/hir/tree/rust-hir-item.cc @@ -1001,17 +1001,18 @@ ExternalTypeItem::ExternalTypeItem (ExternalTypeItem const &other) {} ExternBlock::ExternBlock ( - Analysis::NodeMapping mappings, ABI abi, + Analysis::NodeMapping mappings, ABI abi, bool explicit_abi, std::vector<std::unique_ptr<ExternalItem>> extern_items, Visibility vis, AST::AttrVec inner_attrs, AST::AttrVec outer_attrs, location_t locus) : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), WithInnerAttrs (std::move (inner_attrs)), abi (abi), - extern_items (std::move (extern_items)), locus (locus) + explicit_abi (explicit_abi), extern_items (std::move (extern_items)), + locus (locus) {} ExternBlock::ExternBlock (ExternBlock const &other) : VisItem (other), WithInnerAttrs (other.inner_attrs), abi (other.abi), - locus (other.locus) + explicit_abi (other.explicit_abi), locus (other.locus) { extern_items.reserve (other.extern_items.size ()); for (const auto &e : other.extern_items) @@ -1023,6 +1024,7 @@ ExternBlock::operator= (ExternBlock const &other) { VisItem::operator= (other); abi = other.abi; + explicit_abi = other.explicit_abi; inner_attrs = other.inner_attrs; locus = other.locus; diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 588cf5f90096..a956e0b530f4 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -2638,6 +2638,7 @@ protected: class ExternBlock : public VisItem, public WithInnerAttrs { ABI abi; + bool explicit_abi; std::vector<std::unique_ptr<ExternalItem>> extern_items; location_t locus; @@ -2647,9 +2648,12 @@ public: // Returns whether extern block has extern items. bool has_extern_items () const { return !extern_items.empty (); } + // Returns whether the extern block was given an explicit ABI string. + bool has_abi () const { return explicit_abi; } + ABI get_abi () const { return abi; } - ExternBlock (Analysis::NodeMapping mappings, ABI abi, + ExternBlock (Analysis::NodeMapping mappings, ABI abi, bool explicit_abi, std::vector<std::unique_ptr<ExternalItem>> extern_items, Visibility vis, AST::AttrVec inner_attrs, AST::AttrVec outer_attrs, location_t locus); diff --git a/gcc/testsuite/rust/compile/missing-abi_0.rs b/gcc/testsuite/rust/compile/missing-abi_0.rs new file mode 100644 index 000000000000..e8c130bd94f1 --- /dev/null +++ b/gcc/testsuite/rust/compile/missing-abi_0.rs @@ -0,0 +1,12 @@ +// { dg-additional-options "-frust-unused-check-2.0" } +#![feature(no_core)] +#![no_core] + +extern { +// { dg-warning "extern declarations without an explicit ABI are deprecated" "" { target *-*-* } .-1 } + fn foo(); +} + +extern "C" { + fn bar(); +}
