Skip to content

Commit a8f7004

Browse files
committed
gccrs: add unused-assignments lint
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]>
1 parent 0b4d9eb commit a8f7004

File tree

6 files changed

+83
-21
lines changed

6 files changed

+83
-21
lines changed

gcc/rust/checks/lints/unused-var/rust-unused-var-checker.cc

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// <http://www.gnu.org/licenses/>.
1818

1919
#include "rust-unused-var-checker.h"
20+
#include "rust-hir-expr.h"
2021
#include "rust-hir-item.h"
2122

2223
#include "options.h"
@@ -27,12 +28,12 @@ UnusedVarChecker::UnusedVarChecker ()
2728
: nr_context (
2829
Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
2930
mappings (Analysis::Mappings::get ()),
30-
unused_var_context (std::make_unique<UnusedVarContext> ())
31+
unused_var_context (UnusedVarContext ())
3132
{}
3233
void
3334
UnusedVarChecker::go (HIR::Crate &crate)
3435
{
35-
UnusedVarCollector collector (*unused_var_context);
36+
UnusedVarCollector collector (unused_var_context);
3637
collector.go (crate);
3738
for (auto &item : crate.get_items ())
3839
item->accept_vis (*this);
@@ -43,9 +44,8 @@ UnusedVarChecker::visit (HIR::ConstantItem &item)
4344
std::string var_name = item.get_identifier ().as_string ();
4445
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
4546
auto id = item.get_mappings ().get_hirid ();
46-
if (!unused_var_context->is_variable_used (id) && !starts_with_under_score)
47-
rust_warning_at (item.get_locus (), OPT_Wunused_variable,
48-
"unused name '%s'",
47+
if (!unused_var_context.is_variable_used (id) && !starts_with_under_score)
48+
rust_warning_at (item.get_locus (), OPT_Wunused_variable, "unused name %qs",
4949
item.get_identifier ().as_string ().c_str ());
5050
}
5151

@@ -55,9 +55,8 @@ UnusedVarChecker::visit (HIR::StaticItem &item)
5555
std::string var_name = item.get_identifier ().as_string ();
5656
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
5757
auto id = item.get_mappings ().get_hirid ();
58-
if (!unused_var_context->is_variable_used (id) && !starts_with_under_score)
59-
rust_warning_at (item.get_locus (), OPT_Wunused_variable,
60-
"unused name '%s'",
58+
if (!unused_var_context.is_variable_used (id) && !starts_with_under_score)
59+
rust_warning_at (item.get_locus (), OPT_Wunused_variable, "unused name %qs",
6160
item.get_identifier ().as_string ().c_str ());
6261
}
6362

@@ -72,11 +71,29 @@ UnusedVarChecker::visit (HIR::IdentifierPattern &pattern)
7271
std::string var_name = pattern.get_identifier ().as_string ();
7372
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
7473
auto id = pattern.get_mappings ().get_hirid ();
75-
if (!unused_var_context->is_variable_used (id) && var_name != "self"
74+
if (!unused_var_context.is_variable_used (id) && var_name != "self"
7675
&& !starts_with_under_score)
7776
rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
78-
"unused name '%s'",
77+
"unused name %qs",
7978
pattern.get_identifier ().as_string ().c_str ());
8079
}
80+
void
81+
82+
UnusedVarChecker::visit (HIR::AssignmentExpr &expr)
83+
84+
{
85+
const auto &lhs = expr.get_lhs ();
86+
auto s = lhs.as_string ();
87+
std::string var_name = s.substr (0, s.find (':'));
88+
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
89+
NodeId ast_node_id = lhs.get_mappings ().get_nodeid ();
90+
NodeId def_id = nr_context.lookup (ast_node_id).value ();
91+
HirId id = mappings.lookup_node_to_hir (def_id).value ();
92+
if (unused_var_context.is_variable_assigned (id,
93+
lhs.get_mappings ().get_hirid ())
94+
&& !starts_with_under_score)
95+
rust_warning_at (lhs.get_locus (), OPT_Wunused_variable,
96+
"unused assignment %qs", var_name.c_str ());
97+
}
8198
} // namespace Analysis
82-
} // namespace Rust
99+
} // namespace Rust

gcc/rust/checks/lints/unused-var/rust-unused-var-checker.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// along with GCC; see the file COPYING3. If not see
1717
// <http://www.gnu.org/licenses/>.
1818

19+
#include "rust-hir-expr.h"
1920
#include "rust-hir-item.h"
2021
#include "rust-hir-pattern.h"
2122
#include "rust-hir-visitor.h"
@@ -33,13 +34,14 @@ class UnusedVarChecker : public HIR::DefaultHIRVisitor
3334
private:
3435
const Resolver2_0::NameResolutionContext &nr_context;
3536
Analysis::Mappings &mappings;
36-
std::unique_ptr<UnusedVarContext> unused_var_context;
37+
UnusedVarContext unused_var_context;
3738

