LCOV - code coverage report
Current view: top level - gcc - diagnostic-context-rich-location.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.9 % 37 34
Test Date: 2025-08-30 13:27:53 Functions: 100.0 % 1 1
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* A rich_location subclass that lazily populates a diagnostic_path
       2                 :             :    with diagnostic context events, but only if the path is actually to be
       3                 :             :    used.
       4                 :             : 
       5                 :             :    Copyright (C) 2025 Free Software Foundation, Inc.
       6                 :             :    Contributed by Qing Zhao<qing.zhao@oracle.com>
       7                 :             : 
       8                 :             : This file is part of GCC.
       9                 :             : 
      10                 :             : GCC is free software; you can redistribute it and/or modify it under
      11                 :             : the terms of the GNU General Public License as published by the Free
      12                 :             : Software Foundation; either version 3, or (at your option) any later
      13                 :             : version.
      14                 :             : 
      15                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      16                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      17                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      18                 :             : for more details.
      19                 :             : 
      20                 :             : You should have received a copy of the GNU General Public License
      21                 :             : along with GCC; see the file COPYING3.  If not see
      22                 :             : <http://www.gnu.org/licenses/>.  */
      23                 :             : 
      24                 :             : #define INCLUDE_MEMORY
      25                 :             : #include "config.h"
      26                 :             : #include "system.h"
      27                 :             : #include "coretypes.h"
      28                 :             : #include "backend.h"
      29                 :             : #include "tree.h"
      30                 :             : #include "gimple.h"
      31                 :             : #include "gimple-iterator.h"
      32                 :             : #include "cfganal.h"
      33                 :             : #include "tree-cfg.h"
      34                 :             : #include "simple-diagnostic-path.h"
      35                 :             : #include "diagnostic-context-rich-location.h"
      36                 :             : 
      37                 :             : /* Implemenation of the method make_inner_path of the class
      38                 :             :    lazy_diagnostic_context_path.  */
      39                 :             : 
      40                 :             : std::unique_ptr<diagnostics::paths::path>
      41                 :        5726 : lazy_diagnostic_context_path::make_inner_path () const
      42                 :             : {
      43                 :        5726 :   auto path = std::make_unique<simple_diagnostic_path>
      44                 :             :                 (m_logical_loc_mgr,
      45                 :        5726 :                  global_dc->get_reference_printer ());
      46                 :        5726 :   if (!flag_diagnostics_show_context)
      47                 :        5711 :     return path;
      48                 :          15 :   if (!m_stmt)
      49                 :           0 :     return path;
      50                 :             : 
      51                 :             :   /* For the following more complicated code:
      52                 :             :   if (i < 10)                                // B2
      53                 :             :     {
      54                 :             :       if (is_day)                       // B3
      55                 :             :         __builtin_printf ("day");     // B4
      56                 :             :       else
      57                 :             :         __builtin_printf ("night");   // B5
      58                 :             : 
      59                 :             :       if (i == -1)                      // B6
      60                 :             :         {
      61                 :             :           if (is_dollar)                // B7
      62                 :             :             __builtin_printf ("dollar");// B8
      63                 :             :           else
      64                 :             :             __builtin_printf ("euro");        // B9
      65                 :             :           a[i] = -1;                    // B10 (warning here)
      66                 :             :         }
      67                 :             :       else
      68                 :             :         a[i] = i;                       // B11
      69                 :             :     }
      70                 :             :   else
      71                 :             :     a[i] = i + 1;                       // B12
      72                 :             : 
      73                 :             :   it has the following CFG:
      74                 :             : 
      75                 :             :             B2
      76                 :             :            / \
      77                 :             :           V   \
      78                 :             :          B3    \
      79                 :             :         / \     \
      80                 :             :        V   V     \
      81                 :             :       B4  B5      V
      82                 :             :         \ /      B12
      83                 :             :          V
      84                 :             :          B6
      85                 :             :         / \
      86                 :             :        V   V
      87                 :             :       B7  B11
      88                 :             :      / \
      89                 :             :     V   V
      90                 :             :    B8   B9
      91                 :             :      \ /
      92                 :             :       V
      93                 :             :      B10 (warning here)
      94                 :             : 
      95                 :             :   If the STMT that has warning is in B10, the interesting conditions for
      96                 :             :   the diagnostic are:
      97                 :             :   depth=1: the condition stmt at B6, the edge from B6->B7;
      98                 :             :   depth=2: the condition stmt at B2, the edge from B2->B3;
      99                 :             : 
     100                 :             :   In order to get the interesting conditions, the key to the heuristic
     101                 :             :   is to backtrace the immediate dominator block chain of the current
     102                 :             :   block B10, such as, B7, then B6, B3, B2.
     103                 :             : 
     104                 :             :   In this basic block dominator chain, identify the single predecessor
     105                 :             :   edges, such as B6->B7, and B2->B3.
     106                 :             : 
     107                 :             :   For each of the single predecessor edge, the interesting condition is
     108                 :             :   embedded in the single predecessor block, and the TRUE/FALSE of this
     109                 :             :   condition is embedded in the edge.
     110                 :             : 
     111                 :             :   FIXME: We currently only handle GIMPLE_COND, might extend to GIMPLE_SWITCH
     112                 :             :   later.  */
     113                 :             : 
     114                 :          15 :   basic_block cur_bb = gimple_bb (m_stmt);
     115                 :          15 :   if (!cur_bb)
     116                 :           0 :     return path;
     117                 :             :   basic_block cond_bb = NULL;
     118                 :             :   int depth = 0;
     119                 :          27 :   do
     120                 :             :     {
     121                 :             :       /* Step 1. locate the immediate dominator of cur_bb.  */
     122                 :          27 :       if (dom_info_available_p (cfun, CDI_DOMINATORS))
     123                 :          27 :         cond_bb = get_immediate_dominator (CDI_DOMINATORS, cur_bb);
     124                 :             : 
     125                 :          27 :       if (!cond_bb)
     126                 :           0 :         return path;
     127                 :             : 
     128                 :             :       /* Step 2. identify the single predecessor edge to locate the
     129                 :             :          conditional statement.  */
     130                 :          27 :       if (single_pred_p (cur_bb))
     131                 :             :         {
     132                 :          21 :           gcc_assert (cond_bb == single_pred (cur_bb));
     133                 :          21 :           gimple *cond_stmt = NULL;
     134                 :          21 :           gimple_stmt_iterator gsi = gsi_last_bb (cond_bb);
     135                 :             : 
     136                 :             :           /* Currently, we only hanlde GIMPLE_COND.
     137                 :             :              FIXME, will handle GIMPLE_SWITCH and other ctrl stmt later.  */
     138                 :          21 :           if (gsi_stmt (gsi) && stmt_ends_bb_p (gsi_stmt (gsi)))
     139                 :          17 :             if (gimple_code (gsi_stmt (gsi)) == GIMPLE_COND)
     140                 :          17 :               cond_stmt = gsi_stmt (gsi);
     141                 :             : 
     142                 :             :           /* If there is no conditional statement in the cond_bb, continue.  */
     143                 :          21 :           if (!cond_stmt)
     144                 :             :             {
     145                 :           4 :               cur_bb = cond_bb;
     146                 :           4 :               continue;
     147                 :             :             }
     148                 :             : 
     149                 :          17 :           depth++;
     150                 :             : 
     151                 :             :           /* if there is no location information for the cond_stmt, we should
     152                 :             :              not add this event to confuse end user.  */
     153                 :          17 :           if (cond_stmt
     154                 :          17 :               && LOCATION_LOCUS (gimple_location (cond_stmt))
     155                 :             :                  != UNKNOWN_LOCATION)
     156                 :             :             {
     157                 :             :               /* Get the edge from the cond_bb to cur_bb, to determine whether
     158                 :             :                  the stmt is on the taken path of the conditional statement.  */
     159                 :          17 :               edge e = find_edge (cond_bb, cur_bb);
     160                 :          17 :               bool is_branch_taken = e->flags & EDGE_TRUE_VALUE;
     161                 :          22 :               path->add_event (gimple_location (cond_stmt), cfun->decl, 1,
     162                 :             :                                "when the condition is evaluated to %s",
     163                 :             :                                is_branch_taken ? "true" : "false");
     164                 :             :             }
     165                 :             :         }
     166                 :             :         cur_bb = cond_bb;
     167                 :             :     }
     168                 :          27 :   while (cond_bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)
     169                 :          27 :          && depth < flag_diagnostics_show_context);
     170                 :             : 
     171                 :             :   /* Add an end of path warning event in the end of the path.  */
     172                 :          15 :   if (path->num_events () > 0)
     173                 :          15 :     path->add_event (m_location, cfun->decl, 1,
     174                 :             :                      "warning happens here");
     175                 :          15 :   return path;
     176                 :        5726 : }
        

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.