"unnecessary trailing semicolons");
}
+void
+UnusedChecker::visit_loop_label (HIR::LoopLabel &label)
+{
+ auto lifetime = label.get_lifetime ();
+ std::string var_name = lifetime.to_string ();
+ auto id = lifetime.get_mappings ().get_hirid ();
+ if (!unused_context.is_label_used (id) && var_name[0] != '_')
+ rust_warning_at (lifetime.get_locus (), OPT_Wunused_variable,
+ "unused label %qs", lifetime.to_string ().c_str ());
+}
+
} // namespace Analysis
} // namespace Rust
virtual void visit (HIR::AssignmentExpr &identifier) override;
virtual void visit (HIR::StructPatternFieldIdent &identifier) override;
virtual void visit (HIR::EmptyStmt &stmt) override;
+ virtual void visit_loop_label (HIR::LoopLabel &label) override;
};
} // namespace Analysis
} // namespace Rust
walk (pattern);
}
+void
+UnusedCollector::visit (HIR::BreakExpr &expr)
+{
+ if (!expr.has_label ())
+ return;
+ mark_label_used (expr.get_label ());
+ walk (expr);
+}
+
+void
+UnusedCollector::visit (HIR::ContinueExpr &expr)
+{
+ if (!expr.has_label ())
+ return;
+ mark_label_used (expr.get_label ());
+ walk (expr);
+}
+
} // namespace Analysis
} // namespace Rust
virtual void visit (HIR::IdentifierPattern &pattern) override;
virtual void visit (HIR::StructPatternFieldIdent &pattern) override;
+ // Unused label
+ virtual void visit (HIR::BreakExpr &expr) override;
+ virtual void visit (HIR::ContinueExpr &expr) override;
+
template <typename T> HirId get_def_id (T &path_expr)
{
NodeId ast_node_id = path_expr.get_mappings ().get_nodeid ();
unused_context.add_variable (def_id);
unused_context.remove_assign (def_id);
}
+
+ template <typename T> void mark_label_used (T &path_expr)
+ {
+ auto def_id = get_def_id (path_expr);
+ unused_context.add_label (def_id);
+ }
};
} // namespace Analysis
} // namespace Rust
return mutable_vars.find (id) == mutable_vars.end ();
}
+void
+UnusedContext::add_label (HirId id)
+
+{
+ used_labels.emplace (id);
+}
+
+bool
+UnusedContext::is_label_used (HirId id) const
+{
+ return used_labels.find (id) != used_labels.end ();
+}
+
std::string
UnusedContext::as_string () const
{
void add_mut (HirId id);
void remove_mut (HirId id);
bool is_mut_used (HirId id) const;
+
+ // Unused label
+ void add_label (HirId id);
+ bool is_label_used (HirId id) const;
+
std::string as_string () const;
private:
std::unordered_set<HirId> used_vars;
std::unordered_set<HirId> mutable_vars;
std::map<HirId, std::vector<HirId>> assigned_vars;
+ std::unordered_set<HirId> used_labels;
};
} // namespace Analysis
--- /dev/null
+// { dg-additional-options "-frust-unused-check-2.0" }
+
+pub fn foo_1() {
+ 'a: loop {
+ break 'a;
+ }
+}
+
+pub fn foo_2() {
+ 'a: loop {
+// { dg-warning "unused label ..a." "" { target *-*-* } .-1 }
+ break;
+ }
+}
+
+
+pub fn bar_1() {
+ 'a: loop {
+ continue 'a;
+ }
+}
+
+pub fn bar_2() {
+ 'a: loop {
+// { dg-warning "unused label ..a." "" { target *-*-* } .-1 }
+ continue;
+ }
+}