LCOV - code coverage report
Current view: top level - gcc/rust/checks/lints/unused - rust-unused-checker.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.1 % 101 90
Test Date: 2026-02-28 14:20:25 Functions: 85.7 % 14 12
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2025-2026 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-checker.h"
      20              : #include "rust-hir-expr.h"
      21              : #include "rust-hir-generic-param.h"
      22              : #include "rust-hir-item.h"
      23              : 
      24              : #include "options.h"
      25              : #include "rust-keyword-values.h"
      26              : 
      27              : namespace Rust {
      28              : namespace Analysis {
      29            9 : UnusedChecker::UnusedChecker ()
      30            9 :   : nr_context (
      31            9 :     Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()),
      32           18 :     mappings (Analysis::Mappings::get ()), unused_context (UnusedContext ())
      33            9 : {}
      34              : void
      35            9 : UnusedChecker::go (HIR::Crate &crate)
      36              : {
      37            9 :   UnusedCollector collector (unused_context);
      38            9 :   collector.go (crate);
      39           25 :   for (auto &item : crate.get_items ())
      40           16 :     item->accept_vis (*this);
      41            9 : }
      42              : 
      43              : bool
      44           21 : is_snake_case (Identifier identifier)
      45              : {
      46           21 :   auto s = identifier.as_string ();
      47           21 :   return std::all_of (s.begin (), s.end (), [] (unsigned char c) {
      48           48 :     return ISLOWER (c) || ISDIGIT (c) || c == '_';
      49           21 :   });
      50           21 : }
      51              : 
      52              : void
      53            0 : UnusedChecker::visit (HIR::ConstantItem &item)
      54              : {
      55            0 :   std::string var_name = item.get_identifier ().as_string ();
      56            0 :   auto id = item.get_mappings ().get_hirid ();
      57            0 :   if (!unused_context.is_variable_used (id) && var_name[0] != '_')
      58            0 :     rust_warning_at (item.get_locus (), OPT_Wunused_variable,
      59              :                      "unused variable %qs",
      60            0 :                      item.get_identifier ().as_string ().c_str ());
      61            0 : }
      62              : 
      63              : void
      64            2 : UnusedChecker::visit (HIR::StaticItem &item)
      65              : {
      66            4 :   std::string var_name = item.get_identifier ().as_string ();
      67            2 :   auto id = item.get_mappings ().get_hirid ();
      68            2 :   if (!unused_context.is_variable_used (id) && var_name[0] != '_')
      69            1 :     rust_warning_at (item.get_locus (), OPT_Wunused_variable,
      70              :                      "unused variable %qs",
      71            2 :                      item.get_identifier ().as_string ().c_str ());
      72              : 
      73            2 :   if (!std::all_of (var_name.begin (), var_name.end (), [] (unsigned char c) {
      74            6 :         return ISUPPER (c) || ISDIGIT (c) || c == '_';
      75              :       }))
      76            1 :     rust_warning_at (item.get_locus (), OPT_Wunused_variable,
      77              :                      "static variable %qs should have an upper case name",
      78              :                      var_name.c_str ());
      79            2 : }
      80              : 
      81              : void
      82            0 : UnusedChecker::visit (HIR::TraitItemFunc &item)
      83              : {
      84              :   // TODO: check trait item functions if they are not derived.
      85            0 : }
      86              : void
      87            8 : UnusedChecker::visit (HIR::IdentifierPattern &pattern)
      88              : {
      89           16 :   std::string var_name = pattern.get_identifier ().as_string ();
      90            8 :   auto id = pattern.get_mappings ().get_hirid ();
      91            8 :   if (!unused_context.is_variable_used (id)
      92            8 :       && var_name != Values::Keywords::SELF && var_name[0] != '_')
      93            1 :     rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
      94              :                      "unused variable %qs",
      95            2 :                      pattern.get_identifier ().as_string ().c_str ());
      96              : 
      97            8 :   if (pattern.is_mut () && !unused_context.is_mut_used (id)
      98            9 :       && var_name != Values::Keywords::SELF && var_name[0] != '_')
      99            1 :     rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
     100              :                      "unused mut %qs",
     101            2 :                      pattern.get_identifier ().as_string ().c_str ());
     102              : 
     103            8 :   if (!is_snake_case (pattern.get_identifier ()))
     104            1 :     rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
     105              :                      "variable %qs should have a snake case name",
     106              :                      var_name.c_str ());
     107            8 : }
     108              : void
     109              : 
     110            9 : UnusedChecker::visit (HIR::AssignmentExpr &expr)
     111              : 
     112              : {
     113            9 :   const auto &lhs = expr.get_lhs ();
     114            9 :   auto var_name = lhs.to_string ();
     115            9 :   NodeId ast_node_id = lhs.get_mappings ().get_nodeid ();
     116            9 :   NodeId def_id = nr_context.lookup (ast_node_id).value ();
     117            9 :   HirId id = mappings.lookup_node_to_hir (def_id).value ();
     118            9 :   if (unused_context.is_variable_assigned (id, lhs.get_mappings ().get_hirid ())
     119            9 :       && var_name[0] != '_')
     120            7 :     rust_warning_at (lhs.get_locus (), OPT_Wunused_variable,
     121              :                      "unused assignment %qs", var_name.c_str ());
     122            9 : }
     123              : 
     124              : void
     125            2 : UnusedChecker::visit (HIR::StructPatternFieldIdent &pattern)
     126              : {
     127            4 :   std::string var_name = pattern.get_identifier ().as_string ();
     128            2 :   auto id = pattern.get_mappings ().get_hirid ();
     129            2 :   if (!unused_context.is_variable_used (id)
     130            2 :       && var_name != Values::Keywords::SELF && var_name[0] != '_')
     131            0 :     rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
     132              :                      "unused variable %qs",
     133            0 :                      pattern.get_identifier ().as_string ().c_str ());
     134              : 
     135            2 :   if (pattern.is_mut () && !unused_context.is_mut_used (id)
     136            4 :       && var_name != Values::Keywords::SELF && var_name[0] != '_')
     137            2 :     rust_warning_at (pattern.get_locus (), OPT_Wunused_variable,
     138              :                      "unused mut %qs",
     139            4 :                      pattern.get_identifier ().as_string ().c_str ());
     140            2 : }
     141              : 
     142              : void
     143            1 : UnusedChecker::visit (HIR::EmptyStmt &stmt)
     144              : {
     145            1 :   rust_warning_at (stmt.get_locus (), OPT_Wunused_variable,
     146              :                    "unnecessary trailing semicolons");
     147            1 : }
     148              : 
     149              : void
     150           11 : UnusedChecker::visit (HIR::Function &fct)
     151              : {
     152           11 :   if (!is_snake_case (fct.get_function_name ()))
     153            1 :     rust_warning_at (fct.get_locus (), OPT_Wunused_variable,
     154              :                      "function %qs should have a snake case name",
     155            2 :                      fct.get_function_name ().as_string ().c_str ());
     156           11 :   walk (fct);
     157           11 : }
     158              : 
     159              : void
     160            1 : UnusedChecker::visit (HIR::Module &mod)
     161              : {
     162            1 :   if (!is_snake_case (mod.get_module_name ()))
     163            1 :     rust_warning_at (mod.get_locus (), OPT_Wunused_variable,
     164              :                      "module %qs should have a snake case name",
     165            2 :                      mod.get_module_name ().as_string ().c_str ());
     166            1 :   walk (mod);
     167            1 : }
     168              : 
     169              : void
     170            1 : UnusedChecker::visit (HIR::LifetimeParam &lft)
     171              : {
     172            3 :   if (!is_snake_case (lft.get_lifetime ().get_name ()))
     173            1 :     rust_warning_at (lft.get_locus (), OPT_Wunused_variable,
     174              :                      "lifetime %qs should have a snake case name",
     175            2 :                      lft.get_lifetime ().get_name ().c_str ());
     176            1 :   walk (lft);
     177            1 : }
     178              : 
     179              : void
     180            4 : UnusedChecker::visit_loop_label (HIR::LoopLabel &label)
     181              : {
     182            4 :   auto lifetime = label.get_lifetime ();
     183            4 :   std::string var_name = lifetime.to_string ();
     184            4 :   auto id = lifetime.get_mappings ().get_hirid ();
     185            4 :   if (!unused_context.is_label_used (id) && var_name[0] != '_')
     186            2 :     rust_warning_at (lifetime.get_locus (), OPT_Wunused_variable,
     187            4 :                      "unused label %qs", lifetime.to_string ().c_str ());
     188            4 : }
     189              : 
     190              : } // namespace Analysis
     191              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.