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 % 56 56
Test Date: 2026-02-28 14:20:25 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         4028 : class ScanDeadcode : public MarkLiveBase
      39              : {
      40              :   using Rust::Analysis::MarkLiveBase::visit;
      41              : 
      42              : public:
      43         4028 :   static void Scan (HIR::Crate &crate)
      44              :   {
      45         4028 :     std::set<HirId> live_symbols = Analysis::MarkLive::Analysis (crate);
      46         4028 :     ScanDeadcode sdc (live_symbols);
      47        20761 :     for (auto &it : crate.get_items ())
      48        16733 :       it.get ()->accept_vis (sdc);
      49         4028 :   };
      50              : 
      51        12549 :   void visit (HIR::Function &function) override
      52              :   {
      53        12549 :     HirId hirId = function.get_mappings ().get_hirid ();
      54         6203 :     if (should_warn (hirId) && !function.get_visibility ().is_public ())
      55              :       {
      56         3959 :         if (mappings.is_impl_item (hirId))
      57              :           {
      58         3802 :             HIR::ImplBlock *implBlock = mappings.lookup_associated_impl (hirId);
      59         3802 :             if (!implBlock->has_trait_ref ())
      60              :               {
      61           89 :                 rust_warning_at (
      62          178 :                   function.get_function_name ().get_locus (), 0,
      63              :                   "associated function is never used: %qs",
      64          178 :                   function.get_function_name ().as_string ().c_str ());
      65              :               }
      66              :           }
      67              :         else
      68              :           {
      69          157 :             rust_warning_at (
      70          314 :               function.get_function_name ().get_locus (), 0,
      71              :               "function is never used: %qs",
      72          314 :               function.get_function_name ().as_string ().c_str ());
      73              :           }
      74              :       }
      75        12549 :   }
      76              : 
      77         1300 :   void visit (HIR::StructStruct &stct) override
      78              :   {
      79         1300 :     HirId hirId = stct.get_mappings ().get_hirid ();
      80          473 :     if (should_warn (hirId) && !stct.get_visibility ().is_public ())
      81              :       {
      82          238 :         bool name_starts_underscore
      83          238 :           = stct.get_identifier ().as_string ().at (0) == '_';
      84          238 :         if (!name_starts_underscore)
      85          215 :           rust_warning_at (stct.get_locus (), 0,
      86              :                            "struct is never constructed: %qs",
      87          430 :                            stct.get_identifier ().as_string ().c_str ());
      88              :       }
      89              :     else
      90              :       {
      91              :         // only warn the unused fields when in unwarned struct.
      92         2467 :         for (auto &field : stct.get_fields ())
      93              :           {
      94         1405 :             HirId field_hir_id = field.get_mappings ().get_hirid ();
      95         2810 :             if (should_warn (field_hir_id)
      96          659 :                 && !field.get_visibility ().is_public ()
      97         1886 :                 && field.get_field_name ().as_string ().at (0) != '_')
      98              :               {
      99          462 :                 rust_warning_at (field.get_locus (), 0,
     100              :                                  "field is never read: %qs",
     101          924 :                                  field.get_field_name ().as_string ().c_str ());
     102              :               }
     103              :           }
     104              :       }
     105         1300 :   }
     106              : 
     107          792 :   void visit (HIR::TupleStruct &stct) override
     108              :   {
     109              :     // only warn tuple struct unconstructed, and ignoring unused field
     110          792 :     HirId hirId = stct.get_mappings ().get_hirid ();
     111           73 :     if (should_warn (hirId) && !stct.get_visibility ().is_public ())
     112              :       {
     113           57 :         rust_warning_at (stct.get_locus (), 0,
     114              :                          "struct is never constructed: %qs",
     115          114 :                          stct.get_identifier ().as_string ().c_str ());
     116              :       }
     117          792 :   }
     118              : 
     119         5307 :   void visit (HIR::ImplBlock &blc) override
     120              :   {
     121         5307 :     if (blc.has_impl_items ())
     122              :       {
     123        12072 :         for (auto &implItem : blc.get_impl_items ())
     124              :           {
     125         7872 :             implItem->accept_vis (*this);
     126              :           }
     127              :       }
     128         5307 :   }
     129              : 
     130         1152 :   void visit (HIR::Module &mod) override
     131              :   {
     132         4830 :     for (auto &item : mod.get_items ())
     133         3678 :       item->accept_vis (*this);
     134         1152 :   }
     135              : 
     136              : private:
     137              :   std::set<HirId> live_symbols;
     138              :   Resolver::Resolver *resolver;
     139              :   Analysis::Mappings &mappings;
     140              : 
     141         4028 :   ScanDeadcode (std::set<HirId> &live_symbols)
     142         4028 :     : live_symbols (live_symbols), resolver (Resolver::Resolver::get ()),
     143         8056 :       mappings (Analysis::Mappings::get ()){};
     144              : 
     145        16046 :   bool should_warn (HirId hirId)
     146              :   {
     147              :     // TODO: There are more condition to check if should warn, i.e visibility,
     148              :     // attributes.
     149        16046 :     return live_symbols.find (hirId) == live_symbols.end ();
     150              :   }
     151              : };
     152              : 
     153              : } // namespace Analysis
     154              : } // namespace Rust
     155              : 
     156              : #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.