LCOV - code coverage report
Current view: top level - gcc/analyzer - pending-diagnostic.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 84.0 % 106 89
Test Date: 2026-05-11 19:44:49 Functions: 92.9 % 14 13
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Classes for analyzer diagnostics.
       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              : #include "analyzer/common.h"
      22              : 
      23              : #include "diagnostics/event-id.h"
      24              : #include "diagnostics/logging.h"
      25              : #include "cpplib.h"
      26              : #include "digraph.h"
      27              : #include "ordered-hash-map.h"
      28              : #include "cfg.h"
      29              : #include "gimple-iterator.h"
      30              : #include "cgraph.h"
      31              : 
      32              : #include "analyzer/analyzer-logging.h"
      33              : #include "analyzer/sm.h"
      34              : #include "analyzer/sm.h"
      35              : #include "analyzer/pending-diagnostic.h"
      36              : #include "analyzer/diagnostic-manager.h"
      37              : #include "analyzer/call-string.h"
      38              : #include "analyzer/program-point.h"
      39              : #include "analyzer/store.h"
      40              : #include "analyzer/region-model.h"
      41              : #include "analyzer/supergraph.h"
      42              : #include "analyzer/program-state.h"
      43              : #include "analyzer/exploded-graph.h"
      44              : #include "analyzer/checker-path.h"
      45              : 
      46              : #if ENABLE_ANALYZER
      47              : 
      48              : namespace ana {
      49              : 
      50              : /* struct interesting_t.  */
      51              : 
      52              : /* Mark the creation of REG as being interesting.  */
      53              : 
      54              : void
      55         2670 : interesting_t::add_region_creation (const region *reg)
      56              : {
      57         2670 :   gcc_assert (reg);
      58         2670 :   m_region_creation.safe_push (reg);
      59         2670 : }
      60              : 
      61              : /* Mark the value read from REG as being interesting.  */
      62              : 
      63              : void
      64         1198 : interesting_t::add_read_region (const region *reg, std::string debug_desc)
      65              : {
      66         1198 :   gcc_assert (reg);
      67         1198 :   m_read_regions.push_back (diagnostic_state (std::move (debug_desc), reg));
      68         1198 : }
      69              : 
      70              : void
      71            0 : interesting_t::dump_to_pp (pretty_printer *pp, bool simple) const
      72              : {
      73            0 :   pp_string (pp, "{ region creation: [");
      74            0 :   unsigned i;
      75            0 :   const region *reg;
      76            0 :   FOR_EACH_VEC_ELT (m_region_creation, i, reg)
      77              :     {
      78            0 :       if (i > 0)
      79            0 :         pp_string (pp, ", ");
      80            0 :       reg->dump_to_pp (pp, simple);
      81              :     }
      82            0 :   pp_string (pp, "], read regions: [");
      83            0 :   for (i = 0; i < m_read_regions.size (); ++i)
      84              :     {
      85            0 :       auto &ann = m_read_regions[i];
      86            0 :       if (i > 0)
      87            0 :         pp_string (pp, ", ");
      88            0 :       ann.dump_to_pp (pp);
      89              :     }
      90            0 :   pp_string (pp, "]}");
      91            0 : }
      92              : 
      93              : /* class diagnostic_emission_context.  */
      94              : 
      95              : /* Get the pending_diagnostic being emitted.  */
      96              : 
      97              : const pending_diagnostic &
      98         4096 : diagnostic_emission_context::get_pending_diagnostic () const
      99              : {
     100         4096 :   return *m_sd.m_d.get ();
     101              : }
     102              : 
     103              : /* Emit a warning, using the rich_location, metadata, and the
     104              :    pending_diagnostic's option.  */
     105              : 
     106              : bool
     107         3827 : diagnostic_emission_context::warn (const char *gmsgid, ...)
     108              : {
     109         3827 :   auto dc_logger = global_dc->get_logger ();
     110         3827 :   diagnostics::logging::log_function_params
     111         3827 :     (dc_logger, "ana::diagnostic_emission_context::warn")
     112         3827 :     .log_param_string ("gmsgid", gmsgid);
     113         3827 :   diagnostics::logging::auto_inc_depth depth_sentinel (dc_logger);
     114              : 
     115         3827 :   const pending_diagnostic &pd = get_pending_diagnostic ();
     116         3827 :   auto_diagnostic_group d;
     117         3827 :   va_list ap;
     118         3827 :   va_start (ap, gmsgid);
     119        11481 :   const bool result = emit_diagnostic_valist_meta (diagnostics::kind::warning,
     120         3827 :                                                    &m_rich_loc, &m_metadata,
     121         3827 :                                                    pd.get_controlling_option (),
     122              :                                                    gmsgid, &ap);
     123         3827 :   va_end (ap);
     124              : 
     125         3827 :   if (dc_logger)
     126            0 :     dc_logger->log_bool_return ("ana::diagnostic_emission_context::warn",
     127              :                                 result);
     128              : 
     129         7654 :   return result;
     130         3827 : }
     131              : 
     132              : /* Emit a note, using the rich_location and metadata (and the
     133              :    pending_diagnostic's option).  */
     134              : 
     135              : void
     136          269 : diagnostic_emission_context::inform (const char *gmsgid, ...)
     137              : {
     138          269 :   auto dc_logger = global_dc->get_logger ();
     139          269 :   diagnostics::logging::log_function_params
     140          269 :     (dc_logger, "ana::diagnostic_emission_context::inform")
     141          269 :     .log_param_string ("gmsgid", gmsgid);
     142          269 :   diagnostics::logging::auto_inc_depth depth_sentinel (dc_logger);
     143              : 
     144          269 :   const pending_diagnostic &pd = get_pending_diagnostic ();
     145          269 :   auto_diagnostic_group d;
     146          269 :   va_list ap;
     147          269 :   va_start (ap, gmsgid);
     148          807 :   emit_diagnostic_valist_meta (diagnostics::kind::note,
     149          269 :                                &m_rich_loc, &m_metadata,
     150          269 :                                pd.get_controlling_option (),
     151              :                                gmsgid, &ap);
     152          269 :   va_end (ap);
     153          269 : }
     154              : 
     155              : /* Return true if T1 and T2 are "the same" for the purposes of
     156              :    diagnostic deduplication.  */
     157              : 
     158              : bool
     159       165652 : pending_diagnostic::same_tree_p (tree t1, tree t2)
     160              : {
     161       165652 :   return simple_cst_equal (t1, t2) == 1;
     162              : }
     163              : 
     164              : /* Return true iff IDENT is STR.  */
     165              : 
     166              : static bool
     167        21521 : ht_ident_eq (ht_identifier ident, const char *str)
     168              : {
     169        21521 :   return (strlen (str) == ident.len
     170        21521 :           && 0 == strcmp (str, (const char *)ident.str));
     171              : }
     172              : 
     173              : /* Return true if we should show the expansion location rather than unwind
     174              :    within MACRO.  */
     175              : 
     176              : static bool
     177         4341 : fixup_location_in_macro_p (cpp_hashnode *macro)
     178              : {
     179         4341 :   ht_identifier ident = macro->ident;
     180              : 
     181              :   /* Don't unwind inside "alloca" macro, so that we don't suppress warnings
     182              :      from it (due to being in system headers).  */
     183         4341 :   if (ht_ident_eq (ident, "alloca"))
     184              :     return true;
     185              : 
     186              :   /* Don't unwind inside <stdarg.h> macros, so that we don't suppress warnings
     187              :      from them (due to being in system headers).  */
     188         4309 :   if (ht_ident_eq (ident, "va_start")
     189         4299 :       || ht_ident_eq (ident, "va_copy")
     190         4292 :       || ht_ident_eq (ident, "va_arg")
     191         8589 :       || ht_ident_eq (ident, "va_end"))
     192              :     return true;
     193              :   return false;
     194              : }
     195              : 
     196              : /* Base implementation of pending_diagnostic::fixup_location.
     197              :    Don't unwind inside macros for which fixup_location_in_macro_p is true.  */
     198              : 
     199              : location_t
     200        32135 : pending_diagnostic::fixup_location (location_t loc, bool) const
     201              : {
     202        32135 :   if (linemap_location_from_macro_expansion_p (line_table, loc))
     203              :     {
     204         4341 :       line_map *map
     205         4341 :         = const_cast <line_map *> (linemap_lookup (line_table, loc));
     206         4341 :       const line_map_macro *macro_map = linemap_check_macro (map);
     207         4341 :       if (fixup_location_in_macro_p (macro_map->macro))
     208           67 :         loc = linemap_resolve_location (line_table, loc,
     209              :                                         LRK_MACRO_EXPANSION_POINT, nullptr);
     210              :     }
     211        32135 :   return loc;
     212              : }
     213              : 
     214              : /* Base implementation of pending_diagnostic::add_function_entry_event.
     215              :    Add a function_entry_event to EMISSION_PATH.  */
     216              : 
     217              : void
     218         4971 : pending_diagnostic::add_function_entry_event (const exploded_edge &eedge,
     219              :                                               checker_path *emission_path,
     220              :                                               const state_transition_at_call *state_trans)
     221              : {
     222         4971 :   const exploded_node *dst_node = eedge.m_dest;
     223         4971 :   const program_point &dst_point = dst_node->get_point ();
     224         4971 :   const program_state &dst_state = dst_node->get_state ();
     225              : 
     226              :   /* If we have STATE_TRANS with a specific param, put the event on
     227              :      that parameter, otherwise put in on the function name.  */
     228         4971 :   auto loc_info {event_loc_info_for_function_entry (dst_point, state_trans)};
     229              : 
     230         4971 :   emission_path->add_event
     231         4971 :     (std::make_unique<function_entry_event> (loc_info,
     232              :                                              dst_state,
     233              :                                              state_trans));
     234         4971 : }
     235              : 
     236              : /* Base implementation of pending_diagnostic::add_call_event.
     237              :    Add a call_event to EMISSION_PATH.  */
     238              : 
     239              : void
     240         1207 : pending_diagnostic::add_call_event (const exploded_edge &eedge,
     241              :                                     const gcall &,
     242              :                                     checker_path &emission_path,
     243              :                                     const state_transition_at_call *state_trans)
     244              : {
     245         1207 :   emission_path.add_event
     246         1207 :     (std::make_unique<call_event> (eedge,
     247         1207 :                                    event_loc_info (eedge.m_src),
     248              :                                    state_trans));
     249         1207 : }
     250              : 
     251              : /* Base implementation of pending_diagnostic::add_region_creation_events.
     252              :    See the comment for class region_creation_event.  */
     253              : 
     254              : void
     255          601 : pending_diagnostic::add_region_creation_events (const region *reg,
     256              :                                                 tree capacity,
     257              :                                                 const event_loc_info &loc_info,
     258              :                                                 checker_path &emission_path)
     259              : {
     260          601 :   emission_path.add_event
     261          601 :     (std::make_unique<region_creation_event_memory_space>
     262          601 :        (reg->get_memory_space (),
     263              :         loc_info));
     264              : 
     265          601 :   if (capacity)
     266          371 :     emission_path.add_event
     267          371 :       (std::make_unique<region_creation_event_capacity> (capacity, loc_info));
     268          601 : }
     269              : 
     270              : /* Base implementation of pending_diagnostic::add_final_event.
     271              :    Add a warning_event to the end of EMISSION_PATH.  */
     272              : 
     273              : void
     274         3923 : pending_diagnostic::add_final_event (const state_machine *sm,
     275              :                                      const exploded_node *enode,
     276              :                                      const event_loc_info &loc_info,
     277              :                                      tree var, state_machine::state_t state,
     278              :                                      checker_path *emission_path)
     279              : {
     280         3923 :   emission_path->add_event
     281         3923 :     (std::make_unique<warning_event>
     282         3923 :      (loc_info,
     283              :       enode,
     284              :       sm, var, state,
     285         3923 :       get_final_state ()));
     286         3923 : }
     287              : 
     288              : } // namespace ana
     289              : 
     290              : #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.