1  /* Classes for saving, deduplicating, and emitting analyzer diagnostics.
       2     Copyright (C) 2019-2023 Free Software Foundation, Inc.
       3     Contributed by David Malcolm <dmalcolm@redhat.com>.
       4  
       5  This file is part of GCC.
       6  
       7  GCC is free software; you can redistribute it and/or modify it
       8  under the terms of the GNU General Public License as published by
       9  the Free Software Foundation; either version 3, or (at your option)
      10  any later version.
      11  
      12  GCC is distributed in the hope that it will be useful, but
      13  WITHOUT ANY WARRANTY; without even the implied warranty of
      14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15  General Public License for more details.
      16  
      17  You should have received a copy of the GNU General Public License
      18  along with GCC; see the file COPYING3.  If not see
      19  <http://www.gnu.org/licenses/>.  */
      20  
      21  #ifndef GCC_ANALYZER_DIAGNOSTIC_MANAGER_H
      22  #define GCC_ANALYZER_DIAGNOSTIC_MANAGER_H
      23  
      24  namespace ana {
      25  
      26  class epath_finder;
      27  
      28  /* A to-be-emitted diagnostic stored within diagnostic_manager.  */
      29  
      30  class saved_diagnostic
      31  {
      32  public:
      33    saved_diagnostic (const state_machine *sm,
      34  		    const exploded_node *enode,
      35  		    const supernode *snode, const gimple *stmt,
      36  		    const stmt_finder *stmt_finder,
      37  		    tree var, const svalue *sval,
      38  		    state_machine::state_t state,
      39  		    std::unique_ptr<pending_diagnostic> d,
      40  		    unsigned idx);
      41  
      42    bool operator== (const saved_diagnostic &other) const;
      43  
      44    void add_note (std::unique_ptr<pending_note> pn);
      45  
      46    json::object *to_json () const;
      47  
      48    void dump_dot_id (pretty_printer *pp) const;
      49    void dump_as_dot_node (pretty_printer *pp) const;
      50  
      51    const feasibility_problem *get_feasibility_problem () const
      52    {
      53      return m_problem.get ();
      54    }
      55  
      56    bool calc_best_epath (epath_finder *pf);
      57    const exploded_path *get_best_epath () const { return m_best_epath.get (); }
      58    unsigned get_epath_length () const;
      59  
      60    void add_duplicate (saved_diagnostic *other);
      61    unsigned get_num_dupes () const { return m_duplicates.length (); }
      62  
      63    unsigned get_index () const { return m_idx; }
      64  
      65    bool supercedes_p (const saved_diagnostic &other) const;
      66  
      67    void emit_any_notes () const;
      68  
      69    //private:
      70    const state_machine *m_sm;
      71    const exploded_node *m_enode;
      72    const supernode *m_snode;
      73    const gimple *m_stmt;
      74    std::unique_ptr<stmt_finder> m_stmt_finder;
      75    tree m_var;
      76    const svalue *m_sval;
      77    state_machine::state_t m_state;
      78    std::unique_ptr<pending_diagnostic> m_d;
      79    const exploded_edge *m_trailing_eedge;
      80  
      81  private:
      82    DISABLE_COPY_AND_ASSIGN (saved_diagnostic);
      83  
      84    unsigned m_idx;
      85    std::unique_ptr<exploded_path> m_best_epath;
      86    std::unique_ptr<feasibility_problem> m_problem;
      87  
      88    auto_vec<const saved_diagnostic *> m_duplicates;
      89    auto_delete_vec <pending_note> m_notes;
      90  };
      91  
      92  class path_builder;
      93  
      94  /* A class with responsibility for saving pending diagnostics, so that
      95     they can be emitted after the exploded_graph is complete.
      96     This lets us de-duplicate diagnostics, and find the shortest path
      97     for each similar diagnostic, potentially using edges that might
      98     not have been found when each diagnostic was first saved.
      99  
     100     This also lets us compute shortest_paths once, rather than
     101     per-diagnostic.  */
     102  
     103  class diagnostic_manager : public log_user
     104  {
     105  public:
     106    diagnostic_manager (logger *logger, engine *eng, int verbosity);
     107  
     108    engine *get_engine () const { return m_eng; }
     109  
     110    json::object *to_json () const;
     111  
     112    bool add_diagnostic (const state_machine *sm,
     113  		       exploded_node *enode,
     114  		       const supernode *snode, const gimple *stmt,
     115  		       const stmt_finder *finder,
     116  		       tree var,
     117  		       const svalue *sval,
     118  		       state_machine::state_t state,
     119  		       std::unique_ptr<pending_diagnostic> d);
     120  
     121    bool add_diagnostic (exploded_node *enode,
     122  		       const supernode *snode, const gimple *stmt,
     123  		       const stmt_finder *finder,
     124  		       std::unique_ptr<pending_diagnostic> d);
     125  
     126    void add_note (std::unique_ptr<pending_note> pn);
     127  
     128    void emit_saved_diagnostics (const exploded_graph &eg);
     129  
     130    void emit_saved_diagnostic (const exploded_graph &eg,
     131  			      const saved_diagnostic &sd);
     132  
     133    unsigned get_num_diagnostics () const
     134    {
     135      return m_saved_diagnostics.length ();
     136    }
     137    saved_diagnostic *get_saved_diagnostic (unsigned idx)
     138    {
     139      return m_saved_diagnostics[idx];
     140    }
     141    const saved_diagnostic *get_saved_diagnostic (unsigned idx) const
     142    {
     143      return m_saved_diagnostics[idx];
     144    }
     145  
     146  private:
     147    void build_emission_path (const path_builder &pb,
     148  			    const exploded_path &epath,
     149  			    checker_path *emission_path) const;
     150  
     151    void add_event_on_final_node (const path_builder &pb,
     152  				const exploded_node *final_enode,
     153  				checker_path *emission_path,
     154  				interesting_t *interest) const;
     155  
     156    void add_events_for_eedge (const path_builder &pb,
     157  			     const exploded_edge &eedge,
     158  			     checker_path *emission_path,
     159  			     interesting_t *interest) const;
     160  
     161    bool significant_edge_p (const path_builder &pb,
     162  			   const exploded_edge &eedge) const;
     163  
     164    void add_events_for_superedge (const path_builder &pb,
     165  				 const exploded_edge &eedge,
     166  				 checker_path *emission_path) const;
     167  
     168    void prune_path (checker_path *path,
     169  		   const state_machine *sm,
     170  		   const svalue *sval,
     171  		   state_machine::state_t state) const;
     172  
     173    void prune_for_sm_diagnostic (checker_path *path,
     174  				const state_machine *sm,
     175  				tree var,
     176  				state_machine::state_t state) const;
     177    void prune_for_sm_diagnostic (checker_path *path,
     178  				const state_machine *sm,
     179  				const svalue *sval,
     180  				state_machine::state_t state) const;
     181    void update_for_unsuitable_sm_exprs (tree *expr) const;
     182    void prune_interproc_events (checker_path *path) const;
     183    void consolidate_conditions (checker_path *path) const;
     184    void finish_pruning (checker_path *path) const;
     185  
     186    engine *m_eng;
     187    auto_delete_vec<saved_diagnostic> m_saved_diagnostics;
     188    const int m_verbosity;
     189    int m_num_disabled_diagnostics;
     190  };
     191  
     192  } // namespace ana
     193  
     194  #endif /* GCC_ANALYZER_DIAGNOSTIC_MANAGER_H */