[gcc r17-2259] gccrs: add missing_abi lint

Arthur Cohen via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
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();
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.