Skip to content

Commit 319e98d

Browse files
sakupan102lucasly-ba
authored andcommitted
Implement unused variable checker on HIR.
gcc/rust/ChangeLog: * Make-lang.in: New file. * lang.opt: Add new flag. * rust-session-manager.cc (Session::compile_crate): Execute new variable checker. * checks/lints/unused-var/rust-unused-var-checker.cc (UnusedVarChecker): Implement unused variable checker. * checks/lints/unused-var/rust-unused-var-checker.h (UnusedVarChecker): Implement unused variable checker. * checks/lints/unused-var/rust-unused-var-collector.cc (UnusedVarCollector): Implement unused variable collector. * checks/lints/unused-var/rust-unused-var-collector.h (UnusedVarCollector): Implement unused variable collector. * checks/lints/unused-var/rust-unused-var-context.cc (UnusedVarContext): Implement unused variable context. * checks/lints/unused-var/rust-unused-var-context.h (UnusedVarContext): Implement unused variable context. gcc/testsuite/ChangeLog: * rust/compile/static_item_0.rs: New test. * rust/compile/template_function_0.rs: New test. Signed-off-by: Lucas Ly Ba <lucas.ly-ba@outlook.com>
1 parent fe2320d commit 319e98d

File tree

11 files changed

+390
-1
lines changed

11 files changed

+390
-1
lines changed

gcc/rust/Make-lang.in

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ GRS_OBJS = \
200200
rust/rust-const-checker.o \
201201
rust/rust-lint-marklive.o \
202202
rust/rust-lint-unused-var.o \
203+
rust/rust-unused-var-checker.o \
204+
rust/rust-unused-var-collector.o \
205+
rust/rust-unused-var-context.o \
203206
rust/rust-readonly-check.o \
204207
rust/rust-hir-type-check-path.o \
205208
rust/rust-unsafe-checker.o \
@@ -432,6 +435,7 @@ RUST_INCLUDES = -I $(srcdir)/rust \
432435
-I $(srcdir)/rust/typecheck \
433436
-I $(srcdir)/rust/checks/lints \
434437
-I $(srcdir)/rust/checks/errors \
438+
-I $(srcdir)/rust/checks/lints/unused-var \
435439
-I $(srcdir)/rust/checks/errors/privacy \
436440
-I $(srcdir)/rust/checks/errors/borrowck \
437441
-I $(srcdir)/rust/checks/errors/feature \
@@ -502,6 +506,11 @@ rust/%.o: rust/checks/lints/%.cc
502506
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
503507
$(POSTCOMPILE)
504508

