LCOV - code coverage report
Current view: top level - gcc/analyzer - pending-diagnostic.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 88.4 % 95 84
Test Date: 2026-02-28 14:20:25 Functions: 92.3 % 13 12
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         1328 : interesting_t::add_region_creation (const region *reg)
      56              : {
      57         1328 :   gcc_assert (reg);
      58         1328 :   m_region_creation.safe_push (reg);
      59         1328 : }
      60              : 
      61              : void
      62            0 : interesting_t::dump_to_pp (pretty_printer *pp, bool simple) const
      63              : {
      64            0 :   pp_string (pp, "{ region creation: [");
      65            0 :   unsigned i;
      66            0 :   const region *reg;
      67            0 :   FOR_EACH_VEC_ELT (m_region_creation, i, reg)
      68              :     {
      69            0 :       if (i > 0)
      70            0 :         pp_string (pp, ", ");
      71            0 :       reg->dump_to_pp (pp, simple);
      72              :     }
      73            0 :   pp_string (pp, "]}");
      74            0 : }
      75              : 
      76              : /* class diagnostic_emission_context.  */
      77              : 
      78              : /* Get the pending_diagnostic being emitted.  */
      79              : 
      80              : const pending_diagnostic &
      81         3927 : diagnostic_emission_context::get_pending_diagnostic () const
      82              : {
      83         3927 :   return *m_sd.m_d.get ();
      84              : }
      85              : 
      86              : /* Emit a warning, using the rich_location, metadata, and the
      87              :    pending_diagnostic's option.  */
      88              : 
      89              : bool
      90         3658 : diagnostic_emission_context::warn (const char *gmsgid, ...)
      91              : {
      92         3658 :   auto dc_logger = global_dc->get_logger ();
      93         3658 :   diagnostics::logging::log_function_params
      94         3658 :     (dc_logger, "ana::diagnostic_emission_context::warn")
      95         3658 :     .log_param_string ("gmsgid", gmsgid);
      96         3658 :   diagnostics::logging::auto_inc_depth depth_sentinel (dc_logger);
      97              : 
      98         3658 :   const pending_diagnostic &pd = get_pending_diagnostic ();
      99         3658 :   auto_diagnostic_group d;
     100         3658 :   va_list ap;
     101         3658 :   va_start (ap, gmsgid);
     102        10974 :   const bool result = emit_diagnostic_valist_meta (diagnostics::kind::warning,
     103         3658 :                                                    &m_rich_loc, &m_metadata,
     104         3658 :                                                    pd.get_controlling_option (),
     105              :                                                    gmsgid, &ap);
     106         3658 :   va_end (ap);
     107              : 
     108         3658 :   if (dc_logger)
     109            0 :     dc_logger->log_bool_return ("ana::diagnostic_emission_context::warn",
     110              :                                 result);
     111              : 
     112         7316 :   return result;
     113         3658 : }
     114              : 
     115              : /* Emit a note, using the rich_location and metadata (and the
     116              :    pending_diagnostic's option).  */
     117              : 
     118              : void
     119          269 : diagnostic_emission_context::inform (const char *gmsgid, ...)
     120              : {
     121          269 :   auto dc_logger = global_dc->get_logger ();
     122          269 :   diagnostics::logging::log_function_params
     123          269 :     (dc_logger, "ana::diagnostic_emission_context::inform")
     124          269 :     .log_param_string ("gmsgid", gmsgid);
     125          269 :   diagnostics::logging::auto_inc_depth depth_sentinel (dc_logger);
     126              : 
     127          269 :   const pending_diagnostic &pd = get_pending_diagnostic ();
     128          269 :   auto_diagnostic_group d;
     129          269 :   va_list ap;
     130          269 :   va_start (ap, gmsgid);
     131          807 :   emit_diagnostic_valist_meta (diagnostics::kind::note,
     132          269 :                                &m_rich_loc, &m_metadata,
     133          269 :                                pd.get_controlling_option (),
     134              :                                gmsgid, &ap);
     135          269 :   va_end (ap);
     136          269 : }
     137              : 
     138              : /* Return true if T1 and T2 are "the same" for the purposes of
     139              :    diagnostic deduplication.  */
     140              : 
     141              : bool
     142       164479 : pending_diagnostic::same_tree_p (tree t1, tree t2)
     143              : {
     144       164479 :   return simple_cst_equal (t1, t2) == 1;
     145              : }
     146              : 
     147              : /* Return true iff IDENT is STR.  */
     148              : 
     149              : static bool
     150        21521 : ht_ident_eq (ht_identifier ident, const char *str)
     151              : {
     152        21521 :   return (strlen (str) == ident.len
     153        21521 :           && 0 == strcmp (str, (const char *)ident.str));
     154              : }
     155              : 
     156              : /* Return true if we should show the expansion location rather than unwind
     157              :    within MACRO.  */
     158              : 
     159              : static bool
     160         4341 : fixup_location_in_macro_p (cpp_hashnode *macro)
     161              : {
     162         4341 :   ht_identifier ident = macro->ident;
     163              : 
     164              :   /* Don't unwind inside "alloca" macro, so that we don't suppress warnings
     165              :      from it (due to being in system headers).  */
     166         4341 :   if (ht_ident_eq (ident, "alloca"))
     167              :     return true;
     168              : 
     169              :   /* Don't unwind inside <stdarg.h> macros, so that we don't suppress warnings
     170              :      from them (due to being in system headers).  */
     171         4309 :   if (ht_ident_eq (ident, "va_start")
     172         4299 :       || ht_ident_eq (ident, "va_copy")
     173         4292 :       || ht_ident_eq (ident, "va_arg")
     174         8589 :       || ht_ident_eq (ident, "va_end"))
     175              :     return true;
     176              :   return false;
     177              : }
     178              : 
     179              : /* Base implementation of pending_diagnostic::fixup_location.
     180              :    Don't unwind inside macros for which fixup_location_in_macro_p is true.  */
     181              : 
     182              : location_t
     183        31073 : pending_diagnostic::fixup_location (location_t loc, bool) const
     184              : {
     185        31073 :   if (linemap_location_from_macro_expansion_p (line_table, loc))
     186              :     {
     187         4341 :       line_map *map
     188         4341 :         = const_cast <line_map *> (linemap_lookup (line_table, loc));
     189         4341 :       const line_map_macro *macro_map = linemap_check_macro (map);
     190         4341 :       if (fixup_location_in_macro_p (macro_map->macro))
     191           67 :         loc = linemap_resolve_location (line_table, loc,
     192              :                                         LRK_MACRO_EXPANSION_POINT, nullptr);
     193              :     }
     194        31073 :   return loc;
     195              : }
     196              : 
     197              : /* Base implementation of pending_diagnostic::add_function_entry_event.
     198              :    Add a function_entry_event to EMISSION_PATH.  */
     199              : 
     200              : void
     201         4810 : pending_diagnostic::add_function_entry_event (const exploded_edge &eedge,
     202              :                                               checker_path *emission_path)
     203              : {
     204         4810 :   const exploded_node *dst_node = eedge.m_dest;
     205         4810 :   const program_point &dst_point = dst_node->get_point ();
     206         4810 :   const program_state &dst_state = dst_node->get_state ();
     207         4810 :   emission_path->add_event
     208         4810 :     (std::make_unique<function_entry_event> (dst_point,
     209              :                                              dst_state));
     210         4810 : }
     211              : 
     212              : /* Base implementation of pending_diagnostic::add_call_event.
     213              :    Add a call_event to EMISSION_PATH.  */
     214              : 
     215              : void
     216         1159 : pending_diagnostic::add_call_event (const exploded_edge &eedge,
     217              :                                     const gcall &,
     218              :                                     checker_path &emission_path)
     219              : {
     220         1159 :   emission_path.add_event
     221         1159 :     (std::make_unique<call_event> (eedge,
     222         1159 :                                    event_loc_info (eedge.m_src)));
     223         1159 : }
     224              : 
     225              : /* Base implementation of pending_diagnostic::add_region_creation_events.
     226              :    See the comment for class region_creation_event.  */
     227              : 
     228              : void
     229          599 : pending_diagnostic::add_region_creation_events (const region *reg,
     230              :                                                 tree capacity,
     231              :                                                 const event_loc_info &loc_info,
     232              :                                                 checker_path &emission_path)
     233              : {
     234          599 :   emission_path.add_event
     235          599 :     (std::make_unique<region_creation_event_memory_space>
     236          599 :        (reg->get_memory_space (),
     237              :         loc_info));
     238              : 
     239          599 :   if (capacity)
     240          370 :     emission_path.add_event
     241          370 :       (std::make_unique<region_creation_event_capacity> (capacity, loc_info));
     242          599 : }
     243              : 
     244              : /* Base implementation of pending_diagnostic::add_final_event.
     245              :    Add a warning_event to the end of EMISSION_PATH.  */
     246              : 
     247              : void
     248         3753 : pending_diagnostic::add_final_event (const state_machine *sm,
     249              :                                      const exploded_node *enode,
     250              :                                      const event_loc_info &loc_info,
     251              :                                      tree var, state_machine::state_t state,
     252              :                                      checker_path *emission_path)
     253              : {
     254         3753 :   emission_path->add_event
     255         3753 :     (std::make_unique<warning_event>
     256         3753 :      (loc_info,
     257              :       enode,
     258              :       sm, var, state,
     259         3753 :       get_final_state ()));
     260         3753 : }
     261              : 
     262              : } // namespace ana
     263              : 
     264              : #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.