aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorThomas Young <wenzhang5800@gmail.com>2021-07-01 15:40:49 +0800
committerThomas Young <wenzhang5800@gmail.com>2021-07-02 21:12:39 +0800
commitd882a0c97f82e9919d6ffe76183b78ed86db1793 (patch)
tree0a47a64c3df8feba4f52686bcc72a139f598a446 /gcc/rust
parent6d7b87f9dd9223da0f3994be5bef5ea9458ebdff (diff)
downloadgcc-d882a0c97f82e9919d6ffe76183b78ed86db1793.zip
gcc-d882a0c97f82e9919d6ffe76183b78ed86db1793.tar.gz
gcc-d882a0c97f82e9919d6ffe76183b78ed86db1793.tar.bz2
detect unused struct field.
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/lint/rust-lint-marklive.cc167
-rw-r--r--gcc/rust/lint/rust-lint-marklive.h17
-rw-r--r--gcc/rust/lint/rust-lint-scan-deadcode.h42
3 files changed, 163 insertions, 63 deletions
diff --git a/gcc/rust/lint/rust-lint-marklive.cc b/gcc/rust/lint/rust-lint-marklive.cc
index 5cdb5d4..af871a5 100644
--- a/gcc/rust/lint/rust-lint-marklive.cc
+++ b/gcc/rust/lint/rust-lint-marklive.cc
@@ -92,89 +92,156 @@ void
MarkLive::visit (HIR::PathInExpression &expr)
{
expr.iterate_path_segments ([&] (HIR::PathExprSegment &seg) -> bool {
- NodeId ast_node_id = seg.get_mappings ().get_nodeid ();
- NodeId ref_node_id = UNKNOWN_NODEID;
- HirId ref;
- if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
- {
- Resolver::Definition def;
- if (!resolver->lookup_definition (ref_node_id, &def))
- {
- rust_error_at (seg.get_locus (),
- "unknown reference for resolved name");
- return false;
- }
- ref_node_id = def.parent;
- }
- else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id))
- {
- return false;
- }
-
- if (!mappings->lookup_node_to_hir (seg.get_mappings ().get_crate_num (),
- ref_node_id, &ref))
- {
- rust_error_at (seg.get_locus (), "reverse lookup failure");
- return false;
- }
- if (scannedSymbols.find (ref) == scannedSymbols.end ())
- {
- worklist.push_back (ref);
- }
- liveSymbols.emplace (ref);
- return true;
+ return visit_path_segment (seg);
});
}
void
-MarkLive::visit (HIR::IdentifierExpr &expr)
+MarkLive::visit (HIR::MethodCallExpr &expr)
{
+ expr.get_receiver ()->accept_vis (*this);
+ visit_path_segment (expr.get_method_name ());
+ expr.iterate_params ([&] (HIR::Expr *param) -> bool {
+ param->accept_vis (*this);
+ return true;
+ });
+
NodeId ast_node_id = expr.get_mappings ().get_nodeid ();
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ find_ref_node_id (ast_node_id, ref_node_id, expr.get_locus (),
+ expr.as_string ());
- // then lookup the reference_node_id
+ // node back to HIR
+ HirId ref;
+ node_id_to_hir_id (expr.get_mappings ().get_crate_num (), ref_node_id, ref,
+ expr.get_locus ());
+ mark_hir_id (ref);
+}
+
+bool
+MarkLive::visit_path_segment (HIR::PathExprSegment seg)
+{
+ NodeId ast_node_id = seg.get_mappings ().get_nodeid ();
NodeId ref_node_id = UNKNOWN_NODEID;
if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
{
- // these ref_node_ids will resolve to a pattern declaration but we are
- // interested in the definition that this refers to get the parent id
Resolver::Definition def;
if (!resolver->lookup_definition (ref_node_id, &def))
{
- rust_error_at (expr.get_locus (),
+ rust_error_at (seg.get_locus (),
"unknown reference for resolved name");
- return;
+ return false;
}
ref_node_id = def.parent;
}
else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id))
{
- rust_error_at (expr.get_locus (),
- "Failed to lookup type reference for node: %s",
- expr.as_string ().c_str ());
- return;
+ return false;
}
+ HirId ref;
+ node_id_to_hir_id (seg.get_mappings ().get_crate_num (), ref_node_id, ref,
+ seg.get_locus ());
+ mark_hir_id (ref);
+ return true;
+}
- if (ref_node_id == UNKNOWN_NODEID)
+void
+MarkLive::visit (HIR::FieldAccessExpr &expr)
+{
+ // visit receiver at first
+ expr.get_receiver_expr ()->accept_vis (*this);
+
+ // resolve the receiver back to ADT type
+ TyTy::BaseType *receiver = nullptr;
+ if (!tyctx->lookup_type (
+ expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver))
+ {
+ rust_error_at (expr.get_receiver_expr ()->get_locus_slow (),
+ "unresolved type for receiver");
+ }
+ rust_assert (receiver->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver);
+
+ // get the field index
+ size_t index = 0;
+ adt->get_field (expr.get_field_name (), &index);
+ if (index >= adt->num_fields ())
{
- rust_error_at (expr.get_locus (), "unresolved node: %s",
- expr.as_string ().c_str ());
+ rust_error_at (expr.get_receiver_expr ()->get_locus_slow (),
+ "cannot access struct %s by index: %ld",
+ adt->get_name ().c_str (), index);
return;
}
+ // get the field hir id
+ HirId field_id = adt->get_field (index)->get_ref ();
+ mark_hir_id (field_id);
+}
+
+void
+MarkLive::visit (HIR::TupleIndexExpr &expr)
+{
+ // TODO: unused tuple field detection
+ expr.get_tuple_expr ()->accept_vis (*this);
+}
+
+void
+MarkLive::visit (HIR::IdentifierExpr &expr)
+{
+ NodeId ast_node_id = expr.get_mappings ().get_nodeid ();
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ find_ref_node_id (ast_node_id, ref_node_id, expr.get_locus (),
+ expr.as_string ());
// node back to HIR
HirId ref;
- if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
- ref_node_id, &ref))
+ node_id_to_hir_id (expr.get_mappings ().get_crate_num (), ref_node_id, ref,
+ expr.get_locus ());
+ mark_hir_id (ref);
+}
+
+void
+MarkLive::mark_hir_id (HirId id)
+{
+ if (scannedSymbols.find (id) == scannedSymbols.end ())
+ {
+ worklist.push_back (id);
+ }
+ liveSymbols.emplace (id);
+}
+
+void
+MarkLive::find_ref_node_id (NodeId ast_node_id, NodeId &ref_node_id,
+ Location locus, const std::string &node_name)
+{
+ if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
{
- rust_error_at (expr.get_locus (), "reverse lookup failure");
+ // these ref_node_ids will resolve to a pattern declaration but we are
+ // interested in the definition that this refers to get the parent id
+ Resolver::Definition def;
+ if (!resolver->lookup_definition (ref_node_id, &def))
+ {
+ rust_error_at (locus, "unknown reference for resolved name");
+ return;
+ }
+ ref_node_id = def.parent;
+ }
+ else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id))
+ {
+ rust_error_at (locus, "Failed to lookup type reference for node: %s",
+ node_name.c_str ());
return;
}
+}
- if (scannedSymbols.find (ref) == scannedSymbols.end ())
+void
+MarkLive::node_id_to_hir_id (CrateNum crateNum, NodeId ref_node_id, HirId &ref,
+ Location locus)
+{
+ if (!mappings->lookup_node_to_hir (crateNum, ref_node_id, &ref))
{
- worklist.push_back (ref);
+ rust_error_at (locus, "reverse lookup failure");
+ return;
}
- liveSymbols.emplace (ref);
}
} // namespace Analysis
diff --git a/gcc/rust/lint/rust-lint-marklive.h b/gcc/rust/lint/rust-lint-marklive.h
index 2db5294..72274d0 100644
--- a/gcc/rust/lint/rust-lint-marklive.h
+++ b/gcc/rust/lint/rust-lint-marklive.h
@@ -38,6 +38,9 @@ public:
void visit (HIR::PathInExpression &expr) override;
void visit (HIR::IdentifierExpr &expr) override;
+ void visit (HIR::FieldAccessExpr &expr) override;
+ void visit (HIR::TupleIndexExpr &expr) override;
+ void visit (HIR::MethodCallExpr &expr) override;
void visit (HIR::BorrowExpr &expr) override
{
@@ -156,6 +159,10 @@ public:
void visit (HIR::CallExpr &expr) override
{
expr.get_fnexpr ()->accept_vis (*this);
+ expr.iterate_params ([&] (HIR::Expr *expr) -> bool {
+ expr->accept_vis (*this);
+ return true;
+ });
}
void visit (HIR::ArithmeticOrLogicalExpr &expr) override
@@ -226,9 +233,17 @@ private:
std::set<HirId> scannedSymbols;
Analysis::Mappings *mappings;
Resolver::Resolver *resolver;
+ Resolver::TypeCheckContext *tyctx;
MarkLive (std::vector<HirId> worklist)
: worklist (worklist), mappings (Analysis::Mappings::get ()),
- resolver (Resolver::Resolver::get ()){};
+ resolver (Resolver::Resolver::get ()),
+ tyctx (Resolver::TypeCheckContext::get ()){};
+
+ void mark_hir_id (HirId);
+ bool visit_path_segment (HIR::PathExprSegment);
+ void find_ref_node_id (NodeId ast_node_id, NodeId &ref_node_id,
+ Location locus, const std::string &node_name);
+ void node_id_to_hir_id (CrateNum, NodeId, HirId &, Location);
};
} // namespace Analysis
diff --git a/gcc/rust/lint/rust-lint-scan-deadcode.h b/gcc/rust/lint/rust-lint-scan-deadcode.h
index 1dee18a..ad48a47 100644
--- a/gcc/rust/lint/rust-lint-scan-deadcode.h
+++ b/gcc/rust/lint/rust-lint-scan-deadcode.h
@@ -46,15 +46,37 @@ public:
void visit (HIR::Function &function) override
{
HirId hirId = function.get_mappings ().get_hirid ();
- warning (hirId, function.get_locus (), "function",
- function.get_function_name (), "used");
+ if (should_warn (hirId))
+ {
+ rust_warning_at (function.get_locus (), 0, "%s is never %s: %<%s%>",
+ "function", "used",
+ function.get_function_name ().c_str ());
+ }
}
void visit (HIR::StructStruct &stct) override
{
HirId hirId = stct.get_mappings ().get_hirid ();
- warning (hirId, stct.get_locus (), "struct", stct.get_identifier (),
- "constructed");
+ if (should_warn (hirId))
+ {
+ rust_warning_at (stct.get_locus (), 0, "%s is never %s: %<%s%>",
+ "struct", "constructed",
+ stct.get_identifier ().c_str ());
+ }
+ else
+ {
+ // only warn the unused fields when in unwarned struct.
+ stct.iterate ([&] (HIR::StructField &field) -> bool {
+ HirId field_hir_id = field.get_mappings ().get_hirid ();
+ if (should_warn (field_hir_id))
+ {
+ rust_warning_at (field.get_locus (), 0, "%s is never %s: %<%s%>",
+ "field", "read",
+ field.get_field_name ().c_str ());
+ }
+ return true;
+ });
+ }
}
private:
@@ -64,15 +86,11 @@ private:
ScanDeadcode (std::set<HirId> &live_symbols)
: live_symbols (live_symbols), resolver (Resolver::Resolver::get ()){};
- void warning (HirId hirId, Location loc, const std::string &span,
- const std::string &name, const std::string &participle) const
+ bool should_warn (HirId hirId)
{
- if (live_symbols.find (hirId) == live_symbols.end ())
- {
- rust_warning_at (loc, 0, "%s is never %s: %<%s%>", span.c_str (),
- participle.c_str (), name.c_str ());
- return;
- }
+ // TODO: There are more condition to check if should warn, i.e visibility,
+ // attributes.
+ return live_symbols.find (hirId) == live_symbols.end ();
}
};