diff options
author | Thomas Young <wenzhang5800@gmail.com> | 2021-07-01 15:40:49 +0800 |
---|---|---|
committer | Thomas Young <wenzhang5800@gmail.com> | 2021-07-02 21:12:39 +0800 |
commit | d882a0c97f82e9919d6ffe76183b78ed86db1793 (patch) | |
tree | 0a47a64c3df8feba4f52686bcc72a139f598a446 /gcc/rust | |
parent | 6d7b87f9dd9223da0f3994be5bef5ea9458ebdff (diff) | |
download | gcc-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.cc | 167 | ||||
-rw-r--r-- | gcc/rust/lint/rust-lint-marklive.h | 17 | ||||
-rw-r--r-- | gcc/rust/lint/rust-lint-scan-deadcode.h | 42 |
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 (); } }; |