Home | History | Annotate | Line # | Download | only in analyzer
diagnostic-manager.cc revision 1.1
      1  1.1  mrg /* Classes for saving, deduplicating, and emitting analyzer diagnostics.
      2  1.1  mrg    Copyright (C) 2019-2020 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  mrg #include "analyzer/analyzer.h"
     41  1.1  mrg #include "analyzer/analyzer-logging.h"
     42  1.1  mrg #include "analyzer/sm.h"
     43  1.1  mrg #include "analyzer/pending-diagnostic.h"
     44  1.1  mrg #include "analyzer/diagnostic-manager.h"
     45  1.1  mrg #include "analyzer/region-model.h"
     46  1.1  mrg #include "analyzer/constraint-manager.h"
     47  1.1  mrg #include "cfg.h"
     48  1.1  mrg #include "basic-block.h"
     49  1.1  mrg #include "gimple.h"
     50  1.1  mrg #include "gimple-iterator.h"
     51  1.1  mrg #include "cgraph.h"
     52  1.1  mrg #include "digraph.h"
     53  1.1  mrg #include "analyzer/supergraph.h"
     54  1.1  mrg #include "analyzer/call-string.h"
     55  1.1  mrg #include "analyzer/program-point.h"
     56  1.1  mrg #include "analyzer/program-state.h"
     57  1.1  mrg #include "analyzer/exploded-graph.h"
     58  1.1  mrg #include "analyzer/checker-path.h"
     59  1.1  mrg #include "analyzer/reachability.h"
     60  1.1  mrg 
     61  1.1  mrg #if ENABLE_ANALYZER
     62  1.1  mrg 
     63  1.1  mrg namespace ana {
     64  1.1  mrg 
     65  1.1  mrg /* class saved_diagnostic.  */
     66  1.1  mrg 
     67  1.1  mrg /* saved_diagnostic's ctor.
     68  1.1  mrg    Take ownership of D and STMT_FINDER.  */
     69  1.1  mrg 
     70  1.1  mrg saved_diagnostic::saved_diagnostic (const state_machine *sm,
     71  1.1  mrg 				    const exploded_node *enode,
     72  1.1  mrg 				    const supernode *snode, const gimple *stmt,
     73  1.1  mrg 				    stmt_finder *stmt_finder,
     74  1.1  mrg 				    tree var, state_machine::state_t state,
     75  1.1  mrg 				    pending_diagnostic *d)
     76  1.1  mrg : m_sm (sm), m_enode (enode), m_snode (snode), m_stmt (stmt),
     77  1.1  mrg  /* stmt_finder could be on-stack; we want our own copy that can
     78  1.1  mrg     outlive that.  */
     79  1.1  mrg   m_stmt_finder (stmt_finder ? stmt_finder->clone () : NULL),
     80  1.1  mrg   m_var (var), m_state (state),
     81  1.1  mrg   m_d (d), m_trailing_eedge (NULL),
     82  1.1  mrg   m_status (STATUS_NEW), m_epath_length (0), m_problem (NULL)
     83  1.1  mrg {
     84  1.1  mrg   gcc_assert (m_stmt || m_stmt_finder);
     85  1.1  mrg 
     86  1.1  mrg   /* We must have an enode in order to be able to look for paths
     87  1.1  mrg      through the exploded_graph to this diagnostic.  */
     88  1.1  mrg   gcc_assert (m_enode);
     89  1.1  mrg }
     90  1.1  mrg 
     91  1.1  mrg /* saved_diagnostic's dtor.  */
     92  1.1  mrg 
     93  1.1  mrg saved_diagnostic::~saved_diagnostic ()
     94  1.1  mrg {
     95  1.1  mrg   delete m_stmt_finder;
     96  1.1  mrg   delete m_d;
     97  1.1  mrg   delete m_problem;
     98  1.1  mrg }
     99  1.1  mrg 
    100  1.1  mrg bool
    101  1.1  mrg saved_diagnostic::operator== (const saved_diagnostic &other) const
    102  1.1  mrg {
    103  1.1  mrg   return (m_sm == other.m_sm
    104  1.1  mrg 	  /* We don't compare m_enode.  */
    105  1.1  mrg 	  && m_snode == other.m_snode
    106  1.1  mrg 	  && m_stmt == other.m_stmt
    107  1.1  mrg 	  /* We don't compare m_stmt_finder.  */
    108  1.1  mrg 	  && pending_diagnostic::same_tree_p (m_var, other.m_var)
    109  1.1  mrg 	  && m_state == other.m_state
    110  1.1  mrg 	  && m_d->equal_p (*other.m_d)
    111  1.1  mrg 	  && m_trailing_eedge == other.m_trailing_eedge);
    112  1.1  mrg }
    113  1.1  mrg 
    114  1.1  mrg /* State for building a checker_path from a particular exploded_path.
    115  1.1  mrg    In particular, this precomputes reachability information: the set of
    116  1.1  mrg    source enodes for which a path be found to the diagnostic enode.  */
    117  1.1  mrg 
    118  1.1  mrg class path_builder
    119  1.1  mrg {
    120  1.1  mrg public:
    121  1.1  mrg   path_builder (const exploded_graph &eg,
    122  1.1  mrg 		const exploded_path &epath)
    123  1.1  mrg   : m_eg (eg),
    124  1.1  mrg     m_diag_enode (epath.get_final_enode ()),
    125  1.1  mrg     m_reachability (eg, m_diag_enode)
    126  1.1  mrg   {}
    127  1.1  mrg 
    128  1.1  mrg   const exploded_node *get_diag_node () const { return m_diag_enode; }
    129  1.1  mrg 
    130  1.1  mrg   bool reachable_from_p (const exploded_node *src_enode) const
    131  1.1  mrg   {
    132  1.1  mrg     return m_reachability.reachable_from_p (src_enode);
    133  1.1  mrg   }
    134  1.1  mrg 
    135  1.1  mrg   const extrinsic_state &get_ext_state () const { return m_eg.get_ext_state (); }
    136  1.1  mrg 
    137  1.1  mrg private:
    138  1.1  mrg   typedef reachability<eg_traits> enode_reachability;
    139  1.1  mrg 
    140  1.1  mrg   const exploded_graph &m_eg;
    141  1.1  mrg 
    142  1.1  mrg   /* The enode where the diagnostic occurs.  */
    143  1.1  mrg   const exploded_node *m_diag_enode;
    144  1.1  mrg 
    145  1.1  mrg   /* Precompute all enodes from which the diagnostic is reachable.  */
    146  1.1  mrg   enode_reachability m_reachability;
    147  1.1  mrg };
    148  1.1  mrg 
    149  1.1  mrg /* class diagnostic_manager.  */
    150  1.1  mrg 
    151  1.1  mrg /* diagnostic_manager's ctor.  */
    152  1.1  mrg 
    153  1.1  mrg diagnostic_manager::diagnostic_manager (logger *logger, int verbosity)
    154  1.1  mrg : log_user (logger), m_verbosity (verbosity)
    155  1.1  mrg {
    156  1.1  mrg }
    157  1.1  mrg 
    158  1.1  mrg /* Queue pending_diagnostic D at ENODE for later emission.  */
    159  1.1  mrg 
    160  1.1  mrg void
    161  1.1  mrg diagnostic_manager::add_diagnostic (const state_machine *sm,
    162  1.1  mrg 				    const exploded_node *enode,
    163  1.1  mrg 				    const supernode *snode, const gimple *stmt,
    164  1.1  mrg 				    stmt_finder *finder,
    165  1.1  mrg 				    tree var, state_machine::state_t state,
    166  1.1  mrg 				    pending_diagnostic *d)
    167  1.1  mrg {
    168  1.1  mrg   LOG_FUNC (get_logger ());
    169  1.1  mrg 
    170  1.1  mrg   /* We must have an enode in order to be able to look for paths
    171  1.1  mrg      through the exploded_graph to the diagnostic.  */
    172  1.1  mrg   gcc_assert (enode);
    173  1.1  mrg 
    174  1.1  mrg   saved_diagnostic *sd
    175  1.1  mrg     = new saved_diagnostic (sm, enode, snode, stmt, finder, var, state, d);
    176  1.1  mrg   m_saved_diagnostics.safe_push (sd);
    177  1.1  mrg   if (get_logger ())
    178  1.1  mrg     log ("adding saved diagnostic %i at SN %i: %qs",
    179  1.1  mrg 	 m_saved_diagnostics.length () - 1,
    180  1.1  mrg 	 snode->m_index, d->get_kind ());
    181  1.1  mrg }
    182  1.1  mrg 
    183  1.1  mrg /* Queue pending_diagnostic D at ENODE for later emission.  */
    184  1.1  mrg 
    185  1.1  mrg void
    186  1.1  mrg diagnostic_manager::add_diagnostic (const exploded_node *enode,
    187  1.1  mrg 				    const supernode *snode, const gimple *stmt,
    188  1.1  mrg 				    stmt_finder *finder,
    189  1.1  mrg 				    pending_diagnostic *d)
    190  1.1  mrg {
    191  1.1  mrg   gcc_assert (enode);
    192  1.1  mrg   add_diagnostic (NULL, enode, snode, stmt, finder, NULL_TREE, 0, d);
    193  1.1  mrg }
    194  1.1  mrg 
    195  1.1  mrg /* A class for identifying sets of duplicated pending_diagnostic.
    196  1.1  mrg 
    197  1.1  mrg    We want to find the simplest dedupe_candidate amongst those that share a
    198  1.1  mrg    dedupe_key.  */
    199  1.1  mrg 
    200  1.1  mrg class dedupe_key
    201  1.1  mrg {
    202  1.1  mrg public:
    203  1.1  mrg   dedupe_key (const saved_diagnostic &sd,
    204  1.1  mrg 	      const exploded_path &epath)
    205  1.1  mrg   : m_sd (sd), m_stmt (sd.m_stmt)
    206  1.1  mrg   {
    207  1.1  mrg     /* Support deferring the choice of stmt until after an emission path has
    208  1.1  mrg      been built, using an optional stmt_finder.  */
    209  1.1  mrg     if (m_stmt == NULL)
    210  1.1  mrg       {
    211  1.1  mrg 	gcc_assert (sd.m_stmt_finder);
    212  1.1  mrg 	m_stmt = sd.m_stmt_finder->find_stmt (epath);
    213  1.1  mrg       }
    214  1.1  mrg     gcc_assert (m_stmt);
    215  1.1  mrg   }
    216  1.1  mrg 
    217  1.1  mrg   hashval_t hash () const
    218  1.1  mrg   {
    219  1.1  mrg     inchash::hash hstate;
    220  1.1  mrg     hstate.add_ptr (m_stmt);
    221  1.1  mrg     // TODO: m_sd
    222  1.1  mrg     return hstate.end ();
    223  1.1  mrg   }
    224  1.1  mrg   bool operator== (const dedupe_key &other) const
    225  1.1  mrg   {
    226  1.1  mrg     return (m_sd == other.m_sd
    227  1.1  mrg 	    && m_stmt == other.m_stmt);
    228  1.1  mrg   }
    229  1.1  mrg 
    230  1.1  mrg   location_t get_location () const
    231  1.1  mrg   {
    232  1.1  mrg     return m_stmt->location;
    233  1.1  mrg   }
    234  1.1  mrg 
    235  1.1  mrg   /* A qsort comparator for use by dedupe_winners::emit_best
    236  1.1  mrg      to sort them into location_t order.  */
    237  1.1  mrg 
    238  1.1  mrg   static int
    239  1.1  mrg   comparator (const void *p1, const void *p2)
    240  1.1  mrg   {
    241  1.1  mrg     const dedupe_key *pk1 = *(const dedupe_key * const *)p1;
    242  1.1  mrg     const dedupe_key *pk2 = *(const dedupe_key * const *)p2;
    243  1.1  mrg 
    244  1.1  mrg     location_t loc1 = pk1->get_location ();
    245  1.1  mrg     location_t loc2 = pk2->get_location ();
    246  1.1  mrg 
    247  1.1  mrg     return linemap_compare_locations (line_table, loc2, loc1);
    248  1.1  mrg   }
    249  1.1  mrg 
    250  1.1  mrg   const saved_diagnostic &m_sd;
    251  1.1  mrg   const gimple *m_stmt;
    252  1.1  mrg };
    253  1.1  mrg 
    254  1.1  mrg /* The value of a slot for a dedupe_key within dedupe_winners:
    255  1.1  mrg    the exploded_path for the best candidate for that key, and the
    256  1.1  mrg    number of duplicates seen so far.  */
    257  1.1  mrg 
    258  1.1  mrg class dedupe_candidate
    259  1.1  mrg {
    260  1.1  mrg public:
    261  1.1  mrg   // has the exploded_path
    262  1.1  mrg   dedupe_candidate (const shortest_exploded_paths &sp,
    263  1.1  mrg 		    saved_diagnostic *sd)
    264  1.1  mrg   : m_epath (sp.get_shortest_path (sd->m_enode)),
    265  1.1  mrg     m_num_dupes (0)
    266  1.1  mrg   {
    267  1.1  mrg   }
    268  1.1  mrg 
    269  1.1  mrg   unsigned length () const { return m_epath.length (); }
    270  1.1  mrg   const exploded_path &get_path () const { return m_epath; }
    271  1.1  mrg 
    272  1.1  mrg   void add_duplicate () { m_num_dupes++; }
    273  1.1  mrg   int get_num_dupes () const { return m_num_dupes; }
    274  1.1  mrg 
    275  1.1  mrg private:
    276  1.1  mrg   exploded_path m_epath;
    277  1.1  mrg public:
    278  1.1  mrg   int m_num_dupes;
    279  1.1  mrg };
    280  1.1  mrg 
    281  1.1  mrg /* Traits for use by dedupe_winners.  */
    282  1.1  mrg 
    283  1.1  mrg class dedupe_hash_map_traits
    284  1.1  mrg {
    285  1.1  mrg public:
    286  1.1  mrg   typedef const dedupe_key *key_type;
    287  1.1  mrg   typedef dedupe_candidate *value_type;
    288  1.1  mrg   typedef dedupe_candidate *compare_type;
    289  1.1  mrg 
    290  1.1  mrg   static inline hashval_t hash (const key_type &v)
    291  1.1  mrg   {
    292  1.1  mrg     return v->hash ();
    293  1.1  mrg   }
    294  1.1  mrg   static inline bool equal_keys (const key_type &k1, const key_type &k2)
    295  1.1  mrg   {
    296  1.1  mrg     return *k1 == *k2;
    297  1.1  mrg   }
    298  1.1  mrg   template <typename T>
    299  1.1  mrg   static inline void remove (T &)
    300  1.1  mrg   {
    301  1.1  mrg     // TODO
    302  1.1  mrg   }
    303  1.1  mrg   template <typename T>
    304  1.1  mrg   static inline void mark_deleted (T &entry)
    305  1.1  mrg   {
    306  1.1  mrg     entry.m_key = reinterpret_cast<key_type> (1);
    307  1.1  mrg   }
    308  1.1  mrg   template <typename T>
    309  1.1  mrg   static inline void mark_empty (T &entry)
    310  1.1  mrg   {
    311  1.1  mrg     entry.m_key = NULL;
    312  1.1  mrg   }
    313  1.1  mrg   template <typename T>
    314  1.1  mrg   static inline bool is_deleted (const T &entry)
    315  1.1  mrg   {
    316  1.1  mrg     return entry.m_key == reinterpret_cast<key_type> (1);
    317  1.1  mrg   }
    318  1.1  mrg   template <typename T>
    319  1.1  mrg   static inline bool is_empty (const T &entry)
    320  1.1  mrg   {
    321  1.1  mrg     return entry.m_key == NULL;
    322  1.1  mrg   }
    323  1.1  mrg   static const bool empty_zero_p = true;
    324  1.1  mrg };
    325  1.1  mrg 
    326  1.1  mrg /* A class for deduplicating diagnostics and finding (and emitting) the
    327  1.1  mrg    best diagnostic within each partition.  */
    328  1.1  mrg 
    329  1.1  mrg class dedupe_winners
    330  1.1  mrg {
    331  1.1  mrg public:
    332  1.1  mrg   ~dedupe_winners ()
    333  1.1  mrg   {
    334  1.1  mrg     /* Delete all keys and candidates.  */
    335  1.1  mrg     for (map_t::iterator iter = m_map.begin ();
    336  1.1  mrg 	 iter != m_map.end ();
    337  1.1  mrg 	 ++iter)
    338  1.1  mrg       {
    339  1.1  mrg 	delete (*iter).first;
    340  1.1  mrg 	delete (*iter).second;
    341  1.1  mrg       }
    342  1.1  mrg   }
    343  1.1  mrg 
    344  1.1  mrg   /* Determine an exploded_path for SD using SP and, if it's feasible,
    345  1.1  mrg      determine if it's the best seen so far for its dedupe_key.
    346  1.1  mrg      Retain the winner for each dedupe_key, and discard the rest.  */
    347  1.1  mrg 
    348  1.1  mrg   void add (logger *logger,
    349  1.1  mrg 	    const shortest_exploded_paths &sp,
    350  1.1  mrg 	    saved_diagnostic *sd)
    351  1.1  mrg   {
    352  1.1  mrg     /* Build a dedupe_candidate for SD.
    353  1.1  mrg        This uses SP to build an exploded_path.  */
    354  1.1  mrg     dedupe_candidate *dc = new dedupe_candidate (sp, sd);
    355  1.1  mrg 
    356  1.1  mrg     sd->set_epath_length (dc->length ());
    357  1.1  mrg 
    358  1.1  mrg     /* Verify that the epath is feasible.
    359  1.1  mrg        State-merging means that not every path in the epath corresponds
    360  1.1  mrg        to a feasible one w.r.t. states.
    361  1.1  mrg        Here we simply check each duplicate saved_diagnostic's
    362  1.1  mrg        shortest_path, and reject any that aren't feasible.
    363  1.1  mrg        This could introduce false negatives, as there could be longer
    364  1.1  mrg        feasible paths within the egraph.  */
    365  1.1  mrg     if (logger)
    366  1.1  mrg       logger->log ("considering %qs at EN: %i, SN: %i",
    367  1.1  mrg 		   sd->m_d->get_kind (), sd->m_enode->m_index,
    368  1.1  mrg 		   sd->m_snode->m_index);
    369  1.1  mrg 
    370  1.1  mrg     feasibility_problem *p = NULL;
    371  1.1  mrg     if (!dc->get_path ().feasible_p (logger, &p))
    372  1.1  mrg       {
    373  1.1  mrg 	if (logger)
    374  1.1  mrg 	  logger->log ("rejecting %qs at EN: %i, SN: %i"
    375  1.1  mrg 		       " due to infeasible path",
    376  1.1  mrg 		       sd->m_d->get_kind (), sd->m_enode->m_index,
    377  1.1  mrg 		       sd->m_snode->m_index);
    378  1.1  mrg 	sd->set_infeasible (p);
    379  1.1  mrg 	delete dc;
    380  1.1  mrg 	return;
    381  1.1  mrg       }
    382  1.1  mrg     else
    383  1.1  mrg       if (logger)
    384  1.1  mrg 	logger->log ("accepting %qs at EN: %i, SN: %i with feasible path",
    385  1.1  mrg 		     sd->m_d->get_kind (), sd->m_enode->m_index,
    386  1.1  mrg 		     sd->m_snode->m_index);
    387  1.1  mrg 
    388  1.1  mrg     sd->set_feasible ();
    389  1.1  mrg 
    390  1.1  mrg     dedupe_key *key = new dedupe_key (*sd, dc->get_path ());
    391  1.1  mrg     if (dedupe_candidate **slot = m_map.get (key))
    392  1.1  mrg       {
    393  1.1  mrg 	if (logger)
    394  1.1  mrg 	  logger->log ("already have this dedupe_key");
    395  1.1  mrg 
    396  1.1  mrg 	(*slot)->add_duplicate ();
    397  1.1  mrg 
    398  1.1  mrg 	if (dc->length () < (*slot)->length ())
    399  1.1  mrg 	  {
    400  1.1  mrg 	    /* We've got a shorter path for the key; replace
    401  1.1  mrg 	       the current candidate.  */
    402  1.1  mrg 	    if (logger)
    403  1.1  mrg 	      logger->log ("length %i is better than existing length %i;"
    404  1.1  mrg 			   " taking over this dedupe_key",
    405  1.1  mrg 			   dc->length (), (*slot)->length ());
    406  1.1  mrg 	    dc->m_num_dupes = (*slot)->get_num_dupes ();
    407  1.1  mrg 	    delete *slot;
    408  1.1  mrg 	    *slot = dc;
    409  1.1  mrg 	  }
    410  1.1  mrg 	else
    411  1.1  mrg 	  /* We haven't beaten the current best candidate;
    412  1.1  mrg 	     drop the new candidate.  */
    413  1.1  mrg 	  {
    414  1.1  mrg 	    if (logger)
    415  1.1  mrg 	      logger->log ("length %i isn't better than existing length %i;"
    416  1.1  mrg 			   " dropping this candidate",
    417  1.1  mrg 			   dc->length (), (*slot)->length ());
    418  1.1  mrg 	    delete dc;
    419  1.1  mrg 	  }
    420  1.1  mrg 	delete key;
    421  1.1  mrg       }
    422  1.1  mrg     else
    423  1.1  mrg       {
    424  1.1  mrg 	/* This is the first candidate for this key.  */
    425  1.1  mrg 	m_map.put (key, dc);
    426  1.1  mrg 	if (logger)
    427  1.1  mrg 	  logger->log ("first candidate for this dedupe_key");
    428  1.1  mrg       }
    429  1.1  mrg   }
    430  1.1  mrg 
    431  1.1  mrg  /* Emit the simplest diagnostic within each set.  */
    432  1.1  mrg 
    433  1.1  mrg   void emit_best (diagnostic_manager *dm,
    434  1.1  mrg 		  const exploded_graph &eg)
    435  1.1  mrg   {
    436  1.1  mrg     LOG_SCOPE (dm->get_logger ());
    437  1.1  mrg 
    438  1.1  mrg     /* Get keys into a vec for sorting.  */
    439  1.1  mrg     auto_vec<const dedupe_key *> keys (m_map.elements ());
    440  1.1  mrg     for (map_t::iterator iter = m_map.begin ();
    441  1.1  mrg 	 iter != m_map.end ();
    442  1.1  mrg 	 ++iter)
    443  1.1  mrg       keys.quick_push ((*iter).first);
    444  1.1  mrg 
    445  1.1  mrg     dm->log ("# keys after de-duplication: %i", keys.length ());
    446  1.1  mrg 
    447  1.1  mrg     /* Sort into a good emission order.  */
    448  1.1  mrg     keys.qsort (dedupe_key::comparator);
    449  1.1  mrg 
    450  1.1  mrg     /* Emit the best candidate for each key.  */
    451  1.1  mrg     int i;
    452  1.1  mrg     const dedupe_key *key;
    453  1.1  mrg     FOR_EACH_VEC_ELT (keys, i, key)
    454  1.1  mrg       {
    455  1.1  mrg 	dedupe_candidate **slot = m_map.get (key);
    456  1.1  mrg 	gcc_assert (*slot);
    457  1.1  mrg 	const dedupe_candidate &dc = **slot;
    458  1.1  mrg 
    459  1.1  mrg 	dm->emit_saved_diagnostic (eg, key->m_sd,
    460  1.1  mrg 				   dc.get_path (), key->m_stmt,
    461  1.1  mrg 				   dc.get_num_dupes ());
    462  1.1  mrg       }
    463  1.1  mrg   }
    464  1.1  mrg 
    465  1.1  mrg private:
    466  1.1  mrg 
    467  1.1  mrg   /* This maps from each dedupe_key to a current best dedupe_candidate.  */
    468  1.1  mrg 
    469  1.1  mrg   typedef hash_map<const dedupe_key *, dedupe_candidate *,
    470  1.1  mrg 		   dedupe_hash_map_traits> map_t;
    471  1.1  mrg   map_t m_map;
    472  1.1  mrg };
    473  1.1  mrg 
    474  1.1  mrg /* Emit all saved diagnostics.  */
    475  1.1  mrg 
    476  1.1  mrg void
    477  1.1  mrg diagnostic_manager::emit_saved_diagnostics (const exploded_graph &eg)
    478  1.1  mrg {
    479  1.1  mrg   LOG_SCOPE (get_logger ());
    480  1.1  mrg   auto_timevar tv (TV_ANALYZER_DIAGNOSTICS);
    481  1.1  mrg   log ("# saved diagnostics: %i", m_saved_diagnostics.length ());
    482  1.1  mrg   if (get_logger ())
    483  1.1  mrg     {
    484  1.1  mrg       unsigned i;
    485  1.1  mrg       saved_diagnostic *sd;
    486  1.1  mrg       FOR_EACH_VEC_ELT (m_saved_diagnostics, i, sd)
    487  1.1  mrg 	log ("[%i] sd: %qs at EN: %i, SN: %i",
    488  1.1  mrg 	     i, sd->m_d->get_kind (), sd->m_enode->m_index,
    489  1.1  mrg 	     sd->m_snode->m_index);
    490  1.1  mrg     }
    491  1.1  mrg 
    492  1.1  mrg   if (m_saved_diagnostics.length () == 0)
    493  1.1  mrg     return;
    494  1.1  mrg 
    495  1.1  mrg   /* Compute the shortest_paths once, sharing it between all diagnostics.  */
    496  1.1  mrg   shortest_exploded_paths sp (eg, eg.get_origin ());
    497  1.1  mrg 
    498  1.1  mrg   /* Iterate through all saved diagnostics, adding them to a dedupe_winners
    499  1.1  mrg      instance.  This partitions the saved diagnostics by dedupe_key,
    500  1.1  mrg      generating exploded_paths for them, and retaining the best one in each
    501  1.1  mrg      partition.  */
    502  1.1  mrg   dedupe_winners best_candidates;
    503  1.1  mrg 
    504  1.1  mrg   int i;
    505  1.1  mrg   saved_diagnostic *sd;
    506  1.1  mrg   FOR_EACH_VEC_ELT (m_saved_diagnostics, i, sd)
    507  1.1  mrg     best_candidates.add (get_logger (), sp, sd);
    508  1.1  mrg 
    509  1.1  mrg   /* For each dedupe-key, call emit_saved_diagnostic on the "best"
    510  1.1  mrg      saved_diagnostic.  */
    511  1.1  mrg   best_candidates.emit_best (this, eg);
    512  1.1  mrg }
    513  1.1  mrg 
    514  1.1  mrg /* Given a saved_diagnostic SD at STMT with feasible path EPATH through EG,
    515  1.1  mrg    create an checker_path of suitable events and use it to call
    516  1.1  mrg    SD's underlying pending_diagnostic "emit" vfunc to emit a diagnostic.  */
    517  1.1  mrg 
    518  1.1  mrg void
    519  1.1  mrg diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
    520  1.1  mrg 					   const saved_diagnostic &sd,
    521  1.1  mrg 					   const exploded_path &epath,
    522  1.1  mrg 					   const gimple *stmt,
    523  1.1  mrg 					   int num_dupes)
    524  1.1  mrg {
    525  1.1  mrg   LOG_SCOPE (get_logger ());
    526  1.1  mrg   log ("sd: %qs at SN: %i", sd.m_d->get_kind (), sd.m_snode->m_index);
    527  1.1  mrg   log ("num dupes: %i", num_dupes);
    528  1.1  mrg 
    529  1.1  mrg   pretty_printer *pp = global_dc->printer->clone ();
    530  1.1  mrg 
    531  1.1  mrg   /* Precompute all enodes from which the diagnostic is reachable.  */
    532  1.1  mrg   path_builder pb (eg, epath);
    533  1.1  mrg 
    534  1.1  mrg   /* This is the diagnostic_path subclass that will be built for
    535  1.1  mrg      the diagnostic.  */
    536  1.1  mrg   checker_path emission_path;
    537  1.1  mrg 
    538  1.1  mrg   /* Populate emission_path with a full description of EPATH.  */
    539  1.1  mrg   build_emission_path (pb, epath, &emission_path);
    540  1.1  mrg 
    541  1.1  mrg   /* Now prune it to just cover the most pertinent events.  */
    542  1.1  mrg   prune_path (&emission_path, sd.m_sm, sd.m_var, sd.m_state);
    543  1.1  mrg 
    544  1.1  mrg   /* Add a final event to the path, covering the diagnostic itself.
    545  1.1  mrg      We use the final enode from the epath, which might be different from
    546  1.1  mrg      the sd.m_enode, as the dedupe code doesn't care about enodes, just
    547  1.1  mrg      snodes.  */
    548  1.1  mrg   emission_path.add_final_event (sd.m_sm, epath.get_final_enode (), stmt,
    549  1.1  mrg 				 sd.m_var, sd.m_state);
    550  1.1  mrg 
    551  1.1  mrg   /* The "final" event might not be final; if the saved_diagnostic has a
    552  1.1  mrg      trailing eedge stashed, add any events for it.  This is for use
    553  1.1  mrg      in handling longjmp, to show where a longjmp is rewinding to.  */
    554  1.1  mrg   if (sd.m_trailing_eedge)
    555  1.1  mrg     add_events_for_eedge (pb, *sd.m_trailing_eedge, &emission_path);
    556  1.1  mrg 
    557  1.1  mrg   emission_path.prepare_for_emission (sd.m_d);
    558  1.1  mrg 
    559  1.1  mrg   gcc_rich_location rich_loc (stmt->location);
    560  1.1  mrg   rich_loc.set_path (&emission_path);
    561  1.1  mrg 
    562  1.1  mrg   auto_diagnostic_group d;
    563  1.1  mrg   auto_cfun sentinel (sd.m_snode->m_fun);
    564  1.1  mrg   if (sd.m_d->emit (&rich_loc))
    565  1.1  mrg     {
    566  1.1  mrg       if (flag_analyzer_show_duplicate_count && num_dupes > 0)
    567  1.1  mrg 	inform_n (stmt->location, num_dupes,
    568  1.1  mrg 		  "%i duplicate", "%i duplicates",
    569  1.1  mrg 		  num_dupes);
    570  1.1  mrg     }
    571  1.1  mrg   delete pp;
    572  1.1  mrg }
    573  1.1  mrg 
    574  1.1  mrg /* Given a state change to DST_REP, determine a tree that gives the origin
    575  1.1  mrg    of that state at STMT, using DST_STATE's region model, so that state
    576  1.1  mrg    changes based on assignments can be tracked back to their origins.
    577  1.1  mrg 
    578  1.1  mrg    For example, if we have
    579  1.1  mrg 
    580  1.1  mrg      (S1) _1 = malloc (64);
    581  1.1  mrg      (S2) EXPR = _1;
    582  1.1  mrg 
    583  1.1  mrg    then at stmt S2 we can get the origin of EXPR's state as being _1,
    584  1.1  mrg    and thus track the allocation back to S1.  */
    585  1.1  mrg 
    586  1.1  mrg static tree
    587  1.1  mrg get_any_origin (const gimple *stmt,
    588  1.1  mrg 		tree dst_rep,
    589  1.1  mrg 		const program_state &dst_state)
    590  1.1  mrg {
    591  1.1  mrg   if (!stmt)
    592  1.1  mrg     return NULL_TREE;
    593  1.1  mrg 
    594  1.1  mrg   gcc_assert (dst_rep);
    595  1.1  mrg 
    596  1.1  mrg   if (const gassign *assign = dyn_cast <const gassign *> (stmt))
    597  1.1  mrg     {
    598  1.1  mrg       tree lhs = gimple_assign_lhs (assign);
    599  1.1  mrg       /* Use region IDs to compare lhs with DST_REP, bulletproofing against
    600  1.1  mrg 	 cases where they can't have lvalues by using
    601  1.1  mrg 	 tentative_region_model_context.  */
    602  1.1  mrg       tentative_region_model_context ctxt;
    603  1.1  mrg       region_id lhs_rid = dst_state.m_region_model->get_lvalue (lhs, &ctxt);
    604  1.1  mrg       region_id dst_rep_rid
    605  1.1  mrg 	= dst_state.m_region_model->get_lvalue (dst_rep, &ctxt);
    606  1.1  mrg       if (lhs_rid == dst_rep_rid && !ctxt.had_errors_p ())
    607  1.1  mrg 	{
    608  1.1  mrg 	  tree rhs1 = gimple_assign_rhs1 (assign);
    609  1.1  mrg 	  enum tree_code op = gimple_assign_rhs_code (assign);
    610  1.1  mrg 	  switch (op)
    611  1.1  mrg 	    {
    612  1.1  mrg 	    default:
    613  1.1  mrg 	      //gcc_unreachable ();  // TODO
    614  1.1  mrg 	      break;
    615  1.1  mrg 	    case COMPONENT_REF:
    616  1.1  mrg 	    case SSA_NAME:
    617  1.1  mrg 	      return rhs1;
    618  1.1  mrg 	    }
    619  1.1  mrg 	}
    620  1.1  mrg     }
    621  1.1  mrg   return NULL_TREE;
    622  1.1  mrg }
    623  1.1  mrg 
    624  1.1  mrg /* Emit a "path" of events to EMISSION_PATH describing the exploded path
    625  1.1  mrg    EPATH within EG.  */
    626  1.1  mrg 
    627  1.1  mrg void
    628  1.1  mrg diagnostic_manager::build_emission_path (const path_builder &pb,
    629  1.1  mrg 					 const exploded_path &epath,
    630  1.1  mrg 					 checker_path *emission_path) const
    631  1.1  mrg {
    632  1.1  mrg   LOG_SCOPE (get_logger ());
    633  1.1  mrg   for (unsigned i = 0; i < epath.m_edges.length (); i++)
    634  1.1  mrg     {
    635  1.1  mrg       const exploded_edge *eedge = epath.m_edges[i];
    636  1.1  mrg       add_events_for_eedge (pb, *eedge, emission_path);
    637  1.1  mrg     }
    638  1.1  mrg }
    639  1.1  mrg 
    640  1.1  mrg /* Subclass of state_change_visitor that creates state_change_event
    641  1.1  mrg    instances.  */
    642  1.1  mrg 
    643  1.1  mrg class state_change_event_creator : public state_change_visitor
    644  1.1  mrg {
    645  1.1  mrg public:
    646  1.1  mrg   state_change_event_creator (const exploded_edge &eedge,
    647  1.1  mrg 			      checker_path *emission_path)
    648  1.1  mrg     : m_eedge (eedge),
    649  1.1  mrg       m_emission_path (emission_path)
    650  1.1  mrg   {}
    651  1.1  mrg 
    652  1.1  mrg   bool on_global_state_change (const state_machine &sm,
    653  1.1  mrg 			       state_machine::state_t src_sm_val,
    654  1.1  mrg 			       state_machine::state_t dst_sm_val)
    655  1.1  mrg     FINAL OVERRIDE
    656  1.1  mrg   {
    657  1.1  mrg     const exploded_node *src_node = m_eedge.m_src;
    658  1.1  mrg     const program_point &src_point = src_node->get_point ();
    659  1.1  mrg     const int src_stack_depth = src_point.get_stack_depth ();
    660  1.1  mrg     const exploded_node *dst_node = m_eedge.m_dest;
    661  1.1  mrg     const gimple *stmt = src_point.get_stmt ();
    662  1.1  mrg     const supernode *supernode = src_point.get_supernode ();
    663  1.1  mrg     const program_state &dst_state = dst_node->get_state ();
    664  1.1  mrg 
    665  1.1  mrg     int stack_depth = src_stack_depth;
    666  1.1  mrg 
    667  1.1  mrg     m_emission_path->add_event (new state_change_event (supernode,
    668  1.1  mrg 							stmt,
    669  1.1  mrg 							stack_depth,
    670  1.1  mrg 							sm,
    671  1.1  mrg 							NULL_TREE,
    672  1.1  mrg 							src_sm_val,
    673  1.1  mrg 							dst_sm_val,
    674  1.1  mrg 							NULL_TREE,
    675  1.1  mrg 							dst_state));
    676  1.1  mrg     return false;
    677  1.1  mrg   }
    678  1.1  mrg 
    679  1.1  mrg   bool on_state_change (const state_machine &sm,
    680  1.1  mrg 			state_machine::state_t src_sm_val,
    681  1.1  mrg 			state_machine::state_t dst_sm_val,
    682  1.1  mrg 			tree dst_rep,
    683  1.1  mrg 			svalue_id dst_origin_sid) FINAL OVERRIDE
    684  1.1  mrg   {
    685  1.1  mrg     const exploded_node *src_node = m_eedge.m_src;
    686  1.1  mrg     const program_point &src_point = src_node->get_point ();
    687  1.1  mrg     const int src_stack_depth = src_point.get_stack_depth ();
    688  1.1  mrg     const exploded_node *dst_node = m_eedge.m_dest;
    689  1.1  mrg     const gimple *stmt = src_point.get_stmt ();
    690  1.1  mrg     const supernode *supernode = src_point.get_supernode ();
    691  1.1  mrg     const program_state &dst_state = dst_node->get_state ();
    692  1.1  mrg 
    693  1.1  mrg     int stack_depth = src_stack_depth;
    694  1.1  mrg 
    695  1.1  mrg     if (m_eedge.m_sedge
    696  1.1  mrg 	&& m_eedge.m_sedge->m_kind == SUPEREDGE_CFG_EDGE)
    697  1.1  mrg       {
    698  1.1  mrg 	supernode = src_point.get_supernode ();
    699  1.1  mrg 	stmt = supernode->get_last_stmt ();
    700  1.1  mrg 	stack_depth = src_stack_depth;
    701  1.1  mrg       }
    702  1.1  mrg 
    703  1.1  mrg     /* Bulletproofing for state changes at calls/returns;
    704  1.1  mrg        TODO: is there a better way? */
    705  1.1  mrg     if (!stmt)
    706  1.1  mrg       return false;
    707  1.1  mrg 
    708  1.1  mrg     tree origin_rep
    709  1.1  mrg       = dst_state.get_representative_tree (dst_origin_sid);
    710  1.1  mrg 
    711  1.1  mrg     if (origin_rep == NULL_TREE)
    712  1.1  mrg       origin_rep = get_any_origin (stmt, dst_rep, dst_state);
    713  1.1  mrg     m_emission_path->add_event (new state_change_event (supernode,
    714  1.1  mrg 							stmt,
    715  1.1  mrg 							stack_depth,
    716  1.1  mrg 							sm,
    717  1.1  mrg 							dst_rep,
    718  1.1  mrg 							src_sm_val,
    719  1.1  mrg 							dst_sm_val,
    720  1.1  mrg 							origin_rep,
    721  1.1  mrg 							dst_state));
    722  1.1  mrg     return false;
    723  1.1  mrg   }
    724  1.1  mrg 
    725  1.1  mrg   const exploded_edge &m_eedge;
    726  1.1  mrg   checker_path *m_emission_path;
    727  1.1  mrg };
    728  1.1  mrg 
    729  1.1  mrg /* Compare SRC_STATE and DST_STATE (which use EXT_STATE), and call
    730  1.1  mrg    VISITOR's on_state_change for every sm-state change that occurs
    731  1.1  mrg    to a tree, and on_global_state_change for every global state change
    732  1.1  mrg    that occurs.
    733  1.1  mrg 
    734  1.1  mrg    This determines the state changes that ought to be reported to
    735  1.1  mrg    the user: a combination of the effects of changes to sm_state_map
    736  1.1  mrg    (which maps svalues to sm-states), and of region_model changes
    737  1.1  mrg    (which map trees to svalues).
    738  1.1  mrg 
    739  1.1  mrg    Bail out early and return true if any call to on_global_state_change
    740  1.1  mrg    or on_state_change returns true, otherwise return false.
    741  1.1  mrg 
    742  1.1  mrg    This is split out to make it easier to experiment with changes to
    743  1.1  mrg    exploded_node granularity (so that we can observe what state changes
    744  1.1  mrg    lead to state_change_events being emitted).  */
    745  1.1  mrg 
    746  1.1  mrg bool
    747  1.1  mrg for_each_state_change (const program_state &src_state,
    748  1.1  mrg 		       const program_state &dst_state,
    749  1.1  mrg 		       const extrinsic_state &ext_state,
    750  1.1  mrg 		       state_change_visitor *visitor)
    751  1.1  mrg {
    752  1.1  mrg   gcc_assert (src_state.m_checker_states.length ()
    753  1.1  mrg 	      == ext_state.get_num_checkers ());
    754  1.1  mrg   gcc_assert (dst_state.m_checker_states.length ()
    755  1.1  mrg 	      == ext_state.get_num_checkers ());
    756  1.1  mrg   for (unsigned i = 0; i < ext_state.get_num_checkers (); i++)
    757  1.1  mrg     {
    758  1.1  mrg       const state_machine &sm = ext_state.get_sm (i);
    759  1.1  mrg       const sm_state_map &src_smap = *src_state.m_checker_states[i];
    760  1.1  mrg       const sm_state_map &dst_smap = *dst_state.m_checker_states[i];
    761  1.1  mrg 
    762  1.1  mrg       /* Add events for any global state changes.  */
    763  1.1  mrg       if (src_smap.get_global_state () != dst_smap.get_global_state ())
    764  1.1  mrg 	if (visitor->on_global_state_change (sm,
    765  1.1  mrg 					     src_smap.get_global_state (),
    766  1.1  mrg 					     dst_smap.get_global_state ()))
    767  1.1  mrg 	  return true;
    768  1.1  mrg 
    769  1.1  mrg       /* Add events for per-svalue state changes.  */
    770  1.1  mrg       for (sm_state_map::iterator_t iter = dst_smap.begin ();
    771  1.1  mrg 	   iter != dst_smap.end ();
    772  1.1  mrg 	   ++iter)
    773  1.1  mrg 	{
    774  1.1  mrg 	  /* Ideally we'd directly compare the SM state between src state
    775  1.1  mrg 	     and dst state, but there's no guarantee that the IDs can
    776  1.1  mrg 	     be meaningfully compared.  */
    777  1.1  mrg 	  svalue_id dst_sid = (*iter).first;
    778  1.1  mrg 	  state_machine::state_t dst_sm_val = (*iter).second.m_state;
    779  1.1  mrg 
    780  1.1  mrg 	  auto_vec<path_var> dst_pvs;
    781  1.1  mrg 	  dst_state.m_region_model->get_path_vars_for_svalue (dst_sid,
    782  1.1  mrg 							      &dst_pvs);
    783  1.1  mrg 
    784  1.1  mrg 	  unsigned j;
    785  1.1  mrg 	  path_var *dst_pv;
    786  1.1  mrg 	  FOR_EACH_VEC_ELT (dst_pvs, j, dst_pv)
    787  1.1  mrg 	    {
    788  1.1  mrg 	      tree dst_rep = dst_pv->m_tree;
    789  1.1  mrg 	      gcc_assert (dst_rep);
    790  1.1  mrg 	      if (dst_pv->m_stack_depth
    791  1.1  mrg 		  >= src_state.m_region_model->get_stack_depth ())
    792  1.1  mrg 		continue;
    793  1.1  mrg 	      tentative_region_model_context ctxt;
    794  1.1  mrg 	      svalue_id src_sid
    795  1.1  mrg 		= src_state.m_region_model->get_rvalue (*dst_pv, &ctxt);
    796  1.1  mrg 	      if (src_sid.null_p () || ctxt.had_errors_p ())
    797  1.1  mrg 		continue;
    798  1.1  mrg 	      state_machine::state_t src_sm_val = src_smap.get_state (src_sid);
    799  1.1  mrg 	      if (dst_sm_val != src_sm_val)
    800  1.1  mrg 		{
    801  1.1  mrg 		  svalue_id dst_origin_sid = (*iter).second.m_origin;
    802  1.1  mrg 		  if (visitor->on_state_change (sm, src_sm_val, dst_sm_val,
    803  1.1  mrg 						dst_rep, dst_origin_sid))
    804  1.1  mrg 		    return true;
    805  1.1  mrg 		}
    806  1.1  mrg 	    }
    807  1.1  mrg 	}
    808  1.1  mrg     }
    809  1.1  mrg   return false;
    810  1.1  mrg }
    811  1.1  mrg 
    812  1.1  mrg /* Subroutine of diagnostic_manager::build_emission_path.
    813  1.1  mrg    Add any events for EEDGE to EMISSION_PATH.  */
    814  1.1  mrg 
    815  1.1  mrg void
    816  1.1  mrg diagnostic_manager::add_events_for_eedge (const path_builder &pb,
    817  1.1  mrg 					  const exploded_edge &eedge,
    818  1.1  mrg 					  checker_path *emission_path) const
    819  1.1  mrg {
    820  1.1  mrg   const exploded_node *src_node = eedge.m_src;
    821  1.1  mrg   const program_point &src_point = src_node->get_point ();
    822  1.1  mrg   const exploded_node *dst_node = eedge.m_dest;
    823  1.1  mrg   const program_point &dst_point = dst_node->get_point ();
    824  1.1  mrg   const int dst_stack_depth = dst_point.get_stack_depth ();
    825  1.1  mrg   if (get_logger ())
    826  1.1  mrg     {
    827  1.1  mrg       get_logger ()->start_log_line ();
    828  1.1  mrg       pretty_printer *pp = get_logger ()->get_printer ();
    829  1.1  mrg       pp_printf (pp, "EN %i -> EN %i: ",
    830  1.1  mrg 		 eedge.m_src->m_index,
    831  1.1  mrg 		 eedge.m_dest->m_index);
    832  1.1  mrg       src_point.print (pp, format (false));
    833  1.1  mrg       pp_string (pp, "-> ");
    834  1.1  mrg       dst_point.print (pp, format (false));
    835  1.1  mrg       get_logger ()->end_log_line ();
    836  1.1  mrg     }
    837  1.1  mrg   const program_state &src_state = src_node->get_state ();
    838  1.1  mrg   const program_state &dst_state = dst_node->get_state ();
    839  1.1  mrg 
    840  1.1  mrg   /* Add state change events for the states that have changed.
    841  1.1  mrg      We add these before events for superedges, so that if we have a
    842  1.1  mrg      state_change_event due to following an edge, we'll get this sequence
    843  1.1  mrg      of events:
    844  1.1  mrg 
    845  1.1  mrg       | if (!ptr)
    846  1.1  mrg       |    ~
    847  1.1  mrg       |    |
    848  1.1  mrg       |    (1) assuming 'ptr' is non-NULL  (state_change_event)
    849  1.1  mrg       |    (2) following 'false' branch... (start_cfg_edge_event)
    850  1.1  mrg      ...
    851  1.1  mrg       | do_something (ptr);
    852  1.1  mrg       | ~~~~~~~~~~~~~^~~~~
    853  1.1  mrg       |              |
    854  1.1  mrg       |              (3) ...to here        (end_cfg_edge_event).  */
    855  1.1  mrg   state_change_event_creator visitor (eedge, emission_path);
    856  1.1  mrg   for_each_state_change (src_state, dst_state, pb.get_ext_state (),
    857  1.1  mrg 			 &visitor);
    858  1.1  mrg 
    859  1.1  mrg   /* Allow non-standard edges to add events, e.g. when rewinding from
    860  1.1  mrg      longjmp to a setjmp.  */
    861  1.1  mrg   if (eedge.m_custom_info)
    862  1.1  mrg     eedge.m_custom_info->add_events_to_path (emission_path, eedge);
    863  1.1  mrg 
    864  1.1  mrg   /* Add events for superedges, function entries, and for statements.  */
    865  1.1  mrg   switch (dst_point.get_kind ())
    866  1.1  mrg     {
    867  1.1  mrg     default:
    868  1.1  mrg       break;
    869  1.1  mrg     case PK_BEFORE_SUPERNODE:
    870  1.1  mrg       if (src_point.get_kind () == PK_AFTER_SUPERNODE)
    871  1.1  mrg 	{
    872  1.1  mrg 	  if (eedge.m_sedge)
    873  1.1  mrg 	    add_events_for_superedge (pb, eedge, emission_path);
    874  1.1  mrg 	}
    875  1.1  mrg       /* Add function entry events.  */
    876  1.1  mrg       if (dst_point.get_supernode ()->entry_p ())
    877  1.1  mrg 	{
    878  1.1  mrg 	  emission_path->add_event
    879  1.1  mrg 	    (new function_entry_event
    880  1.1  mrg 	     (dst_point.get_supernode ()->get_start_location (),
    881  1.1  mrg 	      dst_point.get_fndecl (),
    882  1.1  mrg 	      dst_stack_depth));
    883  1.1  mrg 	}
    884  1.1  mrg       break;
    885  1.1  mrg     case PK_BEFORE_STMT:
    886  1.1  mrg       {
    887  1.1  mrg 	const gimple *stmt = dst_point.get_stmt ();
    888  1.1  mrg 	const gcall *call = dyn_cast <const gcall *> (stmt);
    889  1.1  mrg 	if (call && is_setjmp_call_p (call))
    890  1.1  mrg 	  emission_path->add_event
    891  1.1  mrg 	    (new setjmp_event (stmt->location,
    892  1.1  mrg 			       dst_node,
    893  1.1  mrg 			       dst_point.get_fndecl (),
    894  1.1  mrg 			       dst_stack_depth,
    895  1.1  mrg 			       call));
    896  1.1  mrg 	else
    897  1.1  mrg 	  emission_path->add_event
    898  1.1  mrg 	    (new statement_event (stmt,
    899  1.1  mrg 				  dst_point.get_fndecl (),
    900  1.1  mrg 				  dst_stack_depth, dst_state));
    901  1.1  mrg       }
    902  1.1  mrg       break;
    903  1.1  mrg     }
    904  1.1  mrg }
    905  1.1  mrg 
    906  1.1  mrg /* Return true if EEDGE is a significant edge in the path to the diagnostic
    907  1.1  mrg    for PB.
    908  1.1  mrg 
    909  1.1  mrg    Consider all of the sibling out-eedges from the same source enode
    910  1.1  mrg    as EEDGE.
    911  1.1  mrg    If there's no path from the destinations of those eedges to the
    912  1.1  mrg    diagnostic enode, then we have to take this eedge and thus it's
    913  1.1  mrg    significant.
    914  1.1  mrg 
    915  1.1  mrg    Conversely if there is a path from the destination of any other sibling
    916  1.1  mrg    eedge to the diagnostic enode, then this edge is insignificant.
    917  1.1  mrg 
    918  1.1  mrg    Example 1: redundant if-else:
    919  1.1  mrg 
    920  1.1  mrg      (A) if (...)            A
    921  1.1  mrg      (B)   ...              / \
    922  1.1  mrg          else              B   C
    923  1.1  mrg      (C)   ...              \ /
    924  1.1  mrg      (D) [DIAGNOSTIC]        D
    925  1.1  mrg 
    926  1.1  mrg      D is reachable by either B or C, so neither of these edges
    927  1.1  mrg      are significant.
    928  1.1  mrg 
    929  1.1  mrg    Example 2: pertinent if-else:
    930  1.1  mrg 
    931  1.1  mrg      (A) if (...)                         A
    932  1.1  mrg      (B)   ...                           / \
    933  1.1  mrg          else                           B   C
    934  1.1  mrg      (C)   [NECESSARY CONDITION]        |   |
    935  1.1  mrg      (D) [POSSIBLE DIAGNOSTIC]          D1  D2
    936  1.1  mrg 
    937  1.1  mrg      D becomes D1 and D2 in the exploded graph, where the diagnostic occurs
    938  1.1  mrg      at D2.  D2 is only reachable via C, so the A -> C edge is significant.
    939  1.1  mrg 
    940  1.1  mrg    Example 3: redundant loop:
    941  1.1  mrg 
    942  1.1  mrg      (A) while (...)          +-->A
    943  1.1  mrg      (B)   ...                |  / \
    944  1.1  mrg      (C) ...                  +-B  C
    945  1.1  mrg      (D) [DIAGNOSTIC]              |
    946  1.1  mrg                                    D
    947  1.1  mrg 
    948  1.1  mrg      D is reachable from both B and C, so the A->C edge is not significant.  */
    949  1.1  mrg 
    950  1.1  mrg bool
    951  1.1  mrg diagnostic_manager::significant_edge_p (const path_builder &pb,
    952  1.1  mrg 					const exploded_edge &eedge) const
    953  1.1  mrg {
    954  1.1  mrg   int i;
    955  1.1  mrg   exploded_edge *sibling;
    956  1.1  mrg   FOR_EACH_VEC_ELT (eedge.m_src->m_succs, i, sibling)
    957  1.1  mrg     {
    958  1.1  mrg       if (sibling == &eedge)
    959  1.1  mrg 	continue;
    960  1.1  mrg       if (pb.reachable_from_p (sibling->m_dest))
    961  1.1  mrg 	{
    962  1.1  mrg 	  if (get_logger ())
    963  1.1  mrg 	    get_logger ()->log ("  edge EN: %i -> EN: %i is insignificant as"
    964  1.1  mrg 				" EN: %i is also reachable via"
    965  1.1  mrg 				" EN: %i -> EN: %i",
    966  1.1  mrg 				eedge.m_src->m_index, eedge.m_dest->m_index,
    967  1.1  mrg 				pb.get_diag_node ()->m_index,
    968  1.1  mrg 				sibling->m_src->m_index,
    969  1.1  mrg 				sibling->m_dest->m_index);
    970  1.1  mrg 	  return false;
    971  1.1  mrg 	}
    972  1.1  mrg     }
    973  1.1  mrg 
    974  1.1  mrg   return true;
    975  1.1  mrg }
    976  1.1  mrg 
    977  1.1  mrg /* Subroutine of diagnostic_manager::add_events_for_eedge
    978  1.1  mrg    where EEDGE has an underlying superedge i.e. a CFG edge,
    979  1.1  mrg    or an interprocedural call/return.
    980  1.1  mrg    Add any events for the superedge to EMISSION_PATH.  */
    981  1.1  mrg 
    982  1.1  mrg void
    983  1.1  mrg diagnostic_manager::add_events_for_superedge (const path_builder &pb,
    984  1.1  mrg 					      const exploded_edge &eedge,
    985  1.1  mrg 					      checker_path *emission_path)
    986  1.1  mrg   const
    987  1.1  mrg {
    988  1.1  mrg   gcc_assert (eedge.m_sedge);
    989  1.1  mrg 
    990  1.1  mrg   /* Don't add events for insignificant edges at verbosity levels below 3.  */
    991  1.1  mrg   if (m_verbosity < 3)
    992  1.1  mrg     if (!significant_edge_p (pb, eedge))
    993  1.1  mrg       return;
    994  1.1  mrg 
    995  1.1  mrg   const exploded_node *src_node = eedge.m_src;
    996  1.1  mrg   const program_point &src_point = src_node->get_point ();
    997  1.1  mrg   const exploded_node *dst_node = eedge.m_dest;
    998  1.1  mrg   const program_point &dst_point = dst_node->get_point ();
    999  1.1  mrg   const int src_stack_depth = src_point.get_stack_depth ();
   1000  1.1  mrg   const int dst_stack_depth = dst_point.get_stack_depth ();
   1001  1.1  mrg   const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
   1002  1.1  mrg 
   1003  1.1  mrg   switch (eedge.m_sedge->m_kind)
   1004  1.1  mrg     {
   1005  1.1  mrg     case SUPEREDGE_CFG_EDGE:
   1006  1.1  mrg       {
   1007  1.1  mrg 	emission_path->add_event
   1008  1.1  mrg 	  (new start_cfg_edge_event (eedge,
   1009  1.1  mrg 			       (last_stmt
   1010  1.1  mrg 				? last_stmt->location
   1011  1.1  mrg 				: UNKNOWN_LOCATION),
   1012  1.1  mrg 			       src_point.get_fndecl (),
   1013  1.1  mrg 			       src_stack_depth));
   1014  1.1  mrg 	emission_path->add_event
   1015  1.1  mrg 	  (new end_cfg_edge_event (eedge,
   1016  1.1  mrg 				   dst_point.get_supernode ()->get_start_location (),
   1017  1.1  mrg 				   dst_point.get_fndecl (),
   1018  1.1  mrg 				   dst_stack_depth));
   1019  1.1  mrg       }
   1020  1.1  mrg       break;
   1021  1.1  mrg 
   1022  1.1  mrg     case SUPEREDGE_CALL:
   1023  1.1  mrg       {
   1024  1.1  mrg 	emission_path->add_event
   1025  1.1  mrg 	  (new call_event (eedge,
   1026  1.1  mrg 			   (last_stmt
   1027  1.1  mrg 			    ? last_stmt->location
   1028  1.1  mrg 			    : UNKNOWN_LOCATION),
   1029  1.1  mrg 			   src_point.get_fndecl (),
   1030  1.1  mrg 			   src_stack_depth));
   1031  1.1  mrg       }
   1032  1.1  mrg       break;
   1033  1.1  mrg 
   1034  1.1  mrg     case SUPEREDGE_INTRAPROCEDURAL_CALL:
   1035  1.1  mrg       {
   1036  1.1  mrg 	/* TODO: add a subclass for this, or generate events for the
   1037  1.1  mrg 	   summary.  */
   1038  1.1  mrg 	emission_path->add_event
   1039  1.1  mrg 	  (new debug_event ((last_stmt
   1040  1.1  mrg 			     ? last_stmt->location
   1041  1.1  mrg 			     : UNKNOWN_LOCATION),
   1042  1.1  mrg 			    src_point.get_fndecl (),
   1043  1.1  mrg 			    src_stack_depth,
   1044  1.1  mrg 			    "call summary"));
   1045  1.1  mrg       }
   1046  1.1  mrg       break;
   1047  1.1  mrg 
   1048  1.1  mrg     case SUPEREDGE_RETURN:
   1049  1.1  mrg       {
   1050  1.1  mrg 	const return_superedge *return_edge
   1051  1.1  mrg 	  = as_a <const return_superedge *> (eedge.m_sedge);
   1052  1.1  mrg 
   1053  1.1  mrg 	const gcall *call_stmt = return_edge->get_call_stmt ();
   1054  1.1  mrg 	emission_path->add_event
   1055  1.1  mrg 	  (new return_event (eedge,
   1056  1.1  mrg 			     (call_stmt
   1057  1.1  mrg 			      ? call_stmt->location
   1058  1.1  mrg 			      : UNKNOWN_LOCATION),
   1059  1.1  mrg 			     dst_point.get_fndecl (),
   1060  1.1  mrg 			     dst_stack_depth));
   1061  1.1  mrg       }
   1062  1.1  mrg       break;
   1063  1.1  mrg     }
   1064  1.1  mrg }
   1065  1.1  mrg 
   1066  1.1  mrg /* Prune PATH, based on the verbosity level, to the most pertinent
   1067  1.1  mrg    events for a diagnostic that involves VAR ending in state STATE
   1068  1.1  mrg    (for state machine SM).
   1069  1.1  mrg 
   1070  1.1  mrg    PATH is updated in place, and the redundant checker_events are deleted.
   1071  1.1  mrg 
   1072  1.1  mrg    As well as deleting events, call record_critical_state on events in
   1073  1.1  mrg    which state critical to the pending_diagnostic is being handled; see
   1074  1.1  mrg    the comment for diagnostic_manager::prune_for_sm_diagnostic.  */
   1075  1.1  mrg 
   1076  1.1  mrg void
   1077  1.1  mrg diagnostic_manager::prune_path (checker_path *path,
   1078  1.1  mrg 				const state_machine *sm,
   1079  1.1  mrg 				tree var,
   1080  1.1  mrg 				state_machine::state_t state) const
   1081  1.1  mrg {
   1082  1.1  mrg   LOG_FUNC (get_logger ());
   1083  1.1  mrg   path->maybe_log (get_logger (), "path");
   1084  1.1  mrg   prune_for_sm_diagnostic (path, sm, var, state);
   1085  1.1  mrg   prune_interproc_events (path);
   1086  1.1  mrg   finish_pruning (path);
   1087  1.1  mrg   path->maybe_log (get_logger (), "pruned");
   1088  1.1  mrg }
   1089  1.1  mrg 
   1090  1.1  mrg /* A cheap test to determine if EXPR can be the expression of interest in
   1091  1.1  mrg    an sm-diagnostic, so that we can reject cases where we have a non-lvalue.
   1092  1.1  mrg    We don't have always have a model when calling this, so we can't use
   1093  1.1  mrg    tentative_region_model_context, so there can be false positives.  */
   1094  1.1  mrg 
   1095  1.1  mrg static bool
   1096  1.1  mrg can_be_expr_of_interest_p (tree expr)
   1097  1.1  mrg {
   1098  1.1  mrg   if (!expr)
   1099  1.1  mrg     return false;
   1100  1.1  mrg 
   1101  1.1  mrg   /* Reject constants.  */
   1102  1.1  mrg   if (CONSTANT_CLASS_P (expr))
   1103  1.1  mrg     return false;
   1104  1.1  mrg 
   1105  1.1  mrg   /* Otherwise assume that it can be an lvalue.  */
   1106  1.1  mrg   return true;
   1107  1.1  mrg }
   1108  1.1  mrg 
   1109  1.1  mrg /* First pass of diagnostic_manager::prune_path: apply verbosity level,
   1110  1.1  mrg    pruning unrelated state change events.
   1111  1.1  mrg 
   1112  1.1  mrg    Iterate backwards through PATH, skipping state change events that aren't
   1113  1.1  mrg    VAR but update the pertinent VAR when state-copying occurs.
   1114  1.1  mrg 
   1115  1.1  mrg    As well as deleting events, call record_critical_state on events in
   1116  1.1  mrg    which state critical to the pending_diagnostic is being handled, so
   1117  1.1  mrg    that the event's get_desc vfunc can potentially supply a more precise
   1118  1.1  mrg    description of the event to the user.
   1119  1.1  mrg    e.g. improving
   1120  1.1  mrg      "calling 'foo' from 'bar'"
   1121  1.1  mrg    to
   1122  1.1  mrg      "passing possibly-NULL pointer 'ptr' to 'foo' from 'bar' as param 1"
   1123  1.1  mrg    when the diagnostic relates to later dereferencing 'ptr'.  */
   1124  1.1  mrg 
   1125  1.1  mrg void
   1126  1.1  mrg diagnostic_manager::prune_for_sm_diagnostic (checker_path *path,
   1127  1.1  mrg 					     const state_machine *sm,
   1128  1.1  mrg 					     tree var,
   1129  1.1  mrg 					     state_machine::state_t state) const
   1130  1.1  mrg {
   1131  1.1  mrg   update_for_unsuitable_sm_exprs (&var);
   1132  1.1  mrg 
   1133  1.1  mrg   int idx = path->num_events () - 1;
   1134  1.1  mrg   while (idx >= 0 && idx < (signed)path->num_events ())
   1135  1.1  mrg     {
   1136  1.1  mrg       checker_event *base_event = path->get_checker_event (idx);
   1137  1.1  mrg       if (get_logger ())
   1138  1.1  mrg 	{
   1139  1.1  mrg 	  if (sm)
   1140  1.1  mrg 	    {
   1141  1.1  mrg 	      if (var)
   1142  1.1  mrg 		log ("considering event %i, with var: %qE, state: %qs",
   1143  1.1  mrg 		     idx, var, sm->get_state_name (state));
   1144  1.1  mrg 	      else
   1145  1.1  mrg 		log ("considering event %i, with global state: %qs",
   1146  1.1  mrg 		     idx, sm->get_state_name (state));
   1147  1.1  mrg 	    }
   1148  1.1  mrg 	  else
   1149  1.1  mrg 	    log ("considering event %i", idx);
   1150  1.1  mrg 	}
   1151  1.1  mrg       gcc_assert (var == NULL || can_be_expr_of_interest_p (var));
   1152  1.1  mrg       switch (base_event->m_kind)
   1153  1.1  mrg 	{
   1154  1.1  mrg 	default:
   1155  1.1  mrg 	  gcc_unreachable ();
   1156  1.1  mrg 
   1157  1.1  mrg 	case EK_DEBUG:
   1158  1.1  mrg 	  if (m_verbosity < 4)
   1159  1.1  mrg 	    {
   1160  1.1  mrg 	      log ("filtering event %i: debug event", idx);
   1161  1.1  mrg 	      path->delete_event (idx);
   1162  1.1  mrg 	    }
   1163  1.1  mrg 	  break;
   1164  1.1  mrg 
   1165  1.1  mrg 	case EK_CUSTOM:
   1166  1.1  mrg 	  /* Don't filter custom events.  */
   1167  1.1  mrg 	  break;
   1168  1.1  mrg 
   1169  1.1  mrg 	case EK_STMT:
   1170  1.1  mrg 	  {
   1171  1.1  mrg 	    /* If this stmt is the origin of "var", update var.  */
   1172  1.1  mrg 	    if (var)
   1173  1.1  mrg 	      {
   1174  1.1  mrg 		statement_event *stmt_event = (statement_event *)base_event;
   1175  1.1  mrg 		tree new_var = get_any_origin (stmt_event->m_stmt, var,
   1176  1.1  mrg 					       stmt_event->m_dst_state);
   1177  1.1  mrg 		if (new_var)
   1178  1.1  mrg 		  {
   1179  1.1  mrg 		    log ("event %i: switching var of interest from %qE to %qE",
   1180  1.1  mrg 			 idx, var, new_var);
   1181  1.1  mrg 		    var = new_var;
   1182  1.1  mrg 		  }
   1183  1.1  mrg 	      }
   1184  1.1  mrg 	    if (m_verbosity < 4)
   1185  1.1  mrg 	      {
   1186  1.1  mrg 		log ("filtering event %i: statement event", idx);
   1187  1.1  mrg 		path->delete_event (idx);
   1188  1.1  mrg 	      }
   1189  1.1  mrg 	  }
   1190  1.1  mrg 	  break;
   1191  1.1  mrg 
   1192  1.1  mrg 	case EK_FUNCTION_ENTRY:
   1193  1.1  mrg 	  if (m_verbosity < 1)
   1194  1.1  mrg 	    {
   1195  1.1  mrg 	      log ("filtering event %i: function entry", idx);
   1196  1.1  mrg 	      path->delete_event (idx);
   1197  1.1  mrg 	    }
   1198  1.1  mrg 	  break;
   1199  1.1  mrg 
   1200  1.1  mrg 	case EK_STATE_CHANGE:
   1201  1.1  mrg 	  {
   1202  1.1  mrg 	    state_change_event *state_change = (state_change_event *)base_event;
   1203  1.1  mrg 	    /* Use region IDs to compare var with the state_change's m_var,
   1204  1.1  mrg 	       bulletproofing against cases where they can't have lvalues by
   1205  1.1  mrg 	       using tentative_region_model_context.  */
   1206  1.1  mrg 	    tentative_region_model_context ctxt;
   1207  1.1  mrg 	    region_id state_var_rid
   1208  1.1  mrg 	      = state_change->get_lvalue (state_change->m_var, &ctxt);
   1209  1.1  mrg 	    region_id var_rid = state_change->get_lvalue (var, &ctxt);
   1210  1.1  mrg 	    if (state_var_rid == var_rid && !ctxt.had_errors_p ())
   1211  1.1  mrg 	      {
   1212  1.1  mrg 		if (state_change->m_origin)
   1213  1.1  mrg 		  {
   1214  1.1  mrg 		    log ("event %i: switching var of interest from %qE to %qE",
   1215  1.1  mrg 			 idx, var, state_change->m_origin);
   1216  1.1  mrg 		    var = state_change->m_origin;
   1217  1.1  mrg 		    update_for_unsuitable_sm_exprs (&var);
   1218  1.1  mrg 		  }
   1219  1.1  mrg 		log ("event %i: switching state of interest from %qs to %qs",
   1220  1.1  mrg 		     idx, sm->get_state_name (state_change->m_to),
   1221  1.1  mrg 		     sm->get_state_name (state_change->m_from));
   1222  1.1  mrg 		state = state_change->m_from;
   1223  1.1  mrg 	      }
   1224  1.1  mrg 	    else if (m_verbosity < 4)
   1225  1.1  mrg 	      {
   1226  1.1  mrg 		if (var)
   1227  1.1  mrg 		  log ("filtering event %i:"
   1228  1.1  mrg 		       " state change to %qE unrelated to %qE",
   1229  1.1  mrg 		       idx, state_change->m_var, var);
   1230  1.1  mrg 		else
   1231  1.1  mrg 		  log ("filtering event %i: state change to %qE",
   1232  1.1  mrg 		       idx, state_change->m_var);
   1233  1.1  mrg 		if (ctxt.had_errors_p ())
   1234  1.1  mrg 		  log ("context had errors");
   1235  1.1  mrg 		path->delete_event (idx);
   1236  1.1  mrg 	      }
   1237  1.1  mrg 	  }
   1238  1.1  mrg 	  break;
   1239  1.1  mrg 
   1240  1.1  mrg 	case EK_START_CFG_EDGE:
   1241  1.1  mrg 	  {
   1242  1.1  mrg 	    cfg_edge_event *event = (cfg_edge_event *)base_event;
   1243  1.1  mrg 	    const cfg_superedge& cfg_superedge
   1244  1.1  mrg 	      = event->get_cfg_superedge ();
   1245  1.1  mrg 	    const supernode *dest = event->m_sedge->m_dest;
   1246  1.1  mrg 	    /* Do we have an SSA_NAME defined via a phi node in
   1247  1.1  mrg 	       the dest CFG node?  */
   1248  1.1  mrg 	    if (var && TREE_CODE (var) == SSA_NAME)
   1249  1.1  mrg 	      if (SSA_NAME_DEF_STMT (var)->bb == dest->m_bb)
   1250  1.1  mrg 		{
   1251  1.1  mrg 		  if (gphi *phi
   1252  1.1  mrg 		      = dyn_cast <gphi *> (SSA_NAME_DEF_STMT (var)))
   1253  1.1  mrg 		    {
   1254  1.1  mrg 		      /* Update var based on its phi node.  */
   1255  1.1  mrg 		      tree old_var = var;
   1256  1.1  mrg 		      var = cfg_superedge.get_phi_arg (phi);
   1257  1.1  mrg 		      log ("updating from %qE to %qE based on phi node",
   1258  1.1  mrg 			   old_var, var);
   1259  1.1  mrg 		      if (get_logger ())
   1260  1.1  mrg 			{
   1261  1.1  mrg 			  pretty_printer pp;
   1262  1.1  mrg 			  pp_gimple_stmt_1 (&pp, phi, 0, (dump_flags_t)0);
   1263  1.1  mrg 			  log ("  phi: %s", pp_formatted_text (&pp));
   1264  1.1  mrg 			}
   1265  1.1  mrg 		      /* If we've chosen a bad exploded_path, then the
   1266  1.1  mrg 			 phi arg might be a constant.  Fail gracefully for
   1267  1.1  mrg 			 this case.  */
   1268  1.1  mrg 		      update_for_unsuitable_sm_exprs (&var);
   1269  1.1  mrg 		    }
   1270  1.1  mrg 		}
   1271  1.1  mrg 
   1272  1.1  mrg 	    /* TODO: is this edge significant to var?
   1273  1.1  mrg 	       See if var can be in other states in the dest, but not
   1274  1.1  mrg 	       in other states in the src?
   1275  1.1  mrg 	       Must have multiple sibling edges.  */
   1276  1.1  mrg 
   1277  1.1  mrg 	    if (event->should_filter_p (m_verbosity))
   1278  1.1  mrg 	      {
   1279  1.1  mrg 		log ("filtering event %i: CFG edge", idx);
   1280  1.1  mrg 		path->delete_event (idx);
   1281  1.1  mrg 		/* Also delete the corresponding EK_END_CFG_EDGE.  */
   1282  1.1  mrg 		gcc_assert (path->get_checker_event (idx)->m_kind
   1283  1.1  mrg 			    == EK_END_CFG_EDGE);
   1284  1.1  mrg 		path->delete_event (idx);
   1285  1.1  mrg 	      }
   1286  1.1  mrg 	  }
   1287  1.1  mrg 	  break;
   1288  1.1  mrg 
   1289  1.1  mrg 	case EK_END_CFG_EDGE:
   1290  1.1  mrg 	  /* These come in pairs with EK_START_CFG_EDGE events and are
   1291  1.1  mrg 	     filtered when their start event is filtered.  */
   1292  1.1  mrg 	  break;
   1293  1.1  mrg 
   1294  1.1  mrg 	case EK_CALL_EDGE:
   1295  1.1  mrg 	  {
   1296  1.1  mrg 	    call_event *event = (call_event *)base_event;
   1297  1.1  mrg 	    const callgraph_superedge& cg_superedge
   1298  1.1  mrg 	      = event->get_callgraph_superedge ();
   1299  1.1  mrg 	    callsite_expr expr;
   1300  1.1  mrg 	    tree caller_var
   1301  1.1  mrg 	      = cg_superedge.map_expr_from_callee_to_caller (var, &expr);
   1302  1.1  mrg 	    if (caller_var)
   1303  1.1  mrg 	      {
   1304  1.1  mrg 		log ("event %i:"
   1305  1.1  mrg 		     " switching var of interest"
   1306  1.1  mrg 		     " from %qE in callee to %qE in caller",
   1307  1.1  mrg 		     idx, var, caller_var);
   1308  1.1  mrg 		var = caller_var;
   1309  1.1  mrg 		if (expr.param_p ())
   1310  1.1  mrg 		  event->record_critical_state (var, state);
   1311  1.1  mrg 		update_for_unsuitable_sm_exprs (&var);
   1312  1.1  mrg 	      }
   1313  1.1  mrg 	  }
   1314  1.1  mrg 	  break;
   1315  1.1  mrg 
   1316  1.1  mrg 	case EK_RETURN_EDGE:
   1317  1.1  mrg 	  // TODO: potentially update var/state based on return value,
   1318  1.1  mrg 	  // args etc
   1319  1.1  mrg 	  {
   1320  1.1  mrg 	    if (var)
   1321  1.1  mrg 	      {
   1322  1.1  mrg 		return_event *event = (return_event *)base_event;
   1323  1.1  mrg 		const callgraph_superedge& cg_superedge
   1324  1.1  mrg 		  = event->get_callgraph_superedge ();
   1325  1.1  mrg 		callsite_expr expr;
   1326  1.1  mrg 		tree callee_var
   1327  1.1  mrg 		  = cg_superedge.map_expr_from_caller_to_callee (var, &expr);
   1328  1.1  mrg 		if (callee_var)
   1329  1.1  mrg 		  {
   1330  1.1  mrg 		    log ("event %i:"
   1331  1.1  mrg 			 " switching var of interest"
   1332  1.1  mrg 			 " from %qE in caller to %qE in callee",
   1333  1.1  mrg 			 idx, var, callee_var);
   1334  1.1  mrg 		    var = callee_var;
   1335  1.1  mrg 		    if (expr.return_value_p ())
   1336  1.1  mrg 		      event->record_critical_state (var, state);
   1337  1.1  mrg 		    update_for_unsuitable_sm_exprs (&var);
   1338  1.1  mrg 		  }
   1339  1.1  mrg 	      }
   1340  1.1  mrg 	  }
   1341  1.1  mrg 	  break;
   1342  1.1  mrg 
   1343  1.1  mrg 	case EK_SETJMP:
   1344  1.1  mrg 	  /* TODO: only show setjmp_events that matter i.e. those for which
   1345  1.1  mrg 	     there is a later rewind event using them.  */
   1346  1.1  mrg 	case EK_REWIND_FROM_LONGJMP:
   1347  1.1  mrg 	case EK_REWIND_TO_SETJMP:
   1348  1.1  mrg 	  break;
   1349  1.1  mrg 
   1350  1.1  mrg 	case EK_WARNING:
   1351  1.1  mrg 	  /* Always show the final "warning" event in the path.  */
   1352  1.1  mrg 	  break;
   1353  1.1  mrg 	}
   1354  1.1  mrg       idx--;
   1355  1.1  mrg     }
   1356  1.1  mrg }
   1357  1.1  mrg 
   1358  1.1  mrg /* Subroutine of diagnostic_manager::prune_for_sm_diagnostic.
   1359  1.1  mrg    If *EXPR is not suitable to be the expression of interest in
   1360  1.1  mrg    an sm-diagnostic, set *EXPR to NULL and log.  */
   1361  1.1  mrg 
   1362  1.1  mrg void
   1363  1.1  mrg diagnostic_manager::update_for_unsuitable_sm_exprs (tree *expr) const
   1364  1.1  mrg {
   1365  1.1  mrg   gcc_assert (expr);
   1366  1.1  mrg   if (*expr && !can_be_expr_of_interest_p (*expr))
   1367  1.1  mrg     {
   1368  1.1  mrg       log ("new var %qE is unsuitable; setting var to NULL", *expr);
   1369  1.1  mrg       *expr = NULL_TREE;
   1370  1.1  mrg     }
   1371  1.1  mrg }
   1372  1.1  mrg 
   1373  1.1  mrg /* Second pass of diagnostic_manager::prune_path: remove redundant
   1374  1.1  mrg    interprocedural information.
   1375  1.1  mrg 
   1376  1.1  mrg    For example, given:
   1377  1.1  mrg      (1)- calling "f2" from "f1"
   1378  1.1  mrg      (2)--- entry to "f2"
   1379  1.1  mrg      (3)--- calling "f3" from "f2"
   1380  1.1  mrg      (4)----- entry to "f3"
   1381  1.1  mrg      (5)--- returning to "f2" to "f3"
   1382  1.1  mrg      (6)- returning to "f1" to "f2"
   1383  1.1  mrg    with no other intervening events, then none of these events are
   1384  1.1  mrg    likely to be interesting to the user.
   1385  1.1  mrg 
   1386  1.1  mrg    Prune [..., call, function-entry, return, ...] triples repeatedly
   1387  1.1  mrg    until nothing has changed.  For the example above, this would
   1388  1.1  mrg    remove events (3, 4, 5), and then remove events (1, 2, 6).  */
   1389  1.1  mrg 
   1390  1.1  mrg void
   1391  1.1  mrg diagnostic_manager::prune_interproc_events (checker_path *path) const
   1392  1.1  mrg {
   1393  1.1  mrg   bool changed = false;
   1394  1.1  mrg   do
   1395  1.1  mrg     {
   1396  1.1  mrg       changed = false;
   1397  1.1  mrg       int idx = path->num_events () - 1;
   1398  1.1  mrg       while (idx >= 0)
   1399  1.1  mrg 	{
   1400  1.1  mrg 	  /* Prune [..., call, function-entry, return, ...] triples.  */
   1401  1.1  mrg 	  if (idx + 2 < (signed)path->num_events ()
   1402  1.1  mrg 	      && path->get_checker_event (idx)->is_call_p ()
   1403  1.1  mrg 	      && path->get_checker_event (idx + 1)->is_function_entry_p ()
   1404  1.1  mrg 	      && path->get_checker_event (idx + 2)->is_return_p ())
   1405  1.1  mrg 	    {
   1406  1.1  mrg 	      if (get_logger ())
   1407  1.1  mrg 		{
   1408  1.1  mrg 		  label_text desc
   1409  1.1  mrg 		    (path->get_checker_event (idx)->get_desc (false));
   1410  1.1  mrg 		  log ("filtering events %i-%i:"
   1411  1.1  mrg 		       " irrelevant call/entry/return: %s",
   1412  1.1  mrg 		       idx, idx + 2, desc.m_buffer);
   1413  1.1  mrg 		  desc.maybe_free ();
   1414  1.1  mrg 		}
   1415  1.1  mrg 	      path->delete_event (idx + 2);
   1416  1.1  mrg 	      path->delete_event (idx + 1);
   1417  1.1  mrg 	      path->delete_event (idx);
   1418  1.1  mrg 	      changed = true;
   1419  1.1  mrg 	      idx--;
   1420  1.1  mrg 	      continue;
   1421  1.1  mrg 	    }
   1422  1.1  mrg 
   1423  1.1  mrg 	  /* Prune [..., call, return, ...] pairs
   1424  1.1  mrg 	     (for -fanalyzer-verbosity=0).  */
   1425  1.1  mrg 	  if (idx + 1 < (signed)path->num_events ()
   1426  1.1  mrg 	      && path->get_checker_event (idx)->is_call_p ()
   1427  1.1  mrg 	      && path->get_checker_event (idx + 1)->is_return_p ())
   1428  1.1  mrg 	    {
   1429  1.1  mrg 	      if (get_logger ())
   1430  1.1  mrg 		{
   1431  1.1  mrg 		  label_text desc
   1432  1.1  mrg 		    (path->get_checker_event (idx)->get_desc (false));
   1433  1.1  mrg 		  log ("filtering events %i-%i:"
   1434  1.1  mrg 		       " irrelevant call/return: %s",
   1435  1.1  mrg 		       idx, idx + 1, desc.m_buffer);
   1436  1.1  mrg 		  desc.maybe_free ();
   1437  1.1  mrg 		}
   1438  1.1  mrg 	      path->delete_event (idx + 1);
   1439  1.1  mrg 	      path->delete_event (idx);
   1440  1.1  mrg 	      changed = true;
   1441  1.1  mrg 	      idx--;
   1442  1.1  mrg 	      continue;
   1443  1.1  mrg 	    }
   1444  1.1  mrg 
   1445  1.1  mrg 	  idx--;
   1446  1.1  mrg 	}
   1447  1.1  mrg 
   1448  1.1  mrg     }
   1449  1.1  mrg   while (changed);
   1450  1.1  mrg }
   1451  1.1  mrg 
   1452  1.1  mrg /* Final pass of diagnostic_manager::prune_path.
   1453  1.1  mrg 
   1454  1.1  mrg    If all we're left with is in one function, then filter function entry
   1455  1.1  mrg    events.  */
   1456  1.1  mrg 
   1457  1.1  mrg void
   1458  1.1  mrg diagnostic_manager::finish_pruning (checker_path *path) const
   1459  1.1  mrg {
   1460  1.1  mrg   if (!path->interprocedural_p ())
   1461  1.1  mrg     {
   1462  1.1  mrg       int idx = path->num_events () - 1;
   1463  1.1  mrg       while (idx >= 0 && idx < (signed)path->num_events ())
   1464  1.1  mrg 	{
   1465  1.1  mrg 	  checker_event *base_event = path->get_checker_event (idx);
   1466  1.1  mrg 	  if (base_event->m_kind == EK_FUNCTION_ENTRY)
   1467  1.1  mrg 	    {
   1468  1.1  mrg 	      log ("filtering event %i:"
   1469  1.1  mrg 		   " function entry for purely intraprocedural path", idx);
   1470  1.1  mrg 	      path->delete_event (idx);
   1471  1.1  mrg 	    }
   1472  1.1  mrg 	  idx--;
   1473  1.1  mrg 	}
   1474  1.1  mrg     }
   1475  1.1  mrg }
   1476  1.1  mrg 
   1477  1.1  mrg } // namespace ana
   1478  1.1  mrg 
   1479  1.1  mrg #endif /* #if ENABLE_ANALYZER */
   1480