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: 2026-02-28 14:20:25 Functions: 100.0 % 1 1
Legend: Lines:     hit not hit

            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-2026 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         5750 : lazy_diagnostic_context_path::make_inner_path () const
      42              : {
      43         5750 :   auto path = std::make_unique<simple_diagnostic_path>
      44              :                 (m_logical_loc_mgr,
      45         5750 :                  global_dc->get_reference_printer ());
      46         5750 :   if (!flag_diagnostics_show_context)
      47         5735 :     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         5750 : }
        

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.