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 % 59 59
Test Date: 2026-03-28 14:25:54 Functions: 100.0 % 7 7
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 "rust-hir-full-decls.h"
      23              : #include "rust-hir-map.h"
      24              : #include "rust-lint-marklive.h"
      25              : #include "rust-name-resolver.h"
      26              : #include "rust-diagnostics.h"
      27              : 
      28              : namespace Rust {
      29              : namespace Analysis {
      30              : 
      31              : // Scan item symbols and warn the symbol if it is not in the live_symbols set.
      32              : // There are three kinds of item we should handle in this pass.
      33              : // 1. Function item
      34              : // 2. The function item in the impl block without trait
      35              : // 3. StructStruct, e.g., `Struct Foo{one: 1, two: 2}`. Furthermore, the unused
      36              : //    struct fields will be warned too.
      37              : // 4. TupleStruct, e.g., `Struct Foo(i32, i32)`
      38         4032 : class ScanDeadcode : public MarkLiveBase
      39              : {
      40              :   using Rust::Analysis::MarkLiveBase::visit;
      41              : 
      42              : public:
      43         4032 :   static void Scan (HIR::Crate &crate)
      44              :   {
      45         4032 :     std::set<HirId> live_symbols = Analysis::MarkLive::Analysis (crate);
      46         4032 :     ScanDeadcode sdc (live_symbols);
      47        20783 :     for (auto &it : crate.get_items ())
      48        16751 :       it.get ()->accept_vis (sdc);
      49         4032 :   };
      50              : 
      51        12556 :   void visit (HIR::Function &function) override
      52              :   {
      53        12556 :     HirId hirId = function.get_mappings ().get_hirid ();
      54        12556 :     auto starts_with_underscore
      55        12556 :       = function.get_function_name ().as_string ().rfind ('_', 0) == 0;
      56        12408 :     if (should_warn (hirId) && !function.get_visibility ().is_public ()
      57        16516 :         && !starts_with_underscore)
      58              :       {
      59         3958 :         if (mappings.is_impl_item (hirId))
      60              :           {
      61         3802 :             HIR::ImplBlock *implBlock = mappings.lookup_associated_impl (hirId);
      62         3802 :             if (!implBlock->has_trait_ref ())
      63              :               {
      64           89 :                 rust_warning_at (
      65          178 :                   function.get_function_name ().get_locus (), 0,
      66              :                   "associated function is never used: %qs",
      67          178 :                   function.get_function_name ().as_string ().c_str ());
      68              :               }
      69              :           }
      70              :         else
      71              :           {
      72          156 :             rust_warning_at (
      73          312 :               function.get_function_name ().get_locus (), 0,
      74              :               "function is never used: %qs",
      75          312 :               function.get_function_name ().as_string ().c_str ());
      76              :           }
      77              :       }
      78        12556 :   }
      79              : 
      80         1300 :   void visit (HIR::StructStruct &stct) override
      81              :   {
      82         1300 :     HirId hirId = stct.get_mappings ().get_hirid ();
      83          473 :     if (should_warn (hirId) && !stct.get_visibility ().is_public ())
      84              :       {
      85          238 :         bool name_starts_underscore
      86          238 :           = stct.get_identifier ().as_string ().at (0) == '_';
      87          238 :         if (!name_starts_underscore)
      88          215 :           rust_warning_at (stct.get_locus (), 0,
      89              :                            "struct is never constructed: %qs",
      90          430 :                            stct.get_identifier ().as_string ().c_str ());
      91              :       }
      92              :     else
      93              :       {
      94              :         // only warn the unused fields when in unwarned struct.
      95         2467 :         for (auto &field : stct.get_fields ())
      96              :           {
      97         1405 :             HirId field_hir_id = field.get_mappings ().get_hirid ();
      98         2810 :             if (should_warn (field_hir_id)
      99          659 :                 && !field.get_visibility ().is_public ()
     100         1886 :                 && field.get_field_name ().as_string ().at (0) != '_')
     101              :               {
     102          462 :                 rust_warning_at (field.get_locus (), 0,
     103              :                                  "field is never read: %qs",
     104          924 :                                  field.get_field_name ().as_string ().c_str ());
     105              :               }
     106              :           }
     107              :       }
     108         1300 :   }
     109              : 
     110          792 :   void visit (HIR::TupleStruct &stct) override
     111              :   {
     112              :     // only warn tuple struct unconstructed, and ignoring unused field
     113          792 :     HirId hirId = stct.get_mappings ().get_hirid ();
     114           73 :     if (should_warn (hirId) && !stct.get_visibility ().is_public ())
     115              :       {
     116           57 :         rust_warning_at (stct.get_locus (), 0,
     117              :                          "struct is never constructed: %qs",
     118          114 :                          stct.get_identifier ().as_string ().c_str ());
     119              :       }
     120          792 :   }
     121              : 
     122         5307 :   void visit (HIR::ImplBlock &blc) override
     123              :   {
     124         5307 :     if (blc.has_impl_items ())
     125              :       {
     126        12072 :         for (auto &implItem : blc.get_impl_items ())
     127              :           {
     128         7872 :             implItem->accept_vis (*this);
     129              :           }
     130              :       }
     131         5307 :   }
     132              : 
     133         1152 :   void visit (HIR::Module &mod) override
     134              :   {
     135         4830 :     for (auto &item : mod.get_items ())
     136         3678 :       item->accept_vis (*this);
     137         1152 :   }
     138              : 
     139              : private:
     140              :   std::set<HirId> live_symbols;
     141              :   Resolver::Resolver *resolver;
     142              :   Analysis::Mappings &mappings;
     143              : 
     144         4032 :   ScanDeadcode (std::set<HirId> &live_symbols)
     145         4032 :     : live_symbols (live_symbols), resolver (Resolver::Resolver::get ()),
     146         8064 :       mappings (Analysis::Mappings::get ()){};
     147              : 
     148        16053 :   bool should_warn (HirId hirId)
     149              :   {
     150              :     // TODO: There are more condition to check if should warn, i.e visibility,
     151              :     // attributes.
     152        16053 :     return live_symbols.find (hirId) == live_symbols.end ();
     153              :   }
     154              : };
     155              : 
     156              : } // namespace Analysis
     157              : } // namespace Rust
     158              : 
     159              : #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.