509+
# build unused variable checking pass files in rust folder
510+
rust/%.o: rust/checks/lints/unused-var/%.cc
511+
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
512+
$(POSTCOMPILE)
513+
505514
# build rust/checks/errors files in rust folder
506515
rust/%.o: rust/checks/errors/%.cc
507516
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-unused-var-checker.h"
20+
#include "rust-hir-item.h"
21+
22+
#include "options.h"
23+
24+
namespace Rust {
25+
namespace Analysis {
26+
UnusedVarChecker::UnusedVarChecker ()
27+
: nr_context (
28+
Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
29+
mappings (Analysis::Mappings::get ()),
30+
unused_var_context (std::make_unique<UnusedVarContext> ())
31+
{}
32+
void
33+
UnusedVarChecker::go (HIR::Crate &crate)
34+
{
35+
UnusedVarCollector collector (*unused_var_context);
36+
collector.go (crate);
37+
for (auto &item : crate.get_items ())
38+
item->accept_vis (*this);
39+
}
40+
void
41+
UnusedVarChecker::visit (HIR::ConstantItem &item)
42+
{
43+
std::string var_name = item.get_identifier ().as_string ();
44+
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
45+
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'",
49+
item.get_identifier ().as_string ().c_str ());
50+
}
51+
52+
void
53+
UnusedVarChecker::visit (HIR::StaticItem &item)
54+
{
55+
std::string var_name = item.get_identifier ().as_string ();
56+
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
57+
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'",
61+
item.get_identifier ().as_string ().c_str ());
62+
}
63+
64+
void
65+
UnusedVarChecker::visit (HIR::TraitItemFunc &item)
66+
{
67+
// TODO: check trait item functions if they are not derived.
68+
}
69+
void
70+
UnusedVarChecker::visit (HIR::IdentifierPattern &pattern)
71+
{
72+
std::string var_name = pattern.get_identifier ().as_string ();
73+
bool starts_with_under_score = var_name.compare (0, 1, "_") == 0;
74+
auto id = pattern.get_mappings ().get_hirid ();
75+
if (!unused_var_context->is_variable_used (id) && var_name != "self"
76+
&& !starts_with_under_score)
77+
rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
78+
"unused name '%s'",
79+
pattern.get_identifier ().as_string ().c_str ());
80+
}
81+
} // namespace Analysis
82+
} // namespace Rust
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-hir-item.h"
20+
#include "rust-hir-pattern.h"
21+
#include "rust-hir-visitor.h"
22+
#include "rust-immutable-name-resolution-context.h"
23+
#include "rust-unused-var-collector.h"
24+
25+
namespace Rust {
26+
namespace Analysis {
27+
class UnusedVarChecker : public HIR::DefaultHIRVisitor
28+
{
29+
public:
30+
UnusedVarChecker ();
31+
void go (HIR::Crate &crate);
32+
33+
private:
34+
const Resolver2_0::NameResolutionContext &nr_context;
35+
Analysis::Mappings &mappings;
36+
std::unique_ptr<UnusedVarContext> unused_var_context;
37+
38+
using HIR::DefaultHIRVisitor::visit;
39+
virtual void visit (HIR::TraitItemFunc &decl) override;
40+
virtual void visit (HIR::ConstantItem &item) override;
41+
virtual void visit (HIR::StaticItem &item) override;
42+
virtual void visit (HIR::IdentifierPattern &identifier) override;
43+
};
44+
} // namespace Analysis
45+
} // namespace Rust
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-unused-var-collector.h"
20+
#include "rust-hir-full-decls.h"
21+
#include "rust-hir-item.h"
22+
#include "rust-hir-path.h"
23+
#include "rust-hir-pattern.h"
24+
#include "rust-immutable-name-resolution-context.h"
25+
26+
namespace Rust {
27+
namespace Analysis {
28+
UnusedVarCollector::UnusedVarCollector (UnusedVarContext &context)
29+
: nr_context (
30+
Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
31+
mappings (Analysis::Mappings::get ()), unused_var_context (context)
32+
{}
33+
void
34+
UnusedVarCollector::go (HIR::Crate &crate)
35+
{
36+
for (auto &item : crate.get_items ())
37+
item->accept_vis (*this);
38+
}
39+
40+
void
41+
UnusedVarCollector::visit (HIR::ConstantItem &item)
42+
{
43+
unused_var_context.add_variable (item.get_mappings ().get_hirid ());
44+
walk (item);
45+
}
46+
47+
void
48+
UnusedVarCollector::visit (HIR::StaticItem &item)
49+
{
50+
unused_var_context.add_variable (item.get_mappings ().get_hirid ());
51+
walk (item);
52+
}
53+
54+
void
55+
UnusedVarCollector::visit (HIR::IdentifierPattern &pattern)
56+
{
57+
auto id = pattern.get_mappings ().get_hirid ();
58+
unused_var_context.add_variable (id);
59+
}
60+
61+
void
62+
UnusedVarCollector::visit (HIR::PathInExpression &expr)
63+
{
64+
mark_path_used (expr);
65+
}
66+
67+
void
68+
UnusedVarCollector::visit (HIR::QualifiedPathInExpression &expr)
69+
{
70+
mark_path_used (expr);
71+
}
72+
73+
void
74+
UnusedVarCollector::visit (HIR::StructExprFieldIdentifier &ident)
75+
{
76+
mark_path_used (ident);
77+
}
78+
} // namespace Analysis
79+
} // namespace Rust
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-hir-expr.h"
20+
#include "rust-hir-item.h"
21+
#include "rust-hir-path.h"
22+
#include "rust-hir-pattern.h"
23+
#include "rust-hir-visitor.h"
24+
#include "rust-mapping-common.h"
25+
#include "rust-name-resolution-context.h"
26+
#include "rust-unused-var-context.h"
27+
#include "rust-name-resolver.h"
28+
29+
namespace Rust {
30+
namespace Analysis {
31+
class UnusedVarCollector : public HIR::DefaultHIRVisitor
32+
{
33+
public:
34+
UnusedVarCollector (UnusedVarContext &context);
35+
void go (HIR::Crate &crate);
36+
37+
private:
38+
const Resolver2_0::NameResolutionContext &nr_context;
39+
Analysis::Mappings &mappings;
40+
UnusedVarContext &unused_var_context;
41+
42+
using HIR::DefaultHIRVisitor::visit;
43+
virtual void visit (HIR::PathInExpression &expr) override;
44+
virtual void visit (HIR::StructExprFieldIdentifier &ident) override;
45+
virtual void visit (HIR::ConstantItem &item) override;
46+
virtual void visit (HIR::StaticItem &item) override;
47+
virtual void visit (HIR::IdentifierPattern &pattern) override;
48+
virtual void visit (HIR::QualifiedPathInExpression &expr) override;
49+
50+
template <typename T> void mark_path_used (T &path_expr)
51+
{
52+
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);
56+
}
57+
};
58+
} // namespace Analysis
59+
} // namespace Rust
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-unused-var-context.h"
20+
21+
namespace Rust {
22+
namespace Analysis {
23+
24+
void
25+
UnusedVarContext::add_variable (HirId id)
26+
{
27+
if (is_used.find (id) == is_used.end ())
28+
is_used.insert ({id, false});
29+
}
30+
31+
void
32+
UnusedVarContext::mark_used (HirId id)
33+
{
34+
is_used[id] = true;
35+
}
36+
37+
bool
38+
UnusedVarContext::is_variable_used (HirId id) const
39+
{
40+
auto it = is_used.find (id);
41+
return it != is_used.end () && it->second;
42+
}
43+
44+
std::string
45+
UnusedVarContext::as_string () const
46+
{
47+
std::stringstream ss;
48+
ss << "UnusedVarContext: ";
49+
for (const auto &pair : is_used)
50+
{
51+
ss << "HirId: " << pair.first << " Used: " << (pair.second ? "Yes" : "No")
52+
<< "\n";
53+
}
54+
return ss.str ();
55+
}
56+
57+
} // namespace Analysis
58+
} // namespace Rust
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (C) 2025 Free Software Foundation, Inc.
2+
3+
// This file is part of GCC.
4+
5+
// GCC is free software; you can redistribute it and/or modify it under
6+
// the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 3, or (at your option) any later
8+
// version.
9+
10+
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11+
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
// for more details.
14+
15+
// You should have received a copy of the GNU General Public License
16+
// along with GCC; see the file COPYING3. If not see
17+
// <http://www.gnu.org/licenses/>.
18+
19+
#include "rust-mapping-common.h"
20+
21+
namespace Rust {
22+
namespace Analysis {
23+
class UnusedVarContext
24+
{
25+
public:
26+
void add_variable (HirId id);
27+
void mark_used (HirId id);
28+
29+
bool is_variable_used (HirId id) const;
30+
31+
std::string as_string () const;
32+
33+
private:
34+
std::map<HirId, bool> is_used;
35+
};
36+
} // namespace Analysis
37+
} // namespace Rust

0 commit comments

Comments
 (0)