LCOV - code coverage report
Current view: top level - gcc/rust/checks/lints - rust-lint-scan-deadcode.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 81 81
Test Date: 2026-08-22 16:33:35 Functions: 100.0 % 9 9
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2021-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              : #ifndef RUST_HIR_SCAN_DEADCODE
      20              : #define RUST_HIR_SCAN_DEADCODE
      21              : 
      22              : #include "options.h"
      23              : #include "rust-hir-full-decls.h"
      24              : #include "rust-hir-map.h"
      25              : #include "rust-lint-marklive.h"
      26              : #include "rust-name-resolver.h"
      27              : #include "rust-diagnostics.h"
      28              : 
      29              : namespace Rust {
      30              : namespace Analysis {
      31              : 
      32              : // Scan item symbols and warn the symbol if it is not in the live_symbols set.
      33              : // There are three kinds of item we should handle in this pass.
      34              : // 1. Function item
      35              : // 2. The function item in the impl block without trait
      36              : // 3. StructStruct, e.g., `Struct Foo{one: 1, two: 2}`. Furthermore, the unused
      37              : //    struct fields will be warned too.
      38              : // 4. TupleStruct, e.g., `Struct Foo(i32, i32)`
      39         4305 : class ScanDeadcode : public MarkLiveBase
      40              : {
      41              :   using Rust::Analysis::MarkLiveBase::visit;
      42              : 
      43              : public:
      44         4305 :   static void Scan (HIR::Crate &crate)
      45              :   {
      46         4305 :     std::set<HirId> live_symbols = Analysis::MarkLive::Analysis (crate);
      47         4305 :     ScanDeadcode sdc (live_symbols);
      48        22114 :     for (auto &it : crate.get_items ())
      49        17809 :       it.get ()->accept_vis (sdc);
      50         4305 :   };
      51              : 
      52        12994 :   void visit (HIR::Function &function) override
      53              :   {
      54        12994 :     HirId hirId = function.get_mappings ().get_hirid ();
      55        12994 :     auto starts_with_underscore
      56        12994 :       = function.get_function_name ().as_string ().rfind ('_', 0) == 0;
      57         6328 :     if (should_warn (hirId) && !function.get_visibility ().is_public ()
      58        17040 :         && !starts_with_underscore)
      59              :       {
      60         4029 :         if (mappings.is_impl_item (hirId))
      61              :           {
      62         3868 :             HIR::ImplBlock *implBlock = mappings.lookup_associated_impl (hirId);
      63         3868 :             if (!implBlock->has_trait_ref ())
      64              :               {
      65           89 :                 rust_warning_at (
      66          178 :                   function.get_function_name ().get_locus (), 0,
      67              :                   "associated function is never used: %qs",
      68          178 :                   function.get_function_name ().as_string ().c_str ());
      69              :               }
      70              :           }
      71              :         else
      72              :           {
      73          161 :             rust_warning_at (
      74          322 :               function.get_function_name ().get_locus (), 0,
      75              :               "function is never used: %qs",
      76          322 :               function.get_function_name ().as_string ().c_str ());
      77              :           }
      78              :       }
      79        12994 :   }
      80              : 
      81         1375 :   void visit (HIR::StructStruct &stct) override
      82              :   {
      83         1375 :     HirId hirId = stct.get_mappings ().get_hirid ();
      84          486 :     if (should_warn (hirId) && !stct.get_visibility ().is_public ())
      85              :       {
      86          226 :         bool name_starts_underscore
      87          226 :           = stct.get_identifier ().as_string ().at (0) == '_';
      88          226 :         if (!name_starts_underscore)
      89          203 :           rust_warning_at (stct.get_locus (), 0,
      90              :                            "struct is never constructed: %qs",
      91          406 :                            stct.get_identifier ().as_string ().c_str ());
      92              :       }
      93              :     else
      94              :       {
      95              :         // only warn the unused fields when in unwarned struct.
      96         2621 :         for (auto &field : stct.get_fields ())
      97              :           {
      98         1472 :             HirId field_hir_id = field.get_mappings ().get_hirid ();
      99         2944 :             if (should_warn (field_hir_id)
     100          683 :                 && !field.get_visibility ().is_public ()
     101         1957 :                 && field.get_field_name ().as_string ().at (0) != '_')
     102              :               {
     103          455 :                 rust_warning_at (field.get_locus (), 0,
     104              :                                  "field is never read: %qs",
     105          910 :                                  field.get_field_name ().as_string ().c_str ());
     106              :               }
     107              :           }
     108              :       }
     109         1375 :   }
     110              : 
     111          796 :   void visit (HIR::TupleStruct &stct) override
     112              :   {
     113              :     // only warn tuple struct unconstructed, and ignoring unused field
     114          796 :     HirId hirId = stct.get_mappings ().get_hirid ();
     115           68 :     if (should_warn (hirId) && !stct.get_visibility ().is_public ())
     116              :       {
     117           51 :         rust_warning_at (stct.get_locus (), 0,
     118              :                          "struct is never constructed: %qs",
     119          102 :                          stct.get_identifier ().as_string ().c_str ());
     120              :       }
     121          796 :   }
     122              : 
     123         5410 :   void visit (HIR::ImplBlock &blc) override
     124              :   {
     125         5410 :     if (blc.has_impl_items ())
     126              :       {
     127        12280 :         for (auto &implItem : blc.get_impl_items ())
     128              :           {
     129         7988 :             implItem->accept_vis (*this);
     130              :           }
     131              :       }
     132         5410 :   }
     133              : 
     134         1139 :   void visit (HIR::Module &mod) override
     135              :   {
     136         4726 :     for (auto &item : mod.get_items ())
     137         3587 :       item->accept_vis (*this);
     138         1139 :   }
     139              : 
     140          462 :   void visit (HIR::ConstantItem &item) override
     141              :   {
     142          462 :     if (!flag_unused_check_2_0)
     143          460 :       return;
     144            4 :     std::string var_name = item.get_identifier ().as_string ();
     145            2 :     bool starts_with_under_score = var_name.at (0) == '_';
     146            2 :     HirId hirId = item.get_mappings ().get_hirid ();
     147            2 :     if (should_warn (hirId) && !item.get_visibility ().is_public ()
     148            3 :         && !starts_with_under_score)
     149            1 :       rust_warning_at (item.get_locus (), OPT_Wunused_variable,
     150              :                        "deadcode const item %qs",
     151            2 :                        item.get_identifier ().as_string ().c_str ());
     152            2 :   }
     153              : 
     154           48 :   void visit (HIR::StaticItem &item) override
     155              :   {
     156           48 :     if (!flag_unused_check_2_0)
     157           45 :       return;
     158            6 :     std::string var_name = item.get_identifier ().as_string ();
     159            3 :     bool starts_with_under_score = var_name.at (0) == '_';
     160            3 :     HirId hirId = item.get_mappings ().get_hirid ();
     161            3 :     if (should_warn (hirId) && !item.get_visibility ().is_public ()
     162            5 :         && !starts_with_under_score)
     163            1 :       rust_warning_at (item.get_locus (), OPT_Wunused_variable,
     164              :                        "deadcode static item %qs",
     165            2 :                        item.get_identifier ().as_string ().c_str ());
     166            3 :   }
     167              : 
     168              : private:
     169              :   std::set<HirId> live_symbols;
     170              :   Resolver::Resolver *resolver;
     171              :   Analysis::Mappings &mappings;
     172              : 
     173         4305 :   ScanDeadcode (std::set<HirId> &live_symbols)
     174         4305 :     : live_symbols (live_symbols), resolver (Resolver::Resolver::get ()),
     175         8610 :       mappings (Analysis::Mappings::get ()){};
     176              : 
     177        16642 :   bool should_warn (HirId hirId)
     178              :   {
     179              :     // TODO: There are more condition to check if should warn, i.e visibility,
     180              :     // attributes.
     181        16642 :     return live_symbols.find (hirId) == live_symbols.end ();
     182              :   }
     183              : };
     184              : 
     185              : } // namespace Analysis
     186              : } // namespace Rust
     187              : 
     188              : #endif
        

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.