LCOV - code coverage report
Current view: top level - gcc/analyzer - sm.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 70.5 % 78 55
Test Date: 2026-02-28 14:20:25 Functions: 80.0 % 15 12
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Modeling API uses and misuses via state machines.
       2              :    Copyright (C) 2019-2026 Free Software Foundation, Inc.
       3              :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it
       8              : under the terms of the GNU General Public License as published by
       9              : the Free Software Foundation; either version 3, or (at your option)
      10              : any later version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but
      13              : WITHOUT ANY WARRANTY; without even the implied warranty of
      14              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15              : General Public License for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #define INCLUDE_LIST
      22              : #include "analyzer/common.h"
      23              : 
      24              : #include "tree-diagnostic.h"
      25              : 
      26              : #include "analyzer/analyzer-logging.h"
      27              : #include "analyzer/sm.h"
      28              : #include "analyzer/call-string.h"
      29              : #include "analyzer/program-point.h"
      30              : #include "analyzer/store.h"
      31              : #include "analyzer/svalue.h"
      32              : #include "analyzer/program-state.h"
      33              : #include "analyzer/pending-diagnostic.h"
      34              : 
      35              : #if ENABLE_ANALYZER
      36              : 
      37              : namespace ana {
      38              : 
      39              : /* Return true if VAR has pointer or reference type.  */
      40              : 
      41              : bool
      42        53472 : any_pointer_p (tree var)
      43              : {
      44        53472 :   return POINTER_TYPE_P (TREE_TYPE (var));
      45              : }
      46              : 
      47              : /* Return true if SVAL has pointer or reference type.  */
      48              : 
      49              : bool
      50        58740 : any_pointer_p (const svalue *sval)
      51              : {
      52        58740 :   if (!sval->get_type ())
      53              :     return false;
      54        58740 :   return POINTER_TYPE_P (sval->get_type ());
      55              : }
      56              : 
      57              : /* class state_machine::state.  */
      58              : 
      59              : /* Base implementation of dump_to_pp vfunc.  */
      60              : 
      61              : void
      62          703 : state_machine::state::dump_to_pp (pretty_printer *pp) const
      63              : {
      64          703 :   pp_string (pp, m_name);
      65          703 : }
      66              : 
      67              : /* Return a new json::string describing the state.  */
      68              : 
      69              : std::unique_ptr<json::value>
      70           16 : state_machine::state::to_json () const
      71              : {
      72           16 :   pretty_printer pp;
      73           16 :   pp_format_decoder (&pp) = default_tree_printer;
      74           16 :   dump_to_pp (&pp);
      75           16 :   return std::make_unique<json::string> (pp_formatted_text (&pp));
      76           16 : }
      77              : 
      78              : /* class state_machine.  */
      79              : 
      80              : /* state_machine's ctor.  */
      81              : 
      82        23666 : state_machine::state_machine (const char *name, logger *logger)
      83        23666 : : log_user (logger), m_name (name), m_next_state_id (0),
      84        23666 :   m_start (add_state ("start"))
      85              : {
      86        23666 : }
      87              : 
      88              : /* Add a state with name NAME to this state_machine.
      89              :    The string is required to outlive the state_machine.
      90              : 
      91              :    Return the state_t for the new state.  */
      92              : 
      93              : state_machine::state_t
      94       138494 : state_machine::add_state (const char *name)
      95              : {
      96       138494 :   state *s = new state (name, alloc_state_id ());
      97       138494 :   m_states.safe_push (s);
      98       138494 :   return s;
      99              : }
     100              : 
     101              : /* Get the state with name NAME, which must exist.
     102              :    This is purely intended for use in selftests.  */
     103              : 
     104              : state_machine::state_t
     105          188 : state_machine::get_state_by_name (const char *name) const
     106              : {
     107          188 :   unsigned i;
     108          188 :   state *s;
     109          376 :   FOR_EACH_VEC_ELT (m_states, i, s)
     110          376 :     if (!strcmp (name, s->get_name ()))
     111          188 :       return s;
     112              :   /* Name not found.  */
     113            0 :   gcc_unreachable ();
     114              : }
     115              : 
     116              : /* Base implementation of state_machine::on_leak.  */
     117              : 
     118              : std::unique_ptr<pending_diagnostic>
     119          249 : state_machine::on_leak (tree var ATTRIBUTE_UNUSED,
     120              :                         const program_state *old_state ATTRIBUTE_UNUSED,
     121              :                         const program_state *new_state ATTRIBUTE_UNUSED) const
     122              : {
     123          249 :   return nullptr;
     124              : }
     125              : 
     126              : /* Dump a multiline representation of this state machine to PP.  */
     127              : 
     128              : void
     129            0 : state_machine::dump_to_pp (pretty_printer *pp) const
     130              : {
     131            0 :   unsigned i;
     132            0 :   state *s;
     133            0 :   FOR_EACH_VEC_ELT (m_states, i, s)
     134              :     {
     135            0 :       pp_printf (pp, "  state %i: ", i);
     136            0 :       s->dump_to_pp (pp);
     137            0 :       pp_newline (pp);
     138              :     }
     139            0 : }
     140              : 
     141              : /* Return a new json::object of the form
     142              :    {"name" : str,
     143              :     "states" : [str]}.  */
     144              : 
     145              : std::unique_ptr<json::object>
     146            0 : state_machine::to_json () const
     147              : {
     148            0 :   auto sm_obj = std::make_unique<json::object> ();
     149              : 
     150            0 :   sm_obj->set_string ("name", m_name);
     151            0 :   {
     152            0 :     auto states_arr = std::make_unique<json::array> ();
     153            0 :     unsigned i;
     154            0 :     state *s;
     155            0 :     FOR_EACH_VEC_ELT (m_states, i, s)
     156            0 :       states_arr->append (s->to_json ());
     157            0 :     sm_obj->set ("states", std::move (states_arr));
     158            0 :   }
     159              : 
     160            0 :   return sm_obj;
     161              : }
     162              : 
     163              : void
     164            0 : state_machine::add_state_to_state_graph (analyzer_state_graph &/*out_state_graph*/,
     165              :                                          const svalue &/*sval*/,
     166              :                                          state_machine::state_t /*state*/) const
     167              : {
     168              :   // no-op
     169            0 : }
     170              : 
     171              : void
     172          196 : state_machine::add_global_state_to_state_graph (analyzer_state_graph &/*out_state_graph*/,
     173              :                                                 state_machine::state_t /*state*/) const
     174              : {
     175              :   // no-op
     176          196 : }
     177              : 
     178              : /* class sm_context.  */
     179              : 
     180              : const region_model *
     181       272937 : sm_context::get_old_region_model () const
     182              : {
     183       272937 :   if (const program_state *old_state = get_old_program_state ())
     184       272937 :     return old_state->m_region_model;
     185              :   else
     186              :     return nullptr;
     187              : }
     188              : 
     189              : /* Create instances of the various state machines, each using LOGGER,
     190              :    returning a vector of them.  */
     191              : 
     192              : std::vector<std::unique_ptr<state_machine>>
     193         3377 : make_checkers (logger *logger)
     194              : {
     195              :   /* Start with a list so that we can filter it.  */
     196         3377 :   std::list<std::unique_ptr<state_machine>> out;
     197         3377 :   out.push_back (make_malloc_state_machine (logger));
     198         3377 :   out.push_back (make_fileptr_state_machine (logger));
     199         3377 :   out.push_back (make_fd_state_machine (logger));
     200         3377 :   out.push_back (make_taint_state_machine (logger));
     201         3377 :   out.push_back (make_sensitive_state_machine (logger));
     202         3377 :   out.push_back (make_signal_state_machine (logger));
     203         3377 :   out.push_back (make_va_list_state_machine (logger));
     204              : 
     205              :   /* We only attempt to run the pattern tests if it might have been manually
     206              :      enabled (for DejaGnu purposes).  */
     207         3377 :   if (flag_analyzer_checker)
     208           10 :     out.push_back (make_pattern_test_state_machine (logger));
     209              : 
     210         3377 :   if (flag_analyzer_checker)
     211              :     {
     212           10 :       out.remove_if ([] (auto &sm)
     213              :                      {
     214           80 :                        return 0 != strcmp (flag_analyzer_checker,
     215           80 :                                            sm->get_name ());
     216              :                      });
     217              :     }
     218              : 
     219         3377 :   std::vector<std::unique_ptr<state_machine>> out_vec;
     220        26956 :   for (auto &iter: out)
     221        23579 :     out_vec.push_back (std::move (iter));
     222              : 
     223         3377 :   return out_vec;
     224         3377 : }
     225              : 
     226              : } // namespace ana
     227              : 
     228              : #endif /* #if ENABLE_ANALYZER */
        

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.