1 /* Classes for saving, deduplicating, and emitting analyzer diagnostics. 2 Copyright (C) 2019-2021 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 stmt_finder *stmt_finder, 37 tree var, const svalue *sval, 38 state_machine::state_t state, 39 pending_diagnostic *d, 40 unsigned idx); 41 ~saved_diagnostic (); 42 43 bool operator== (const saved_diagnostic &other) const; 44 45 json::object *to_json () const; 46 get_feasibility_problem()47 const feasibility_problem *get_feasibility_problem () const 48 { 49 return m_problem; 50 } 51 52 bool calc_best_epath (epath_finder *pf); get_best_epath()53 const exploded_path *get_best_epath () const { return m_best_epath; } 54 unsigned get_epath_length () const; 55 56 void add_duplicate (saved_diagnostic *other); get_num_dupes()57 unsigned get_num_dupes () const { return m_duplicates.length (); } 58 get_index()59 unsigned get_index () const { return m_idx; } 60 61 bool supercedes_p (const saved_diagnostic &other) const; 62 63 //private: 64 const state_machine *m_sm; 65 const exploded_node *m_enode; 66 const supernode *m_snode; 67 const gimple *m_stmt; 68 stmt_finder *m_stmt_finder; 69 tree m_var; 70 const svalue *m_sval; 71 state_machine::state_t m_state; 72 pending_diagnostic *m_d; // owned 73 const exploded_edge *m_trailing_eedge; 74 75 private: 76 DISABLE_COPY_AND_ASSIGN (saved_diagnostic); 77 78 unsigned m_idx; 79 exploded_path *m_best_epath; // owned 80 feasibility_problem *m_problem; // owned 81 82 auto_vec<const saved_diagnostic *> m_duplicates; 83 }; 84 85 class path_builder; 86 87 /* A class with responsibility for saving pending diagnostics, so that 88 they can be emitted after the exploded_graph is complete. 89 This lets us de-duplicate diagnostics, and find the shortest path 90 for each similar diagnostic, potentially using edges that might 91 not have been found when each diagnostic was first saved. 92 93 This also lets us compute shortest_paths once, rather than 94 per-diagnostic. */ 95 96 class diagnostic_manager : public log_user 97 { 98 public: 99 diagnostic_manager (logger *logger, engine *eng, int verbosity); 100 get_engine()101 engine *get_engine () const { return m_eng; } 102 103 json::object *to_json () const; 104 105 void add_diagnostic (const state_machine *sm, 106 exploded_node *enode, 107 const supernode *snode, const gimple *stmt, 108 stmt_finder *finder, 109 tree var, 110 const svalue *sval, 111 state_machine::state_t state, 112 pending_diagnostic *d); 113 114 void add_diagnostic (exploded_node *enode, 115 const supernode *snode, const gimple *stmt, 116 stmt_finder *finder, 117 pending_diagnostic *d); 118 119 void emit_saved_diagnostics (const exploded_graph &eg); 120 121 void emit_saved_diagnostic (const exploded_graph &eg, 122 const saved_diagnostic &sd); 123 get_num_diagnostics()124 unsigned get_num_diagnostics () const 125 { 126 return m_saved_diagnostics.length (); 127 } get_saved_diagnostic(unsigned idx)128 saved_diagnostic *get_saved_diagnostic (unsigned idx) 129 { 130 return m_saved_diagnostics[idx]; 131 } get_saved_diagnostic(unsigned idx)132 const saved_diagnostic *get_saved_diagnostic (unsigned idx) const 133 { 134 return m_saved_diagnostics[idx]; 135 } 136 137 private: 138 void build_emission_path (const path_builder &pb, 139 const exploded_path &epath, 140 checker_path *emission_path) const; 141 142 void add_events_for_eedge (const path_builder &pb, 143 const exploded_edge &eedge, 144 checker_path *emission_path) const; 145 146 bool significant_edge_p (const path_builder &pb, 147 const exploded_edge &eedge) const; 148 149 void add_events_for_superedge (const path_builder &pb, 150 const exploded_edge &eedge, 151 checker_path *emission_path) const; 152 153 void prune_path (checker_path *path, 154 const state_machine *sm, 155 const svalue *sval, 156 state_machine::state_t state) const; 157 158 void prune_for_sm_diagnostic (checker_path *path, 159 const state_machine *sm, 160 tree var, 161 state_machine::state_t state) const; 162 void prune_for_sm_diagnostic (checker_path *path, 163 const state_machine *sm, 164 const svalue *sval, 165 state_machine::state_t state) const; 166 void update_for_unsuitable_sm_exprs (tree *expr) const; 167 void prune_interproc_events (checker_path *path) const; 168 void consolidate_conditions (checker_path *path) const; 169 void finish_pruning (checker_path *path) const; 170 171 engine *m_eng; 172 auto_delete_vec<saved_diagnostic> m_saved_diagnostics; 173 const int m_verbosity; 174 }; 175 176 } // namespace ana 177 178 #endif /* GCC_ANALYZER_DIAGNOSTIC_MANAGER_H */ 179