Skip to content

Commit acb0062

Browse files
committed
Add unused code pass
In order to find more examples of dead code we must create liveness variables and scan after type resolution. In this case, if a function is unused and it calls another function the 2nd function is now unused since the caller is not used etc. This is a WIP but demonstrates the pattern we can follow to add more dead code analysis warnings like rustc does. Addresses #330
1 parent 4937562 commit acb0062

File tree

7 files changed

+531
-1
lines changed

7 files changed

+531
-1
lines changed

gcc/rust/Make-lang.in

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ GRS_OBJS = \
7979
rust/rust-hir-type-check.o \
8080
rust/rust-tyty.o \
8181
rust/rust-tyctx.o \
82+
rust/rust-hir-liveness.o \
8283
$(END)
8384
# removed object files from here
8485

@@ -233,7 +234,8 @@ RUST_INCLUDES = -I $(srcdir)/rust \
233234
-I $(srcdir)/rust/hir \
234235
-I $(srcdir)/rust/resolve \
235236
-I $(srcdir)/rust/util \
236-
-I $(srcdir)/rust/typecheck
237+
-I $(srcdir)/rust/typecheck \
238+
-I $(srcdir)/rust/analysis
237239

238240
# add files that require cross-folder includes - currently rust-lang.o, rust-lex.o
239241
CFLAGS-rust/rust-lang.o += $(RUST_INCLUDES)
@@ -294,3 +296,8 @@ rust/%.o: rust/typecheck/%.cc
294296
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
295297
$(POSTCOMPILE)
296298

