From: Lucas Ly Ba <[email protected]>

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]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/520f9e075285ee1759f99f88a0fa3b3506e95615

The commit has NOT been mentioned in any issue.

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4649

 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(-)
 create mode 100644 gcc/testsuite/rust/compile/missing-abi_0.rs

diff --git a/gcc/rust/checks/lints/unused/rust-unused-checker.cc 
b/gcc/rust/checks/lints/unused/rust-unused-checker.cc
index 30fb37cfb..643d262d2 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 c8a272041..2f2557ce3 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 a1f84c9f0..ffa7a0f39 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 309118cff..d5c9ad154 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 588cf5f90..a956e0b53 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 000000000..e8c130bd9
--- /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();
+}

base-commit: b63444666d45969e518b67677f522a85cbcaa22e
-- 
2.54.0

Reply via email to