From: Lucas Ly Ba <[email protected]>
gcc/rust/ChangeLog:
* checks/lints/unused-var/rust-unused-var-checker.cc (UnusedVarChecker):
Implement unused assignments warning.
(UnusedVarChecker::go): Remove unique pointer unused var context.
(UnusedVarChecker::visit): Visit AssignExpr in HIR default visitor.
* checks/lints/unused-var/rust-unused-var-checker.h: Add visit method.
* checks/lints/unused-var/rust-unused-var-collector.cc
(UnusedVarCollector):
Collect warnings for assignments.
(UnusedVarCollector::visit): Visit AssignExpr in HIR default visitor.
* checks/lints/unused-var/rust-unused-var-collector.h: Add visit method.
* checks/lints/unused-var/rust-unused-var-context.cc
(UnusedVarContext::add_assign):
Add assignment in map.
(UnusedVarContext::remove_assign): Remove assignment in map.
(UnusedVarContext::is_variable_assigned): Check if a variable is
assigned.
* checks/lints/unused-var/rust-unused-var-context.h: Add a map to stock
assignments.
gcc/testsuite/ChangeLog:
* rust/compile/issue-4260_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/e33909eff1e6d22e5ea31c167882605be94f503d
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4285
.../unused-var/rust-unused-var-checker.cc | 37 +++++++++++++------
.../unused-var/rust-unused-var-checker.h | 6 ++-
.../unused-var/rust-unused-var-collector.cc | 15 +++++++-
.../unused-var/rust-unused-var-collector.h | 18 ++++++---
.../unused-var/rust-unused-var-context.cc | 20 ++++++++++
.../unused-var/rust-unused-var-context.h | 6 ++-
gcc/testsuite/rust/compile/issue-4260_0.rs | 22 +++++++++++
7 files changed, 103 insertions(+), 21 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/issue-4260_0.rs
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.cc
b/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.cc
index c6cfd5bb2..e4df446f7 100644
--- a/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.cc
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.cc
@@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "rust-unused-var-checker.h"
+#include "rust-hir-expr.h"
#include "rust-hir-item.h"
#include "options.h"
@@ -27,12 +28,12 @@ UnusedVarChecker::UnusedVarChecker ()
: nr_context (
Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
mappings (Analysis::Mappings::get ()),
- unused_var_context (std::make_unique<UnusedVarContext> ())
+ unused_var_context (UnusedVarContext ())
{}
void
UnusedVarChecker::go (HIR::Crate &crate)
{
- UnusedVarCollector collector (*unused_var_context);
+ UnusedVarCollector collector (unused_var_context);
collector.go (crate);
for (auto &item : crate.get_items ())
item->accept_vis (*this);
@@ -43,9 +44,8 @@ UnusedVarChecker::visit (HIR::ConstantItem &item)
std::string var_name = item.get_identifier ().as_string ();
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
auto id = item.get_mappings ().get_hirid ();
- if (!unused_var_context->is_variable_used (id) && !starts_with_under_score)
- rust_warning_at (item.get_locus (), OPT_Wunused_variable,
- "unused name '%s'",
+ if (!unused_var_context.is_variable_used (id) && !starts_with_under_score)
+ rust_warning_at (item.get_locus (), OPT_Wunused_variable, "unused name
%qs",
item.get_identifier ().as_string ().c_str ());
}
@@ -55,9 +55,8 @@ UnusedVarChecker::visit (HIR::StaticItem &item)
std::string var_name = item.get_identifier ().as_string ();
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
auto id = item.get_mappings ().get_hirid ();
- if (!unused_var_context->is_variable_used (id) && !starts_with_under_score)
- rust_warning_at (item.get_locus (), OPT_Wunused_variable,
- "unused name '%s'",
+ if (!unused_var_context.is_variable_used (id) && !starts_with_under_score)
+ rust_warning_at (item.get_locus (), OPT_Wunused_variable, "unused name
%qs",
item.get_identifier ().as_string ().c_str ());
}
@@ -72,11 +71,27 @@ UnusedVarChecker::visit (HIR::IdentifierPattern &pattern)
std::string var_name = pattern.get_identifier ().as_string ();
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
auto id = pattern.get_mappings ().get_hirid ();
- if (!unused_var_context->is_variable_used (id) && var_name != "self"
+ if (!unused_var_context.is_variable_used (id) && var_name != "self"
&& !starts_with_under_score)
rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
- "unused name '%s'",
+ "unused name %qs",
pattern.get_identifier ().as_string ().c_str ());
}
+void
+
+UnusedVarChecker::visit (HIR::AssignmentExpr &expr)
+
+{
+ const auto &lhs = expr.get_lhs ();
+ auto var_name = lhs.to_string ();
+ NodeId ast_node_id = lhs.get_mappings ().get_nodeid ();
+ NodeId def_id = nr_context.lookup (ast_node_id).value ();
+ HirId id = mappings.lookup_node_to_hir (def_id).value ();
+ if (unused_var_context.is_variable_assigned (id,
+ lhs.get_mappings ().get_hirid ())
+ && !starts_with_under_score)
+ rust_warning_at (lhs.get_locus (), OPT_Wunused_variable,
+ "unused assignment %qs", var_name.c_str ());
+}
} // namespace Analysis
-} // namespace Rust
\ No newline at end of file
+} // namespace Rust
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.h
b/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.h
index d916caa2d..bb9c8ac85 100644
--- a/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.h
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-checker.h
@@ -16,6 +16,7 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+#include "rust-hir-expr.h"
#include "rust-hir-item.h"
#include "rust-hir-pattern.h"
#include "rust-hir-visitor.h"
@@ -33,13 +34,14 @@ public:
private:
const Resolver2_0::NameResolutionContext &nr_context;
Analysis::Mappings &mappings;
- std::unique_ptr<UnusedVarContext> unused_var_context;
+ UnusedVarContext unused_var_context;
using HIR::DefaultHIRVisitor::visit;
virtual void visit (HIR::TraitItemFunc &decl) override;
virtual void visit (HIR::ConstantItem &item) override;
virtual void visit (HIR::StaticItem &item) override;
virtual void visit (HIR::IdentifierPattern &identifier) override;
+ virtual void visit (HIR::AssignmentExpr &identifier) override;
};
} // namespace Analysis
-} // namespace Rust
\ No newline at end of file
+} // namespace Rust
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.cc
b/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.cc
index deeabdef5..e9e98c5f2 100644
--- a/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.cc
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.cc
@@ -17,11 +17,13 @@
// <http://www.gnu.org/licenses/>.
#include "rust-unused-var-collector.h"
+#include "rust-hir-expr.h"
#include "rust-hir-full-decls.h"
#include "rust-hir-item.h"
#include "rust-hir-path.h"
#include "rust-hir-pattern.h"
#include "rust-immutable-name-resolution-context.h"
+#include "tree-check.h"
namespace Rust {
namespace Analysis {
@@ -54,8 +56,7 @@ UnusedVarCollector::visit (HIR::StaticItem &item)
void
UnusedVarCollector::visit (HIR::IdentifierPattern &pattern)
{
- auto id = pattern.get_mappings ().get_hirid ();
- unused_var_context.add_variable (id);
+ unused_var_context.add_variable (pattern.get_mappings ().get_hirid ());
}
void
@@ -75,5 +76,15 @@ UnusedVarCollector::visit (HIR::StructExprFieldIdentifier
&ident)
{
mark_path_used (ident);
}
+void
+UnusedVarCollector::visit (HIR::AssignmentExpr &expr)
+{
+ auto def_id = get_def_id (expr.get_lhs ());
+ HirId id = expr.get_lhs ().get_mappings ().get_hirid ();
+ unused_var_context.add_assign (def_id, id);
+ visit_outer_attrs (expr);
+ expr.get_rhs ().accept_vis (*this);
+}
+
} // namespace Analysis
} // namespace Rust
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.h
b/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.h
index ed3384056..e3fed0c29 100644
--- a/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.h
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-collector.h
@@ -46,14 +46,22 @@ private:
virtual void visit (HIR::StaticItem &item) override;
virtual void visit (HIR::IdentifierPattern &pattern) override;
virtual void visit (HIR::QualifiedPathInExpression &expr) override;
+ virtual void visit (HIR::AssignmentExpr &expr) override;
- template <typename T> void mark_path_used (T &path_expr)
+ template <typename T> HirId get_def_id (T &path_expr)
{
NodeId ast_node_id = path_expr.get_mappings ().get_nodeid ();
- NodeId def_id = nr_context.lookup (ast_node_id).value ();
- HirId hir_id = mappings.lookup_node_to_hir (def_id).value ();
- unused_var_context.mark_used (hir_id);
+ NodeId id = nr_context.lookup (ast_node_id).value ();
+ HirId def_id = mappings.lookup_node_to_hir (id).value ();
+ return def_id;
+ }
+
+ template <typename T> void mark_path_used (T &path_expr)
+ {
+ auto def_id = get_def_id (path_expr);
+ unused_var_context.mark_used (def_id);
+ unused_var_context.remove_assign (def_id);
}
};
} // namespace Analysis
-} // namespace Rust
\ No newline at end of file
+} // namespace Rust
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-context.cc
b/gcc/rust/checks/lints/unused-var/rust-unused-var-context.cc
index 728d61d21..435fba46a 100644
--- a/gcc/rust/checks/lints/unused-var/rust-unused-var-context.cc
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-context.cc
@@ -41,6 +41,26 @@ UnusedVarContext::is_variable_used (HirId id) const
return it != is_used.end () && it->second;
}
+void
+UnusedVarContext::add_assign (HirId id_def, HirId id)
+{
+ assigned_vars[id_def].push_back (id);
+}
+
+void
+UnusedVarContext::remove_assign (HirId id_def)
+{
+ if (assigned_vars.find (id_def) != assigned_vars.end ())
+ assigned_vars[id_def].pop_back ();
+}
+bool
+UnusedVarContext::is_variable_assigned (HirId id_def, HirId id)
+{
+ auto assigned_vec = assigned_vars[id_def];
+ return std::find (assigned_vec.begin (), assigned_vec.end (), id)
+ != assigned_vec.end ();
+}
+
std::string
UnusedVarContext::as_string () const
{
diff --git a/gcc/rust/checks/lints/unused-var/rust-unused-var-context.h
b/gcc/rust/checks/lints/unused-var/rust-unused-var-context.h
index 14f89da78..bde793def 100644
--- a/gcc/rust/checks/lints/unused-var/rust-unused-var-context.h
+++ b/gcc/rust/checks/lints/unused-var/rust-unused-var-context.h
@@ -26,13 +26,17 @@ class UnusedVarContext
public:
void add_variable (HirId id);
void mark_used (HirId id);
-
bool is_variable_used (HirId id) const;
+ void add_assign (HirId id_def, HirId id);
+ void remove_assign (HirId id_def);
+ bool is_variable_assigned (HirId id_def, HirId id);
+
std::string as_string () const;
private:
std::map<HirId, bool> is_used;
+ std::map<HirId, std::vector<HirId>> assigned_vars;
};
} // namespace Analysis
diff --git a/gcc/testsuite/rust/compile/issue-4260_0.rs
b/gcc/testsuite/rust/compile/issue-4260_0.rs
new file mode 100644
index 000000000..b6f1fba3b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4260_0.rs
@@ -0,0 +1,22 @@
+// { dg-additional-options "-frust-unused-check-2.0" }
+pub fn a()->i32 {
+ let mut a = 1;
+ a = 2;
+// { dg-warning "unused assignment .a." "" { target *-*-* } .-1 }
+ a = 3;
+// { dg-warning "unused assignment .a." "" { target *-*-* } .-1 }
+ a = 4;
+// { dg-warning "unused assignment .a." "" { target *-*-* } .-1 }
+ a = 5;
+ let mut b = a;
+ b = 1;
+// { dg-warning "unused assignment .b." "" { target *-*-* } .-1 }
+ b = 2;
+// { dg-warning "unused assignment .b." "" { target *-*-* } .-1 }
+ b = 3;
+// { dg-warning "unused assignment .b." "" { target *-*-* } .-1 }
+ b = 4;
+// { dg-warning "unused assignment .b." "" { target *-*-* } .-1 }
+ b = 5;
+ return b
+}
base-commit: 38bccd0ece07aaa52ae906036fb428edec74655d
--
2.52.0