3839
using HIR::DefaultHIRVisitor::visit;
3940
virtual void visit (HIR::TraitItemFunc &decl) override;
4041
virtual void visit (HIR::ConstantItem &item) override;
4142
virtual void visit (HIR::StaticItem &item) override;
4243
virtual void visit (HIR::IdentifierPattern &identifier) override;
44+
virtual void visit (HIR::AssignmentExpr &identifier) override;
4345
};
4446
} // namespace Analysis
45-
} // namespace Rust
47+
} // namespace Rust

gcc/rust/checks/lints/unused-var/rust-unused-var-collector.cc

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
// <http://www.gnu.org/licenses/>.
1818

1919
#include "rust-unused-var-collector.h"
20+
#include "rust-hir-expr.h"
2021
#include "rust-hir-full-decls.h"
2122
#include "rust-hir-item.h"
2223
#include "rust-hir-path.h"
2324
#include "rust-hir-pattern.h"
2425
#include "rust-immutable-name-resolution-context.h"
26+
#include "tree-check.h"
2527

2628
namespace Rust {
2729
namespace Analysis {
@@ -54,8 +56,7 @@ UnusedVarCollector::visit (HIR::StaticItem &item)
5456
void
5557
UnusedVarCollector::visit (HIR::IdentifierPattern &pattern)
5658
{
57-
auto id = pattern.get_mappings ().get_hirid ();
58-
unused_var_context.add_variable (id);
59+
unused_var_context.add_variable (pattern.get_mappings ().get_hirid ());
5960
}
6061

6162
void
@@ -75,5 +76,15 @@ UnusedVarCollector::visit (HIR::StructExprFieldIdentifier &ident)
7576
{
7677
mark_path_used (ident);
7778
}
79+
void
80+
UnusedVarCollector::visit (HIR::AssignmentExpr &expr)
81+
{
82+
auto def_id = get_def_id (expr.get_lhs ());
83+
HirId id = expr.get_lhs ().get_mappings ().get_hirid ();
84+
unused_var_context.add_assign (def_id, id);
85+
visit_outer_attrs (expr);
86+
expr.get_rhs ().accept_vis (*this);
87+
}
88+
7889
} // namespace Analysis
7990
} // namespace Rust

gcc/rust/checks/lints/unused-var/rust-unused-var-collector.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,22 @@ class UnusedVarCollector : public HIR::DefaultHIRVisitor
4646
virtual void visit (HIR::StaticItem &item) override;
4747
virtual void visit (HIR::IdentifierPattern &pattern) override;
4848
virtual void visit (HIR::QualifiedPathInExpression &expr) override;
49+
virtual void visit (HIR::AssignmentExpr &expr) override;
4950

50-
template <typename T> void mark_path_used (T &path_expr)
51+
template <typename T> HirId get_def_id (T &path_expr)
5152
{
5253
NodeId ast_node_id = path_expr.get_mappings ().get_nodeid ();
53-
NodeId def_id = nr_context.lookup (ast_node_id).value ();
54-
HirId hir_id = mappings.lookup_node_to_hir (def_id).value ();
55-
unused_var_context.mark_used (hir_id);
54+
NodeId id = nr_context.lookup (ast_node_id).value ();
55+
HirId def_id = mappings.lookup_node_to_hir (id).value ();
56+
return def_id;
57+
}
58+
59+
template <typename T> void mark_path_used (T &path_expr)
60+
{
61+
auto def_id = get_def_id (path_expr);
62+
unused_var_context.mark_used (def_id);
63+
unused_var_context.remove_assign (def_id);
5664
}
5765
};
5866
} // namespace Analysis
59-
} // namespace Rust
67+
} // namespace Rust

gcc/rust/checks/lints/unused-var/rust-unused-var-context.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,26 @@ UnusedVarContext::is_variable_used (HirId id) const
4141
return it != is_used.end () && it->second;
4242
}
4343

44+
void
45+
UnusedVarContext::add_assign (HirId id_def, HirId id)
46+
{
47+
assigned_vars[id_def].push_back (id);
48+
}
49+
50+
void
51+
UnusedVarContext::remove_assign (HirId id_def)
52+
{
53+
if (assigned_vars.find (id_def) != assigned_vars.end ())
54+
assigned_vars[id_def].pop_back ();
55+
}
56+
bool
57+
UnusedVarContext::is_variable_assigned (HirId id_def, HirId id)
58+
{
59+
auto assigned_vec = assigned_vars[id_def];
60+
return std::find (assigned_vec.begin (), assigned_vec.end (), id)
61+
!= assigned_vec.end ();
62+
}
63+
4464
std::string
4565
UnusedVarContext::as_string () const
4666
{

gcc/rust/checks/lints/unused-var/rust-unused-var-context.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@ class UnusedVarContext
2525
public:
2626
void add_variable (HirId id);
2727
void mark_used (HirId id);
28-
2928
bool is_variable_used (HirId id) const;
3029

30+
void add_assign (HirId id_def, HirId id);
31+
void remove_assign (HirId id_def);
32+
bool is_variable_assigned (HirId id_def, HirId id);
33+
3134
std::string as_string () const;
3235

3336
private:
3437
std::map<HirId, bool> is_used;
38+
std::map<HirId, std::vector<HirId>> assigned_vars;
3539
};
3640
} // namespace Analysis
3741
} // namespace Rust

0 commit comments

Comments
 (0)