LCOV - code coverage report
Current view: top level - gcc/diagnostics - paths.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 75.5 % 102 77
Test Date: 2026-02-28 14:20:25 Functions: 77.8 % 9 7
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Paths through the code associated with a diagnostic.
       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 under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : 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_ALGORITHM
      23              : #define INCLUDE_MAP
      24              : #define INCLUDE_STRING
      25              : #define INCLUDE_VECTOR
      26              : #include "system.h"
      27              : #include "coretypes.h"
      28              : #include "diagnostics/paths.h"
      29              : #include "diagnostics/state-graphs.h"
      30              : 
      31              : /* Disable warnings about missing quoting in GCC diagnostics for the print
      32              :    calls below.  */
      33              : #if __GNUC__ >= 10
      34              : #  pragma GCC diagnostic push
      35              : #  pragma GCC diagnostic ignored "-Wformat-diag"
      36              : #endif
      37              : 
      38              : using namespace diagnostics;
      39              : using namespace diagnostics::paths;
      40              : 
      41              : /* class diagnostics::paths::event.  */
      42              : 
      43              : /* struct event::meaning.  */
      44              : 
      45              : void
      46          144 : event::meaning::dump_to_pp (pretty_printer *pp) const
      47              : {
      48          144 :   bool need_comma = false;
      49          144 :   pp_character (pp, '{');
      50          144 :   if (const char *verb_str = maybe_get_verb_str (m_verb))
      51              :     {
      52          112 :       pp_printf (pp, "verb: %qs", verb_str);
      53          112 :       need_comma = true;
      54              :     }
      55          144 :   if (const char *noun_str = maybe_get_noun_str (m_noun))
      56              :     {
      57          112 :       if (need_comma)
      58          112 :         pp_string (pp, ", ");
      59          112 :       pp_printf (pp, "noun: %qs", noun_str);
      60          112 :       need_comma = true;
      61              :     }
      62          144 :   if (const char *property_str = maybe_get_property_str (m_property))
      63              :     {
      64            0 :       if (need_comma)
      65            0 :         pp_string (pp, ", ");
      66            0 :       pp_printf (pp, "property: %qs", property_str);
      67            0 :       need_comma = true;
      68              :     }
      69          144 :   pp_character (pp, '}');
      70          144 : }
      71              : 
      72              : /* Get a string (or nullptr) for V suitable for use within a SARIF
      73              :    threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
      74              : 
      75              : const char *
      76          286 : event::meaning::maybe_get_verb_str (enum verb v)
      77              : {
      78          286 :   switch (v)
      79              :     {
      80            0 :     default:
      81            0 :       gcc_unreachable ();
      82              :     case verb::unknown:
      83              :       return nullptr;
      84           81 :     case verb::acquire:
      85           81 :       return "acquire";
      86           56 :     case verb::release:
      87           56 :       return "release";
      88           21 :     case verb::enter:
      89           21 :       return "enter";
      90            0 :     case verb::exit:
      91            0 :       return "exit";
      92           13 :     case verb::call:
      93           13 :       return "call";
      94            3 :     case verb::return_:
      95            3 :       return "return";
      96           30 :     case verb::branch:
      97           30 :       return "branch";
      98           32 :     case verb::danger:
      99           32 :       return "danger";
     100              : 
     101              :     /* Special control flow operations.
     102              : 
     103              :        These are not part of SARIF v2.1.0 section 3.38.8, but the
     104              :        spec allows other values; see
     105              :        https://github.com/oasis-tcs/sarif-spec/issues/735  */
     106            6 :     case verb::throw_:
     107            6 :       return "throw";
     108            6 :     case verb::catch_:
     109            6 :       return "catch";
     110            3 :     case verb::unwind_:
     111            3 :       return "unwind";
     112            1 :     case verb::setjmp_:
     113            1 :       return "setjmp";
     114            2 :     case verb::longjmp_:
     115            2 :       return "longjmp";
     116              :     }
     117              : }
     118              : 
     119              : /* Get a string (or nullptr) for N suitable for use within a SARIF
     120              :    threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
     121              : 
     122              : const char *
     123          286 : event::meaning::maybe_get_noun_str (enum noun n)
     124              : {
     125          286 :   switch (n)
     126              :     {
     127            0 :     default:
     128            0 :       gcc_unreachable ();
     129              :     case noun::unknown:
     130              :       return nullptr;
     131            0 :     case noun::taint:
     132            0 :       return "taint";
     133            0 :     case noun::sensitive:
     134            0 :       return "sensitive";
     135           37 :     case noun::function:
     136           37 :       return "function";
     137            0 :     case noun::lock:
     138            0 :       return "lock";
     139           41 :     case noun::memory:
     140           41 :       return "memory";
     141           96 :     case noun::resource:
     142           96 :       return "resource";
     143              :     }
     144              : }
     145              : 
     146              : /* Get a string (or nullptr) for P suitable for use within a SARIF
     147              :    threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8).  */
     148              : 
     149              : const char *
     150          286 : event::meaning::maybe_get_property_str (enum property p)
     151              : {
     152          286 :   switch (p)
     153              :     {
     154            0 :     default:
     155            0 :       gcc_unreachable ();
     156              :     case property::unknown:
     157              :       return nullptr;
     158           16 :     case property::true_:
     159           16 :       return "true";
     160           14 :     case property::false_:
     161           14 :       return "false";
     162              :     }
     163              : }
     164              : 
     165              : /* Generate a label_text containing the description of this event
     166              :    (for debugging/logging purposes).  */
     167              : 
     168              : label_text
     169           16 : event::get_desc (pretty_printer &ref_pp) const
     170              : {
     171           16 :   auto pp = ref_pp.clone ();
     172           16 :   pp_show_color (pp.get ()) = false;
     173           16 :   print_desc (*pp.get ());
     174           16 :   return label_text::take (xstrdup (pp_formatted_text (pp.get ())));
     175           16 : }
     176              : 
     177              : // Base implementation of event::maybe_make_diagnostic_state_graph
     178              : 
     179              : std::unique_ptr<digraphs::digraph>
     180            0 : event::maybe_make_diagnostic_state_graph (bool) const
     181              : {
     182              :   // Don't attempt to make a state graph:
     183            0 :   return nullptr;
     184              : }
     185              : 
     186              : /* class diagnostics::paths::path.  */
     187              : 
     188              : /* Subroutine of path::interprocedural_p.
     189              :    Look for the first event in this path that is within a function
     190              :    i.e. has a non-null logical location for which function_p is true.
     191              :    If found, write its index to *OUT_IDX and return true.
     192              :    Otherwise return false.  */
     193              : 
     194              : bool
     195         4019 : path::get_first_event_in_a_function (unsigned *out_idx) const
     196              : {
     197         4019 :   const unsigned num = num_events ();
     198         4157 :   for (unsigned i = 0; i < num; i++)
     199              :     {
     200         4061 :       const event &event = get_event (i);
     201         4061 :       if (logical_locations::key logical_loc = event.get_logical_location ())
     202         3923 :         if (m_logical_loc_mgr.function_p (logical_loc))
     203              :           {
     204         3923 :             *out_idx = i;
     205         3923 :             return true;
     206              :           }
     207              :     }
     208              :   return false;
     209              : }
     210              : 
     211              : /* Return true if the events in this path involve more than one
     212              :    function, or false if it is purely intraprocedural.  */
     213              : 
     214              : bool
     215         4019 : path::interprocedural_p () const
     216              : {
     217              :   /* Ignore leading events that are outside of any function.  */
     218         4019 :   unsigned first_fn_event_idx;
     219         4019 :   if (!get_first_event_in_a_function (&first_fn_event_idx))
     220              :     return false;
     221              : 
     222         3923 :   const event &first_fn_event = get_event (first_fn_event_idx);
     223         3923 :   int first_fn_stack_depth = first_fn_event.get_stack_depth ();
     224              : 
     225         3923 :   const unsigned num = num_events ();
     226        11838 :   for (unsigned i = first_fn_event_idx + 1; i < num; i++)
     227              :     {
     228         8704 :       if (!same_function_p (first_fn_event_idx, i))
     229              :         return true;
     230         8147 :       if (get_event (i).get_stack_depth () != first_fn_stack_depth)
     231              :         return true;
     232              :     }
     233              :   return false;
     234              : }
     235              : 
     236              : /* Print PATH by emitting a dummy "note" associated with it.  */
     237              : 
     238              : DEBUG_FUNCTION
     239            0 : void debug (path *p)
     240              : {
     241            0 :   rich_location richloc (line_table, UNKNOWN_LOCATION);
     242            0 :   richloc.set_path (p);
     243            0 :   inform (&richloc, "debug path");
     244            0 : }
     245              : 
     246              : #if __GNUC__ >= 10
     247              : #  pragma GCC diagnostic pop
     248              : #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.