LCOV - code coverage report
Current view: top level - gcc/analyzer - pending-diagnostic.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.8 % 98 88
Test Date: 2024-04-20 14:03:02 Functions: 92.9 % 14 13
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Classes for analyzer diagnostics.
       2                 :             :    Copyright (C) 2019-2024 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 "config.h"
      22                 :             : #define INCLUDE_MEMORY
      23                 :             : #include "system.h"
      24                 :             : #include "coretypes.h"
      25                 :             : #include "tree.h"
      26                 :             : #include "intl.h"
      27                 :             : #include "diagnostic.h"
      28                 :             : #include "analyzer/analyzer.h"
      29                 :             : #include "diagnostic-event-id.h"
      30                 :             : #include "analyzer/analyzer-logging.h"
      31                 :             : #include "analyzer/sm.h"
      32                 :             : #include "diagnostic-event-id.h"
      33                 :             : #include "analyzer/sm.h"
      34                 :             : #include "analyzer/pending-diagnostic.h"
      35                 :             : #include "analyzer/diagnostic-manager.h"
      36                 :             : #include "analyzer/call-string.h"
      37                 :             : #include "analyzer/program-point.h"
      38                 :             : #include "analyzer/store.h"
      39                 :             : #include "analyzer/region-model.h"
      40                 :             : #include "cpplib.h"
      41                 :             : #include "digraph.h"
      42                 :             : #include "ordered-hash-map.h"
      43                 :             : #include "cfg.h"
      44                 :             : #include "basic-block.h"
      45                 :             : #include "gimple.h"
      46                 :             : #include "gimple-iterator.h"
      47                 :             : #include "cgraph.h"
      48                 :             : #include "analyzer/supergraph.h"
      49                 :             : #include "analyzer/program-state.h"
      50                 :             : #include "analyzer/exploded-graph.h"
      51                 :             : #include "diagnostic-path.h"
      52                 :             : #include "analyzer/checker-path.h"
      53                 :             : #include "make-unique.h"
      54                 :             : 
      55                 :             : #if ENABLE_ANALYZER
      56                 :             : 
      57                 :             : namespace ana {
      58                 :             : 
      59                 :             : /* struct interesting_t.  */
      60                 :             : 
      61                 :             : /* Mark the creation of REG as being interesting.  */
      62                 :             : 
      63                 :             : void
      64                 :        1488 : interesting_t::add_region_creation (const region *reg)
      65                 :             : {
      66                 :        1488 :   gcc_assert (reg);
      67                 :        1488 :   m_region_creation.safe_push (reg);
      68                 :        1488 : }
      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, "]}");
      83                 :           0 : }
      84                 :             : 
      85                 :             : /* Generate a label_text by printing FMT.
      86                 :             : 
      87                 :             :    Use a clone of the global_dc for formatting callbacks.
      88                 :             : 
      89                 :             :    Use this evdesc::event_desc's m_colorize flag to control colorization
      90                 :             :    (so that e.g. we can disable it for JSON output).  */
      91                 :             : 
      92                 :             : label_text
      93                 :       11556 : evdesc::event_desc::formatted_print (const char *fmt, ...) const
      94                 :             : {
      95                 :       11556 :   pretty_printer *pp = global_dc->printer->clone ();
      96                 :             : 
      97                 :       11556 :   pp_show_color (pp) = m_colorize;
      98                 :             : 
      99                 :       11556 :   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
     100                 :       11556 :   va_list ap;
     101                 :       11556 :   va_start (ap, fmt);
     102                 :       11556 :   text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
     103                 :       11556 :   pp_format (pp, &ti);
     104                 :       11556 :   pp_output_formatted_text (pp);
     105                 :       11556 :   va_end (ap);
     106                 :             : 
     107                 :       11556 :   label_text result = label_text::take (xstrdup (pp_formatted_text (pp)));
     108                 :       11556 :   delete pp;
     109                 :       23112 :   return result;
     110                 :       11556 : }
     111                 :             : 
     112                 :             : /* class diagnostic_emission_context.  */
     113                 :             : 
     114                 :             : /* Get the pending_diagnostic being emitted.  */
     115                 :             : 
     116                 :             : const pending_diagnostic &
     117                 :        4442 : diagnostic_emission_context::get_pending_diagnostic () const
     118                 :             : {
     119                 :        4442 :   return *m_sd.m_d.get ();
     120                 :             : }
     121                 :             : 
     122                 :             : /* Emit a warning, using the rich_location, metadata, and the
     123                 :             :    pending_diagnostic's option.  */
     124                 :             : 
     125                 :             : bool
     126                 :        4259 : diagnostic_emission_context::warn (const char *gmsgid, ...)
     127                 :             : {
     128                 :        4259 :   const pending_diagnostic &pd = get_pending_diagnostic ();
     129                 :        4259 :   auto_diagnostic_group d;
     130                 :        4259 :   va_list ap;
     131                 :        4259 :   va_start (ap, gmsgid);
     132                 :       12777 :   const bool result = emit_diagnostic_valist_meta (DK_WARNING,
     133                 :        4259 :                                                    &m_rich_loc, &m_metadata,
     134                 :        4259 :                                                    pd.get_controlling_option (),
     135                 :             :                                                    gmsgid, &ap);
     136                 :        4259 :   va_end (ap);
     137                 :        8518 :   return result;
     138                 :        4259 : }
     139                 :             : 
     140                 :             : /* Emit a note, using the rich_location and metadata (and the
     141                 :             :    pending_diagnostic's option).  */
     142                 :             : 
     143                 :             : void
     144                 :         183 : diagnostic_emission_context::inform (const char *gmsgid, ...)
     145                 :             : {
     146                 :         183 :   const pending_diagnostic &pd = get_pending_diagnostic ();
     147                 :         183 :   auto_diagnostic_group d;
     148                 :         183 :   va_list ap;
     149                 :         183 :   va_start (ap, gmsgid);
     150                 :         366 :   emit_diagnostic_valist_meta (DK_NOTE,
     151                 :         183 :                                &m_rich_loc, &m_metadata,
     152                 :         183 :                                pd.get_controlling_option (),
     153                 :             :                                gmsgid, &ap);
     154                 :         183 :   va_end (ap);
     155                 :         183 : }
     156                 :             : 
     157                 :             : /* Return true if T1 and T2 are "the same" for the purposes of
     158                 :             :    diagnostic deduplication.  */
     159                 :             : 
     160                 :             : bool
     161                 :      174372 : pending_diagnostic::same_tree_p (tree t1, tree t2)
     162                 :             : {
     163                 :      174372 :   return simple_cst_equal (t1, t2) == 1;
     164                 :             : }
     165                 :             : 
     166                 :             : /* Return true iff IDENT is STR.  */
     167                 :             : 
     168                 :             : static bool
     169                 :       26611 : ht_ident_eq (ht_identifier ident, const char *str)
     170                 :             : {
     171                 :       26611 :   return (strlen (str) == ident.len
     172                 :       26611 :           && 0 == strcmp (str, (const char *)ident.str));
     173                 :             : }
     174                 :             : 
     175                 :             : /* Return true if we should show the expansion location rather than unwind
     176                 :             :    within MACRO.  */
     177                 :             : 
     178                 :             : static bool
     179                 :        5366 : fixup_location_in_macro_p (cpp_hashnode *macro)
     180                 :             : {
     181                 :        5366 :   ht_identifier ident = macro->ident;
     182                 :             : 
     183                 :             :   /* Don't unwind inside "alloca" macro, so that we don't suppress warnings
     184                 :             :      from it (due to being in system headers).  */
     185                 :        5366 :   if (ht_ident_eq (ident, "alloca"))
     186                 :             :     return true;
     187                 :             : 
     188                 :             :   /* Don't unwind inside <stdarg.h> macros, so that we don't suppress warnings
     189                 :             :      from them (due to being in system headers).  */
     190                 :        5326 :   if (ht_ident_eq (ident, "va_start")
     191                 :        5316 :       || ht_ident_eq (ident, "va_copy")
     192                 :        5309 :       || ht_ident_eq (ident, "va_arg")
     193                 :       10620 :       || ht_ident_eq (ident, "va_end"))
     194                 :             :     return true;
     195                 :             :   return false;
     196                 :             : }
     197                 :             : 
     198                 :             : /* Base implementation of pending_diagnostic::fixup_location.
     199                 :             :    Don't unwind inside macros for which fixup_location_in_macro_p is true.  */
     200                 :             : 
     201                 :             : location_t
     202                 :       35348 : pending_diagnostic::fixup_location (location_t loc, bool) const
     203                 :             : {
     204                 :       35348 :   if (linemap_location_from_macro_expansion_p (line_table, loc))
     205                 :             :     {
     206                 :        5366 :       line_map *map
     207                 :        5366 :         = const_cast <line_map *> (linemap_lookup (line_table, loc));
     208                 :        5366 :       const line_map_macro *macro_map = linemap_check_macro (map);
     209                 :        5366 :       if (fixup_location_in_macro_p (macro_map->macro))
     210                 :          78 :         loc = linemap_resolve_location (line_table, loc,
     211                 :             :                                         LRK_MACRO_EXPANSION_POINT, NULL);
     212                 :             :     }
     213                 :       35348 :   return loc;
     214                 :             : }
     215                 :             : 
     216                 :             : /* Base implementation of pending_diagnostic::add_function_entry_event.
     217                 :             :    Add a function_entry_event to EMISSION_PATH.  */
     218                 :             : 
     219                 :             : void
     220                 :        5541 : pending_diagnostic::add_function_entry_event (const exploded_edge &eedge,
     221                 :             :                                               checker_path *emission_path)
     222                 :             : {
     223                 :        5541 :   const exploded_node *dst_node = eedge.m_dest;
     224                 :        5541 :   const program_point &dst_point = dst_node->get_point ();
     225                 :        5541 :   emission_path->add_event (make_unique<function_entry_event> (dst_point));
     226                 :        5541 : }
     227                 :             : 
     228                 :             : /* Base implementation of pending_diagnostic::add_call_event.
     229                 :             :    Add a call_event to EMISSION_PATH.  */
     230                 :             : 
     231                 :             : void
     232                 :        1272 : pending_diagnostic::add_call_event (const exploded_edge &eedge,
     233                 :             :                                     checker_path *emission_path)
     234                 :             : {
     235                 :        1272 :   const exploded_node *src_node = eedge.m_src;
     236                 :        1272 :   const program_point &src_point = src_node->get_point ();
     237                 :        1272 :   const int src_stack_depth = src_point.get_stack_depth ();
     238                 :        1272 :   const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
     239                 :        1272 :   emission_path->add_event
     240                 :        1272 :     (make_unique<call_event> (eedge,
     241                 :        1272 :                               event_loc_info (last_stmt
     242                 :             :                                               ? last_stmt->location
     243                 :             :                                               : UNKNOWN_LOCATION,
     244                 :             :                                               src_point.get_fndecl (),
     245                 :             :                                               src_stack_depth)));
     246                 :        1272 : }
     247                 :             : 
     248                 :             : /* Base implementation of pending_diagnostic::add_region_creation_events.
     249                 :             :    See the comment for class region_creation_event.  */
     250                 :             : 
     251                 :             : void
     252                 :         690 : pending_diagnostic::add_region_creation_events (const region *reg,
     253                 :             :                                                 tree capacity,
     254                 :             :                                                 const event_loc_info &loc_info,
     255                 :             :                                                 checker_path &emission_path)
     256                 :             : {
     257                 :         690 :   emission_path.add_event
     258                 :         690 :     (make_unique<region_creation_event_memory_space> (reg->get_memory_space (),
     259                 :             :                                                       loc_info));
     260                 :             : 
     261                 :         690 :   if (capacity)
     262                 :         412 :     emission_path.add_event
     263                 :         412 :       (make_unique<region_creation_event_capacity> (capacity, loc_info));
     264                 :         690 : }
     265                 :             : 
     266                 :             : /* Base implementation of pending_diagnostic::add_final_event.
     267                 :             :    Add a warning_event to the end of EMISSION_PATH.  */
     268                 :             : 
     269                 :             : void
     270                 :        4246 : pending_diagnostic::add_final_event (const state_machine *sm,
     271                 :             :                                      const exploded_node *enode,
     272                 :             :                                      const gimple *stmt,
     273                 :             :                                      tree var, state_machine::state_t state,
     274                 :             :                                      checker_path *emission_path)
     275                 :             : {
     276                 :        4246 :   emission_path->add_event
     277                 :        4246 :     (make_unique<warning_event>
     278                 :       12738 :      (event_loc_info (get_stmt_location (stmt, enode->get_function ()),
     279                 :        4246 :                       enode->get_function ()->decl,
     280                 :             :                       enode->get_stack_depth ()),
     281                 :             :       enode,
     282                 :             :       sm, var, state));
     283                 :        4246 : }
     284                 :             : 
     285                 :             : } // namespace ana
     286                 :             : 
     287                 :             : #endif /* #if ENABLE_ANALYZER */
        

Generated by: LCOV version 2.1-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.