299+
# build rust/analysis files in rust folder
300+
rust/%.o: rust/analysis/%.cc
301+
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
302+
$(POSTCOMPILE)
303+
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
// Copyright (C) 2021 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+
#ifndef RUST_HIR_LIVENESS_BASE
20+
#define RUST_HIR_LIVENESS_BASE
21+
22+
#include "rust-diagnostics.h"
23+
#include "rust-hir-liveness.h"
24+
#include "rust-hir-liveness-base.h"
25+
#include "rust-hir-visitor.h"
26+
#include "rust-hir-map.h"
27+
28+
namespace Rust {
29+
namespace Analysis {
30+
31+
class LivenessBase : public HIR::HIRVisitor
32+
{
33+
public:
34+
virtual ~LivenessBase () {}
35+
virtual void visit (HIR::Token &) override {}
36+
virtual void visit (HIR::DelimTokenTree &) override {}
37+
virtual void visit (HIR::AttrInputMetaItemContainer &) override {}
38+
virtual void visit (HIR::IdentifierExpr &) override {}
39+
virtual void visit (HIR::Lifetime &) override {}
40+
virtual void visit (HIR::LifetimeParam &) override {}
41+
virtual void visit (HIR::PathInExpression &) override {}
42+
virtual void visit (HIR::TypePathSegment &) override {}
43+
virtual void visit (HIR::TypePathSegmentGeneric &) override {}
44+
virtual void visit (HIR::TypePathSegmentFunction &) override {}
45+
virtual void visit (HIR::TypePath &) override {}
46+
virtual void visit (HIR::QualifiedPathInExpression &) override {}
47+
virtual void visit (HIR::QualifiedPathInType &) override {}
48+
49+
virtual void visit (HIR::LiteralExpr &) override {}
50+
virtual void visit (HIR::AttrInputLiteral &) override {}
51+
virtual void visit (HIR::MetaItemLitExpr &) override {}
52+
virtual void visit (HIR::MetaItemPathLit &) override {}
53+
virtual void visit (HIR::BorrowExpr &) override {}
54+
virtual void visit (HIR::DereferenceExpr &) override {}
55+
virtual void visit (HIR::ErrorPropagationExpr &) override {}
56+
virtual void visit (HIR::NegationExpr &) override {}
57+
virtual void visit (HIR::ArithmeticOrLogicalExpr &) override {}
58+
virtual void visit (HIR::ComparisonExpr &) override {}
59+
virtual void visit (HIR::LazyBooleanExpr &) override {}
60+
virtual void visit (HIR::TypeCastExpr &) override {}
61+
virtual void visit (HIR::AssignmentExpr &) override {}
62+
63+
virtual void visit (HIR::GroupedExpr &) override {}
64+
65+
virtual void visit (HIR::ArrayElemsValues &) override {}
66+
virtual void visit (HIR::ArrayElemsCopied &) override {}
67+
virtual void visit (HIR::ArrayExpr &) override {}
68+
virtual void visit (HIR::ArrayIndexExpr &) override {}
69+
virtual void visit (HIR::TupleExpr &) override {}
70+
virtual void visit (HIR::TupleIndexExpr &) override {}
71+
virtual void visit (HIR::StructExprStruct &) override {}
72+
73+
virtual void visit (HIR::StructExprFieldIdentifier &) override {}
74+
virtual void visit (HIR::StructExprFieldIdentifierValue &) override {}
75+
76+
virtual void visit (HIR::StructExprFieldIndexValue &) override {}
77+
virtual void visit (HIR::StructExprStructFields &) override {}
78+
virtual void visit (HIR::StructExprStructBase &) override {}
79+
virtual void visit (HIR::StructExprTuple &) override {}
80+
virtual void visit (HIR::StructExprUnit &) override {}
81+
82+
virtual void visit (HIR::EnumExprFieldIdentifier &) override {}
83+
virtual void visit (HIR::EnumExprFieldIdentifierValue &) override {}
84+
85+
virtual void visit (HIR::EnumExprFieldIndexValue &) override {}
86+
virtual void visit (HIR::EnumExprStruct &) override {}
87+
virtual void visit (HIR::EnumExprTuple &) override {}
88+
virtual void visit (HIR::EnumExprFieldless &) override {}
89+
virtual void visit (HIR::CallExpr &) override {}
90+
virtual void visit (HIR::MethodCallExpr &) override {}
91+
virtual void visit (HIR::FieldAccessExpr &) override {}
92+
virtual void visit (HIR::ClosureExprInner &) override {}
93+
virtual void visit (HIR::BlockExpr &) override {}
94+
virtual void visit (HIR::ClosureExprInnerTyped &) override {}
95+
virtual void visit (HIR::ContinueExpr &) override {}
96+
virtual void visit (HIR::BreakExpr &) override {}
97+
virtual void visit (HIR::RangeFromToExpr &) override {}
98+
virtual void visit (HIR::RangeFromExpr &) override {}
99+
virtual void visit (HIR::RangeToExpr &) override {}
100+
virtual void visit (HIR::RangeFullExpr &) override {}
101+
virtual void visit (HIR::RangeFromToInclExpr &) override {}
102+
virtual void visit (HIR::RangeToInclExpr &) override {}
103+
virtual void visit (HIR::ReturnExpr &) override {}
104+
virtual void visit (HIR::UnsafeBlockExpr &) override {}
105+
virtual void visit (HIR::LoopExpr &) override {}
106+
virtual void visit (HIR::WhileLoopExpr &) override {}
107+
virtual void visit (HIR::WhileLetLoopExpr &) override {}
108+
virtual void visit (HIR::ForLoopExpr &) override {}
109+
virtual void visit (HIR::IfExpr &) override {}
110+
virtual void visit (HIR::IfExprConseqElse &) override {}
111+
virtual void visit (HIR::IfExprConseqIf &) override {}
112+
virtual void visit (HIR::IfExprConseqIfLet &) override {}
113+
virtual void visit (HIR::IfLetExpr &) override {}
114+
virtual void visit (HIR::IfLetExprConseqElse &) override {}
115+
virtual void visit (HIR::IfLetExprConseqIf &) override {}
116+
virtual void visit (HIR::IfLetExprConseqIfLet &) override {}
117+
118+
virtual void visit (HIR::MatchExpr &) override {}
119+
virtual void visit (HIR::AwaitExpr &) override {}
120+
virtual void visit (HIR::AsyncBlockExpr &) override {}
121+
122+
virtual void visit (HIR::TypeParam &) override {}
123+
124+
virtual void visit (HIR::LifetimeWhereClauseItem &) override {}
125+
virtual void visit (HIR::TypeBoundWhereClauseItem &) override {}
126+
virtual void visit (HIR::Method &) override {}
127+
virtual void visit (HIR::ModuleBodied &) override {}
128+
virtual void visit (HIR::ModuleNoBody &) override {}
129+
virtual void visit (HIR::ExternCrate &) override {}
130+
131+
virtual void visit (HIR::UseTreeGlob &) override {}
132+
virtual void visit (HIR::UseTreeList &) override {}
133+
virtual void visit (HIR::UseTreeRebind &) override {}
134+
virtual void visit (HIR::UseDeclaration &) override {}
135+
virtual void visit (HIR::Function &) override {}
136+
virtual void visit (HIR::TypeAlias &) override {}
137+
virtual void visit (HIR::StructStruct &) override {}
138+
virtual void visit (HIR::TupleStruct &) override {}
139+
virtual void visit (HIR::EnumItem &) override {}
140+
virtual void visit (HIR::EnumItemTuple &) override {}
141+
virtual void visit (HIR::EnumItemStruct &) override {}
142+
virtual void visit (HIR::EnumItemDiscriminant &) override {}
143+
virtual void visit (HIR::Enum &) override {}
144+
virtual void visit (HIR::Union &) override {}
145+
virtual void visit (HIR::ConstantItem &) override {}
146+
virtual void visit (HIR::StaticItem &) override {}
147+
virtual void visit (HIR::TraitItemFunc &) override {}
148+
virtual void visit (HIR::TraitItemMethod &) override {}
149+
virtual void visit (HIR::TraitItemConst &) override {}
150+
virtual void visit (HIR::TraitItemType &) override {}
151+
virtual void visit (HIR::Trait &) override {}
152+
virtual void visit (HIR::InherentImpl &) override {}
153+
virtual void visit (HIR::TraitImpl &) override {}
154+
155+
virtual void visit (HIR::ExternalStaticItem &) override {}
156+
virtual void visit (HIR::ExternalFunctionItem &) override {}
157+
virtual void visit (HIR::ExternBlock &) override {}
158+
159+
virtual void visit (HIR::MacroMatchFragment &) override {}
160+
virtual void visit (HIR::MacroMatchRepetition &) override {}
161+
virtual void visit (HIR::MacroMatcher &) override {}
162+
virtual void visit (HIR::MacroRulesDefinition &) override {}
163+
virtual void visit (HIR::MacroInvocation &) override {}
164+
virtual void visit (HIR::MetaItemPath &) override {}
165+
virtual void visit (HIR::MetaItemSeq &) override {}
166+
virtual void visit (HIR::MetaWord &) override {}
167+
virtual void visit (HIR::MetaNameValueStr &) override {}
168+
virtual void visit (HIR::MetaListPaths &) override {}
169+
virtual void visit (HIR::MetaListNameValueStr &) override {}
170+
171+
virtual void visit (HIR::LiteralPattern &) override {}
172+
virtual void visit (HIR::IdentifierPattern &) override {}
173+
virtual void visit (HIR::WildcardPattern &) override {}
174+
175+
virtual void visit (HIR::RangePatternBoundLiteral &) override {}
176+
virtual void visit (HIR::RangePatternBoundPath &) override {}
177+
virtual void visit (HIR::RangePatternBoundQualPath &) override {}
178+
virtual void visit (HIR::RangePattern &) override {}
179+
virtual void visit (HIR::ReferencePattern &) override {}
180+
181+
virtual void visit (HIR::StructPatternFieldTuplePat &) override {}
182+
virtual void visit (HIR::StructPatternFieldIdentPat &) override {}
183+
virtual void visit (HIR::StructPatternFieldIdent &) override {}
184+
virtual void visit (HIR::StructPattern &) override {}
185+
186+
virtual void visit (HIR::TupleStructItemsNoRange &) override {}
187+
virtual void visit (HIR::TupleStructItemsRange &) override {}
188+
virtual void visit (HIR::TupleStructPattern &) override {}
189+
190+
virtual void visit (HIR::TuplePatternItemsMultiple &) override {}
191+
virtual void visit (HIR::TuplePatternItemsRanged &) override {}
192+
virtual void visit (HIR::TuplePattern &) override {}
193+
virtual void visit (HIR::GroupedPattern &) override {}
194+
virtual void visit (HIR::SlicePattern &) override {}
195+
196+
virtual void visit (HIR::EmptyStmt &) override {}
197+
virtual void visit (HIR::LetStmt &) override {}
198+
virtual void visit (HIR::ExprStmtWithoutBlock &) override {}
199+
virtual void visit (HIR::ExprStmtWithBlock &) override {}
200+
201+
virtual void visit (HIR::TraitBound &) override {}
202+
virtual void visit (HIR::ImplTraitType &) override {}
203+
virtual void visit (HIR::TraitObjectType &) override {}
204+
virtual void visit (HIR::ParenthesisedType &) override {}
205+
virtual void visit (HIR::ImplTraitTypeOneBound &) override {}
206+
virtual void visit (HIR::TraitObjectTypeOneBound &) override {}
207+
virtual void visit (HIR::TupleType &) override {}
208+
virtual void visit (HIR::NeverType &) override {}
209+
virtual void visit (HIR::RawPointerType &) override {}
210+
virtual void visit (HIR::ReferenceType &) override {}
211+
virtual void visit (HIR::ArrayType &) override {}
212+
virtual void visit (HIR::SliceType &) override {}
213+
virtual void visit (HIR::InferredType &) override {}
214+
virtual void visit (HIR::BareFunctionType &) override {}
215+
216+
protected:
217+
LivenessBase () : mappings (Analysis::Mappings::get ()) {}
218+
219+
Analysis::Mappings *mappings;
220+
};
221+
222+
} // namespace Analysis
223+
} // namespace Rust
224+
225+
#endif
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Copyright (C) 2021 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-liveness.h"
20+
#include "rust-hir-full.h"
21+
#include "rust-name-resolver.h"
22+
23+
namespace Rust {
24+
namespace Analysis {
25+
26+
class FindEntryPoint : public LivenessBase
27+
{
28+
using Rust::Analysis::LivenessBase::visit;
29+
30+
public:
31+
static std::vector<HirId> find (HIR::Crate &crate)
32+
{
33+
FindEntryPoint findEntryPoint;
34+
for (auto it = crate.items.begin (); it != crate.items.end (); it++)
35+
{
36+
it->get ()->accept_vis (findEntryPoint);
37+
}
38+
return findEntryPoint.getEntryPoint ();
39+
}
40+
41+
// TODO not only fn main can be a entry point.
42+
void visit (HIR::Function &function) override
43+
{
44+
if (function.get_function_name () == "main")
45+
{
46+
entryPoints.push_back (function.get_mappings ().get_hirid ());
47+
}
48+
}
49+
50+
private:
51+
FindEntryPoint () : LivenessBase () {}
52+
std::vector<HirId> entryPoints;
53+
std::vector<HirId> getEntryPoint () { return entryPoints; }
54+
};
55+
56+
std::set<HirId>
57+
Liveness::Analysis (HIR::Crate &crate)
58+
{
59+
Liveness liveness (FindEntryPoint::find (crate));
60+
liveness.go (crate);
61+
62+
return liveness.liveSymbols;
63+
}
64+
65+
void
66+
Liveness::go (HIR::Crate &crate)
67+
{
68+
while (!worklist.empty ())
69+
{
70+
HirId hirId = worklist.back ();
71+
worklist.pop_back ();
72+
scannedSymbols.emplace (hirId);
73+
HIR::Item *item
74+
= mappings->lookup_hir_item (crate.get_mappings ().get_crate_num (),
75+
hirId);
76+
if (item == nullptr)
77+
continue;
78+
liveSymbols.emplace (hirId);
79+
item->accept_vis (*this);
80+
}
81+
}
82+
83+
void
84+
Liveness::visit (HIR::ExprStmtWithoutBlock &stmt)
85+
{
86+
stmt.get_expr ()->accept_vis (*this);
87+
}
88+
89+
void
90+
Liveness::visit (HIR::CallExpr &expr)
91+
{
92+
expr.get_fnexpr ()->accept_vis (*this);
93+
}
94+
95+
void
96+
Liveness::visit (HIR::PathInExpression &expr)
97+
{
98+
NodeId ast_node_id = expr.get_mappings ().get_nodeid ();
99+
NodeId ref_node_id = UNKNOWN_NODEID;
100+
if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
101+
{
102+
Resolver::Definition def;
103+
if (!resolver->lookup_definition (ref_node_id, &def))
104+
{
105+
rust_error_at (expr.get_locus (),
106+
"unknown reference for resolved name");
107+
return;
108+
}
109+
ref_node_id = def.parent;
110+
HirId ref;
111+
if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
112+
ref_node_id, &ref))
113+
{
114+
rust_error_at (expr.get_locus (), "reverse lookup failure");
115+
return;
116+
}
117+
if (scannedSymbols.find (ref) != scannedSymbols.end ())
118+
{
119+
worklist.push_back (ref);
120+
}
121+
liveSymbols.emplace (ref);
122+
}
123+
}
124+
125+
void
126+
Liveness::visit (HIR::Function &function)
127+
{
128+
function.get_definition ().get ()->accept_vis (*this);
129+
}
130+
131+
void
132+
Liveness::visit (HIR::BlockExpr &expr)
133+
{
134+
expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool {
135+
s->accept_vis (*this);
136+
return true;
137+
});
138+
}
139+
140+
} // namespace Analysis
141+
} // namespace Rust

0 commit comments

Comments
 (0)