Home | History | Annotate | Line # | Download | only in analyzer
      1      1.1  mrg /* Classes for saving, deduplicating, and emitting analyzer diagnostics.
      2  1.1.1.2  mrg    Copyright (C) 2019-2022 Free Software Foundation, Inc.
      3      1.1  mrg    Contributed by David Malcolm <dmalcolm (at) redhat.com>.
      4      1.1  mrg 
      5      1.1  mrg This file is part of GCC.
      6      1.1  mrg 
      7      1.1  mrg GCC is free software; you can redistribute it and/or modify it
      8      1.1  mrg under the terms of the GNU General Public License as published by
      9      1.1  mrg the Free Software Foundation; either version 3, or (at your option)
     10      1.1  mrg any later version.
     11      1.1  mrg 
     12      1.1  mrg GCC is distributed in the hope that it will be useful, but
     13      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15      1.1  mrg General Public License for more details.
     16      1.1  mrg 
     17      1.1  mrg You should have received a copy of the GNU General Public License
     18      1.1  mrg along with GCC; see the file COPYING3.  If not see
     19      1.1  mrg <http://www.gnu.org/licenses/>.  */
     20      1.1  mrg 
     21      1.1  mrg #include "config.h"
     22      1.1  mrg #include "system.h"
     23      1.1  mrg #include "coretypes.h"
     24      1.1  mrg #include "tree.h"
     25      1.1  mrg #include "pretty-print.h"
     26      1.1  mrg #include "gcc-rich-location.h"
     27      1.1  mrg #include "gimple-pretty-print.h"
     28      1.1  mrg #include "function.h"
     29      1.1  mrg #include "diagnostic-core.h"
     30      1.1  mrg #include "diagnostic-event-id.h"
     31      1.1  mrg #include "diagnostic-path.h"
     32      1.1  mrg #include "alloc-pool.h"
     33      1.1  mrg #include "fibonacci_heap.h"
     34      1.1  mrg #include "shortest-paths.h"
     35      1.1  mrg #include "sbitmap.h"
     36      1.1  mrg #include "bitmap.h"
     37      1.1  mrg #include "tristate.h"
     38      1.1  mrg #include "selftest.h"
     39      1.1  mrg #include "ordered-hash-map.h"
     40  1.1.1.2  mrg #include "json.h"
     41      1.1  mrg #include "analyzer/analyzer.h"
     42      1.1  mrg #include "analyzer/analyzer-logging.h"
     43      1.1  mrg #include "analyzer/sm.h"
     44      1.1  mrg #include "analyzer/pending-diagnostic.h"
     45      1.1  mrg #include "analyzer/diagnostic-manager.h"
     46  1.1.1.2  mrg #include "analyzer/call-string.h"
     47  1.1.1.2  mrg #include "analyzer/program-point.h"
     48  1.1.1.2  mrg #include "analyzer/store.h"
     49      1.1  mrg #include "analyzer/region-model.h"
     50      1.1  mrg #include "analyzer/constraint-manager.h"
     51      1.1  mrg #include "cfg.h"
     52      1.1  mrg #include "basic-block.h"
     53      1.1  mrg #include "gimple.h"
     54      1.1  mrg #include "gimple-iterator.h"
     55      1.1  mrg #include "cgraph.h"
     56      1.1  mrg #include "digraph.h"
     57      1.1  mrg #include "analyzer/supergraph.h"
     58      1.1  mrg #include "analyzer/program-state.h"
     59      1.1  mrg #include "analyzer/exploded-graph.h"
     60  1.1.1.2  mrg #include "analyzer/trimmed-graph.h"
     61  1.1.1.2  mrg #include "analyzer/feasible-graph.h"
     62      1.1  mrg #include "analyzer/checker-path.h"
     63      1.1  mrg #include "analyzer/reachability.h"
     64      1.1  mrg 
     65      1.1  mrg #if ENABLE_ANALYZER
     66      1.1  mrg 
     67      1.1  mrg namespace ana {
     68      1.1  mrg 
     69  1.1.1.2  mrg class feasible_worklist;
     70  1.1.1.2  mrg 
     71  1.1.1.2  mrg /* State for finding the shortest feasible exploded_path for a
     72  1.1.1.2  mrg    saved_diagnostic.
     73  1.1.1.2  mrg    This is shared between all diagnostics, so that we avoid repeating work.  */
     74  1.1.1.2  mrg 
     75  1.1.1.2  mrg class epath_finder
     76  1.1.1.2  mrg {
     77  1.1.1.2  mrg public:
     78  1.1.1.2  mrg   epath_finder (const exploded_graph &eg)
     79  1.1.1.2  mrg   : m_eg (eg),
     80  1.1.1.2  mrg     m_sep (NULL)
     81  1.1.1.2  mrg   {
     82  1.1.1.2  mrg     /* This is shared by all diagnostics, but only needed if
     83  1.1.1.2  mrg        !flag_analyzer_feasibility.  */
     84  1.1.1.2  mrg     if (!flag_analyzer_feasibility)
     85  1.1.1.2  mrg       m_sep = new shortest_exploded_paths (eg, eg.get_origin (),
     86  1.1.1.2  mrg 					   SPS_FROM_GIVEN_ORIGIN);
     87  1.1.1.2  mrg   }
     88  1.1.1.2  mrg 
     89  1.1.1.2  mrg   ~epath_finder () { delete m_sep; }
     90  1.1.1.2  mrg 
     91  1.1.1.2  mrg   logger *get_logger () const { return m_eg.get_logger (); }
     92  1.1.1.2  mrg 
     93  1.1.1.2  mrg   exploded_path *get_best_epath (const exploded_node *target_enode,
     94  1.1.1.2  mrg 				 const char *desc, unsigned diag_idx,
     95  1.1.1.2  mrg 				 feasibility_problem **out_problem);
     96  1.1.1.2  mrg 
     97  1.1.1.2  mrg private:
     98  1.1.1.2  mrg   DISABLE_COPY_AND_ASSIGN(epath_finder);
     99  1.1.1.2  mrg 
    100  1.1.1.2  mrg   exploded_path *explore_feasible_paths (const exploded_node *target_enode,
    101  1.1.1.2  mrg 					 const char *desc, unsigned diag_idx);
    102  1.1.1.2  mrg   bool process_worklist_item (feasible_worklist *worklist,
    103  1.1.1.2  mrg 			      const trimmed_graph &tg,
    104  1.1.1.2  mrg 			      feasible_graph *fg,
    105  1.1.1.2  mrg 			      const exploded_node *target_enode,
    106  1.1.1.2  mrg 			      unsigned diag_idx,
    107  1.1.1.2  mrg 			      exploded_path **out_best_path) const;
    108  1.1.1.2  mrg   void dump_trimmed_graph (const exploded_node *target_enode,
    109  1.1.1.2  mrg 			   const char *desc, unsigned diag_idx,
    110  1.1.1.2  mrg 			   const trimmed_graph &tg,
    111  1.1.1.2  mrg 			   const shortest_paths<eg_traits, exploded_path> &sep);
    112  1.1.1.2  mrg   void dump_feasible_graph (const exploded_node *target_enode,
    113  1.1.1.2  mrg 			    const char *desc, unsigned diag_idx,
    114  1.1.1.2  mrg 			    const feasible_graph &fg);
    115  1.1.1.2  mrg   void dump_feasible_path (const exploded_node *target_enode,
    116  1.1.1.2  mrg 			   unsigned diag_idx,
    117  1.1.1.2  mrg 			   const feasible_graph &fg,
    118  1.1.1.2  mrg 			   const feasible_node &fnode) const;
    119  1.1.1.2  mrg 
    120  1.1.1.2  mrg   const exploded_graph &m_eg;
    121  1.1.1.2  mrg   shortest_exploded_paths *m_sep;
    122  1.1.1.2  mrg };
    123  1.1.1.2  mrg 
    124  1.1.1.2  mrg /* class epath_finder.  */
    125  1.1.1.2  mrg 
    126  1.1.1.2  mrg /* Get the "best" exploded_path for reaching ENODE from the origin,
    127  1.1.1.2  mrg    returning ownership of it to the caller.
    128  1.1.1.2  mrg 
    129  1.1.1.2  mrg    Ideally we want to report the shortest feasible path.
    130  1.1.1.2  mrg    Return NULL if we could not find a feasible path
    131  1.1.1.2  mrg    (when flag_analyzer_feasibility is true).
    132  1.1.1.2  mrg 
    133  1.1.1.2  mrg    If flag_analyzer_feasibility is false, then simply return the
    134  1.1.1.2  mrg    shortest path.
    135  1.1.1.2  mrg 
    136  1.1.1.2  mrg    Use DESC and DIAG_IDX when logging.
    137  1.1.1.2  mrg 
    138  1.1.1.2  mrg    Write any feasibility_problem to *OUT_PROBLEM.  */
    139  1.1.1.2  mrg 
    140  1.1.1.2  mrg exploded_path *
    141  1.1.1.2  mrg epath_finder::get_best_epath (const exploded_node *enode,
    142  1.1.1.2  mrg 			      const char *desc, unsigned diag_idx,
    143  1.1.1.2  mrg 			      feasibility_problem **out_problem)
    144  1.1.1.2  mrg {
    145  1.1.1.2  mrg   logger *logger = get_logger ();
    146  1.1.1.2  mrg   LOG_SCOPE (logger);
    147  1.1.1.2  mrg 
    148  1.1.1.2  mrg   unsigned snode_idx = enode->get_supernode ()->m_index;
    149  1.1.1.2  mrg   if (logger)
    150  1.1.1.2  mrg     logger->log ("considering %qs at EN: %i, SN: %i (sd: %i)",
    151  1.1.1.2  mrg 		 desc, enode->m_index, snode_idx, diag_idx);
    152  1.1.1.2  mrg 
    153  1.1.1.2  mrg   /* State-merging means that not every path in the egraph corresponds
    154  1.1.1.2  mrg      to a feasible one w.r.t. states.
    155  1.1.1.2  mrg 
    156  1.1.1.2  mrg      We want to find the shortest feasible path from the origin to ENODE
    157  1.1.1.2  mrg      in the egraph.  */
    158  1.1.1.2  mrg 
    159  1.1.1.2  mrg   if (flag_analyzer_feasibility)
    160  1.1.1.2  mrg     {
    161  1.1.1.2  mrg       /* Attempt to find the shortest feasible path using feasible_graph.  */
    162  1.1.1.2  mrg       if (logger)
    163  1.1.1.2  mrg 	logger->log ("trying to find shortest feasible path");
    164  1.1.1.2  mrg       if (exploded_path *epath = explore_feasible_paths (enode, desc, diag_idx))
    165  1.1.1.2  mrg 	{
    166  1.1.1.2  mrg 	  if (logger)
    167  1.1.1.2  mrg 	    logger->log ("accepting %qs at EN: %i, SN: %i (sd: %i)"
    168  1.1.1.2  mrg 			 " with feasible path (length: %i)",
    169  1.1.1.2  mrg 			 desc, enode->m_index, snode_idx, diag_idx,
    170  1.1.1.2  mrg 			 epath->length ());
    171  1.1.1.2  mrg 	  return epath;
    172  1.1.1.2  mrg 	}
    173  1.1.1.2  mrg       else
    174  1.1.1.2  mrg 	{
    175  1.1.1.2  mrg 	  if (logger)
    176  1.1.1.2  mrg 	    logger->log ("rejecting %qs at EN: %i, SN: %i (sd: %i)"
    177  1.1.1.2  mrg 			 " due to not finding feasible path",
    178  1.1.1.2  mrg 			 desc, enode->m_index, snode_idx, diag_idx);
    179  1.1.1.2  mrg 	  return NULL;
    180  1.1.1.2  mrg 	}
    181  1.1.1.2  mrg     }
    182  1.1.1.2  mrg   else
    183  1.1.1.2  mrg     {
    184  1.1.1.2  mrg       /* As a crude approximation to shortest feasible path, simply find
    185  1.1.1.2  mrg 	 the shortest path, and note whether it is feasible.
    186  1.1.1.2  mrg 	 There could be longer feasible paths within the egraph, so this
    187  1.1.1.2  mrg 	 approach would lead to diagnostics being falsely rejected
    188  1.1.1.2  mrg 	 (PR analyzer/96374).  */
    189  1.1.1.2  mrg       if (logger)
    190  1.1.1.2  mrg 	logger->log ("trying to find shortest path ignoring feasibility");
    191  1.1.1.2  mrg       gcc_assert (m_sep);
    192  1.1.1.2  mrg       exploded_path *epath
    193  1.1.1.2  mrg 	= new exploded_path (m_sep->get_shortest_path (enode));
    194  1.1.1.2  mrg       if (epath->feasible_p (logger, out_problem, m_eg.get_engine (), &m_eg))
    195  1.1.1.2  mrg 	{
    196  1.1.1.2  mrg 	  if (logger)
    197  1.1.1.2  mrg 	    logger->log ("accepting %qs at EN: %i, SN: %i (sn: %i)"
    198  1.1.1.2  mrg 			 " with feasible path (length: %i)",
    199  1.1.1.2  mrg 			 desc, enode->m_index, snode_idx, diag_idx,
    200  1.1.1.2  mrg 			 epath->length ());
    201  1.1.1.2  mrg 	}
    202  1.1.1.2  mrg       else
    203  1.1.1.2  mrg 	{
    204  1.1.1.2  mrg 	  if (logger)
    205  1.1.1.2  mrg 	    logger->log ("accepting %qs at EN: %i, SN: %i (sn: %i) (length: %i)"
    206  1.1.1.2  mrg 			 " despite infeasible path (due to %qs)",
    207  1.1.1.2  mrg 			 desc, enode->m_index, snode_idx, diag_idx,
    208  1.1.1.2  mrg 			 epath->length (),
    209  1.1.1.2  mrg 			 "-fno-analyzer-feasibility");
    210  1.1.1.2  mrg 	}
    211  1.1.1.2  mrg       return epath;
    212  1.1.1.2  mrg     }
    213  1.1.1.2  mrg }
    214  1.1.1.2  mrg 
    215  1.1.1.2  mrg /* A class for managing the worklist of feasible_nodes in
    216  1.1.1.2  mrg    epath_finder::explore_feasible_paths, prioritizing them
    217  1.1.1.2  mrg    so that shorter paths appear earlier in the queue.  */
    218  1.1.1.2  mrg 
    219  1.1.1.2  mrg class feasible_worklist
    220  1.1.1.2  mrg {
    221  1.1.1.2  mrg public:
    222  1.1.1.2  mrg   feasible_worklist (const shortest_paths<eg_traits, exploded_path> &sep)
    223  1.1.1.2  mrg   : m_queue (key_t (*this, NULL)),
    224  1.1.1.2  mrg     m_sep (sep)
    225  1.1.1.2  mrg   {
    226  1.1.1.2  mrg   }
    227  1.1.1.2  mrg 
    228  1.1.1.2  mrg   feasible_node *take_next () { return m_queue.extract_min (); }
    229  1.1.1.2  mrg 
    230  1.1.1.2  mrg   void add_node (feasible_node *fnode)
    231  1.1.1.2  mrg   {
    232  1.1.1.2  mrg     m_queue.insert (key_t (*this, fnode), fnode);
    233  1.1.1.2  mrg   }
    234  1.1.1.2  mrg 
    235  1.1.1.2  mrg private:
    236  1.1.1.2  mrg   struct key_t
    237  1.1.1.2  mrg   {
    238  1.1.1.2  mrg     key_t (const feasible_worklist &w, feasible_node *fnode)
    239  1.1.1.2  mrg     : m_worklist (w), m_fnode (fnode)
    240  1.1.1.2  mrg     {}
    241  1.1.1.2  mrg 
    242  1.1.1.2  mrg     bool operator< (const key_t &other) const
    243  1.1.1.2  mrg     {
    244  1.1.1.2  mrg       return cmp (*this, other) < 0;
    245  1.1.1.2  mrg     }
    246  1.1.1.2  mrg 
    247  1.1.1.2  mrg     bool operator== (const key_t &other) const
    248  1.1.1.2  mrg     {
    249  1.1.1.2  mrg       return cmp (*this, other) == 0;
    250  1.1.1.2  mrg     }
    251  1.1.1.2  mrg 
    252  1.1.1.2  mrg     bool operator> (const key_t &other) const
    253  1.1.1.2  mrg     {
    254  1.1.1.2  mrg       return !(*this == other || *this < other);
    255  1.1.1.2  mrg     }
    256  1.1.1.2  mrg 
    257  1.1.1.2  mrg   private:
    258  1.1.1.2  mrg     static int cmp (const key_t &ka, const key_t &kb)
    259  1.1.1.2  mrg     {
    260  1.1.1.2  mrg       /* Choose the node for which if the remaining path were feasible,
    261  1.1.1.2  mrg 	 it would be the shortest path (summing the length of the
    262  1.1.1.2  mrg 	 known-feasible path so far with that of the remaining
    263  1.1.1.2  mrg 	 possibly-feasible path).  */
    264  1.1.1.2  mrg       int ca = ka.m_worklist.get_estimated_cost (ka.m_fnode);
    265  1.1.1.2  mrg       int cb = kb.m_worklist.get_estimated_cost (kb.m_fnode);
    266  1.1.1.2  mrg       return ca - cb;
    267  1.1.1.2  mrg     }
    268  1.1.1.2  mrg 
    269  1.1.1.2  mrg     const feasible_worklist &m_worklist;
    270  1.1.1.2  mrg     feasible_node *m_fnode;
    271  1.1.1.2  mrg   };
    272  1.1.1.2  mrg 
    273  1.1.1.2  mrg   /* Get the estimated length of a path involving FNODE from
    274  1.1.1.2  mrg      the origin to the target enode.
    275  1.1.1.2  mrg      Sum the length of the known-feasible path so far with
    276  1.1.1.2  mrg      that of the remaining possibly-feasible path.  */
    277  1.1.1.2  mrg 
    278  1.1.1.2  mrg   int get_estimated_cost (const feasible_node *fnode) const
    279  1.1.1.2  mrg   {
    280  1.1.1.2  mrg     unsigned length_so_far = fnode->get_path_length ();
    281  1.1.1.2  mrg     int shortest_remaining_path
    282  1.1.1.2  mrg       = m_sep.get_shortest_distance (fnode->get_inner_node ());
    283  1.1.1.2  mrg 
    284  1.1.1.2  mrg     gcc_assert (shortest_remaining_path >= 0);
    285  1.1.1.2  mrg     /* This should be true since we're only exploring nodes within
    286  1.1.1.2  mrg        the trimmed graph (and we anticipate it being much smaller
    287  1.1.1.2  mrg        than this, and thus not overflowing the sum).  */
    288  1.1.1.2  mrg     gcc_assert (shortest_remaining_path < INT_MAX);
    289  1.1.1.2  mrg 
    290  1.1.1.2  mrg     return length_so_far + shortest_remaining_path;
    291  1.1.1.2  mrg   }
    292  1.1.1.2  mrg 
    293  1.1.1.2  mrg   /* Priority queue, backed by a fibonacci_heap.  */
    294  1.1.1.2  mrg   typedef fibonacci_heap<key_t, feasible_node> queue_t;
    295  1.1.1.2  mrg   queue_t m_queue;
    296  1.1.1.2  mrg   const shortest_paths<eg_traits, exploded_path> &m_sep;
    297  1.1.1.2  mrg };
    298  1.1.1.2  mrg 
    299  1.1.1.2  mrg /* When we're building the exploded graph we want to simplify
    300  1.1.1.2  mrg    overly-complicated symbolic values down to "UNKNOWN" to try to avoid
    301  1.1.1.2  mrg    state explosions and unbounded chains of exploration.
    302  1.1.1.2  mrg 
    303  1.1.1.2  mrg    However, when we're building the feasibility graph for a diagnostic
    304  1.1.1.2  mrg    (actually a tree), we don't want UNKNOWN values, as conditions on them
    305  1.1.1.2  mrg    are also unknown: we don't want to have a contradiction such as a path
    306  1.1.1.2  mrg    where (VAL != 0) and then (VAL == 0) along the same path.
    307  1.1.1.2  mrg 
    308  1.1.1.2  mrg    Hence this is an RAII class for temporarily disabling complexity-checking
    309  1.1.1.2  mrg    in the region_model_manager, for use within
    310  1.1.1.2  mrg    epath_finder::explore_feasible_paths.
    311  1.1.1.2  mrg 
    312  1.1.1.2  mrg    We also disable the creation of unknown_svalue instances during feasibility
    313  1.1.1.2  mrg    checking, instead creating unique svalues, to avoid paradoxes in paths.  */
    314  1.1.1.2  mrg 
    315  1.1.1.2  mrg class auto_checking_feasibility
    316  1.1.1.2  mrg {
    317  1.1.1.2  mrg public:
    318  1.1.1.2  mrg   auto_checking_feasibility (region_model_manager *mgr) : m_mgr (mgr)
    319  1.1.1.2  mrg   {
    320  1.1.1.2  mrg     m_mgr->begin_checking_feasibility ();
    321  1.1.1.2  mrg   }
    322  1.1.1.2  mrg   ~auto_checking_feasibility ()
    323  1.1.1.2  mrg   {
    324  1.1.1.2  mrg     m_mgr->end_checking_feasibility ();
    325  1.1.1.2  mrg   }
    326  1.1.1.2  mrg private:
    327  1.1.1.2  mrg   region_model_manager *m_mgr;
    328  1.1.1.2  mrg };
    329  1.1.1.2  mrg 
    330  1.1.1.2  mrg /* Attempt to find the shortest feasible path from the origin to
    331  1.1.1.2  mrg    TARGET_ENODE by iteratively building a feasible_graph, in which
    332  1.1.1.2  mrg    every path to a feasible_node is feasible by construction.
    333  1.1.1.2  mrg 
    334  1.1.1.2  mrg    We effectively explore the tree of feasible paths in order of shortest
    335  1.1.1.2  mrg    path until we either find a feasible path to TARGET_ENODE, or hit
    336  1.1.1.2  mrg    a limit and give up.
    337  1.1.1.2  mrg 
    338  1.1.1.2  mrg    Preliminaries:
    339  1.1.1.2  mrg    - Find the shortest path from each node to the TARGET_ENODE (without
    340  1.1.1.2  mrg    checking feasibility), so that we can prioritize our worklist.
    341  1.1.1.2  mrg    - Construct a trimmed_graph: the subset of nodes/edges that
    342  1.1.1.2  mrg    are on a path that eventually reaches TARGET_ENODE.  We will only need
    343  1.1.1.2  mrg    to consider these when considering the shortest feasible path.
    344  1.1.1.2  mrg 
    345  1.1.1.2  mrg    Build a feasible_graph, in which every path to a feasible_node
    346  1.1.1.2  mrg    is feasible by construction.
    347  1.1.1.2  mrg    We use a worklist to flatten the exploration into an iteration.
    348  1.1.1.2  mrg    Starting at the origin, find feasible out-edges within the trimmed graph.
    349  1.1.1.2  mrg    At each stage, choose the node for which if the remaining path were feasible,
    350  1.1.1.2  mrg    it would be the shortest path (summing the length of the known-feasible path
    351  1.1.1.2  mrg    so far with that of the remaining possibly-feasible path).
    352  1.1.1.2  mrg    This way, the first feasible path we find to TARGET_ENODE is the shortest.
    353  1.1.1.2  mrg    We start by trying the shortest possible path, but if that fails,
    354  1.1.1.2  mrg    we explore progressively longer paths, eventually trying iterations through
    355  1.1.1.2  mrg    loops.  The exploration is captured in the feasible_graph, which can be
    356  1.1.1.2  mrg    dumped as a .dot file to visualize the exploration.  The indices of the
    357  1.1.1.2  mrg    feasible_nodes show the order in which they were created.
    358  1.1.1.2  mrg 
    359  1.1.1.2  mrg    This is something of a brute-force approach, but the trimmed_graph
    360  1.1.1.2  mrg    hopefully keeps the complexity manageable.
    361  1.1.1.2  mrg 
    362  1.1.1.2  mrg    Terminate with failure when the number of infeasible edges exceeds
    363  1.1.1.2  mrg    a threshold (--param=analyzer-max-infeasible-edges=).
    364  1.1.1.2  mrg    This is guaranteed to eventually lead to terminatation, as
    365  1.1.1.2  mrg    we can't keep creating feasible nodes without eventually
    366  1.1.1.2  mrg    either reaching an infeasible edge, or reaching the
    367  1.1.1.2  mrg    TARGET_ENODE.  Specifically, there can't be a cycle of
    368  1.1.1.2  mrg    feasible edges that doesn't reach the target_enode without
    369  1.1.1.2  mrg    an out-edge that either fails feasibility or gets closer
    370  1.1.1.2  mrg    to the TARGET_ENODE: on each iteration we are either:
    371  1.1.1.2  mrg    - effectively getting closer to the TARGET_ENODE (which can't
    372  1.1.1.2  mrg      continue forever without reaching the target), or
    373  1.1.1.2  mrg    - getting monotonically closer to the termination threshold.  */
    374  1.1.1.2  mrg 
    375  1.1.1.2  mrg exploded_path *
    376  1.1.1.2  mrg epath_finder::explore_feasible_paths (const exploded_node *target_enode,
    377  1.1.1.2  mrg 				      const char *desc, unsigned diag_idx)
    378  1.1.1.2  mrg {
    379  1.1.1.2  mrg   logger *logger = get_logger ();
    380  1.1.1.2  mrg   LOG_SCOPE (logger);
    381  1.1.1.2  mrg 
    382  1.1.1.2  mrg   region_model_manager *mgr = m_eg.get_engine ()->get_model_manager ();
    383  1.1.1.2  mrg 
    384  1.1.1.2  mrg   /* Determine the shortest path to TARGET_ENODE from each node in
    385  1.1.1.2  mrg      the exploded graph.  */
    386  1.1.1.2  mrg   shortest_paths<eg_traits, exploded_path> sep
    387  1.1.1.2  mrg     (m_eg, target_enode, SPS_TO_GIVEN_TARGET);
    388  1.1.1.2  mrg 
    389  1.1.1.2  mrg   /* Construct a trimmed_graph: the subset of nodes/edges that
    390  1.1.1.2  mrg      are on a path that eventually reaches TARGET_ENODE.
    391  1.1.1.2  mrg      We only need to consider these when considering the shortest
    392  1.1.1.2  mrg      feasible path.  */
    393  1.1.1.2  mrg   trimmed_graph tg (m_eg, target_enode);
    394  1.1.1.2  mrg 
    395  1.1.1.2  mrg   if (flag_dump_analyzer_feasibility)
    396  1.1.1.2  mrg     dump_trimmed_graph (target_enode, desc, diag_idx, tg, sep);
    397  1.1.1.2  mrg 
    398  1.1.1.2  mrg   feasible_graph fg;
    399  1.1.1.2  mrg   feasible_worklist worklist (sep);
    400  1.1.1.2  mrg 
    401  1.1.1.2  mrg   /* Populate the worklist with the origin node.  */
    402  1.1.1.2  mrg   {
    403  1.1.1.2  mrg     feasibility_state init_state (mgr, m_eg.get_supergraph ());
    404  1.1.1.2  mrg     feasible_node *origin = fg.add_node (m_eg.get_origin (), init_state, 0);
    405  1.1.1.2  mrg     worklist.add_node (origin);
    406  1.1.1.2  mrg   }
    407  1.1.1.2  mrg 
    408  1.1.1.2  mrg   /* Iteratively explore the tree of feasible paths in order of shortest
    409  1.1.1.2  mrg      path until we either find a feasible path to TARGET_ENODE, or hit
    410  1.1.1.2  mrg      a limit.  */
    411  1.1.1.2  mrg 
    412  1.1.1.2  mrg   /* Set this if we find a feasible path to TARGET_ENODE.  */
    413  1.1.1.2  mrg   exploded_path *best_path = NULL;
    414  1.1.1.2  mrg 
    415  1.1.1.2  mrg   {
    416  1.1.1.2  mrg     auto_checking_feasibility sentinel (mgr);
    417  1.1.1.2  mrg 
    418  1.1.1.2  mrg     while (process_worklist_item (&worklist, tg, &fg, target_enode, diag_idx,
    419  1.1.1.2  mrg 				  &best_path))
    420  1.1.1.2  mrg       {
    421  1.1.1.2  mrg 	/* Empty; the work is done within process_worklist_item.  */
    422  1.1.1.2  mrg       }
    423  1.1.1.2  mrg   }
    424  1.1.1.2  mrg 
    425  1.1.1.2  mrg   if (logger)
    426  1.1.1.2  mrg     {
    427  1.1.1.2  mrg       logger->log ("tg for sd: %i:", diag_idx);
    428  1.1.1.2  mrg       logger->inc_indent ();
    429  1.1.1.2  mrg       tg.log_stats (logger);
    430  1.1.1.2  mrg       logger->dec_indent ();
    431  1.1.1.2  mrg 
    432  1.1.1.2  mrg       logger->log ("fg for sd: %i:", diag_idx);
    433  1.1.1.2  mrg       logger->inc_indent ();
    434  1.1.1.2  mrg       fg.log_stats (logger);
    435  1.1.1.2  mrg       logger->dec_indent ();
    436  1.1.1.2  mrg     }
    437  1.1.1.2  mrg 
    438  1.1.1.2  mrg   /* Dump the feasible_graph.  */
    439  1.1.1.2  mrg   if (flag_dump_analyzer_feasibility)
    440  1.1.1.2  mrg     dump_feasible_graph (target_enode, desc, diag_idx, fg);
    441  1.1.1.2  mrg 
    442  1.1.1.2  mrg   return best_path;
    443  1.1.1.2  mrg }
    444  1.1.1.2  mrg 
    445  1.1.1.2  mrg /* Process the next item in WORKLIST, potentially adding new items
    446  1.1.1.2  mrg    based on feasible out-edges, and extending FG accordingly.
    447  1.1.1.2  mrg    Use TG to ignore out-edges that don't lead to TARGET_ENODE.
    448  1.1.1.2  mrg    Return true if the worklist processing should continue.
    449  1.1.1.2  mrg    Return false if the processing of the worklist should stop
    450  1.1.1.2  mrg    (either due to reaching TARGET_ENODE, or hitting a limit).
    451  1.1.1.2  mrg    Write to *OUT_BEST_PATH if stopping due to finding a feasible path
    452  1.1.1.2  mrg    to TARGET_ENODE.  */
    453  1.1.1.2  mrg 
    454  1.1.1.2  mrg bool
    455  1.1.1.2  mrg epath_finder::process_worklist_item (feasible_worklist *worklist,
    456  1.1.1.2  mrg 				     const trimmed_graph &tg,
    457  1.1.1.2  mrg 				     feasible_graph *fg,
    458  1.1.1.2  mrg 				     const exploded_node *target_enode,
    459  1.1.1.2  mrg 				     unsigned diag_idx,
    460  1.1.1.2  mrg 				     exploded_path **out_best_path) const
    461  1.1.1.2  mrg {
    462  1.1.1.2  mrg   logger *logger = get_logger ();
    463  1.1.1.2  mrg 
    464  1.1.1.2  mrg   feasible_node *fnode = worklist->take_next ();
    465  1.1.1.2  mrg   if (!fnode)
    466  1.1.1.2  mrg     {
    467  1.1.1.2  mrg       if (logger)
    468  1.1.1.2  mrg 	logger->log ("drained worklist for sd: %i"
    469  1.1.1.2  mrg 		     " without finding feasible path",
    470  1.1.1.2  mrg 		     diag_idx);
    471  1.1.1.2  mrg       return false;
    472  1.1.1.2  mrg     }
    473  1.1.1.2  mrg 
    474  1.1.1.2  mrg   log_scope s (logger, "fg worklist item",
    475  1.1.1.2  mrg 	       "considering FN: %i (EN: %i) for sd: %i",
    476  1.1.1.2  mrg 	       fnode->get_index (), fnode->get_inner_node ()->m_index,
    477  1.1.1.2  mrg 	       diag_idx);
    478  1.1.1.2  mrg 
    479  1.1.1.2  mrg   /* Iterate through all out-edges from this item.  */
    480  1.1.1.2  mrg   unsigned i;
    481  1.1.1.2  mrg   exploded_edge *succ_eedge;
    482  1.1.1.2  mrg   FOR_EACH_VEC_ELT (fnode->get_inner_node ()->m_succs, i, succ_eedge)
    483  1.1.1.2  mrg     {
    484  1.1.1.2  mrg       log_scope s (logger, "edge", "considering edge: EN:%i -> EN:%i",
    485  1.1.1.2  mrg 		   succ_eedge->m_src->m_index,
    486  1.1.1.2  mrg 		   succ_eedge->m_dest->m_index);
    487  1.1.1.2  mrg       /* Reject edges that aren't in the trimmed graph.  */
    488  1.1.1.2  mrg       if (!tg.contains_p (succ_eedge))
    489  1.1.1.2  mrg 	{
    490  1.1.1.2  mrg 	  if (logger)
    491  1.1.1.2  mrg 	    logger->log ("rejecting: not in trimmed graph");
    492  1.1.1.2  mrg 	  continue;
    493  1.1.1.2  mrg 	}
    494  1.1.1.2  mrg 
    495  1.1.1.2  mrg       feasibility_state succ_state (fnode->get_state ());
    496  1.1.1.2  mrg       rejected_constraint *rc = NULL;
    497  1.1.1.2  mrg       if (succ_state.maybe_update_for_edge (logger, succ_eedge, &rc))
    498  1.1.1.2  mrg 	{
    499  1.1.1.2  mrg 	  gcc_assert (rc == NULL);
    500  1.1.1.2  mrg 	  feasible_node *succ_fnode
    501  1.1.1.2  mrg 	    = fg->add_node (succ_eedge->m_dest,
    502  1.1.1.2  mrg 			    succ_state,
    503  1.1.1.2  mrg 			    fnode->get_path_length () + 1);
    504  1.1.1.2  mrg 	  if (logger)
    505  1.1.1.2  mrg 	    logger->log ("accepting as FN: %i", succ_fnode->get_index ());
    506  1.1.1.2  mrg 	  fg->add_edge (new feasible_edge (fnode, succ_fnode, succ_eedge));
    507  1.1.1.2  mrg 
    508  1.1.1.2  mrg 	  /* Have we reached TARGET_ENODE?  */
    509  1.1.1.2  mrg 	  if (succ_fnode->get_inner_node () == target_enode)
    510  1.1.1.2  mrg 	    {
    511  1.1.1.2  mrg 	      if (logger)
    512  1.1.1.2  mrg 		logger->log ("success: got feasible path to EN: %i (sd: %i)"
    513  1.1.1.2  mrg 			     " (length: %i)",
    514  1.1.1.2  mrg 			     target_enode->m_index, diag_idx,
    515  1.1.1.2  mrg 			     succ_fnode->get_path_length ());
    516  1.1.1.2  mrg 	      *out_best_path = fg->make_epath (succ_fnode);
    517  1.1.1.2  mrg 	      if (flag_dump_analyzer_feasibility)
    518  1.1.1.2  mrg 		dump_feasible_path (target_enode, diag_idx, *fg, *succ_fnode);
    519  1.1.1.2  mrg 
    520  1.1.1.2  mrg 	      /* Success: stop the worklist iteration.  */
    521  1.1.1.2  mrg 	      return false;
    522  1.1.1.2  mrg 	    }
    523  1.1.1.2  mrg 	  else
    524  1.1.1.2  mrg 	    worklist->add_node (succ_fnode);
    525  1.1.1.2  mrg 	}
    526  1.1.1.2  mrg       else
    527  1.1.1.2  mrg 	{
    528  1.1.1.2  mrg 	  if (logger)
    529  1.1.1.2  mrg 	    logger->log ("infeasible");
    530  1.1.1.2  mrg 	  gcc_assert (rc);
    531  1.1.1.2  mrg 	  fg->add_feasibility_problem (fnode,
    532  1.1.1.2  mrg 				       succ_eedge,
    533  1.1.1.2  mrg 				       rc);
    534  1.1.1.2  mrg 
    535  1.1.1.2  mrg 	  /* Give up if there have been too many infeasible edges.  */
    536  1.1.1.2  mrg 	  if (fg->get_num_infeasible ()
    537  1.1.1.2  mrg 	      > (unsigned)param_analyzer_max_infeasible_edges)
    538  1.1.1.2  mrg 	    {
    539  1.1.1.2  mrg 	      if (logger)
    540  1.1.1.2  mrg 		logger->log ("too many infeasible edges (%i); giving up",
    541  1.1.1.2  mrg 			     fg->get_num_infeasible ());
    542  1.1.1.2  mrg 	      return false;
    543  1.1.1.2  mrg 	    }
    544  1.1.1.2  mrg 	}
    545  1.1.1.2  mrg     }
    546  1.1.1.2  mrg 
    547  1.1.1.2  mrg   /* Continue the worklist iteration.  */
    548  1.1.1.2  mrg   return true;
    549  1.1.1.2  mrg }
    550  1.1.1.2  mrg 
    551  1.1.1.2  mrg /* Helper class for epath_finder::dump_trimmed_graph
    552  1.1.1.2  mrg    to dump extra per-node information.
    553  1.1.1.2  mrg    Use SEP to add the length of the shortest path from each
    554  1.1.1.2  mrg    node to the target node to each node's dump.  */
    555  1.1.1.2  mrg 
    556  1.1.1.2  mrg class dump_eg_with_shortest_path : public eg_traits::dump_args_t
    557  1.1.1.2  mrg {
    558  1.1.1.2  mrg public:
    559  1.1.1.2  mrg   dump_eg_with_shortest_path
    560  1.1.1.2  mrg     (const exploded_graph &eg,
    561  1.1.1.2  mrg      const shortest_paths<eg_traits, exploded_path> &sep)
    562  1.1.1.2  mrg   : dump_args_t (eg),
    563  1.1.1.2  mrg     m_sep (sep)
    564  1.1.1.2  mrg   {
    565  1.1.1.2  mrg   }
    566  1.1.1.2  mrg 
    567  1.1.1.2  mrg   void dump_extra_info (const exploded_node *enode,
    568  1.1.1.2  mrg 			pretty_printer *pp) const FINAL OVERRIDE
    569  1.1.1.2  mrg   {
    570  1.1.1.2  mrg     pp_printf (pp, "sp: %i", m_sep.get_shortest_path (enode).length ());
    571  1.1.1.2  mrg     pp_newline (pp);
    572  1.1.1.2  mrg   }
    573  1.1.1.2  mrg 
    574  1.1.1.2  mrg private:
    575  1.1.1.2  mrg   const shortest_paths<eg_traits, exploded_path> &m_sep;
    576  1.1.1.2  mrg };
    577  1.1.1.2  mrg 
    578  1.1.1.2  mrg /* Dump TG to "BASE_NAME.DESC.DIAG_IDX.to-enN.tg.dot",
    579  1.1.1.2  mrg    annotating each node with the length of the shortest path
    580  1.1.1.2  mrg    from that node to TARGET_ENODE (using SEP).  */
    581  1.1.1.2  mrg 
    582  1.1.1.2  mrg void
    583  1.1.1.2  mrg epath_finder::
    584  1.1.1.2  mrg dump_trimmed_graph (const exploded_node *target_enode,
    585  1.1.1.2  mrg 		    const char *desc, unsigned diag_idx,
    586  1.1.1.2  mrg 		    const trimmed_graph &tg,
    587  1.1.1.2  mrg 		    const shortest_paths<eg_traits, exploded_path> &sep)
    588  1.1.1.2  mrg {
    589  1.1.1.2  mrg   auto_timevar tv (TV_ANALYZER_DUMP);
    590  1.1.1.2  mrg   dump_eg_with_shortest_path inner_args (m_eg, sep);
    591  1.1.1.2  mrg   trimmed_graph::dump_args_t args (inner_args);
    592  1.1.1.2  mrg   pretty_printer pp;
    593  1.1.1.2  mrg   pp_printf (&pp, "%s.%s.%i.to-en%i.tg.dot",
    594  1.1.1.2  mrg 	     dump_base_name, desc, diag_idx, target_enode->m_index);
    595  1.1.1.2  mrg   char *filename = xstrdup (pp_formatted_text (&pp));
    596  1.1.1.2  mrg   tg.dump_dot (filename, NULL, args);
    597  1.1.1.2  mrg   free (filename);
    598  1.1.1.2  mrg }
    599  1.1.1.2  mrg 
    600  1.1.1.2  mrg /* Dump FG to "BASE_NAME.DESC.DIAG_IDX.to-enN.fg.dot".  */
    601  1.1.1.2  mrg 
    602  1.1.1.2  mrg void
    603  1.1.1.2  mrg epath_finder::dump_feasible_graph (const exploded_node *target_enode,
    604  1.1.1.2  mrg 				   const char *desc, unsigned diag_idx,
    605  1.1.1.2  mrg 				   const feasible_graph &fg)
    606  1.1.1.2  mrg {
    607  1.1.1.2  mrg   auto_timevar tv (TV_ANALYZER_DUMP);
    608  1.1.1.2  mrg   exploded_graph::dump_args_t inner_args (m_eg);
    609  1.1.1.2  mrg   feasible_graph::dump_args_t args (inner_args);
    610  1.1.1.2  mrg   pretty_printer pp;
    611  1.1.1.2  mrg   pp_printf (&pp, "%s.%s.%i.to-en%i.fg.dot",
    612  1.1.1.2  mrg 	     dump_base_name, desc, diag_idx, target_enode->m_index);
    613  1.1.1.2  mrg   char *filename = xstrdup (pp_formatted_text (&pp));
    614  1.1.1.2  mrg   fg.dump_dot (filename, NULL, args);
    615  1.1.1.2  mrg   free (filename);
    616  1.1.1.2  mrg }
    617  1.1.1.2  mrg 
    618  1.1.1.2  mrg /* Dump the path to FNODE to "BASE_NAME.DIAG_IDX.to-enN.fpath.txt".  */
    619  1.1.1.2  mrg 
    620  1.1.1.2  mrg void
    621  1.1.1.2  mrg epath_finder::dump_feasible_path (const exploded_node *target_enode,
    622  1.1.1.2  mrg 				  unsigned diag_idx,
    623  1.1.1.2  mrg 				  const feasible_graph &fg,
    624  1.1.1.2  mrg 				  const feasible_node &fnode) const
    625  1.1.1.2  mrg {
    626  1.1.1.2  mrg   auto_timevar tv (TV_ANALYZER_DUMP);
    627  1.1.1.2  mrg   pretty_printer pp;
    628  1.1.1.2  mrg   pp_printf (&pp, "%s.%i.to-en%i.fpath.txt",
    629  1.1.1.2  mrg 	     dump_base_name, diag_idx, target_enode->m_index);
    630  1.1.1.2  mrg   char *filename = xstrdup (pp_formatted_text (&pp));
    631  1.1.1.2  mrg   fg.dump_feasible_path (fnode, filename);
    632  1.1.1.2  mrg   free (filename);
    633  1.1.1.2  mrg }
    634  1.1.1.2  mrg 
    635      1.1  mrg /* class saved_diagnostic.  */
    636      1.1  mrg 
    637      1.1  mrg /* saved_diagnostic's ctor.
    638      1.1  mrg    Take ownership of D and STMT_FINDER.  */
    639      1.1  mrg 
    640      1.1  mrg saved_diagnostic::saved_diagnostic (const state_machine *sm,
    641      1.1  mrg 				    const exploded_node *enode,
    642      1.1  mrg 				    const supernode *snode, const gimple *stmt,
    643      1.1  mrg 				    stmt_finder *stmt_finder,
    644  1.1.1.2  mrg 				    tree var,
    645  1.1.1.2  mrg 				    const svalue *sval,
    646  1.1.1.2  mrg 				    state_machine::state_t state,
    647  1.1.1.2  mrg 				    pending_diagnostic *d,
    648  1.1.1.2  mrg 				    unsigned idx)
    649      1.1  mrg : m_sm (sm), m_enode (enode), m_snode (snode), m_stmt (stmt),
    650      1.1  mrg  /* stmt_finder could be on-stack; we want our own copy that can
    651      1.1  mrg     outlive that.  */
    652      1.1  mrg   m_stmt_finder (stmt_finder ? stmt_finder->clone () : NULL),
    653  1.1.1.2  mrg   m_var (var), m_sval (sval), m_state (state),
    654      1.1  mrg   m_d (d), m_trailing_eedge (NULL),
    655  1.1.1.2  mrg   m_idx (idx),
    656  1.1.1.2  mrg   m_best_epath (NULL), m_problem (NULL),
    657  1.1.1.2  mrg   m_notes ()
    658      1.1  mrg {
    659      1.1  mrg   gcc_assert (m_stmt || m_stmt_finder);
    660      1.1  mrg 
    661      1.1  mrg   /* We must have an enode in order to be able to look for paths
    662      1.1  mrg      through the exploded_graph to this diagnostic.  */
    663      1.1  mrg   gcc_assert (m_enode);
    664      1.1  mrg }
    665      1.1  mrg 
    666      1.1  mrg /* saved_diagnostic's dtor.  */
    667      1.1  mrg 
    668      1.1  mrg saved_diagnostic::~saved_diagnostic ()
    669      1.1  mrg {
    670      1.1  mrg   delete m_stmt_finder;
    671      1.1  mrg   delete m_d;
    672  1.1.1.2  mrg   delete m_best_epath;
    673      1.1  mrg   delete m_problem;
    674      1.1  mrg }
    675      1.1  mrg 
    676      1.1  mrg bool
    677      1.1  mrg saved_diagnostic::operator== (const saved_diagnostic &other) const
    678      1.1  mrg {
    679  1.1.1.2  mrg   if (m_notes.length () != other.m_notes.length ())
    680  1.1.1.2  mrg     return false;
    681  1.1.1.2  mrg   for (unsigned i = 0; i < m_notes.length (); i++)
    682  1.1.1.2  mrg     if (!m_notes[i]->equal_p (*other.m_notes[i]))
    683  1.1.1.2  mrg       return false;
    684      1.1  mrg   return (m_sm == other.m_sm
    685      1.1  mrg 	  /* We don't compare m_enode.  */
    686      1.1  mrg 	  && m_snode == other.m_snode
    687      1.1  mrg 	  && m_stmt == other.m_stmt
    688      1.1  mrg 	  /* We don't compare m_stmt_finder.  */
    689      1.1  mrg 	  && pending_diagnostic::same_tree_p (m_var, other.m_var)
    690      1.1  mrg 	  && m_state == other.m_state
    691      1.1  mrg 	  && m_d->equal_p (*other.m_d)
    692      1.1  mrg 	  && m_trailing_eedge == other.m_trailing_eedge);
    693      1.1  mrg }
    694      1.1  mrg 
    695  1.1.1.2  mrg /* Add PN to this diagnostic, taking ownership of it.  */
    696  1.1.1.2  mrg 
    697  1.1.1.2  mrg void
    698  1.1.1.2  mrg saved_diagnostic::add_note (pending_note *pn)
    699  1.1.1.2  mrg {
    700  1.1.1.2  mrg   gcc_assert (pn);
    701  1.1.1.2  mrg   m_notes.safe_push (pn);
    702  1.1.1.2  mrg }
    703  1.1.1.2  mrg 
    704  1.1.1.2  mrg /* Return a new json::object of the form
    705  1.1.1.2  mrg    {"sm": optional str,
    706  1.1.1.2  mrg     "enode": int,
    707  1.1.1.2  mrg     "snode": int,
    708  1.1.1.2  mrg     "sval": optional str,
    709  1.1.1.2  mrg     "state": optional str,
    710  1.1.1.2  mrg     "path_length": optional int,
    711  1.1.1.2  mrg     "pending_diagnostic": str,
    712  1.1.1.2  mrg     "idx": int}.  */
    713  1.1.1.2  mrg 
    714  1.1.1.2  mrg json::object *
    715  1.1.1.2  mrg saved_diagnostic::to_json () const
    716  1.1.1.2  mrg {
    717  1.1.1.2  mrg   json::object *sd_obj = new json::object ();
    718  1.1.1.2  mrg 
    719  1.1.1.2  mrg   if (m_sm)
    720  1.1.1.2  mrg     sd_obj->set ("sm", new json::string (m_sm->get_name ()));
    721  1.1.1.2  mrg   sd_obj->set ("enode", new json::integer_number (m_enode->m_index));
    722  1.1.1.2  mrg   sd_obj->set ("snode", new json::integer_number (m_snode->m_index));
    723  1.1.1.2  mrg   if (m_sval)
    724  1.1.1.2  mrg     sd_obj->set ("sval", m_sval->to_json ());
    725  1.1.1.2  mrg   if (m_state)
    726  1.1.1.2  mrg     sd_obj->set ("state", m_state->to_json ());
    727  1.1.1.2  mrg   if (m_best_epath)
    728  1.1.1.2  mrg     sd_obj->set ("path_length", new json::integer_number (get_epath_length ()));
    729  1.1.1.2  mrg   sd_obj->set ("pending_diagnostic", new json::string (m_d->get_kind ()));
    730  1.1.1.2  mrg   sd_obj->set ("idx", new json::integer_number (m_idx));
    731  1.1.1.2  mrg 
    732  1.1.1.2  mrg   /* We're not yet JSONifying the following fields:
    733  1.1.1.2  mrg      const gimple *m_stmt;
    734  1.1.1.2  mrg      stmt_finder *m_stmt_finder;
    735  1.1.1.2  mrg      tree m_var;
    736  1.1.1.2  mrg      exploded_edge *m_trailing_eedge;
    737  1.1.1.2  mrg      enum status m_status;
    738  1.1.1.2  mrg      feasibility_problem *m_problem;
    739  1.1.1.2  mrg      auto_delete_vec <pending_note> m_notes;
    740  1.1.1.2  mrg   */
    741  1.1.1.2  mrg 
    742  1.1.1.2  mrg   return sd_obj;
    743  1.1.1.2  mrg }
    744  1.1.1.2  mrg 
    745  1.1.1.2  mrg /* Dump this to PP in a form suitable for use as an id in .dot output.  */
    746  1.1.1.2  mrg 
    747  1.1.1.2  mrg void
    748  1.1.1.2  mrg saved_diagnostic::dump_dot_id (pretty_printer *pp) const
    749  1.1.1.2  mrg {
    750  1.1.1.2  mrg   pp_printf (pp, "sd_%i", m_idx);
    751  1.1.1.2  mrg }
    752  1.1.1.2  mrg 
    753  1.1.1.2  mrg /* Dump this to PP in a form suitable for use as a node in .dot output.  */
    754  1.1.1.2  mrg 
    755  1.1.1.2  mrg void
    756  1.1.1.2  mrg saved_diagnostic::dump_as_dot_node (pretty_printer *pp) const
    757  1.1.1.2  mrg {
    758  1.1.1.2  mrg   dump_dot_id (pp);
    759  1.1.1.2  mrg   pp_printf (pp,
    760  1.1.1.2  mrg 	     " [shape=none,margin=0,style=filled,fillcolor=\"red\",label=\"");
    761  1.1.1.2  mrg   pp_write_text_to_stream (pp);
    762  1.1.1.2  mrg 
    763  1.1.1.2  mrg   /* Node label.  */
    764  1.1.1.2  mrg   pp_printf (pp, "DIAGNOSTIC: %s (sd: %i)\n",
    765  1.1.1.2  mrg 	     m_d->get_kind (), m_idx);
    766  1.1.1.2  mrg   if (m_sm)
    767  1.1.1.2  mrg     {
    768  1.1.1.2  mrg       pp_printf (pp, "sm: %s", m_sm->get_name ());
    769  1.1.1.2  mrg       if (m_state)
    770  1.1.1.2  mrg 	{
    771  1.1.1.2  mrg 	  pp_printf (pp, "; state: ");
    772  1.1.1.2  mrg 	  m_state->dump_to_pp (pp);
    773  1.1.1.2  mrg 	}
    774  1.1.1.2  mrg       pp_newline (pp);
    775  1.1.1.2  mrg     }
    776  1.1.1.2  mrg   if (m_stmt)
    777  1.1.1.2  mrg     {
    778  1.1.1.2  mrg       pp_string (pp, "stmt: ");
    779  1.1.1.2  mrg       pp_gimple_stmt_1 (pp, m_stmt, 0, (dump_flags_t)0);
    780  1.1.1.2  mrg       pp_newline (pp);
    781  1.1.1.2  mrg     }
    782  1.1.1.2  mrg   if (m_var)
    783  1.1.1.2  mrg     pp_printf (pp, "var: %qE\n", m_var);
    784  1.1.1.2  mrg   if (m_sval)
    785  1.1.1.2  mrg     {
    786  1.1.1.2  mrg       pp_string (pp, "sval: ");
    787  1.1.1.2  mrg       m_sval->dump_to_pp (pp, true);
    788  1.1.1.2  mrg       pp_newline (pp);
    789  1.1.1.2  mrg     }
    790  1.1.1.2  mrg   if (m_best_epath)
    791  1.1.1.2  mrg     pp_printf (pp, "path length: %i\n", get_epath_length ());
    792  1.1.1.2  mrg 
    793  1.1.1.2  mrg   pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
    794  1.1.1.2  mrg   pp_string (pp, "\"];\n\n");
    795  1.1.1.2  mrg 
    796  1.1.1.2  mrg   /* Show links to duplicates.  */
    797  1.1.1.2  mrg   for (auto iter : m_duplicates)
    798  1.1.1.2  mrg     {
    799  1.1.1.2  mrg       dump_dot_id (pp);
    800  1.1.1.2  mrg       pp_string (pp, " -> ");
    801  1.1.1.2  mrg       iter->dump_dot_id (pp);
    802  1.1.1.2  mrg       pp_string (pp, " [style=\"dotted\" arrowhead=\"none\"];");
    803  1.1.1.2  mrg       pp_newline (pp);
    804  1.1.1.2  mrg     }
    805  1.1.1.2  mrg }
    806  1.1.1.2  mrg 
    807  1.1.1.2  mrg /* Use PF to find the best exploded_path for this saved_diagnostic,
    808  1.1.1.2  mrg    and store it in m_best_epath.
    809  1.1.1.2  mrg    If m_stmt is still NULL, use m_stmt_finder on the epath to populate
    810  1.1.1.2  mrg    m_stmt.
    811  1.1.1.2  mrg    Return true if a best path was found.  */
    812  1.1.1.2  mrg 
    813  1.1.1.2  mrg bool
    814  1.1.1.2  mrg saved_diagnostic::calc_best_epath (epath_finder *pf)
    815  1.1.1.2  mrg {
    816  1.1.1.2  mrg   logger *logger = pf->get_logger ();
    817  1.1.1.2  mrg   LOG_SCOPE (logger);
    818  1.1.1.2  mrg   delete m_best_epath;
    819  1.1.1.2  mrg   delete m_problem;
    820  1.1.1.2  mrg   m_problem = NULL;
    821  1.1.1.2  mrg 
    822  1.1.1.2  mrg   m_best_epath = pf->get_best_epath (m_enode, m_d->get_kind (), m_idx,
    823  1.1.1.2  mrg 				     &m_problem);
    824  1.1.1.2  mrg 
    825  1.1.1.2  mrg   /* Handle failure to find a feasible path.  */
    826  1.1.1.2  mrg   if (m_best_epath == NULL)
    827  1.1.1.2  mrg     return false;
    828  1.1.1.2  mrg 
    829  1.1.1.2  mrg   gcc_assert (m_best_epath);
    830  1.1.1.2  mrg   if (m_stmt == NULL)
    831  1.1.1.2  mrg     {
    832  1.1.1.2  mrg       gcc_assert (m_stmt_finder);
    833  1.1.1.2  mrg       m_stmt = m_stmt_finder->find_stmt (*m_best_epath);
    834  1.1.1.2  mrg     }
    835  1.1.1.2  mrg   gcc_assert (m_stmt);
    836  1.1.1.2  mrg 
    837  1.1.1.2  mrg   return true;
    838  1.1.1.2  mrg }
    839  1.1.1.2  mrg 
    840  1.1.1.2  mrg unsigned
    841  1.1.1.2  mrg saved_diagnostic::get_epath_length () const
    842  1.1.1.2  mrg {
    843  1.1.1.2  mrg   gcc_assert (m_best_epath);
    844  1.1.1.2  mrg   return m_best_epath->length ();
    845  1.1.1.2  mrg }
    846  1.1.1.2  mrg 
    847  1.1.1.2  mrg /* Record that OTHER (and its duplicates) are duplicates
    848  1.1.1.2  mrg    of this saved_diagnostic.  */
    849  1.1.1.2  mrg 
    850  1.1.1.2  mrg void
    851  1.1.1.2  mrg saved_diagnostic::add_duplicate (saved_diagnostic *other)
    852  1.1.1.2  mrg {
    853  1.1.1.2  mrg   gcc_assert (other);
    854  1.1.1.2  mrg   m_duplicates.reserve (m_duplicates.length ()
    855  1.1.1.2  mrg 			+ other->m_duplicates.length ()
    856  1.1.1.2  mrg 			+ 1);
    857  1.1.1.2  mrg   m_duplicates.splice (other->m_duplicates);
    858  1.1.1.2  mrg   other->m_duplicates.truncate (0);
    859  1.1.1.2  mrg   m_duplicates.safe_push (other);
    860  1.1.1.2  mrg }
    861  1.1.1.2  mrg 
    862  1.1.1.2  mrg /* Return true if this diagnostic supercedes OTHER, and that OTHER should
    863  1.1.1.2  mrg    therefore not be emitted.  */
    864  1.1.1.2  mrg 
    865  1.1.1.2  mrg bool
    866  1.1.1.2  mrg saved_diagnostic::supercedes_p (const saved_diagnostic &other) const
    867  1.1.1.2  mrg {
    868  1.1.1.2  mrg   /* They should be at the same stmt.  */
    869  1.1.1.2  mrg   if (m_stmt != other.m_stmt)
    870  1.1.1.2  mrg     return false;
    871  1.1.1.2  mrg   return m_d->supercedes_p (*other.m_d);
    872  1.1.1.2  mrg }
    873  1.1.1.2  mrg 
    874  1.1.1.2  mrg /* Emit any pending notes owned by this diagnostic.  */
    875  1.1.1.2  mrg 
    876  1.1.1.2  mrg void
    877  1.1.1.2  mrg saved_diagnostic::emit_any_notes () const
    878  1.1.1.2  mrg {
    879  1.1.1.2  mrg   for (auto pn : m_notes)
    880  1.1.1.2  mrg     pn->emit ();
    881  1.1.1.2  mrg }
    882  1.1.1.2  mrg 
    883      1.1  mrg /* State for building a checker_path from a particular exploded_path.
    884      1.1  mrg    In particular, this precomputes reachability information: the set of
    885      1.1  mrg    source enodes for which a path be found to the diagnostic enode.  */
    886      1.1  mrg 
    887      1.1  mrg class path_builder
    888      1.1  mrg {
    889      1.1  mrg public:
    890      1.1  mrg   path_builder (const exploded_graph &eg,
    891  1.1.1.2  mrg 		const exploded_path &epath,
    892  1.1.1.2  mrg 		const feasibility_problem *problem,
    893  1.1.1.2  mrg 		const saved_diagnostic &sd)
    894      1.1  mrg   : m_eg (eg),
    895      1.1  mrg     m_diag_enode (epath.get_final_enode ()),
    896  1.1.1.2  mrg     m_sd (sd),
    897  1.1.1.2  mrg     m_reachability (eg, m_diag_enode),
    898  1.1.1.2  mrg     m_feasibility_problem (problem)
    899      1.1  mrg   {}
    900      1.1  mrg 
    901      1.1  mrg   const exploded_node *get_diag_node () const { return m_diag_enode; }
    902      1.1  mrg 
    903  1.1.1.2  mrg   pending_diagnostic *get_pending_diagnostic () const
    904  1.1.1.2  mrg   {
    905  1.1.1.2  mrg     return m_sd.m_d;
    906  1.1.1.2  mrg   }
    907  1.1.1.2  mrg 
    908      1.1  mrg   bool reachable_from_p (const exploded_node *src_enode) const
    909      1.1  mrg   {
    910      1.1  mrg     return m_reachability.reachable_from_p (src_enode);
    911      1.1  mrg   }
    912      1.1  mrg 
    913      1.1  mrg   const extrinsic_state &get_ext_state () const { return m_eg.get_ext_state (); }
    914      1.1  mrg 
    915  1.1.1.2  mrg   const feasibility_problem *get_feasibility_problem () const
    916  1.1.1.2  mrg   {
    917  1.1.1.2  mrg     return m_feasibility_problem;
    918  1.1.1.2  mrg   }
    919  1.1.1.2  mrg 
    920  1.1.1.2  mrg   const state_machine *get_sm () const { return m_sd.m_sm; }
    921  1.1.1.2  mrg 
    922      1.1  mrg private:
    923      1.1  mrg   typedef reachability<eg_traits> enode_reachability;
    924      1.1  mrg 
    925      1.1  mrg   const exploded_graph &m_eg;
    926      1.1  mrg 
    927      1.1  mrg   /* The enode where the diagnostic occurs.  */
    928      1.1  mrg   const exploded_node *m_diag_enode;
    929      1.1  mrg 
    930  1.1.1.2  mrg   const saved_diagnostic &m_sd;
    931  1.1.1.2  mrg 
    932      1.1  mrg   /* Precompute all enodes from which the diagnostic is reachable.  */
    933      1.1  mrg   enode_reachability m_reachability;
    934  1.1.1.2  mrg 
    935  1.1.1.2  mrg   const feasibility_problem *m_feasibility_problem;
    936      1.1  mrg };
    937      1.1  mrg 
    938  1.1.1.2  mrg /* Determine the emission location for PD at STMT in FUN.  */
    939  1.1.1.2  mrg 
    940  1.1.1.2  mrg static location_t
    941  1.1.1.2  mrg get_emission_location (const gimple *stmt, function *fun,
    942  1.1.1.2  mrg 		       const pending_diagnostic &pd)
    943  1.1.1.2  mrg {
    944  1.1.1.2  mrg   location_t loc = get_stmt_location (stmt, fun);
    945  1.1.1.2  mrg 
    946  1.1.1.2  mrg   /* Allow the pending_diagnostic to fix up the location.  */
    947  1.1.1.2  mrg   loc = pd.fixup_location (loc);
    948  1.1.1.2  mrg 
    949  1.1.1.2  mrg   return loc;
    950  1.1.1.2  mrg }
    951  1.1.1.2  mrg 
    952      1.1  mrg /* class diagnostic_manager.  */
    953      1.1  mrg 
    954      1.1  mrg /* diagnostic_manager's ctor.  */
    955      1.1  mrg 
    956  1.1.1.2  mrg diagnostic_manager::diagnostic_manager (logger *logger, engine *eng,
    957  1.1.1.2  mrg 					int verbosity)
    958  1.1.1.2  mrg : log_user (logger), m_eng (eng), m_verbosity (verbosity),
    959  1.1.1.2  mrg   m_num_disabled_diagnostics (0)
    960      1.1  mrg {
    961      1.1  mrg }
    962      1.1  mrg 
    963  1.1.1.2  mrg /* Queue pending_diagnostic D at ENODE for later emission.
    964  1.1.1.2  mrg    Return true/false signifying if the diagnostic was actually added.
    965  1.1.1.2  mrg    Take ownership of D (or delete it).  */
    966      1.1  mrg 
    967  1.1.1.2  mrg bool
    968      1.1  mrg diagnostic_manager::add_diagnostic (const state_machine *sm,
    969  1.1.1.2  mrg 				    exploded_node *enode,
    970      1.1  mrg 				    const supernode *snode, const gimple *stmt,
    971      1.1  mrg 				    stmt_finder *finder,
    972  1.1.1.2  mrg 				    tree var,
    973  1.1.1.2  mrg 				    const svalue *sval,
    974  1.1.1.2  mrg 				    state_machine::state_t state,
    975      1.1  mrg 				    pending_diagnostic *d)
    976      1.1  mrg {
    977      1.1  mrg   LOG_FUNC (get_logger ());
    978      1.1  mrg 
    979      1.1  mrg   /* We must have an enode in order to be able to look for paths
    980      1.1  mrg      through the exploded_graph to the diagnostic.  */
    981      1.1  mrg   gcc_assert (enode);
    982      1.1  mrg 
    983  1.1.1.2  mrg   /* If this warning is ultimately going to be rejected by a -Wno-analyzer-*
    984  1.1.1.2  mrg      flag, reject it now.
    985  1.1.1.2  mrg      We can only do this for diagnostics where we already know the stmt,
    986  1.1.1.2  mrg      and thus can determine the emission location.  */
    987  1.1.1.2  mrg   if (stmt)
    988  1.1.1.2  mrg     {
    989  1.1.1.2  mrg       location_t loc = get_emission_location (stmt, snode->m_fun, *d);
    990  1.1.1.2  mrg       int option = d->get_controlling_option ();
    991  1.1.1.2  mrg       if (!warning_enabled_at (loc, option))
    992  1.1.1.2  mrg 	{
    993  1.1.1.2  mrg 	  if (get_logger ())
    994  1.1.1.2  mrg 	    get_logger ()->log ("rejecting disabled warning %qs",
    995  1.1.1.2  mrg 				d->get_kind ());
    996  1.1.1.2  mrg 	  delete d;
    997  1.1.1.2  mrg 	  m_num_disabled_diagnostics++;
    998  1.1.1.2  mrg 	  return false;
    999  1.1.1.2  mrg 	}
   1000  1.1.1.2  mrg     }
   1001  1.1.1.2  mrg 
   1002      1.1  mrg   saved_diagnostic *sd
   1003  1.1.1.2  mrg     = new saved_diagnostic (sm, enode, snode, stmt, finder, var, sval,
   1004  1.1.1.2  mrg 			    state, d, m_saved_diagnostics.length ());
   1005      1.1  mrg   m_saved_diagnostics.safe_push (sd);
   1006  1.1.1.2  mrg   enode->add_diagnostic (sd);
   1007      1.1  mrg   if (get_logger ())
   1008  1.1.1.2  mrg     log ("adding saved diagnostic %i at SN %i to EN %i: %qs",
   1009  1.1.1.2  mrg 	 sd->get_index (),
   1010  1.1.1.2  mrg 	 snode->m_index, enode->m_index, d->get_kind ());
   1011  1.1.1.2  mrg   return true;
   1012      1.1  mrg }
   1013      1.1  mrg 
   1014  1.1.1.2  mrg /* Queue pending_diagnostic D at ENODE for later emission.
   1015  1.1.1.2  mrg    Return true/false signifying if the diagnostic was actually added.
   1016  1.1.1.2  mrg    Take ownership of D (or delete it).  */
   1017      1.1  mrg 
   1018  1.1.1.2  mrg bool
   1019  1.1.1.2  mrg diagnostic_manager::add_diagnostic (exploded_node *enode,
   1020      1.1  mrg 				    const supernode *snode, const gimple *stmt,
   1021      1.1  mrg 				    stmt_finder *finder,
   1022      1.1  mrg 				    pending_diagnostic *d)
   1023      1.1  mrg {
   1024      1.1  mrg   gcc_assert (enode);
   1025  1.1.1.2  mrg   return add_diagnostic (NULL, enode, snode, stmt, finder, NULL_TREE,
   1026  1.1.1.2  mrg 			 NULL, 0, d);
   1027  1.1.1.2  mrg }
   1028  1.1.1.2  mrg 
   1029  1.1.1.2  mrg /* Add PN to the most recent saved_diagnostic.  */
   1030  1.1.1.2  mrg 
   1031  1.1.1.2  mrg void
   1032  1.1.1.2  mrg diagnostic_manager::add_note (pending_note *pn)
   1033  1.1.1.2  mrg {
   1034  1.1.1.2  mrg   LOG_FUNC (get_logger ());
   1035  1.1.1.2  mrg   gcc_assert (pn);
   1036  1.1.1.2  mrg 
   1037  1.1.1.2  mrg   /* Get most recent saved_diagnostic.  */
   1038  1.1.1.2  mrg   gcc_assert (m_saved_diagnostics.length () > 0);
   1039  1.1.1.2  mrg   saved_diagnostic *sd = m_saved_diagnostics[m_saved_diagnostics.length () - 1];
   1040  1.1.1.2  mrg   sd->add_note (pn);
   1041  1.1.1.2  mrg }
   1042  1.1.1.2  mrg 
   1043  1.1.1.2  mrg /* Return a new json::object of the form
   1044  1.1.1.2  mrg    {"diagnostics"  : [obj for saved_diagnostic]}.  */
   1045  1.1.1.2  mrg 
   1046  1.1.1.2  mrg json::object *
   1047  1.1.1.2  mrg diagnostic_manager::to_json () const
   1048  1.1.1.2  mrg {
   1049  1.1.1.2  mrg   json::object *dm_obj = new json::object ();
   1050  1.1.1.2  mrg 
   1051  1.1.1.2  mrg   {
   1052  1.1.1.2  mrg     json::array *sd_arr = new json::array ();
   1053  1.1.1.2  mrg     int i;
   1054  1.1.1.2  mrg     saved_diagnostic *sd;
   1055  1.1.1.2  mrg     FOR_EACH_VEC_ELT (m_saved_diagnostics, i, sd)
   1056  1.1.1.2  mrg       sd_arr->append (sd->to_json ());
   1057  1.1.1.2  mrg     dm_obj->set ("diagnostics", sd_arr);
   1058  1.1.1.2  mrg   }
   1059  1.1.1.2  mrg 
   1060  1.1.1.2  mrg   return dm_obj;
   1061      1.1  mrg }
   1062      1.1  mrg 
   1063      1.1  mrg /* A class for identifying sets of duplicated pending_diagnostic.
   1064      1.1  mrg 
   1065  1.1.1.2  mrg    We want to find the simplest saved_diagnostic amongst those that share a
   1066      1.1  mrg    dedupe_key.  */
   1067      1.1  mrg 
   1068      1.1  mrg class dedupe_key
   1069      1.1  mrg {
   1070      1.1  mrg public:
   1071  1.1.1.2  mrg   dedupe_key (const saved_diagnostic &sd)
   1072      1.1  mrg   : m_sd (sd), m_stmt (sd.m_stmt)
   1073      1.1  mrg   {
   1074      1.1  mrg     gcc_assert (m_stmt);
   1075      1.1  mrg   }
   1076      1.1  mrg 
   1077      1.1  mrg   hashval_t hash () const
   1078      1.1  mrg   {
   1079      1.1  mrg     inchash::hash hstate;
   1080      1.1  mrg     hstate.add_ptr (m_stmt);
   1081      1.1  mrg     // TODO: m_sd
   1082      1.1  mrg     return hstate.end ();
   1083      1.1  mrg   }
   1084      1.1  mrg   bool operator== (const dedupe_key &other) const
   1085      1.1  mrg   {
   1086      1.1  mrg     return (m_sd == other.m_sd
   1087      1.1  mrg 	    && m_stmt == other.m_stmt);
   1088      1.1  mrg   }
   1089      1.1  mrg 
   1090      1.1  mrg   location_t get_location () const
   1091      1.1  mrg   {
   1092      1.1  mrg     return m_stmt->location;
   1093      1.1  mrg   }
   1094      1.1  mrg 
   1095      1.1  mrg   /* A qsort comparator for use by dedupe_winners::emit_best
   1096      1.1  mrg      to sort them into location_t order.  */
   1097      1.1  mrg 
   1098      1.1  mrg   static int
   1099      1.1  mrg   comparator (const void *p1, const void *p2)
   1100      1.1  mrg   {
   1101      1.1  mrg     const dedupe_key *pk1 = *(const dedupe_key * const *)p1;
   1102      1.1  mrg     const dedupe_key *pk2 = *(const dedupe_key * const *)p2;
   1103      1.1  mrg 
   1104      1.1  mrg     location_t loc1 = pk1->get_location ();
   1105      1.1  mrg     location_t loc2 = pk2->get_location ();
   1106      1.1  mrg 
   1107  1.1.1.2  mrg     if (int cmp = linemap_compare_locations (line_table, loc2, loc1))
   1108  1.1.1.2  mrg       return cmp;
   1109  1.1.1.2  mrg     if (int cmp = ((int)pk1->m_sd.get_epath_length ()
   1110  1.1.1.2  mrg 		   - (int)pk2->m_sd.get_epath_length ()))
   1111  1.1.1.2  mrg       return cmp;
   1112  1.1.1.2  mrg     if (int cmp = strcmp (pk1->m_sd.m_d->get_kind (),
   1113  1.1.1.2  mrg 			  pk2->m_sd.m_d->get_kind ()))
   1114  1.1.1.2  mrg       return cmp;
   1115  1.1.1.2  mrg     return 0;
   1116      1.1  mrg   }
   1117      1.1  mrg 
   1118      1.1  mrg   const saved_diagnostic &m_sd;
   1119      1.1  mrg   const gimple *m_stmt;
   1120      1.1  mrg };
   1121      1.1  mrg 
   1122      1.1  mrg /* Traits for use by dedupe_winners.  */
   1123      1.1  mrg 
   1124      1.1  mrg class dedupe_hash_map_traits
   1125      1.1  mrg {
   1126      1.1  mrg public:
   1127      1.1  mrg   typedef const dedupe_key *key_type;
   1128  1.1.1.2  mrg   typedef saved_diagnostic *value_type;
   1129  1.1.1.2  mrg   typedef saved_diagnostic *compare_type;
   1130      1.1  mrg 
   1131      1.1  mrg   static inline hashval_t hash (const key_type &v)
   1132      1.1  mrg   {
   1133      1.1  mrg     return v->hash ();
   1134      1.1  mrg   }
   1135      1.1  mrg   static inline bool equal_keys (const key_type &k1, const key_type &k2)
   1136      1.1  mrg   {
   1137      1.1  mrg     return *k1 == *k2;
   1138      1.1  mrg   }
   1139      1.1  mrg   template <typename T>
   1140      1.1  mrg   static inline void remove (T &)
   1141      1.1  mrg   {
   1142      1.1  mrg     // TODO
   1143      1.1  mrg   }
   1144      1.1  mrg   template <typename T>
   1145      1.1  mrg   static inline void mark_deleted (T &entry)
   1146      1.1  mrg   {
   1147      1.1  mrg     entry.m_key = reinterpret_cast<key_type> (1);
   1148      1.1  mrg   }
   1149      1.1  mrg   template <typename T>
   1150      1.1  mrg   static inline void mark_empty (T &entry)
   1151      1.1  mrg   {
   1152      1.1  mrg     entry.m_key = NULL;
   1153      1.1  mrg   }
   1154      1.1  mrg   template <typename T>
   1155      1.1  mrg   static inline bool is_deleted (const T &entry)
   1156      1.1  mrg   {
   1157      1.1  mrg     return entry.m_key == reinterpret_cast<key_type> (1);
   1158      1.1  mrg   }
   1159      1.1  mrg   template <typename T>
   1160      1.1  mrg   static inline bool is_empty (const T &entry)
   1161      1.1  mrg   {
   1162      1.1  mrg     return entry.m_key == NULL;
   1163      1.1  mrg   }
   1164      1.1  mrg   static const bool empty_zero_p = true;
   1165      1.1  mrg };
   1166      1.1  mrg 
   1167      1.1  mrg /* A class for deduplicating diagnostics and finding (and emitting) the
   1168  1.1.1.2  mrg    best saved_diagnostic within each partition.  */
   1169      1.1  mrg 
   1170      1.1  mrg class dedupe_winners
   1171      1.1  mrg {
   1172      1.1  mrg public:
   1173      1.1  mrg   ~dedupe_winners ()
   1174      1.1  mrg   {
   1175  1.1.1.2  mrg     /* Delete all keys, but not the saved_diagnostics.  */
   1176      1.1  mrg     for (map_t::iterator iter = m_map.begin ();
   1177      1.1  mrg 	 iter != m_map.end ();
   1178      1.1  mrg 	 ++iter)
   1179  1.1.1.2  mrg       delete (*iter).first;
   1180      1.1  mrg   }
   1181      1.1  mrg 
   1182  1.1.1.2  mrg   /* Determine an exploded_path for SD using PF and, if it's feasible,
   1183  1.1.1.2  mrg      determine if SD is the best seen so far for its dedupe_key.
   1184  1.1.1.2  mrg      Record the winning SD for each dedupe_key.  */
   1185      1.1  mrg 
   1186      1.1  mrg   void add (logger *logger,
   1187  1.1.1.2  mrg 	    epath_finder *pf,
   1188      1.1  mrg 	    saved_diagnostic *sd)
   1189      1.1  mrg   {
   1190  1.1.1.2  mrg     /* Determine best epath for SD.  */
   1191  1.1.1.2  mrg     if (!sd->calc_best_epath (pf))
   1192  1.1.1.2  mrg       return;
   1193      1.1  mrg 
   1194  1.1.1.2  mrg     dedupe_key *key = new dedupe_key (*sd);
   1195  1.1.1.2  mrg     if (saved_diagnostic **slot = m_map.get (key))
   1196      1.1  mrg       {
   1197      1.1  mrg 	if (logger)
   1198      1.1  mrg 	  logger->log ("already have this dedupe_key");
   1199      1.1  mrg 
   1200  1.1.1.2  mrg 	saved_diagnostic *cur_best_sd = *slot;
   1201      1.1  mrg 
   1202  1.1.1.2  mrg 	if (sd->get_epath_length () < cur_best_sd->get_epath_length ())
   1203      1.1  mrg 	  {
   1204      1.1  mrg 	    /* We've got a shorter path for the key; replace
   1205  1.1.1.2  mrg 	       the current candidate, marking it as a duplicate of SD.  */
   1206      1.1  mrg 	    if (logger)
   1207      1.1  mrg 	      logger->log ("length %i is better than existing length %i;"
   1208      1.1  mrg 			   " taking over this dedupe_key",
   1209  1.1.1.2  mrg 			   sd->get_epath_length (),
   1210  1.1.1.2  mrg 			   cur_best_sd->get_epath_length ());
   1211  1.1.1.2  mrg 	    sd->add_duplicate (cur_best_sd);
   1212  1.1.1.2  mrg 	    *slot = sd;
   1213      1.1  mrg 	  }
   1214      1.1  mrg 	else
   1215  1.1.1.2  mrg 	  /* We haven't beaten the current best candidate; add SD
   1216  1.1.1.2  mrg 	     as a duplicate of it.  */
   1217      1.1  mrg 	  {
   1218      1.1  mrg 	    if (logger)
   1219      1.1  mrg 	      logger->log ("length %i isn't better than existing length %i;"
   1220      1.1  mrg 			   " dropping this candidate",
   1221  1.1.1.2  mrg 			   sd->get_epath_length (),
   1222  1.1.1.2  mrg 			   cur_best_sd->get_epath_length ());
   1223  1.1.1.2  mrg 	    cur_best_sd->add_duplicate (sd);
   1224      1.1  mrg 	  }
   1225      1.1  mrg 	delete key;
   1226      1.1  mrg       }
   1227      1.1  mrg     else
   1228      1.1  mrg       {
   1229      1.1  mrg 	/* This is the first candidate for this key.  */
   1230  1.1.1.2  mrg 	m_map.put (key, sd);
   1231      1.1  mrg 	if (logger)
   1232      1.1  mrg 	  logger->log ("first candidate for this dedupe_key");
   1233      1.1  mrg       }
   1234      1.1  mrg   }
   1235      1.1  mrg 
   1236  1.1.1.2  mrg   /* Handle interactions between the dedupe winners, so that some
   1237  1.1.1.2  mrg      diagnostics can supercede others (of different kinds).
   1238  1.1.1.2  mrg 
   1239  1.1.1.2  mrg      We want use-after-free to supercede use-of-unitialized-value,
   1240  1.1.1.2  mrg      so that if we have these at the same stmt, we don't emit
   1241  1.1.1.2  mrg      a use-of-uninitialized, just the use-after-free.  */
   1242  1.1.1.2  mrg 
   1243  1.1.1.2  mrg   void handle_interactions (diagnostic_manager *dm)
   1244  1.1.1.2  mrg   {
   1245  1.1.1.2  mrg     LOG_SCOPE (dm->get_logger ());
   1246  1.1.1.2  mrg     auto_vec<const dedupe_key *> superceded;
   1247  1.1.1.2  mrg     for (auto outer : m_map)
   1248  1.1.1.2  mrg       {
   1249  1.1.1.2  mrg 	const saved_diagnostic *outer_sd = outer.second;
   1250  1.1.1.2  mrg 	for (auto inner : m_map)
   1251  1.1.1.2  mrg 	  {
   1252  1.1.1.2  mrg 	    const saved_diagnostic *inner_sd = inner.second;
   1253  1.1.1.2  mrg 	    if (inner_sd->supercedes_p (*outer_sd))
   1254  1.1.1.2  mrg 	      {
   1255  1.1.1.2  mrg 		superceded.safe_push (outer.first);
   1256  1.1.1.2  mrg 		if (dm->get_logger ())
   1257  1.1.1.2  mrg 		  dm->log ("sd[%i] \"%s\" superceded by sd[%i] \"%s\"",
   1258  1.1.1.2  mrg 			   outer_sd->get_index (), outer_sd->m_d->get_kind (),
   1259  1.1.1.2  mrg 			   inner_sd->get_index (), inner_sd->m_d->get_kind ());
   1260  1.1.1.2  mrg 		break;
   1261  1.1.1.2  mrg 	      }
   1262  1.1.1.2  mrg 	  }
   1263  1.1.1.2  mrg       }
   1264  1.1.1.2  mrg     for (auto iter : superceded)
   1265  1.1.1.2  mrg       m_map.remove (iter);
   1266  1.1.1.2  mrg   }
   1267  1.1.1.2  mrg 
   1268      1.1  mrg  /* Emit the simplest diagnostic within each set.  */
   1269      1.1  mrg 
   1270      1.1  mrg   void emit_best (diagnostic_manager *dm,
   1271      1.1  mrg 		  const exploded_graph &eg)
   1272      1.1  mrg   {
   1273      1.1  mrg     LOG_SCOPE (dm->get_logger ());
   1274      1.1  mrg 
   1275      1.1  mrg     /* Get keys into a vec for sorting.  */
   1276      1.1  mrg     auto_vec<const dedupe_key *> keys (m_map.elements ());
   1277      1.1  mrg     for (map_t::iterator iter = m_map.begin ();
   1278      1.1  mrg 	 iter != m_map.end ();
   1279      1.1  mrg 	 ++iter)
   1280      1.1  mrg       keys.quick_push ((*iter).first);
   1281      1.1  mrg 
   1282      1.1  mrg     dm->log ("# keys after de-duplication: %i", keys.length ());
   1283      1.1  mrg 
   1284      1.1  mrg     /* Sort into a good emission order.  */
   1285      1.1  mrg     keys.qsort (dedupe_key::comparator);
   1286      1.1  mrg 
   1287  1.1.1.2  mrg     /* Emit the best saved_diagnostics for each key.  */
   1288      1.1  mrg     int i;
   1289      1.1  mrg     const dedupe_key *key;
   1290      1.1  mrg     FOR_EACH_VEC_ELT (keys, i, key)
   1291      1.1  mrg       {
   1292  1.1.1.2  mrg 	saved_diagnostic **slot = m_map.get (key);
   1293      1.1  mrg 	gcc_assert (*slot);
   1294  1.1.1.2  mrg 	const saved_diagnostic *sd = *slot;
   1295  1.1.1.2  mrg 	dm->emit_saved_diagnostic (eg, *sd);
   1296      1.1  mrg       }
   1297      1.1  mrg   }
   1298      1.1  mrg 
   1299      1.1  mrg private:
   1300  1.1.1.2  mrg   /* This maps from each dedupe_key to a current best saved_diagnostic.  */
   1301      1.1  mrg 
   1302  1.1.1.2  mrg   typedef hash_map<const dedupe_key *, saved_diagnostic *,
   1303      1.1  mrg 		   dedupe_hash_map_traits> map_t;
   1304      1.1  mrg   map_t m_map;
   1305      1.1  mrg };
   1306      1.1  mrg 
   1307      1.1  mrg /* Emit all saved diagnostics.  */
   1308      1.1  mrg 
   1309      1.1  mrg void
   1310      1.1  mrg diagnostic_manager::emit_saved_diagnostics (const exploded_graph &eg)
   1311      1.1  mrg {
   1312      1.1  mrg   LOG_SCOPE (get_logger ());
   1313      1.1  mrg   auto_timevar tv (TV_ANALYZER_DIAGNOSTICS);
   1314      1.1  mrg   log ("# saved diagnostics: %i", m_saved_diagnostics.length ());
   1315  1.1.1.2  mrg   log ("# disabled diagnostics: %i", m_num_disabled_diagnostics);
   1316      1.1  mrg   if (get_logger ())
   1317      1.1  mrg     {
   1318      1.1  mrg       unsigned i;
   1319      1.1  mrg       saved_diagnostic *sd;
   1320      1.1  mrg       FOR_EACH_VEC_ELT (m_saved_diagnostics, i, sd)
   1321      1.1  mrg 	log ("[%i] sd: %qs at EN: %i, SN: %i",
   1322      1.1  mrg 	     i, sd->m_d->get_kind (), sd->m_enode->m_index,
   1323      1.1  mrg 	     sd->m_snode->m_index);
   1324      1.1  mrg     }
   1325      1.1  mrg 
   1326      1.1  mrg   if (m_saved_diagnostics.length () == 0)
   1327      1.1  mrg     return;
   1328      1.1  mrg 
   1329      1.1  mrg   /* Compute the shortest_paths once, sharing it between all diagnostics.  */
   1330  1.1.1.2  mrg   epath_finder pf (eg);
   1331      1.1  mrg 
   1332      1.1  mrg   /* Iterate through all saved diagnostics, adding them to a dedupe_winners
   1333      1.1  mrg      instance.  This partitions the saved diagnostics by dedupe_key,
   1334      1.1  mrg      generating exploded_paths for them, and retaining the best one in each
   1335      1.1  mrg      partition.  */
   1336      1.1  mrg   dedupe_winners best_candidates;
   1337      1.1  mrg 
   1338      1.1  mrg   int i;
   1339      1.1  mrg   saved_diagnostic *sd;
   1340      1.1  mrg   FOR_EACH_VEC_ELT (m_saved_diagnostics, i, sd)
   1341  1.1.1.2  mrg     best_candidates.add (get_logger (), &pf, sd);
   1342  1.1.1.2  mrg 
   1343  1.1.1.2  mrg   best_candidates.handle_interactions (this);
   1344      1.1  mrg 
   1345      1.1  mrg   /* For each dedupe-key, call emit_saved_diagnostic on the "best"
   1346      1.1  mrg      saved_diagnostic.  */
   1347      1.1  mrg   best_candidates.emit_best (this, eg);
   1348      1.1  mrg }
   1349      1.1  mrg 
   1350  1.1.1.2  mrg /* Given a saved_diagnostic SD with m_best_epath through EG,
   1351      1.1  mrg    create an checker_path of suitable events and use it to call
   1352      1.1  mrg    SD's underlying pending_diagnostic "emit" vfunc to emit a diagnostic.  */
   1353      1.1  mrg 
   1354      1.1  mrg void
   1355      1.1  mrg diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
   1356  1.1.1.2  mrg 					   const saved_diagnostic &sd)
   1357      1.1  mrg {
   1358      1.1  mrg   LOG_SCOPE (get_logger ());
   1359      1.1  mrg   log ("sd: %qs at SN: %i", sd.m_d->get_kind (), sd.m_snode->m_index);
   1360  1.1.1.2  mrg   log ("num dupes: %i", sd.get_num_dupes ());
   1361      1.1  mrg 
   1362      1.1  mrg   pretty_printer *pp = global_dc->printer->clone ();
   1363      1.1  mrg 
   1364  1.1.1.2  mrg   const exploded_path *epath = sd.get_best_epath ();
   1365  1.1.1.2  mrg   gcc_assert (epath);
   1366  1.1.1.2  mrg 
   1367      1.1  mrg   /* Precompute all enodes from which the diagnostic is reachable.  */
   1368  1.1.1.2  mrg   path_builder pb (eg, *epath, sd.get_feasibility_problem (), sd);
   1369      1.1  mrg 
   1370      1.1  mrg   /* This is the diagnostic_path subclass that will be built for
   1371      1.1  mrg      the diagnostic.  */
   1372      1.1  mrg   checker_path emission_path;
   1373      1.1  mrg 
   1374      1.1  mrg   /* Populate emission_path with a full description of EPATH.  */
   1375  1.1.1.2  mrg   build_emission_path (pb, *epath, &emission_path);
   1376      1.1  mrg 
   1377      1.1  mrg   /* Now prune it to just cover the most pertinent events.  */
   1378  1.1.1.2  mrg   prune_path (&emission_path, sd.m_sm, sd.m_sval, sd.m_state);
   1379      1.1  mrg 
   1380      1.1  mrg   /* Add a final event to the path, covering the diagnostic itself.
   1381      1.1  mrg      We use the final enode from the epath, which might be different from
   1382      1.1  mrg      the sd.m_enode, as the dedupe code doesn't care about enodes, just
   1383      1.1  mrg      snodes.  */
   1384  1.1.1.2  mrg   emission_path.add_final_event (sd.m_sm, epath->get_final_enode (), sd.m_stmt,
   1385      1.1  mrg 				 sd.m_var, sd.m_state);
   1386      1.1  mrg 
   1387      1.1  mrg   /* The "final" event might not be final; if the saved_diagnostic has a
   1388      1.1  mrg      trailing eedge stashed, add any events for it.  This is for use
   1389      1.1  mrg      in handling longjmp, to show where a longjmp is rewinding to.  */
   1390      1.1  mrg   if (sd.m_trailing_eedge)
   1391  1.1.1.2  mrg     add_events_for_eedge (pb, *sd.m_trailing_eedge, &emission_path, NULL);
   1392      1.1  mrg 
   1393      1.1  mrg   emission_path.prepare_for_emission (sd.m_d);
   1394      1.1  mrg 
   1395  1.1.1.2  mrg   location_t loc
   1396  1.1.1.2  mrg     = get_emission_location (sd.m_stmt, sd.m_snode->m_fun, *sd.m_d);
   1397  1.1.1.2  mrg 
   1398  1.1.1.2  mrg   /* Allow the pending_diagnostic to fix up the locations of events.  */
   1399  1.1.1.2  mrg   emission_path.fixup_locations (sd.m_d);
   1400  1.1.1.2  mrg 
   1401  1.1.1.2  mrg   gcc_rich_location rich_loc (loc);
   1402      1.1  mrg   rich_loc.set_path (&emission_path);
   1403      1.1  mrg 
   1404      1.1  mrg   auto_diagnostic_group d;
   1405      1.1  mrg   auto_cfun sentinel (sd.m_snode->m_fun);
   1406      1.1  mrg   if (sd.m_d->emit (&rich_loc))
   1407      1.1  mrg     {
   1408  1.1.1.2  mrg       sd.emit_any_notes ();
   1409  1.1.1.2  mrg 
   1410  1.1.1.2  mrg       unsigned num_dupes = sd.get_num_dupes ();
   1411      1.1  mrg       if (flag_analyzer_show_duplicate_count && num_dupes > 0)
   1412  1.1.1.2  mrg 	inform_n (loc, num_dupes,
   1413      1.1  mrg 		  "%i duplicate", "%i duplicates",
   1414      1.1  mrg 		  num_dupes);
   1415  1.1.1.2  mrg       if (flag_dump_analyzer_exploded_paths)
   1416  1.1.1.2  mrg 	{
   1417  1.1.1.2  mrg 	  auto_timevar tv (TV_ANALYZER_DUMP);
   1418  1.1.1.2  mrg 	  pretty_printer pp;
   1419  1.1.1.2  mrg 	  pp_printf (&pp, "%s.%i.%s.epath.txt",
   1420  1.1.1.2  mrg 		     dump_base_name, sd.get_index (), sd.m_d->get_kind ());
   1421  1.1.1.2  mrg 	  char *filename = xstrdup (pp_formatted_text (&pp));
   1422  1.1.1.2  mrg 	  epath->dump_to_file (filename, eg.get_ext_state ());
   1423  1.1.1.2  mrg 	  inform (loc, "exploded path written to %qs", filename);
   1424  1.1.1.2  mrg 	  free (filename);
   1425      1.1  mrg 	}
   1426      1.1  mrg     }
   1427  1.1.1.2  mrg   delete pp;
   1428      1.1  mrg }
   1429      1.1  mrg 
   1430      1.1  mrg /* Emit a "path" of events to EMISSION_PATH describing the exploded path
   1431      1.1  mrg    EPATH within EG.  */
   1432      1.1  mrg 
   1433      1.1  mrg void
   1434      1.1  mrg diagnostic_manager::build_emission_path (const path_builder &pb,
   1435      1.1  mrg 					 const exploded_path &epath,
   1436      1.1  mrg 					 checker_path *emission_path) const
   1437      1.1  mrg {
   1438      1.1  mrg   LOG_SCOPE (get_logger ());
   1439  1.1.1.2  mrg 
   1440  1.1.1.2  mrg   interesting_t interest;
   1441  1.1.1.2  mrg   pb.get_pending_diagnostic ()->mark_interesting_stuff (&interest);
   1442  1.1.1.2  mrg 
   1443  1.1.1.2  mrg   /* Add region creation events for any globals of interest, at the
   1444  1.1.1.2  mrg      beginning of the path.  */
   1445  1.1.1.2  mrg   {
   1446  1.1.1.2  mrg     for (auto reg : interest.m_region_creation)
   1447  1.1.1.2  mrg       switch (reg->get_memory_space ())
   1448  1.1.1.2  mrg 	{
   1449  1.1.1.2  mrg 	default:
   1450  1.1.1.2  mrg 	  continue;
   1451  1.1.1.2  mrg 	case MEMSPACE_CODE:
   1452  1.1.1.2  mrg 	case MEMSPACE_GLOBALS:
   1453  1.1.1.2  mrg 	case MEMSPACE_READONLY_DATA:
   1454  1.1.1.2  mrg 	  {
   1455  1.1.1.2  mrg 	    const region *base_reg = reg->get_base_region ();
   1456  1.1.1.2  mrg 	    if (tree decl = base_reg->maybe_get_decl ())
   1457  1.1.1.2  mrg 	      if (DECL_P (decl)
   1458  1.1.1.2  mrg 		  && DECL_SOURCE_LOCATION (decl) != UNKNOWN_LOCATION)
   1459  1.1.1.2  mrg 		{
   1460  1.1.1.2  mrg 		  emission_path->add_region_creation_event
   1461  1.1.1.2  mrg 		    (reg,
   1462  1.1.1.2  mrg 		     DECL_SOURCE_LOCATION (decl),
   1463  1.1.1.2  mrg 		     NULL_TREE,
   1464  1.1.1.2  mrg 		     0);
   1465  1.1.1.2  mrg 		}
   1466  1.1.1.2  mrg 	  }
   1467  1.1.1.2  mrg 	}
   1468  1.1.1.2  mrg   }
   1469  1.1.1.2  mrg 
   1470  1.1.1.2  mrg   /* Walk EPATH, adding events as appropriate.  */
   1471      1.1  mrg   for (unsigned i = 0; i < epath.m_edges.length (); i++)
   1472      1.1  mrg     {
   1473      1.1  mrg       const exploded_edge *eedge = epath.m_edges[i];
   1474  1.1.1.2  mrg       add_events_for_eedge (pb, *eedge, emission_path, &interest);
   1475      1.1  mrg     }
   1476      1.1  mrg }
   1477      1.1  mrg 
   1478      1.1  mrg /* Subclass of state_change_visitor that creates state_change_event
   1479      1.1  mrg    instances.  */
   1480      1.1  mrg 
   1481      1.1  mrg class state_change_event_creator : public state_change_visitor
   1482      1.1  mrg {
   1483      1.1  mrg public:
   1484  1.1.1.2  mrg   state_change_event_creator (const path_builder &pb,
   1485  1.1.1.2  mrg 			      const exploded_edge &eedge,
   1486      1.1  mrg 			      checker_path *emission_path)
   1487  1.1.1.2  mrg     : m_pb (pb),
   1488  1.1.1.2  mrg       m_eedge (eedge),
   1489      1.1  mrg       m_emission_path (emission_path)
   1490      1.1  mrg   {}
   1491      1.1  mrg 
   1492      1.1  mrg   bool on_global_state_change (const state_machine &sm,
   1493      1.1  mrg 			       state_machine::state_t src_sm_val,
   1494      1.1  mrg 			       state_machine::state_t dst_sm_val)
   1495      1.1  mrg     FINAL OVERRIDE
   1496      1.1  mrg   {
   1497  1.1.1.2  mrg     if (&sm != m_pb.get_sm ())
   1498  1.1.1.2  mrg       return false;
   1499      1.1  mrg     const exploded_node *src_node = m_eedge.m_src;
   1500      1.1  mrg     const program_point &src_point = src_node->get_point ();
   1501      1.1  mrg     const int src_stack_depth = src_point.get_stack_depth ();
   1502      1.1  mrg     const exploded_node *dst_node = m_eedge.m_dest;
   1503      1.1  mrg     const gimple *stmt = src_point.get_stmt ();
   1504      1.1  mrg     const supernode *supernode = src_point.get_supernode ();
   1505      1.1  mrg     const program_state &dst_state = dst_node->get_state ();
   1506      1.1  mrg 
   1507      1.1  mrg     int stack_depth = src_stack_depth;
   1508      1.1  mrg 
   1509      1.1  mrg     m_emission_path->add_event (new state_change_event (supernode,
   1510      1.1  mrg 							stmt,
   1511      1.1  mrg 							stack_depth,
   1512      1.1  mrg 							sm,
   1513  1.1.1.2  mrg 							NULL,
   1514      1.1  mrg 							src_sm_val,
   1515      1.1  mrg 							dst_sm_val,
   1516  1.1.1.2  mrg 							NULL,
   1517      1.1  mrg 							dst_state));
   1518      1.1  mrg     return false;
   1519      1.1  mrg   }
   1520      1.1  mrg 
   1521      1.1  mrg   bool on_state_change (const state_machine &sm,
   1522      1.1  mrg 			state_machine::state_t src_sm_val,
   1523      1.1  mrg 			state_machine::state_t dst_sm_val,
   1524  1.1.1.2  mrg 			const svalue *sval,
   1525  1.1.1.2  mrg 			const svalue *dst_origin_sval) FINAL OVERRIDE
   1526      1.1  mrg   {
   1527  1.1.1.2  mrg     if (&sm != m_pb.get_sm ())
   1528  1.1.1.2  mrg       return false;
   1529      1.1  mrg     const exploded_node *src_node = m_eedge.m_src;
   1530      1.1  mrg     const program_point &src_point = src_node->get_point ();
   1531      1.1  mrg     const int src_stack_depth = src_point.get_stack_depth ();
   1532      1.1  mrg     const exploded_node *dst_node = m_eedge.m_dest;
   1533      1.1  mrg     const gimple *stmt = src_point.get_stmt ();
   1534      1.1  mrg     const supernode *supernode = src_point.get_supernode ();
   1535      1.1  mrg     const program_state &dst_state = dst_node->get_state ();
   1536      1.1  mrg 
   1537      1.1  mrg     int stack_depth = src_stack_depth;
   1538      1.1  mrg 
   1539      1.1  mrg     if (m_eedge.m_sedge
   1540      1.1  mrg 	&& m_eedge.m_sedge->m_kind == SUPEREDGE_CFG_EDGE)
   1541      1.1  mrg       {
   1542      1.1  mrg 	supernode = src_point.get_supernode ();
   1543      1.1  mrg 	stmt = supernode->get_last_stmt ();
   1544      1.1  mrg 	stack_depth = src_stack_depth;
   1545      1.1  mrg       }
   1546      1.1  mrg 
   1547      1.1  mrg     /* Bulletproofing for state changes at calls/returns;
   1548      1.1  mrg        TODO: is there a better way? */
   1549      1.1  mrg     if (!stmt)
   1550      1.1  mrg       return false;
   1551      1.1  mrg 
   1552      1.1  mrg     m_emission_path->add_event (new state_change_event (supernode,
   1553      1.1  mrg 							stmt,
   1554      1.1  mrg 							stack_depth,
   1555      1.1  mrg 							sm,
   1556  1.1.1.2  mrg 							sval,
   1557      1.1  mrg 							src_sm_val,
   1558      1.1  mrg 							dst_sm_val,
   1559  1.1.1.2  mrg 							dst_origin_sval,
   1560      1.1  mrg 							dst_state));
   1561      1.1  mrg     return false;
   1562      1.1  mrg   }
   1563      1.1  mrg 
   1564  1.1.1.2  mrg   const path_builder &m_pb;
   1565      1.1  mrg   const exploded_edge &m_eedge;
   1566      1.1  mrg   checker_path *m_emission_path;
   1567      1.1  mrg };
   1568      1.1  mrg 
   1569      1.1  mrg /* Compare SRC_STATE and DST_STATE (which use EXT_STATE), and call
   1570      1.1  mrg    VISITOR's on_state_change for every sm-state change that occurs
   1571      1.1  mrg    to a tree, and on_global_state_change for every global state change
   1572      1.1  mrg    that occurs.
   1573      1.1  mrg 
   1574      1.1  mrg    This determines the state changes that ought to be reported to
   1575      1.1  mrg    the user: a combination of the effects of changes to sm_state_map
   1576      1.1  mrg    (which maps svalues to sm-states), and of region_model changes
   1577      1.1  mrg    (which map trees to svalues).
   1578      1.1  mrg 
   1579      1.1  mrg    Bail out early and return true if any call to on_global_state_change
   1580      1.1  mrg    or on_state_change returns true, otherwise return false.
   1581      1.1  mrg 
   1582      1.1  mrg    This is split out to make it easier to experiment with changes to
   1583      1.1  mrg    exploded_node granularity (so that we can observe what state changes
   1584      1.1  mrg    lead to state_change_events being emitted).  */
   1585      1.1  mrg 
   1586      1.1  mrg bool
   1587      1.1  mrg for_each_state_change (const program_state &src_state,
   1588      1.1  mrg 		       const program_state &dst_state,
   1589      1.1  mrg 		       const extrinsic_state &ext_state,
   1590      1.1  mrg 		       state_change_visitor *visitor)
   1591      1.1  mrg {
   1592      1.1  mrg   gcc_assert (src_state.m_checker_states.length ()
   1593      1.1  mrg 	      == ext_state.get_num_checkers ());
   1594      1.1  mrg   gcc_assert (dst_state.m_checker_states.length ()
   1595      1.1  mrg 	      == ext_state.get_num_checkers ());
   1596      1.1  mrg   for (unsigned i = 0; i < ext_state.get_num_checkers (); i++)
   1597      1.1  mrg     {
   1598      1.1  mrg       const state_machine &sm = ext_state.get_sm (i);
   1599      1.1  mrg       const sm_state_map &src_smap = *src_state.m_checker_states[i];
   1600      1.1  mrg       const sm_state_map &dst_smap = *dst_state.m_checker_states[i];
   1601      1.1  mrg 
   1602      1.1  mrg       /* Add events for any global state changes.  */
   1603      1.1  mrg       if (src_smap.get_global_state () != dst_smap.get_global_state ())
   1604      1.1  mrg 	if (visitor->on_global_state_change (sm,
   1605      1.1  mrg 					     src_smap.get_global_state (),
   1606      1.1  mrg 					     dst_smap.get_global_state ()))
   1607      1.1  mrg 	  return true;
   1608      1.1  mrg 
   1609      1.1  mrg       /* Add events for per-svalue state changes.  */
   1610      1.1  mrg       for (sm_state_map::iterator_t iter = dst_smap.begin ();
   1611      1.1  mrg 	   iter != dst_smap.end ();
   1612      1.1  mrg 	   ++iter)
   1613      1.1  mrg 	{
   1614  1.1.1.2  mrg 	  const svalue *sval = (*iter).first;
   1615      1.1  mrg 	  state_machine::state_t dst_sm_val = (*iter).second.m_state;
   1616  1.1.1.2  mrg 	  state_machine::state_t src_sm_val
   1617  1.1.1.2  mrg 	    = src_smap.get_state (sval, ext_state);
   1618  1.1.1.2  mrg 	  if (dst_sm_val != src_sm_val)
   1619      1.1  mrg 	    {
   1620  1.1.1.2  mrg 	      const svalue *origin_sval = (*iter).second.m_origin;
   1621  1.1.1.2  mrg 	      if (visitor->on_state_change (sm, src_sm_val, dst_sm_val,
   1622  1.1.1.2  mrg 					    sval, origin_sval))
   1623  1.1.1.2  mrg 		return true;
   1624      1.1  mrg 	    }
   1625      1.1  mrg 	}
   1626      1.1  mrg     }
   1627      1.1  mrg   return false;
   1628      1.1  mrg }
   1629      1.1  mrg 
   1630  1.1.1.2  mrg /* An sm_context for adding state_change_event on assignments to NULL,
   1631  1.1.1.2  mrg    where the default state isn't m_start.  Storing such state in the
   1632  1.1.1.2  mrg    sm_state_map would lead to bloat of the exploded_graph, so we want
   1633  1.1.1.2  mrg    to leave it as a default state, and inject state change events here
   1634  1.1.1.2  mrg    when we have a diagnostic.
   1635  1.1.1.2  mrg    Find transitions of constants, for handling on_zero_assignment.  */
   1636  1.1.1.2  mrg 
   1637  1.1.1.2  mrg struct null_assignment_sm_context : public sm_context
   1638  1.1.1.2  mrg {
   1639  1.1.1.2  mrg   null_assignment_sm_context (int sm_idx,
   1640  1.1.1.2  mrg 			      const state_machine &sm,
   1641  1.1.1.2  mrg 			      const program_state *old_state,
   1642  1.1.1.2  mrg 			      const program_state *new_state,
   1643  1.1.1.2  mrg 			      const gimple *stmt,
   1644  1.1.1.2  mrg 			      const program_point *point,
   1645  1.1.1.2  mrg 			      checker_path *emission_path,
   1646  1.1.1.2  mrg 			      const extrinsic_state &ext_state)
   1647  1.1.1.2  mrg   : sm_context (sm_idx, sm), m_old_state (old_state), m_new_state (new_state),
   1648  1.1.1.2  mrg     m_stmt (stmt), m_point (point), m_emission_path (emission_path),
   1649  1.1.1.2  mrg     m_ext_state (ext_state)
   1650  1.1.1.2  mrg   {
   1651  1.1.1.2  mrg   }
   1652  1.1.1.2  mrg 
   1653  1.1.1.2  mrg   tree get_fndecl_for_call (const gcall */*call*/) FINAL OVERRIDE
   1654  1.1.1.2  mrg   {
   1655  1.1.1.2  mrg     return NULL_TREE;
   1656  1.1.1.2  mrg   }
   1657  1.1.1.2  mrg 
   1658  1.1.1.2  mrg   state_machine::state_t get_state (const gimple *stmt ATTRIBUTE_UNUSED,
   1659  1.1.1.2  mrg 				    tree var) FINAL OVERRIDE
   1660  1.1.1.2  mrg   {
   1661  1.1.1.2  mrg     const svalue *var_old_sval
   1662  1.1.1.2  mrg       = m_old_state->m_region_model->get_rvalue (var, NULL);
   1663  1.1.1.2  mrg     const sm_state_map *old_smap = m_old_state->m_checker_states[m_sm_idx];
   1664  1.1.1.2  mrg 
   1665  1.1.1.2  mrg     state_machine::state_t current
   1666  1.1.1.2  mrg       = old_smap->get_state (var_old_sval, m_ext_state);
   1667  1.1.1.2  mrg 
   1668  1.1.1.2  mrg     return current;
   1669  1.1.1.2  mrg   }
   1670  1.1.1.2  mrg 
   1671  1.1.1.2  mrg   state_machine::state_t get_state (const gimple *stmt ATTRIBUTE_UNUSED,
   1672  1.1.1.2  mrg 				    const svalue *sval) FINAL OVERRIDE
   1673  1.1.1.2  mrg   {
   1674  1.1.1.2  mrg     const sm_state_map *old_smap = m_old_state->m_checker_states[m_sm_idx];
   1675  1.1.1.2  mrg     state_machine::state_t current = old_smap->get_state (sval, m_ext_state);
   1676  1.1.1.2  mrg     return current;
   1677  1.1.1.2  mrg   }
   1678  1.1.1.2  mrg 
   1679  1.1.1.2  mrg   void set_next_state (const gimple *stmt,
   1680  1.1.1.2  mrg 		       tree var,
   1681  1.1.1.2  mrg 		       state_machine::state_t to,
   1682  1.1.1.2  mrg 		       tree origin ATTRIBUTE_UNUSED) FINAL OVERRIDE
   1683  1.1.1.2  mrg   {
   1684  1.1.1.2  mrg     state_machine::state_t from = get_state (stmt, var);
   1685  1.1.1.2  mrg     if (from != m_sm.get_start_state ())
   1686  1.1.1.2  mrg       return;
   1687  1.1.1.2  mrg 
   1688  1.1.1.2  mrg     const svalue *var_new_sval
   1689  1.1.1.2  mrg       = m_new_state->m_region_model->get_rvalue (var, NULL);
   1690  1.1.1.2  mrg     const supernode *supernode = m_point->get_supernode ();
   1691  1.1.1.2  mrg     int stack_depth = m_point->get_stack_depth ();
   1692  1.1.1.2  mrg 
   1693  1.1.1.2  mrg     m_emission_path->add_event (new state_change_event (supernode,
   1694  1.1.1.2  mrg 							m_stmt,
   1695  1.1.1.2  mrg 							stack_depth,
   1696  1.1.1.2  mrg 							m_sm,
   1697  1.1.1.2  mrg 							var_new_sval,
   1698  1.1.1.2  mrg 							from, to,
   1699  1.1.1.2  mrg 							NULL,
   1700  1.1.1.2  mrg 							*m_new_state));
   1701  1.1.1.2  mrg   }
   1702  1.1.1.2  mrg 
   1703  1.1.1.2  mrg   void set_next_state (const gimple *stmt,
   1704  1.1.1.2  mrg 		       const svalue *sval,
   1705  1.1.1.2  mrg 		       state_machine::state_t to,
   1706  1.1.1.2  mrg 		       tree origin ATTRIBUTE_UNUSED) FINAL OVERRIDE
   1707  1.1.1.2  mrg   {
   1708  1.1.1.2  mrg     state_machine::state_t from = get_state (stmt, sval);
   1709  1.1.1.2  mrg     if (from != m_sm.get_start_state ())
   1710  1.1.1.2  mrg       return;
   1711  1.1.1.2  mrg 
   1712  1.1.1.2  mrg     const supernode *supernode = m_point->get_supernode ();
   1713  1.1.1.2  mrg     int stack_depth = m_point->get_stack_depth ();
   1714  1.1.1.2  mrg 
   1715  1.1.1.2  mrg     m_emission_path->add_event (new state_change_event (supernode,
   1716  1.1.1.2  mrg 							m_stmt,
   1717  1.1.1.2  mrg 							stack_depth,
   1718  1.1.1.2  mrg 							m_sm,
   1719  1.1.1.2  mrg 							sval,
   1720  1.1.1.2  mrg 							from, to,
   1721  1.1.1.2  mrg 							NULL,
   1722  1.1.1.2  mrg 							*m_new_state));
   1723  1.1.1.2  mrg   }
   1724  1.1.1.2  mrg 
   1725  1.1.1.2  mrg   void warn (const supernode *, const gimple *,
   1726  1.1.1.2  mrg 	     tree, pending_diagnostic *d) FINAL OVERRIDE
   1727  1.1.1.2  mrg   {
   1728  1.1.1.2  mrg     delete d;
   1729  1.1.1.2  mrg   }
   1730  1.1.1.2  mrg 
   1731  1.1.1.2  mrg   tree get_diagnostic_tree (tree expr) FINAL OVERRIDE
   1732  1.1.1.2  mrg   {
   1733  1.1.1.2  mrg     return expr;
   1734  1.1.1.2  mrg   }
   1735  1.1.1.2  mrg 
   1736  1.1.1.2  mrg   tree get_diagnostic_tree (const svalue *sval) FINAL OVERRIDE
   1737  1.1.1.2  mrg   {
   1738  1.1.1.2  mrg     return m_new_state->m_region_model->get_representative_tree (sval);
   1739  1.1.1.2  mrg   }
   1740  1.1.1.2  mrg 
   1741  1.1.1.2  mrg   state_machine::state_t get_global_state () const FINAL OVERRIDE
   1742  1.1.1.2  mrg   {
   1743  1.1.1.2  mrg     return 0;
   1744  1.1.1.2  mrg   }
   1745  1.1.1.2  mrg 
   1746  1.1.1.2  mrg   void set_global_state (state_machine::state_t) FINAL OVERRIDE
   1747  1.1.1.2  mrg   {
   1748  1.1.1.2  mrg     /* No-op.  */
   1749  1.1.1.2  mrg   }
   1750  1.1.1.2  mrg 
   1751  1.1.1.2  mrg   void on_custom_transition (custom_transition *) FINAL OVERRIDE
   1752  1.1.1.2  mrg   {
   1753  1.1.1.2  mrg   }
   1754  1.1.1.2  mrg 
   1755  1.1.1.2  mrg   tree is_zero_assignment (const gimple *stmt) FINAL OVERRIDE
   1756  1.1.1.2  mrg   {
   1757  1.1.1.2  mrg     const gassign *assign_stmt = dyn_cast <const gassign *> (stmt);
   1758  1.1.1.2  mrg     if (!assign_stmt)
   1759  1.1.1.2  mrg      return NULL_TREE;
   1760  1.1.1.2  mrg     if (const svalue *sval
   1761  1.1.1.2  mrg 	= m_new_state->m_region_model->get_gassign_result (assign_stmt, NULL))
   1762  1.1.1.2  mrg       if (tree cst = sval->maybe_get_constant ())
   1763  1.1.1.2  mrg 	if (::zerop(cst))
   1764  1.1.1.2  mrg 	  return gimple_assign_lhs (assign_stmt);
   1765  1.1.1.2  mrg     return NULL_TREE;
   1766  1.1.1.2  mrg   }
   1767  1.1.1.2  mrg 
   1768  1.1.1.2  mrg   const program_state *get_old_program_state () const FINAL OVERRIDE
   1769  1.1.1.2  mrg   {
   1770  1.1.1.2  mrg     return m_old_state;
   1771  1.1.1.2  mrg   }
   1772  1.1.1.2  mrg 
   1773  1.1.1.2  mrg   const program_state *m_old_state;
   1774  1.1.1.2  mrg   const program_state *m_new_state;
   1775  1.1.1.2  mrg   const gimple *m_stmt;
   1776  1.1.1.2  mrg   const program_point *m_point;
   1777  1.1.1.2  mrg   checker_path *m_emission_path;
   1778  1.1.1.2  mrg   const extrinsic_state &m_ext_state;
   1779  1.1.1.2  mrg };
   1780  1.1.1.2  mrg 
   1781      1.1  mrg /* Subroutine of diagnostic_manager::build_emission_path.
   1782      1.1  mrg    Add any events for EEDGE to EMISSION_PATH.  */
   1783      1.1  mrg 
   1784      1.1  mrg void
   1785      1.1  mrg diagnostic_manager::add_events_for_eedge (const path_builder &pb,
   1786      1.1  mrg 					  const exploded_edge &eedge,
   1787  1.1.1.2  mrg 					  checker_path *emission_path,
   1788  1.1.1.2  mrg 					  interesting_t *interest) const
   1789      1.1  mrg {
   1790      1.1  mrg   const exploded_node *src_node = eedge.m_src;
   1791      1.1  mrg   const program_point &src_point = src_node->get_point ();
   1792  1.1.1.2  mrg   const int src_stack_depth = src_point.get_stack_depth ();
   1793      1.1  mrg   const exploded_node *dst_node = eedge.m_dest;
   1794      1.1  mrg   const program_point &dst_point = dst_node->get_point ();
   1795      1.1  mrg   const int dst_stack_depth = dst_point.get_stack_depth ();
   1796      1.1  mrg   if (get_logger ())
   1797      1.1  mrg     {
   1798      1.1  mrg       get_logger ()->start_log_line ();
   1799      1.1  mrg       pretty_printer *pp = get_logger ()->get_printer ();
   1800      1.1  mrg       pp_printf (pp, "EN %i -> EN %i: ",
   1801      1.1  mrg 		 eedge.m_src->m_index,
   1802      1.1  mrg 		 eedge.m_dest->m_index);
   1803      1.1  mrg       src_point.print (pp, format (false));
   1804      1.1  mrg       pp_string (pp, "-> ");
   1805      1.1  mrg       dst_point.print (pp, format (false));
   1806      1.1  mrg       get_logger ()->end_log_line ();
   1807      1.1  mrg     }
   1808      1.1  mrg   const program_state &src_state = src_node->get_state ();
   1809      1.1  mrg   const program_state &dst_state = dst_node->get_state ();
   1810      1.1  mrg 
   1811      1.1  mrg   /* Add state change events for the states that have changed.
   1812      1.1  mrg      We add these before events for superedges, so that if we have a
   1813      1.1  mrg      state_change_event due to following an edge, we'll get this sequence
   1814      1.1  mrg      of events:
   1815      1.1  mrg 
   1816      1.1  mrg       | if (!ptr)
   1817      1.1  mrg       |    ~
   1818      1.1  mrg       |    |
   1819      1.1  mrg       |    (1) assuming 'ptr' is non-NULL  (state_change_event)
   1820      1.1  mrg       |    (2) following 'false' branch... (start_cfg_edge_event)
   1821      1.1  mrg      ...
   1822      1.1  mrg       | do_something (ptr);
   1823      1.1  mrg       | ~~~~~~~~~~~~~^~~~~
   1824      1.1  mrg       |              |
   1825      1.1  mrg       |              (3) ...to here        (end_cfg_edge_event).  */
   1826  1.1.1.2  mrg   state_change_event_creator visitor (pb, eedge, emission_path);
   1827      1.1  mrg   for_each_state_change (src_state, dst_state, pb.get_ext_state (),
   1828      1.1  mrg 			 &visitor);
   1829      1.1  mrg 
   1830      1.1  mrg   /* Allow non-standard edges to add events, e.g. when rewinding from
   1831      1.1  mrg      longjmp to a setjmp.  */
   1832      1.1  mrg   if (eedge.m_custom_info)
   1833      1.1  mrg     eedge.m_custom_info->add_events_to_path (emission_path, eedge);
   1834      1.1  mrg 
   1835      1.1  mrg   /* Add events for superedges, function entries, and for statements.  */
   1836      1.1  mrg   switch (dst_point.get_kind ())
   1837      1.1  mrg     {
   1838      1.1  mrg     default:
   1839      1.1  mrg       break;
   1840      1.1  mrg     case PK_BEFORE_SUPERNODE:
   1841      1.1  mrg       if (src_point.get_kind () == PK_AFTER_SUPERNODE)
   1842      1.1  mrg 	{
   1843      1.1  mrg 	  if (eedge.m_sedge)
   1844      1.1  mrg 	    add_events_for_superedge (pb, eedge, emission_path);
   1845      1.1  mrg 	}
   1846      1.1  mrg       /* Add function entry events.  */
   1847      1.1  mrg       if (dst_point.get_supernode ()->entry_p ())
   1848      1.1  mrg 	{
   1849      1.1  mrg 	  emission_path->add_event
   1850      1.1  mrg 	    (new function_entry_event
   1851      1.1  mrg 	     (dst_point.get_supernode ()->get_start_location (),
   1852      1.1  mrg 	      dst_point.get_fndecl (),
   1853      1.1  mrg 	      dst_stack_depth));
   1854  1.1.1.2  mrg 	  /* Create region_creation_events for on-stack regions within
   1855  1.1.1.2  mrg 	     this frame.  */
   1856  1.1.1.2  mrg 	  if (interest)
   1857  1.1.1.2  mrg 	    {
   1858  1.1.1.2  mrg 	      unsigned i;
   1859  1.1.1.2  mrg 	      const region *reg;
   1860  1.1.1.2  mrg 	      FOR_EACH_VEC_ELT (interest->m_region_creation, i, reg)
   1861  1.1.1.2  mrg 		if (const frame_region *frame = reg->maybe_get_frame_region ())
   1862  1.1.1.2  mrg 		  if (frame->get_fndecl () == dst_point.get_fndecl ())
   1863  1.1.1.2  mrg 		    {
   1864  1.1.1.2  mrg 		      const region *base_reg = reg->get_base_region ();
   1865  1.1.1.2  mrg 		      if (tree decl = base_reg->maybe_get_decl ())
   1866  1.1.1.2  mrg 			if (DECL_P (decl)
   1867  1.1.1.2  mrg 			    && DECL_SOURCE_LOCATION (decl) != UNKNOWN_LOCATION)
   1868  1.1.1.2  mrg 			  {
   1869  1.1.1.2  mrg 			    emission_path->add_region_creation_event
   1870  1.1.1.2  mrg 			      (reg,
   1871  1.1.1.2  mrg 			       DECL_SOURCE_LOCATION (decl),
   1872  1.1.1.2  mrg 			       dst_point.get_fndecl (),
   1873  1.1.1.2  mrg 			       dst_stack_depth);
   1874  1.1.1.2  mrg 			  }
   1875  1.1.1.2  mrg 		    }
   1876  1.1.1.2  mrg 	    }
   1877      1.1  mrg 	}
   1878      1.1  mrg       break;
   1879      1.1  mrg     case PK_BEFORE_STMT:
   1880      1.1  mrg       {
   1881      1.1  mrg 	const gimple *stmt = dst_point.get_stmt ();
   1882      1.1  mrg 	const gcall *call = dyn_cast <const gcall *> (stmt);
   1883      1.1  mrg 	if (call && is_setjmp_call_p (call))
   1884      1.1  mrg 	  emission_path->add_event
   1885      1.1  mrg 	    (new setjmp_event (stmt->location,
   1886      1.1  mrg 			       dst_node,
   1887      1.1  mrg 			       dst_point.get_fndecl (),
   1888      1.1  mrg 			       dst_stack_depth,
   1889      1.1  mrg 			       call));
   1890      1.1  mrg 	else
   1891      1.1  mrg 	  emission_path->add_event
   1892      1.1  mrg 	    (new statement_event (stmt,
   1893      1.1  mrg 				  dst_point.get_fndecl (),
   1894      1.1  mrg 				  dst_stack_depth, dst_state));
   1895  1.1.1.2  mrg 
   1896  1.1.1.2  mrg 	/* Create state change events for assignment to NULL.
   1897  1.1.1.2  mrg 	   Iterate through the stmts in dst_enode, adding state change
   1898  1.1.1.2  mrg 	   events for them.  */
   1899  1.1.1.2  mrg 	if (dst_state.m_region_model)
   1900  1.1.1.2  mrg 	  {
   1901  1.1.1.2  mrg 	    program_state iter_state (dst_state);
   1902  1.1.1.2  mrg 	    program_point iter_point (dst_point);
   1903  1.1.1.2  mrg 	    while (1)
   1904  1.1.1.2  mrg 	      {
   1905  1.1.1.2  mrg 		const gimple *stmt = iter_point.get_stmt ();
   1906  1.1.1.2  mrg 		if (const gassign *assign = dyn_cast<const gassign *> (stmt))
   1907  1.1.1.2  mrg 		  {
   1908  1.1.1.2  mrg 		    const extrinsic_state &ext_state = pb.get_ext_state ();
   1909  1.1.1.2  mrg 		    program_state old_state (iter_state);
   1910  1.1.1.2  mrg 		    iter_state.m_region_model->on_assignment (assign, NULL);
   1911  1.1.1.2  mrg 		    for (unsigned i = 0; i < ext_state.get_num_checkers (); i++)
   1912  1.1.1.2  mrg 		      {
   1913  1.1.1.2  mrg 			const state_machine &sm = ext_state.get_sm (i);
   1914  1.1.1.2  mrg 			null_assignment_sm_context sm_ctxt (i, sm,
   1915  1.1.1.2  mrg 							    &old_state,
   1916  1.1.1.2  mrg 							    &iter_state,
   1917  1.1.1.2  mrg 							    stmt,
   1918  1.1.1.2  mrg 							    &iter_point,
   1919  1.1.1.2  mrg 							    emission_path,
   1920  1.1.1.2  mrg 							    pb.get_ext_state ());
   1921  1.1.1.2  mrg 			sm.on_stmt (&sm_ctxt, dst_point.get_supernode (), stmt);
   1922  1.1.1.2  mrg 			// TODO: what about phi nodes?
   1923  1.1.1.2  mrg 		      }
   1924  1.1.1.2  mrg 		  }
   1925  1.1.1.2  mrg 		iter_point.next_stmt ();
   1926  1.1.1.2  mrg 		if (iter_point.get_kind () == PK_AFTER_SUPERNODE
   1927  1.1.1.2  mrg 		    || (dst_node->m_succs.length () > 1
   1928  1.1.1.2  mrg 			&& (iter_point
   1929  1.1.1.2  mrg 			    == dst_node->m_succs[0]->m_dest->get_point ())))
   1930  1.1.1.2  mrg 		  break;
   1931  1.1.1.2  mrg 	      }
   1932  1.1.1.2  mrg 
   1933  1.1.1.2  mrg 	  }
   1934      1.1  mrg       }
   1935      1.1  mrg       break;
   1936      1.1  mrg     }
   1937  1.1.1.2  mrg 
   1938  1.1.1.2  mrg   /* Look for changes in dynamic extents, which will identify
   1939  1.1.1.2  mrg      the creation of heap-based regions and alloca regions.  */
   1940  1.1.1.2  mrg   if (interest)
   1941  1.1.1.2  mrg     {
   1942  1.1.1.2  mrg       const region_model *src_model = src_state.m_region_model;
   1943  1.1.1.2  mrg       const region_model *dst_model = dst_state.m_region_model;
   1944  1.1.1.2  mrg       if (src_model->get_dynamic_extents ()
   1945  1.1.1.2  mrg 	  != dst_model->get_dynamic_extents ())
   1946  1.1.1.2  mrg 	{
   1947  1.1.1.2  mrg 	  unsigned i;
   1948  1.1.1.2  mrg 	  const region *reg;
   1949  1.1.1.2  mrg 	  FOR_EACH_VEC_ELT (interest->m_region_creation, i, reg)
   1950  1.1.1.2  mrg 	    {
   1951  1.1.1.2  mrg 	      const region *base_reg = reg->get_base_region ();
   1952  1.1.1.2  mrg 	      const svalue *old_extents
   1953  1.1.1.2  mrg 		= src_model->get_dynamic_extents (base_reg);
   1954  1.1.1.2  mrg 	      const svalue *new_extents
   1955  1.1.1.2  mrg 		= dst_model->get_dynamic_extents (base_reg);
   1956  1.1.1.2  mrg 	      if (old_extents == NULL && new_extents != NULL)
   1957  1.1.1.2  mrg 		switch (base_reg->get_kind ())
   1958  1.1.1.2  mrg 		  {
   1959  1.1.1.2  mrg 		  default:
   1960  1.1.1.2  mrg 		    break;
   1961  1.1.1.2  mrg 		  case RK_HEAP_ALLOCATED:
   1962  1.1.1.2  mrg 		  case RK_ALLOCA:
   1963  1.1.1.2  mrg 		    emission_path->add_region_creation_event
   1964  1.1.1.2  mrg 		      (reg,
   1965  1.1.1.2  mrg 		       src_point.get_location (),
   1966  1.1.1.2  mrg 		       src_point.get_fndecl (),
   1967  1.1.1.2  mrg 		       src_stack_depth);
   1968  1.1.1.2  mrg 		    break;
   1969  1.1.1.2  mrg 		  }
   1970  1.1.1.2  mrg 	    }
   1971  1.1.1.2  mrg 	}
   1972  1.1.1.2  mrg     }
   1973  1.1.1.2  mrg 
   1974  1.1.1.2  mrg   if (pb.get_feasibility_problem ()
   1975  1.1.1.2  mrg       && &pb.get_feasibility_problem ()->m_eedge == &eedge)
   1976  1.1.1.2  mrg     {
   1977  1.1.1.2  mrg       pretty_printer pp;
   1978  1.1.1.2  mrg       pp_format_decoder (&pp) = default_tree_printer;
   1979  1.1.1.2  mrg       pp_string (&pp,
   1980  1.1.1.2  mrg 		 "this path would have been rejected as infeasible"
   1981  1.1.1.2  mrg 		 " at this edge: ");
   1982  1.1.1.2  mrg       pb.get_feasibility_problem ()->dump_to_pp (&pp);
   1983  1.1.1.2  mrg       emission_path->add_event (new precanned_custom_event
   1984  1.1.1.2  mrg 				(dst_point.get_location (),
   1985  1.1.1.2  mrg 				 dst_point.get_fndecl (),
   1986  1.1.1.2  mrg 				 dst_stack_depth,
   1987  1.1.1.2  mrg 				 pp_formatted_text (&pp)));
   1988  1.1.1.2  mrg     }
   1989      1.1  mrg }
   1990      1.1  mrg 
   1991      1.1  mrg /* Return true if EEDGE is a significant edge in the path to the diagnostic
   1992      1.1  mrg    for PB.
   1993      1.1  mrg 
   1994      1.1  mrg    Consider all of the sibling out-eedges from the same source enode
   1995      1.1  mrg    as EEDGE.
   1996      1.1  mrg    If there's no path from the destinations of those eedges to the
   1997      1.1  mrg    diagnostic enode, then we have to take this eedge and thus it's
   1998      1.1  mrg    significant.
   1999      1.1  mrg 
   2000      1.1  mrg    Conversely if there is a path from the destination of any other sibling
   2001      1.1  mrg    eedge to the diagnostic enode, then this edge is insignificant.
   2002      1.1  mrg 
   2003      1.1  mrg    Example 1: redundant if-else:
   2004      1.1  mrg 
   2005      1.1  mrg      (A) if (...)            A
   2006      1.1  mrg      (B)   ...              / \
   2007      1.1  mrg          else              B   C
   2008      1.1  mrg      (C)   ...              \ /
   2009      1.1  mrg      (D) [DIAGNOSTIC]        D
   2010      1.1  mrg 
   2011      1.1  mrg      D is reachable by either B or C, so neither of these edges
   2012      1.1  mrg      are significant.
   2013      1.1  mrg 
   2014      1.1  mrg    Example 2: pertinent if-else:
   2015      1.1  mrg 
   2016      1.1  mrg      (A) if (...)                         A
   2017      1.1  mrg      (B)   ...                           / \
   2018      1.1  mrg          else                           B   C
   2019      1.1  mrg      (C)   [NECESSARY CONDITION]        |   |
   2020      1.1  mrg      (D) [POSSIBLE DIAGNOSTIC]          D1  D2
   2021      1.1  mrg 
   2022      1.1  mrg      D becomes D1 and D2 in the exploded graph, where the diagnostic occurs
   2023      1.1  mrg      at D2.  D2 is only reachable via C, so the A -> C edge is significant.
   2024      1.1  mrg 
   2025      1.1  mrg    Example 3: redundant loop:
   2026      1.1  mrg 
   2027      1.1  mrg      (A) while (...)          +-->A
   2028      1.1  mrg      (B)   ...                |  / \
   2029      1.1  mrg      (C) ...                  +-B  C
   2030      1.1  mrg      (D) [DIAGNOSTIC]              |
   2031      1.1  mrg                                    D
   2032      1.1  mrg 
   2033      1.1  mrg      D is reachable from both B and C, so the A->C edge is not significant.  */
   2034      1.1  mrg 
   2035      1.1  mrg bool
   2036      1.1  mrg diagnostic_manager::significant_edge_p (const path_builder &pb,
   2037      1.1  mrg 					const exploded_edge &eedge) const
   2038      1.1  mrg {
   2039      1.1  mrg   int i;
   2040      1.1  mrg   exploded_edge *sibling;
   2041      1.1  mrg   FOR_EACH_VEC_ELT (eedge.m_src->m_succs, i, sibling)
   2042      1.1  mrg     {
   2043      1.1  mrg       if (sibling == &eedge)
   2044      1.1  mrg 	continue;
   2045      1.1  mrg       if (pb.reachable_from_p (sibling->m_dest))
   2046      1.1  mrg 	{
   2047      1.1  mrg 	  if (get_logger ())
   2048      1.1  mrg 	    get_logger ()->log ("  edge EN: %i -> EN: %i is insignificant as"
   2049      1.1  mrg 				" EN: %i is also reachable via"
   2050      1.1  mrg 				" EN: %i -> EN: %i",
   2051      1.1  mrg 				eedge.m_src->m_index, eedge.m_dest->m_index,
   2052      1.1  mrg 				pb.get_diag_node ()->m_index,
   2053      1.1  mrg 				sibling->m_src->m_index,
   2054      1.1  mrg 				sibling->m_dest->m_index);
   2055      1.1  mrg 	  return false;
   2056      1.1  mrg 	}
   2057      1.1  mrg     }
   2058      1.1  mrg 
   2059      1.1  mrg   return true;
   2060      1.1  mrg }
   2061      1.1  mrg 
   2062      1.1  mrg /* Subroutine of diagnostic_manager::add_events_for_eedge
   2063      1.1  mrg    where EEDGE has an underlying superedge i.e. a CFG edge,
   2064      1.1  mrg    or an interprocedural call/return.
   2065      1.1  mrg    Add any events for the superedge to EMISSION_PATH.  */
   2066      1.1  mrg 
   2067      1.1  mrg void
   2068      1.1  mrg diagnostic_manager::add_events_for_superedge (const path_builder &pb,
   2069      1.1  mrg 					      const exploded_edge &eedge,
   2070      1.1  mrg 					      checker_path *emission_path)
   2071      1.1  mrg   const
   2072      1.1  mrg {
   2073      1.1  mrg   gcc_assert (eedge.m_sedge);
   2074      1.1  mrg 
   2075  1.1.1.2  mrg   /* Give diagnostics an opportunity to override this function.  */
   2076  1.1.1.2  mrg   pending_diagnostic *pd = pb.get_pending_diagnostic ();
   2077  1.1.1.2  mrg   if (pd->maybe_add_custom_events_for_superedge (eedge, emission_path))
   2078  1.1.1.2  mrg     return;
   2079  1.1.1.2  mrg 
   2080      1.1  mrg   /* Don't add events for insignificant edges at verbosity levels below 3.  */
   2081      1.1  mrg   if (m_verbosity < 3)
   2082      1.1  mrg     if (!significant_edge_p (pb, eedge))
   2083      1.1  mrg       return;
   2084      1.1  mrg 
   2085      1.1  mrg   const exploded_node *src_node = eedge.m_src;
   2086      1.1  mrg   const program_point &src_point = src_node->get_point ();
   2087      1.1  mrg   const exploded_node *dst_node = eedge.m_dest;
   2088      1.1  mrg   const program_point &dst_point = dst_node->get_point ();
   2089      1.1  mrg   const int src_stack_depth = src_point.get_stack_depth ();
   2090      1.1  mrg   const int dst_stack_depth = dst_point.get_stack_depth ();
   2091      1.1  mrg   const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
   2092      1.1  mrg 
   2093      1.1  mrg   switch (eedge.m_sedge->m_kind)
   2094      1.1  mrg     {
   2095      1.1  mrg     case SUPEREDGE_CFG_EDGE:
   2096      1.1  mrg       {
   2097      1.1  mrg 	emission_path->add_event
   2098      1.1  mrg 	  (new start_cfg_edge_event (eedge,
   2099      1.1  mrg 			       (last_stmt
   2100      1.1  mrg 				? last_stmt->location
   2101      1.1  mrg 				: UNKNOWN_LOCATION),
   2102      1.1  mrg 			       src_point.get_fndecl (),
   2103      1.1  mrg 			       src_stack_depth));
   2104      1.1  mrg 	emission_path->add_event
   2105      1.1  mrg 	  (new end_cfg_edge_event (eedge,
   2106      1.1  mrg 				   dst_point.get_supernode ()->get_start_location (),
   2107      1.1  mrg 				   dst_point.get_fndecl (),
   2108      1.1  mrg 				   dst_stack_depth));
   2109      1.1  mrg       }
   2110      1.1  mrg       break;
   2111      1.1  mrg 
   2112      1.1  mrg     case SUPEREDGE_CALL:
   2113      1.1  mrg       {
   2114      1.1  mrg 	emission_path->add_event
   2115      1.1  mrg 	  (new call_event (eedge,
   2116      1.1  mrg 			   (last_stmt
   2117      1.1  mrg 			    ? last_stmt->location
   2118      1.1  mrg 			    : UNKNOWN_LOCATION),
   2119      1.1  mrg 			   src_point.get_fndecl (),
   2120      1.1  mrg 			   src_stack_depth));
   2121      1.1  mrg       }
   2122      1.1  mrg       break;
   2123      1.1  mrg 
   2124      1.1  mrg     case SUPEREDGE_INTRAPROCEDURAL_CALL:
   2125      1.1  mrg       {
   2126      1.1  mrg 	/* TODO: add a subclass for this, or generate events for the
   2127      1.1  mrg 	   summary.  */
   2128      1.1  mrg 	emission_path->add_event
   2129      1.1  mrg 	  (new debug_event ((last_stmt
   2130      1.1  mrg 			     ? last_stmt->location
   2131      1.1  mrg 			     : UNKNOWN_LOCATION),
   2132      1.1  mrg 			    src_point.get_fndecl (),
   2133      1.1  mrg 			    src_stack_depth,
   2134      1.1  mrg 			    "call summary"));
   2135      1.1  mrg       }
   2136      1.1  mrg       break;
   2137      1.1  mrg 
   2138      1.1  mrg     case SUPEREDGE_RETURN:
   2139      1.1  mrg       {
   2140      1.1  mrg 	const return_superedge *return_edge
   2141      1.1  mrg 	  = as_a <const return_superedge *> (eedge.m_sedge);
   2142      1.1  mrg 
   2143      1.1  mrg 	const gcall *call_stmt = return_edge->get_call_stmt ();
   2144      1.1  mrg 	emission_path->add_event
   2145      1.1  mrg 	  (new return_event (eedge,
   2146      1.1  mrg 			     (call_stmt
   2147      1.1  mrg 			      ? call_stmt->location
   2148      1.1  mrg 			      : UNKNOWN_LOCATION),
   2149      1.1  mrg 			     dst_point.get_fndecl (),
   2150      1.1  mrg 			     dst_stack_depth));
   2151      1.1  mrg       }
   2152      1.1  mrg       break;
   2153      1.1  mrg     }
   2154      1.1  mrg }
   2155      1.1  mrg 
   2156      1.1  mrg /* Prune PATH, based on the verbosity level, to the most pertinent
   2157      1.1  mrg    events for a diagnostic that involves VAR ending in state STATE
   2158      1.1  mrg    (for state machine SM).
   2159      1.1  mrg 
   2160      1.1  mrg    PATH is updated in place, and the redundant checker_events are deleted.
   2161      1.1  mrg 
   2162      1.1  mrg    As well as deleting events, call record_critical_state on events in
   2163      1.1  mrg    which state critical to the pending_diagnostic is being handled; see
   2164      1.1  mrg    the comment for diagnostic_manager::prune_for_sm_diagnostic.  */
   2165      1.1  mrg 
   2166      1.1  mrg void
   2167      1.1  mrg diagnostic_manager::prune_path (checker_path *path,
   2168      1.1  mrg 				const state_machine *sm,
   2169  1.1.1.2  mrg 				const svalue *sval,
   2170      1.1  mrg 				state_machine::state_t state) const
   2171      1.1  mrg {
   2172      1.1  mrg   LOG_FUNC (get_logger ());
   2173      1.1  mrg   path->maybe_log (get_logger (), "path");
   2174  1.1.1.2  mrg   prune_for_sm_diagnostic (path, sm, sval, state);
   2175      1.1  mrg   prune_interproc_events (path);
   2176  1.1.1.2  mrg   consolidate_conditions (path);
   2177      1.1  mrg   finish_pruning (path);
   2178      1.1  mrg   path->maybe_log (get_logger (), "pruned");
   2179      1.1  mrg }
   2180      1.1  mrg 
   2181      1.1  mrg /* A cheap test to determine if EXPR can be the expression of interest in
   2182      1.1  mrg    an sm-diagnostic, so that we can reject cases where we have a non-lvalue.
   2183      1.1  mrg    We don't have always have a model when calling this, so we can't use
   2184      1.1  mrg    tentative_region_model_context, so there can be false positives.  */
   2185      1.1  mrg 
   2186      1.1  mrg static bool
   2187      1.1  mrg can_be_expr_of_interest_p (tree expr)
   2188      1.1  mrg {
   2189      1.1  mrg   if (!expr)
   2190      1.1  mrg     return false;
   2191      1.1  mrg 
   2192      1.1  mrg   /* Reject constants.  */
   2193      1.1  mrg   if (CONSTANT_CLASS_P (expr))
   2194      1.1  mrg     return false;
   2195      1.1  mrg 
   2196      1.1  mrg   /* Otherwise assume that it can be an lvalue.  */
   2197      1.1  mrg   return true;
   2198      1.1  mrg }
   2199      1.1  mrg 
   2200      1.1  mrg /* First pass of diagnostic_manager::prune_path: apply verbosity level,
   2201      1.1  mrg    pruning unrelated state change events.
   2202      1.1  mrg 
   2203      1.1  mrg    Iterate backwards through PATH, skipping state change events that aren't
   2204      1.1  mrg    VAR but update the pertinent VAR when state-copying occurs.
   2205      1.1  mrg 
   2206      1.1  mrg    As well as deleting events, call record_critical_state on events in
   2207      1.1  mrg    which state critical to the pending_diagnostic is being handled, so
   2208      1.1  mrg    that the event's get_desc vfunc can potentially supply a more precise
   2209      1.1  mrg    description of the event to the user.
   2210      1.1  mrg    e.g. improving
   2211      1.1  mrg      "calling 'foo' from 'bar'"
   2212      1.1  mrg    to
   2213      1.1  mrg      "passing possibly-NULL pointer 'ptr' to 'foo' from 'bar' as param 1"
   2214      1.1  mrg    when the diagnostic relates to later dereferencing 'ptr'.  */
   2215      1.1  mrg 
   2216      1.1  mrg void
   2217      1.1  mrg diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
   2218      1.1  mrg 					     const state_machine *sm,
   2219  1.1.1.2  mrg 					     const svalue *sval,
   2220      1.1  mrg 					     state_machine::state_t state) const
   2221      1.1  mrg {
   2222      1.1  mrg   int idx = path->num_events () - 1;
   2223      1.1  mrg   while (idx >= 0 && idx < (signed)path->num_events ())
   2224      1.1  mrg     {
   2225      1.1  mrg       checker_event *base_event = path->get_checker_event (idx);
   2226      1.1  mrg       if (get_logger ())
   2227      1.1  mrg 	{
   2228      1.1  mrg 	  if (sm)
   2229      1.1  mrg 	    {
   2230  1.1.1.2  mrg 	      if (sval)
   2231  1.1.1.2  mrg 		{
   2232  1.1.1.2  mrg 		  label_text sval_desc = sval->get_desc ();
   2233  1.1.1.2  mrg 		  log ("considering event %i (%s), with sval: %qs, state: %qs",
   2234  1.1.1.2  mrg 		       idx, event_kind_to_string (base_event->m_kind),
   2235  1.1.1.2  mrg 		       sval_desc.m_buffer, state->get_name ());
   2236  1.1.1.2  mrg 		  sval_desc.maybe_free ();
   2237  1.1.1.2  mrg 		}
   2238      1.1  mrg 	      else
   2239  1.1.1.2  mrg 		log ("considering event %i (%s), with global state: %qs",
   2240  1.1.1.2  mrg 		     idx, event_kind_to_string (base_event->m_kind),
   2241  1.1.1.2  mrg 		     state->get_name ());
   2242      1.1  mrg 	    }
   2243      1.1  mrg 	  else
   2244      1.1  mrg 	    log ("considering event %i", idx);
   2245      1.1  mrg 	}
   2246  1.1.1.2  mrg 
   2247      1.1  mrg       switch (base_event->m_kind)
   2248      1.1  mrg 	{
   2249      1.1  mrg 	default:
   2250      1.1  mrg 	  gcc_unreachable ();
   2251      1.1  mrg 
   2252      1.1  mrg 	case EK_DEBUG:
   2253      1.1  mrg 	  if (m_verbosity < 4)
   2254      1.1  mrg 	    {
   2255      1.1  mrg 	      log ("filtering event %i: debug event", idx);
   2256      1.1  mrg 	      path->delete_event (idx);
   2257      1.1  mrg 	    }
   2258      1.1  mrg 	  break;
   2259      1.1  mrg 
   2260      1.1  mrg 	case EK_CUSTOM:
   2261      1.1  mrg 	  /* Don't filter custom events.  */
   2262      1.1  mrg 	  break;
   2263      1.1  mrg 
   2264      1.1  mrg 	case EK_STMT:
   2265      1.1  mrg 	  {
   2266      1.1  mrg 	    if (m_verbosity < 4)
   2267      1.1  mrg 	      {
   2268      1.1  mrg 		log ("filtering event %i: statement event", idx);
   2269      1.1  mrg 		path->delete_event (idx);
   2270      1.1  mrg 	      }
   2271      1.1  mrg 	  }
   2272      1.1  mrg 	  break;
   2273      1.1  mrg 
   2274  1.1.1.2  mrg 	case EK_REGION_CREATION:
   2275  1.1.1.2  mrg 	  /* Don't filter these.  */
   2276  1.1.1.2  mrg 	  break;
   2277  1.1.1.2  mrg 
   2278      1.1  mrg 	case EK_FUNCTION_ENTRY:
   2279      1.1  mrg 	  if (m_verbosity < 1)
   2280      1.1  mrg 	    {
   2281      1.1  mrg 	      log ("filtering event %i: function entry", idx);
   2282      1.1  mrg 	      path->delete_event (idx);
   2283      1.1  mrg 	    }
   2284      1.1  mrg 	  break;
   2285      1.1  mrg 
   2286      1.1  mrg 	case EK_STATE_CHANGE:
   2287      1.1  mrg 	  {
   2288      1.1  mrg 	    state_change_event *state_change = (state_change_event *)base_event;
   2289  1.1.1.2  mrg 	    gcc_assert (state_change->m_dst_state.m_region_model);
   2290  1.1.1.2  mrg 
   2291  1.1.1.2  mrg 	    if (state_change->m_sval == sval)
   2292      1.1  mrg 	      {
   2293      1.1  mrg 		if (state_change->m_origin)
   2294      1.1  mrg 		  {
   2295  1.1.1.2  mrg 		    if (get_logger ())
   2296  1.1.1.2  mrg 		      {
   2297  1.1.1.2  mrg 			label_text sval_desc = sval->get_desc ();
   2298  1.1.1.2  mrg 			label_text origin_sval_desc
   2299  1.1.1.2  mrg 			  = state_change->m_origin->get_desc ();
   2300  1.1.1.2  mrg 			log ("event %i:"
   2301  1.1.1.2  mrg 			     " switching var of interest from %qs to %qs",
   2302  1.1.1.2  mrg 			     idx, sval_desc.m_buffer,
   2303  1.1.1.2  mrg 			     origin_sval_desc.m_buffer);
   2304  1.1.1.2  mrg 			sval_desc.maybe_free ();
   2305  1.1.1.2  mrg 			origin_sval_desc.maybe_free ();
   2306  1.1.1.2  mrg 		      }
   2307  1.1.1.2  mrg 		    sval = state_change->m_origin;
   2308      1.1  mrg 		  }
   2309      1.1  mrg 		log ("event %i: switching state of interest from %qs to %qs",
   2310  1.1.1.2  mrg 		     idx, state_change->m_to->get_name (),
   2311  1.1.1.2  mrg 		     state_change->m_from->get_name ());
   2312      1.1  mrg 		state = state_change->m_from;
   2313      1.1  mrg 	      }
   2314      1.1  mrg 	    else if (m_verbosity < 4)
   2315      1.1  mrg 	      {
   2316  1.1.1.2  mrg 		if (get_logger ())
   2317  1.1.1.2  mrg 		  {
   2318  1.1.1.2  mrg 		    if (state_change->m_sval)
   2319  1.1.1.2  mrg 		      {
   2320  1.1.1.2  mrg 			label_text change_sval_desc
   2321  1.1.1.2  mrg 			  = state_change->m_sval->get_desc ();
   2322  1.1.1.2  mrg 			if (sval)
   2323  1.1.1.2  mrg 			  {
   2324  1.1.1.2  mrg 			    label_text sval_desc = sval->get_desc ();
   2325  1.1.1.2  mrg 			    log ("filtering event %i:"
   2326  1.1.1.2  mrg 				 " state change to %qs unrelated to %qs",
   2327  1.1.1.2  mrg 				 idx, change_sval_desc.m_buffer,
   2328  1.1.1.2  mrg 				 sval_desc.m_buffer);
   2329  1.1.1.2  mrg 			  }
   2330  1.1.1.2  mrg 			else
   2331  1.1.1.2  mrg 			  log ("filtering event %i: state change to %qs",
   2332  1.1.1.2  mrg 			       idx, change_sval_desc.m_buffer);
   2333  1.1.1.2  mrg 			change_sval_desc.maybe_free ();
   2334  1.1.1.2  mrg 		      }
   2335  1.1.1.2  mrg 		    else
   2336  1.1.1.2  mrg 		      log ("filtering event %i: global state change", idx);
   2337  1.1.1.2  mrg 		  }
   2338      1.1  mrg 		path->delete_event (idx);
   2339      1.1  mrg 	      }
   2340      1.1  mrg 	  }
   2341      1.1  mrg 	  break;
   2342      1.1  mrg 
   2343      1.1  mrg 	case EK_START_CFG_EDGE:
   2344      1.1  mrg 	  {
   2345      1.1  mrg 	    cfg_edge_event *event = (cfg_edge_event *)base_event;
   2346      1.1  mrg 
   2347      1.1  mrg 	    /* TODO: is this edge significant to var?
   2348      1.1  mrg 	       See if var can be in other states in the dest, but not
   2349      1.1  mrg 	       in other states in the src?
   2350      1.1  mrg 	       Must have multiple sibling edges.  */
   2351      1.1  mrg 
   2352      1.1  mrg 	    if (event->should_filter_p (m_verbosity))
   2353      1.1  mrg 	      {
   2354  1.1.1.2  mrg 		log ("filtering events %i and %i: CFG edge", idx, idx + 1);
   2355      1.1  mrg 		path->delete_event (idx);
   2356      1.1  mrg 		/* Also delete the corresponding EK_END_CFG_EDGE.  */
   2357      1.1  mrg 		gcc_assert (path->get_checker_event (idx)->m_kind
   2358      1.1  mrg 			    == EK_END_CFG_EDGE);
   2359      1.1  mrg 		path->delete_event (idx);
   2360      1.1  mrg 	      }
   2361      1.1  mrg 	  }
   2362      1.1  mrg 	  break;
   2363      1.1  mrg 
   2364      1.1  mrg 	case EK_END_CFG_EDGE:
   2365      1.1  mrg 	  /* These come in pairs with EK_START_CFG_EDGE events and are
   2366      1.1  mrg 	     filtered when their start event is filtered.  */
   2367      1.1  mrg 	  break;
   2368      1.1  mrg 
   2369      1.1  mrg 	case EK_CALL_EDGE:
   2370      1.1  mrg 	  {
   2371      1.1  mrg 	    call_event *event = (call_event *)base_event;
   2372  1.1.1.2  mrg 	    const region_model *callee_model
   2373  1.1.1.2  mrg 	      = event->m_eedge.m_dest->get_state ().m_region_model;
   2374  1.1.1.2  mrg 	    const region_model *caller_model
   2375  1.1.1.2  mrg 	      = event->m_eedge.m_src->get_state ().m_region_model;
   2376  1.1.1.2  mrg 	    tree callee_var = callee_model->get_representative_tree (sval);
   2377      1.1  mrg 	    callsite_expr expr;
   2378  1.1.1.2  mrg 
   2379  1.1.1.2  mrg 	    tree caller_var;
   2380  1.1.1.2  mrg             if(event->m_sedge)
   2381  1.1.1.2  mrg               {
   2382  1.1.1.2  mrg                 const callgraph_superedge& cg_superedge
   2383  1.1.1.2  mrg                   = event->get_callgraph_superedge ();
   2384  1.1.1.2  mrg                 if (cg_superedge.m_cedge)
   2385  1.1.1.2  mrg 	          caller_var
   2386  1.1.1.2  mrg 	            = cg_superedge.map_expr_from_callee_to_caller (callee_var,
   2387  1.1.1.2  mrg                                                                    &expr);
   2388  1.1.1.2  mrg                 else
   2389  1.1.1.2  mrg                   caller_var = caller_model->get_representative_tree (sval);
   2390  1.1.1.2  mrg               }
   2391  1.1.1.2  mrg             else
   2392  1.1.1.2  mrg 	      caller_var = caller_model->get_representative_tree (sval);
   2393  1.1.1.2  mrg 
   2394      1.1  mrg 	    if (caller_var)
   2395      1.1  mrg 	      {
   2396  1.1.1.2  mrg 		if (get_logger ())
   2397  1.1.1.2  mrg 		  {
   2398  1.1.1.2  mrg 		    label_text sval_desc = sval->get_desc ();
   2399  1.1.1.2  mrg 		    log ("event %i:"
   2400  1.1.1.2  mrg 			 " recording critical state for %qs at call"
   2401  1.1.1.2  mrg 			 " from %qE in callee to %qE in caller",
   2402  1.1.1.2  mrg 			 idx, sval_desc.m_buffer, callee_var, caller_var);
   2403  1.1.1.2  mrg 		    sval_desc.maybe_free ();
   2404  1.1.1.2  mrg 		  }
   2405      1.1  mrg 		if (expr.param_p ())
   2406  1.1.1.2  mrg 		  event->record_critical_state (caller_var, state);
   2407      1.1  mrg 	      }
   2408      1.1  mrg 	  }
   2409      1.1  mrg 	  break;
   2410      1.1  mrg 
   2411      1.1  mrg 	case EK_RETURN_EDGE:
   2412      1.1  mrg 	  {
   2413  1.1.1.2  mrg 	    if (sval)
   2414      1.1  mrg 	      {
   2415      1.1  mrg 		return_event *event = (return_event *)base_event;
   2416  1.1.1.2  mrg                 const region_model *caller_model
   2417  1.1.1.2  mrg                   = event->m_eedge.m_dest->get_state ().m_region_model;
   2418  1.1.1.2  mrg                 tree caller_var = caller_model->get_representative_tree (sval);
   2419  1.1.1.2  mrg                 const region_model *callee_model
   2420  1.1.1.2  mrg                   = event->m_eedge.m_src->get_state ().m_region_model;
   2421      1.1  mrg 		callsite_expr expr;
   2422  1.1.1.2  mrg 
   2423  1.1.1.2  mrg                 tree callee_var;
   2424  1.1.1.2  mrg                 if (event->m_sedge)
   2425  1.1.1.2  mrg                   {
   2426  1.1.1.2  mrg                     const callgraph_superedge& cg_superedge
   2427  1.1.1.2  mrg                       = event->get_callgraph_superedge ();
   2428  1.1.1.2  mrg                     if (cg_superedge.m_cedge)
   2429  1.1.1.2  mrg                       callee_var
   2430  1.1.1.2  mrg                         = cg_superedge.map_expr_from_caller_to_callee (caller_var,
   2431  1.1.1.2  mrg                                                                        &expr);
   2432  1.1.1.2  mrg                     else
   2433  1.1.1.2  mrg                       callee_var = callee_model->get_representative_tree (sval);
   2434  1.1.1.2  mrg                   }
   2435  1.1.1.2  mrg                 else
   2436  1.1.1.2  mrg                   callee_var = callee_model->get_representative_tree (sval);
   2437  1.1.1.2  mrg 
   2438      1.1  mrg 		if (callee_var)
   2439      1.1  mrg 		  {
   2440  1.1.1.2  mrg 		    if (get_logger ())
   2441  1.1.1.2  mrg 		      {
   2442  1.1.1.2  mrg 			label_text sval_desc = sval->get_desc ();
   2443  1.1.1.2  mrg 			log ("event %i:"
   2444  1.1.1.2  mrg 			     " recording critical state for %qs at return"
   2445  1.1.1.2  mrg 			     " from %qE in caller to %qE in callee",
   2446  1.1.1.2  mrg 			     idx, sval_desc.m_buffer, callee_var, callee_var);
   2447  1.1.1.2  mrg 			sval_desc.maybe_free ();
   2448  1.1.1.2  mrg 		      }
   2449      1.1  mrg 		    if (expr.return_value_p ())
   2450  1.1.1.2  mrg 		      event->record_critical_state (callee_var, state);
   2451      1.1  mrg 		  }
   2452      1.1  mrg 	      }
   2453      1.1  mrg 	  }
   2454      1.1  mrg 	  break;
   2455      1.1  mrg 
   2456      1.1  mrg 	case EK_SETJMP:
   2457      1.1  mrg 	  /* TODO: only show setjmp_events that matter i.e. those for which
   2458      1.1  mrg 	     there is a later rewind event using them.  */
   2459      1.1  mrg 	case EK_REWIND_FROM_LONGJMP:
   2460      1.1  mrg 	case EK_REWIND_TO_SETJMP:
   2461      1.1  mrg 	  break;
   2462      1.1  mrg 
   2463      1.1  mrg 	case EK_WARNING:
   2464      1.1  mrg 	  /* Always show the final "warning" event in the path.  */
   2465      1.1  mrg 	  break;
   2466      1.1  mrg 	}
   2467      1.1  mrg       idx--;
   2468      1.1  mrg     }
   2469      1.1  mrg }
   2470      1.1  mrg 
   2471      1.1  mrg /* Subroutine of diagnostic_manager::prune_for_sm_diagnostic.
   2472      1.1  mrg    If *EXPR is not suitable to be the expression of interest in
   2473      1.1  mrg    an sm-diagnostic, set *EXPR to NULL and log.  */
   2474      1.1  mrg 
   2475      1.1  mrg void
   2476      1.1  mrg diagnostic_manager::update_for_unsuitable_sm_exprs (tree *expr) const
   2477      1.1  mrg {
   2478      1.1  mrg   gcc_assert (expr);
   2479      1.1  mrg   if (*expr && !can_be_expr_of_interest_p (*expr))
   2480      1.1  mrg     {
   2481      1.1  mrg       log ("new var %qE is unsuitable; setting var to NULL", *expr);
   2482      1.1  mrg       *expr = NULL_TREE;
   2483      1.1  mrg     }
   2484      1.1  mrg }
   2485      1.1  mrg 
   2486      1.1  mrg /* Second pass of diagnostic_manager::prune_path: remove redundant
   2487      1.1  mrg    interprocedural information.
   2488      1.1  mrg 
   2489      1.1  mrg    For example, given:
   2490      1.1  mrg      (1)- calling "f2" from "f1"
   2491      1.1  mrg      (2)--- entry to "f2"
   2492      1.1  mrg      (3)--- calling "f3" from "f2"
   2493      1.1  mrg      (4)----- entry to "f3"
   2494      1.1  mrg      (5)--- returning to "f2" to "f3"
   2495      1.1  mrg      (6)- returning to "f1" to "f2"
   2496      1.1  mrg    with no other intervening events, then none of these events are
   2497      1.1  mrg    likely to be interesting to the user.
   2498      1.1  mrg 
   2499      1.1  mrg    Prune [..., call, function-entry, return, ...] triples repeatedly
   2500      1.1  mrg    until nothing has changed.  For the example above, this would
   2501      1.1  mrg    remove events (3, 4, 5), and then remove events (1, 2, 6).  */
   2502      1.1  mrg 
   2503      1.1  mrg void
   2504      1.1  mrg diagnostic_manager::prune_interproc_events (checker_path *path) const
   2505      1.1  mrg {
   2506      1.1  mrg   bool changed = false;
   2507      1.1  mrg   do
   2508      1.1  mrg     {
   2509      1.1  mrg       changed = false;
   2510  1.1.1.2  mrg       int idx = (signed)path->num_events () - 1;
   2511      1.1  mrg       while (idx >= 0)
   2512      1.1  mrg 	{
   2513      1.1  mrg 	  /* Prune [..., call, function-entry, return, ...] triples.  */
   2514      1.1  mrg 	  if (idx + 2 < (signed)path->num_events ()
   2515      1.1  mrg 	      && path->get_checker_event (idx)->is_call_p ()
   2516      1.1  mrg 	      && path->get_checker_event (idx + 1)->is_function_entry_p ()
   2517      1.1  mrg 	      && path->get_checker_event (idx + 2)->is_return_p ())
   2518      1.1  mrg 	    {
   2519      1.1  mrg 	      if (get_logger ())
   2520      1.1  mrg 		{
   2521      1.1  mrg 		  label_text desc
   2522      1.1  mrg 		    (path->get_checker_event (idx)->get_desc (false));
   2523      1.1  mrg 		  log ("filtering events %i-%i:"
   2524      1.1  mrg 		       " irrelevant call/entry/return: %s",
   2525      1.1  mrg 		       idx, idx + 2, desc.m_buffer);
   2526      1.1  mrg 		  desc.maybe_free ();
   2527      1.1  mrg 		}
   2528      1.1  mrg 	      path->delete_event (idx + 2);
   2529      1.1  mrg 	      path->delete_event (idx + 1);
   2530      1.1  mrg 	      path->delete_event (idx);
   2531      1.1  mrg 	      changed = true;
   2532      1.1  mrg 	      idx--;
   2533      1.1  mrg 	      continue;
   2534      1.1  mrg 	    }
   2535      1.1  mrg 
   2536      1.1  mrg 	  /* Prune [..., call, return, ...] pairs
   2537      1.1  mrg 	     (for -fanalyzer-verbosity=0).  */
   2538      1.1  mrg 	  if (idx + 1 < (signed)path->num_events ()
   2539      1.1  mrg 	      && path->get_checker_event (idx)->is_call_p ()
   2540      1.1  mrg 	      && path->get_checker_event (idx + 1)->is_return_p ())
   2541      1.1  mrg 	    {
   2542      1.1  mrg 	      if (get_logger ())
   2543      1.1  mrg 		{
   2544      1.1  mrg 		  label_text desc
   2545      1.1  mrg 		    (path->get_checker_event (idx)->get_desc (false));
   2546      1.1  mrg 		  log ("filtering events %i-%i:"
   2547      1.1  mrg 		       " irrelevant call/return: %s",
   2548      1.1  mrg 		       idx, idx + 1, desc.m_buffer);
   2549      1.1  mrg 		  desc.maybe_free ();
   2550      1.1  mrg 		}
   2551      1.1  mrg 	      path->delete_event (idx + 1);
   2552      1.1  mrg 	      path->delete_event (idx);
   2553      1.1  mrg 	      changed = true;
   2554      1.1  mrg 	      idx--;
   2555      1.1  mrg 	      continue;
   2556      1.1  mrg 	    }
   2557      1.1  mrg 
   2558      1.1  mrg 	  idx--;
   2559      1.1  mrg 	}
   2560      1.1  mrg 
   2561      1.1  mrg     }
   2562      1.1  mrg   while (changed);
   2563      1.1  mrg }
   2564      1.1  mrg 
   2565  1.1.1.2  mrg /* Return true iff event IDX within PATH is on the same line as REF_EXP_LOC.  */
   2566  1.1.1.2  mrg 
   2567  1.1.1.2  mrg static bool
   2568  1.1.1.2  mrg same_line_as_p (const expanded_location &ref_exp_loc,
   2569  1.1.1.2  mrg 		checker_path *path, unsigned idx)
   2570  1.1.1.2  mrg {
   2571  1.1.1.2  mrg   const checker_event *ev = path->get_checker_event (idx);
   2572  1.1.1.2  mrg   expanded_location idx_exp_loc = expand_location (ev->get_location ());
   2573  1.1.1.2  mrg   gcc_assert (ref_exp_loc.file);
   2574  1.1.1.2  mrg   if (idx_exp_loc.file == NULL)
   2575  1.1.1.2  mrg     return false;
   2576  1.1.1.2  mrg   if (strcmp (ref_exp_loc.file, idx_exp_loc.file))
   2577  1.1.1.2  mrg     return false;
   2578  1.1.1.2  mrg   return ref_exp_loc.line == idx_exp_loc.line;
   2579  1.1.1.2  mrg }
   2580  1.1.1.2  mrg 
   2581  1.1.1.2  mrg /* This path-readability optimization reduces the verbosity of compound
   2582  1.1.1.2  mrg    conditional statements (without needing to reconstruct the AST, which
   2583  1.1.1.2  mrg    has already been lost).
   2584  1.1.1.2  mrg 
   2585  1.1.1.2  mrg    For example, it converts:
   2586  1.1.1.2  mrg 
   2587  1.1.1.2  mrg     |   61 |   if (cp[0] != '\0' && cp[0] != '#')
   2588  1.1.1.2  mrg     |      |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   2589  1.1.1.2  mrg     |      |      |              |    |
   2590  1.1.1.2  mrg     |      |      |              |    (6) ...to here
   2591  1.1.1.2  mrg     |      |      |              (7) following true branch...
   2592  1.1.1.2  mrg     |      |      (5) following true branch...
   2593  1.1.1.2  mrg     |   62 |     {
   2594  1.1.1.2  mrg     |   63 |       alias = cp++;
   2595  1.1.1.2  mrg     |      |               ~~~~
   2596  1.1.1.2  mrg     |      |                 |
   2597  1.1.1.2  mrg     |      |                 (8) ...to here
   2598  1.1.1.2  mrg 
   2599  1.1.1.2  mrg    into:
   2600  1.1.1.2  mrg 
   2601  1.1.1.2  mrg     |   61 |   if (cp[0] != '\0' && cp[0] != '#')
   2602  1.1.1.2  mrg     |      |      ~
   2603  1.1.1.2  mrg     |      |      |
   2604  1.1.1.2  mrg     |      |      (5) following true branch...
   2605  1.1.1.2  mrg     |   62 |     {
   2606  1.1.1.2  mrg     |   63 |       alias = cp++;
   2607  1.1.1.2  mrg     |      |               ~~~~
   2608  1.1.1.2  mrg     |      |                 |
   2609  1.1.1.2  mrg     |      |                 (6) ...to here
   2610  1.1.1.2  mrg 
   2611  1.1.1.2  mrg    by combining events 5-8 into new events 5-6.
   2612  1.1.1.2  mrg 
   2613  1.1.1.2  mrg    Find runs of consecutive (start_cfg_edge_event, end_cfg_edge_event) pairs
   2614  1.1.1.2  mrg    in which all events apart from the final end_cfg_edge_event are on the same
   2615  1.1.1.2  mrg    line, and for which either all the CFG edges are TRUE edges, or all are
   2616  1.1.1.2  mrg    FALSE edges.
   2617  1.1.1.2  mrg 
   2618  1.1.1.2  mrg    Consolidate each such run into a
   2619  1.1.1.2  mrg      (start_consolidated_cfg_edges_event, end_consolidated_cfg_edges_event)
   2620  1.1.1.2  mrg    pair.  */
   2621  1.1.1.2  mrg 
   2622  1.1.1.2  mrg void
   2623  1.1.1.2  mrg diagnostic_manager::consolidate_conditions (checker_path *path) const
   2624  1.1.1.2  mrg {
   2625  1.1.1.2  mrg   /* Don't simplify edges if we're debugging them.  */
   2626  1.1.1.2  mrg   if (flag_analyzer_verbose_edges)
   2627  1.1.1.2  mrg     return;
   2628  1.1.1.2  mrg 
   2629  1.1.1.2  mrg   for (int start_idx = 0;
   2630  1.1.1.2  mrg        start_idx < (signed)path->num_events () - 1;
   2631  1.1.1.2  mrg        start_idx++)
   2632  1.1.1.2  mrg     {
   2633  1.1.1.2  mrg       if (path->cfg_edge_pair_at_p (start_idx))
   2634  1.1.1.2  mrg 	{
   2635  1.1.1.2  mrg 	  const checker_event *old_start_ev
   2636  1.1.1.2  mrg 	    = path->get_checker_event (start_idx);
   2637  1.1.1.2  mrg 	  expanded_location start_exp_loc
   2638  1.1.1.2  mrg 	    = expand_location (old_start_ev->get_location ());
   2639  1.1.1.2  mrg 	  if (start_exp_loc.file == NULL)
   2640  1.1.1.2  mrg 	    continue;
   2641  1.1.1.2  mrg 	  if (!same_line_as_p (start_exp_loc, path, start_idx + 1))
   2642  1.1.1.2  mrg 	    continue;
   2643  1.1.1.2  mrg 
   2644  1.1.1.2  mrg 	  /* Are we looking for a run of all TRUE edges, or all FALSE edges?  */
   2645  1.1.1.2  mrg 	  gcc_assert (old_start_ev->m_kind == EK_START_CFG_EDGE);
   2646  1.1.1.2  mrg 	  const start_cfg_edge_event *old_start_cfg_ev
   2647  1.1.1.2  mrg 	    = (const start_cfg_edge_event *)old_start_ev;
   2648  1.1.1.2  mrg 	  const cfg_superedge& first_cfg_sedge
   2649  1.1.1.2  mrg 	    = old_start_cfg_ev->get_cfg_superedge ();
   2650  1.1.1.2  mrg 	  bool edge_sense;
   2651  1.1.1.2  mrg 	  if (first_cfg_sedge.true_value_p ())
   2652  1.1.1.2  mrg 	    edge_sense = true;
   2653  1.1.1.2  mrg 	  else if (first_cfg_sedge.false_value_p ())
   2654  1.1.1.2  mrg 	    edge_sense = false;
   2655  1.1.1.2  mrg 	  else
   2656  1.1.1.2  mrg 	    continue;
   2657  1.1.1.2  mrg 
   2658  1.1.1.2  mrg 	  /* Find a run of CFG start/end event pairs from
   2659  1.1.1.2  mrg 	       [start_idx, next_idx)
   2660  1.1.1.2  mrg 	     where all apart from the final event are on the same line,
   2661  1.1.1.2  mrg 	     and all are either TRUE or FALSE edges, matching the initial.  */
   2662  1.1.1.2  mrg 	  int next_idx = start_idx + 2;
   2663  1.1.1.2  mrg 	  while (path->cfg_edge_pair_at_p (next_idx)
   2664  1.1.1.2  mrg 		 && same_line_as_p (start_exp_loc, path, next_idx))
   2665  1.1.1.2  mrg 	    {
   2666  1.1.1.2  mrg 	      const checker_event *iter_ev
   2667  1.1.1.2  mrg 		= path->get_checker_event (next_idx);
   2668  1.1.1.2  mrg 	      gcc_assert (iter_ev->m_kind == EK_START_CFG_EDGE);
   2669  1.1.1.2  mrg 	      const start_cfg_edge_event *iter_cfg_ev
   2670  1.1.1.2  mrg 		= (const start_cfg_edge_event *)iter_ev;
   2671  1.1.1.2  mrg 	      const cfg_superedge& iter_cfg_sedge
   2672  1.1.1.2  mrg 		= iter_cfg_ev->get_cfg_superedge ();
   2673  1.1.1.2  mrg 	      if (edge_sense)
   2674  1.1.1.2  mrg 		{
   2675  1.1.1.2  mrg 		  if (!iter_cfg_sedge.true_value_p ())
   2676  1.1.1.2  mrg 		    break;
   2677  1.1.1.2  mrg 		}
   2678  1.1.1.2  mrg 	      else
   2679  1.1.1.2  mrg 		{
   2680  1.1.1.2  mrg 		  if (!iter_cfg_sedge.false_value_p ())
   2681  1.1.1.2  mrg 		    break;
   2682  1.1.1.2  mrg 		}
   2683  1.1.1.2  mrg 	      next_idx += 2;
   2684  1.1.1.2  mrg 	    }
   2685  1.1.1.2  mrg 
   2686  1.1.1.2  mrg 	  /* If we have more than one pair in the run, consolidate.  */
   2687  1.1.1.2  mrg 	  if (next_idx > start_idx + 2)
   2688  1.1.1.2  mrg 	    {
   2689  1.1.1.2  mrg 	      const checker_event *old_end_ev
   2690  1.1.1.2  mrg 		= path->get_checker_event (next_idx - 1);
   2691  1.1.1.2  mrg 	      log ("consolidating CFG edge events %i-%i into %i-%i",
   2692  1.1.1.2  mrg 		   start_idx, next_idx - 1, start_idx, start_idx +1);
   2693  1.1.1.2  mrg 	      start_consolidated_cfg_edges_event *new_start_ev
   2694  1.1.1.2  mrg 		= new start_consolidated_cfg_edges_event
   2695  1.1.1.2  mrg 		(old_start_ev->get_location (),
   2696  1.1.1.2  mrg 		 old_start_ev->get_fndecl (),
   2697  1.1.1.2  mrg 		 old_start_ev->get_stack_depth (),
   2698  1.1.1.2  mrg 		 edge_sense);
   2699  1.1.1.2  mrg 	      checker_event *new_end_ev
   2700  1.1.1.2  mrg 		= new end_consolidated_cfg_edges_event
   2701  1.1.1.2  mrg 		(old_end_ev->get_location (),
   2702  1.1.1.2  mrg 		 old_end_ev->get_fndecl (),
   2703  1.1.1.2  mrg 		 old_end_ev->get_stack_depth ());
   2704  1.1.1.2  mrg 	      path->replace_event (start_idx, new_start_ev);
   2705  1.1.1.2  mrg 	      path->replace_event (start_idx + 1, new_end_ev);
   2706  1.1.1.2  mrg 	      path->delete_events (start_idx + 2, next_idx - (start_idx + 2));
   2707  1.1.1.2  mrg 	    }
   2708  1.1.1.2  mrg 	}
   2709  1.1.1.2  mrg     }
   2710  1.1.1.2  mrg }
   2711  1.1.1.2  mrg 
   2712      1.1  mrg /* Final pass of diagnostic_manager::prune_path.
   2713      1.1  mrg 
   2714      1.1  mrg    If all we're left with is in one function, then filter function entry
   2715      1.1  mrg    events.  */
   2716      1.1  mrg 
   2717      1.1  mrg void
   2718      1.1  mrg diagnostic_manager::finish_pruning (checker_path *path) const
   2719      1.1  mrg {
   2720      1.1  mrg   if (!path->interprocedural_p ())
   2721      1.1  mrg     {
   2722      1.1  mrg       int idx = path->num_events () - 1;
   2723      1.1  mrg       while (idx >= 0 && idx < (signed)path->num_events ())
   2724      1.1  mrg 	{
   2725      1.1  mrg 	  checker_event *base_event = path->get_checker_event (idx);
   2726      1.1  mrg 	  if (base_event->m_kind == EK_FUNCTION_ENTRY)
   2727      1.1  mrg 	    {
   2728      1.1  mrg 	      log ("filtering event %i:"
   2729      1.1  mrg 		   " function entry for purely intraprocedural path", idx);
   2730      1.1  mrg 	      path->delete_event (idx);
   2731      1.1  mrg 	    }
   2732      1.1  mrg 	  idx--;
   2733      1.1  mrg 	}
   2734      1.1  mrg     }
   2735      1.1  mrg }
   2736      1.1  mrg 
   2737      1.1  mrg } // namespace ana
   2738      1.1  mrg 
   2739      1.1  mrg #endif /* #if ENABLE_ANALYZER */
   2740