1*4c3eb207Smrg /* Subclasses of diagnostic_path and diagnostic_event for analyzer diagnostics. 2*4c3eb207Smrg Copyright (C) 2019-2020 Free Software Foundation, Inc. 3*4c3eb207Smrg Contributed by David Malcolm <dmalcolm@redhat.com>. 4*4c3eb207Smrg 5*4c3eb207Smrg This file is part of GCC. 6*4c3eb207Smrg 7*4c3eb207Smrg GCC is free software; you can redistribute it and/or modify it 8*4c3eb207Smrg under the terms of the GNU General Public License as published by 9*4c3eb207Smrg the Free Software Foundation; either version 3, or (at your option) 10*4c3eb207Smrg any later version. 11*4c3eb207Smrg 12*4c3eb207Smrg GCC is distributed in the hope that it will be useful, but 13*4c3eb207Smrg WITHOUT ANY WARRANTY; without even the implied warranty of 14*4c3eb207Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15*4c3eb207Smrg General Public License for more details. 16*4c3eb207Smrg 17*4c3eb207Smrg You should have received a copy of the GNU General Public License 18*4c3eb207Smrg along with GCC; see the file COPYING3. If not see 19*4c3eb207Smrg <http://www.gnu.org/licenses/>. */ 20*4c3eb207Smrg 21*4c3eb207Smrg #ifndef GCC_ANALYZER_CHECKER_PATH_H 22*4c3eb207Smrg #define GCC_ANALYZER_CHECKER_PATH_H 23*4c3eb207Smrg 24*4c3eb207Smrg namespace ana { 25*4c3eb207Smrg 26*4c3eb207Smrg /* An enum for discriminating between the concrete subclasses of 27*4c3eb207Smrg checker_event. */ 28*4c3eb207Smrg 29*4c3eb207Smrg enum event_kind 30*4c3eb207Smrg { 31*4c3eb207Smrg EK_DEBUG, 32*4c3eb207Smrg EK_CUSTOM, 33*4c3eb207Smrg EK_STMT, 34*4c3eb207Smrg EK_FUNCTION_ENTRY, 35*4c3eb207Smrg EK_STATE_CHANGE, 36*4c3eb207Smrg EK_START_CFG_EDGE, 37*4c3eb207Smrg EK_END_CFG_EDGE, 38*4c3eb207Smrg EK_CALL_EDGE, 39*4c3eb207Smrg EK_RETURN_EDGE, 40*4c3eb207Smrg EK_SETJMP, 41*4c3eb207Smrg EK_REWIND_FROM_LONGJMP, 42*4c3eb207Smrg EK_REWIND_TO_SETJMP, 43*4c3eb207Smrg EK_WARNING 44*4c3eb207Smrg }; 45*4c3eb207Smrg 46*4c3eb207Smrg extern const char *event_kind_to_string (enum event_kind ek); 47*4c3eb207Smrg 48*4c3eb207Smrg /* Event subclasses. 49*4c3eb207Smrg 50*4c3eb207Smrg The class hierarchy looks like this (using indentation to show 51*4c3eb207Smrg inheritance, and with event_kinds shown for the concrete subclasses): 52*4c3eb207Smrg 53*4c3eb207Smrg diagnostic_event 54*4c3eb207Smrg checker_event 55*4c3eb207Smrg debug_event (EK_DEBUG) 56*4c3eb207Smrg custom_event (EK_CUSTOM) 57*4c3eb207Smrg statement_event (EK_STMT) 58*4c3eb207Smrg function_entry_event (EK_FUNCTION_ENTRY) 59*4c3eb207Smrg state_change_event (EK_STATE_CHANGE) 60*4c3eb207Smrg superedge_event 61*4c3eb207Smrg cfg_edge_event 62*4c3eb207Smrg start_cfg_edge_event (EK_START_CFG_EDGE) 63*4c3eb207Smrg end_cfg_edge_event (EK_END_CFG_EDGE) 64*4c3eb207Smrg call_event (EK_CALL_EDGE) 65*4c3eb207Smrg return_edge (EK_RETURN_EDGE) 66*4c3eb207Smrg setjmp_event (EK_SETJMP) 67*4c3eb207Smrg rewind_event 68*4c3eb207Smrg rewind_from_longjmp_event (EK_REWIND_FROM_LONGJMP) 69*4c3eb207Smrg rewind_to_setjmp_event (EK_REWIND_TO_SETJMP) 70*4c3eb207Smrg warning_event (EK_WARNING). */ 71*4c3eb207Smrg 72*4c3eb207Smrg /* Abstract subclass of diagnostic_event; the base class for use in 73*4c3eb207Smrg checker_path (the analyzer's diagnostic_path subclass). */ 74*4c3eb207Smrg 75*4c3eb207Smrg class checker_event : public diagnostic_event 76*4c3eb207Smrg { 77*4c3eb207Smrg public: checker_event(enum event_kind kind,location_t loc,tree fndecl,int depth)78*4c3eb207Smrg checker_event (enum event_kind kind, 79*4c3eb207Smrg location_t loc, tree fndecl, int depth) 80*4c3eb207Smrg : m_kind (kind), m_loc (loc), m_fndecl (fndecl), m_depth (depth), 81*4c3eb207Smrg m_pending_diagnostic (NULL), m_emission_id () 82*4c3eb207Smrg { 83*4c3eb207Smrg } 84*4c3eb207Smrg 85*4c3eb207Smrg /* Implementation of diagnostic_event. */ 86*4c3eb207Smrg get_location()87*4c3eb207Smrg location_t get_location () const FINAL OVERRIDE { return m_loc; } get_fndecl()88*4c3eb207Smrg tree get_fndecl () const FINAL OVERRIDE { return m_fndecl; } get_stack_depth()89*4c3eb207Smrg int get_stack_depth () const FINAL OVERRIDE { return m_depth; } 90*4c3eb207Smrg 91*4c3eb207Smrg /* Additional functionality. */ 92*4c3eb207Smrg 93*4c3eb207Smrg virtual void prepare_for_emission (checker_path *, 94*4c3eb207Smrg pending_diagnostic *pd, 95*4c3eb207Smrg diagnostic_event_id_t emission_id); is_call_p()96*4c3eb207Smrg virtual bool is_call_p () const { return false; } is_function_entry_p()97*4c3eb207Smrg virtual bool is_function_entry_p () const { return false; } is_return_p()98*4c3eb207Smrg virtual bool is_return_p () const { return false; } 99*4c3eb207Smrg 100*4c3eb207Smrg void dump (pretty_printer *pp) const; 101*4c3eb207Smrg 102*4c3eb207Smrg public: 103*4c3eb207Smrg const enum event_kind m_kind; 104*4c3eb207Smrg protected: 105*4c3eb207Smrg location_t m_loc; 106*4c3eb207Smrg tree m_fndecl; 107*4c3eb207Smrg int m_depth; 108*4c3eb207Smrg pending_diagnostic *m_pending_diagnostic; 109*4c3eb207Smrg diagnostic_event_id_t m_emission_id; // only set once all pruning has occurred 110*4c3eb207Smrg }; 111*4c3eb207Smrg 112*4c3eb207Smrg /* A concrete event subclass for a purely textual event, for use in 113*4c3eb207Smrg debugging path creation and filtering. */ 114*4c3eb207Smrg 115*4c3eb207Smrg class debug_event : public checker_event 116*4c3eb207Smrg { 117*4c3eb207Smrg public: debug_event(location_t loc,tree fndecl,int depth,const char * desc)118*4c3eb207Smrg debug_event (location_t loc, tree fndecl, int depth, 119*4c3eb207Smrg const char *desc) 120*4c3eb207Smrg : checker_event (EK_DEBUG, loc, fndecl, depth), 121*4c3eb207Smrg m_desc (xstrdup (desc)) 122*4c3eb207Smrg { 123*4c3eb207Smrg } ~debug_event()124*4c3eb207Smrg ~debug_event () 125*4c3eb207Smrg { 126*4c3eb207Smrg free (m_desc); 127*4c3eb207Smrg } 128*4c3eb207Smrg 129*4c3eb207Smrg label_text get_desc (bool) const FINAL OVERRIDE; 130*4c3eb207Smrg 131*4c3eb207Smrg private: 132*4c3eb207Smrg char *m_desc; 133*4c3eb207Smrg }; 134*4c3eb207Smrg 135*4c3eb207Smrg /* A concrete event subclass for custom events. These are not filtered, 136*4c3eb207Smrg as they are likely to be pertinent to the diagnostic. */ 137*4c3eb207Smrg 138*4c3eb207Smrg class custom_event : public checker_event 139*4c3eb207Smrg { 140*4c3eb207Smrg public: custom_event(location_t loc,tree fndecl,int depth,const char * desc)141*4c3eb207Smrg custom_event (location_t loc, tree fndecl, int depth, 142*4c3eb207Smrg const char *desc) 143*4c3eb207Smrg : checker_event (EK_CUSTOM, loc, fndecl, depth), 144*4c3eb207Smrg m_desc (xstrdup (desc)) 145*4c3eb207Smrg { 146*4c3eb207Smrg } ~custom_event()147*4c3eb207Smrg ~custom_event () 148*4c3eb207Smrg { 149*4c3eb207Smrg free (m_desc); 150*4c3eb207Smrg } 151*4c3eb207Smrg 152*4c3eb207Smrg label_text get_desc (bool) const FINAL OVERRIDE; 153*4c3eb207Smrg 154*4c3eb207Smrg private: 155*4c3eb207Smrg char *m_desc; 156*4c3eb207Smrg }; 157*4c3eb207Smrg 158*4c3eb207Smrg /* A concrete event subclass describing the execution of a gimple statement, 159*4c3eb207Smrg for use at high verbosity levels when debugging paths. */ 160*4c3eb207Smrg 161*4c3eb207Smrg class statement_event : public checker_event 162*4c3eb207Smrg { 163*4c3eb207Smrg public: 164*4c3eb207Smrg statement_event (const gimple *stmt, tree fndecl, int depth, 165*4c3eb207Smrg const program_state &dst_state); 166*4c3eb207Smrg 167*4c3eb207Smrg label_text get_desc (bool) const FINAL OVERRIDE; 168*4c3eb207Smrg 169*4c3eb207Smrg const gimple * const m_stmt; 170*4c3eb207Smrg const program_state m_dst_state; 171*4c3eb207Smrg }; 172*4c3eb207Smrg 173*4c3eb207Smrg /* An event subclass describing the entry to a function. */ 174*4c3eb207Smrg 175*4c3eb207Smrg class function_entry_event : public checker_event 176*4c3eb207Smrg { 177*4c3eb207Smrg public: function_entry_event(location_t loc,tree fndecl,int depth)178*4c3eb207Smrg function_entry_event (location_t loc, tree fndecl, int depth) 179*4c3eb207Smrg : checker_event (EK_FUNCTION_ENTRY, loc, fndecl, depth) 180*4c3eb207Smrg { 181*4c3eb207Smrg } 182*4c3eb207Smrg 183*4c3eb207Smrg label_text get_desc (bool can_colorize) const FINAL OVERRIDE; 184*4c3eb207Smrg is_function_entry_p()185*4c3eb207Smrg bool is_function_entry_p () const FINAL OVERRIDE { return true; } 186*4c3eb207Smrg }; 187*4c3eb207Smrg 188*4c3eb207Smrg /* Subclass of checker_event describing a state change. */ 189*4c3eb207Smrg 190*4c3eb207Smrg class state_change_event : public checker_event 191*4c3eb207Smrg { 192*4c3eb207Smrg public: 193*4c3eb207Smrg state_change_event (const supernode *node, const gimple *stmt, 194*4c3eb207Smrg int stack_depth, 195*4c3eb207Smrg const state_machine &sm, 196*4c3eb207Smrg tree var, 197*4c3eb207Smrg state_machine::state_t from, 198*4c3eb207Smrg state_machine::state_t to, 199*4c3eb207Smrg tree origin, 200*4c3eb207Smrg const program_state &dst_state); 201*4c3eb207Smrg 202*4c3eb207Smrg label_text get_desc (bool can_colorize) const FINAL OVERRIDE; 203*4c3eb207Smrg get_lvalue(tree expr,region_model_context * ctxt)204*4c3eb207Smrg region_id get_lvalue (tree expr, region_model_context *ctxt) const 205*4c3eb207Smrg { 206*4c3eb207Smrg return m_dst_state.m_region_model->get_lvalue (expr, ctxt); 207*4c3eb207Smrg } 208*4c3eb207Smrg 209*4c3eb207Smrg const supernode *m_node; 210*4c3eb207Smrg const gimple *m_stmt; 211*4c3eb207Smrg const state_machine &m_sm; 212*4c3eb207Smrg tree m_var; 213*4c3eb207Smrg state_machine::state_t m_from; 214*4c3eb207Smrg state_machine::state_t m_to; 215*4c3eb207Smrg tree m_origin; 216*4c3eb207Smrg program_state m_dst_state; 217*4c3eb207Smrg }; 218*4c3eb207Smrg 219*4c3eb207Smrg /* Subclass of checker_event; parent class for subclasses that relate to 220*4c3eb207Smrg a superedge. */ 221*4c3eb207Smrg 222*4c3eb207Smrg class superedge_event : public checker_event 223*4c3eb207Smrg { 224*4c3eb207Smrg public: 225*4c3eb207Smrg /* Mark this edge event as being either an interprocedural call or 226*4c3eb207Smrg return in which VAR is in STATE, and that this is critical to the 227*4c3eb207Smrg diagnostic (so that get_desc can attempt to get a better description 228*4c3eb207Smrg from any pending_diagnostic). */ record_critical_state(tree var,state_machine::state_t state)229*4c3eb207Smrg void record_critical_state (tree var, state_machine::state_t state) 230*4c3eb207Smrg { 231*4c3eb207Smrg m_var = var; 232*4c3eb207Smrg m_critical_state = state; 233*4c3eb207Smrg } 234*4c3eb207Smrg 235*4c3eb207Smrg const callgraph_superedge& get_callgraph_superedge () const; 236*4c3eb207Smrg 237*4c3eb207Smrg bool should_filter_p (int verbosity) const; 238*4c3eb207Smrg 239*4c3eb207Smrg protected: 240*4c3eb207Smrg superedge_event (enum event_kind kind, const exploded_edge &eedge, 241*4c3eb207Smrg location_t loc, tree fndecl, int depth); 242*4c3eb207Smrg 243*4c3eb207Smrg public: 244*4c3eb207Smrg const exploded_edge &m_eedge; 245*4c3eb207Smrg const superedge *m_sedge; 246*4c3eb207Smrg tree m_var; 247*4c3eb207Smrg state_machine::state_t m_critical_state; 248*4c3eb207Smrg }; 249*4c3eb207Smrg 250*4c3eb207Smrg /* An abstract event subclass for when a CFG edge is followed; it has two 251*4c3eb207Smrg subclasses, representing the start of the edge and the end of the 252*4c3eb207Smrg edge, which come in pairs. */ 253*4c3eb207Smrg 254*4c3eb207Smrg class cfg_edge_event : public superedge_event 255*4c3eb207Smrg { 256*4c3eb207Smrg public: 257*4c3eb207Smrg const cfg_superedge& get_cfg_superedge () const; 258*4c3eb207Smrg 259*4c3eb207Smrg protected: 260*4c3eb207Smrg cfg_edge_event (enum event_kind kind, const exploded_edge &eedge, 261*4c3eb207Smrg location_t loc, tree fndecl, int depth); 262*4c3eb207Smrg }; 263*4c3eb207Smrg 264*4c3eb207Smrg /* A concrete event subclass for the start of a CFG edge 265*4c3eb207Smrg e.g. "following 'false' branch...'. */ 266*4c3eb207Smrg 267*4c3eb207Smrg class start_cfg_edge_event : public cfg_edge_event 268*4c3eb207Smrg { 269*4c3eb207Smrg public: start_cfg_edge_event(const exploded_edge & eedge,location_t loc,tree fndecl,int depth)270*4c3eb207Smrg start_cfg_edge_event (const exploded_edge &eedge, 271*4c3eb207Smrg location_t loc, tree fndecl, int depth) 272*4c3eb207Smrg : cfg_edge_event (EK_START_CFG_EDGE, eedge, loc, fndecl, depth) 273*4c3eb207Smrg { 274*4c3eb207Smrg } 275*4c3eb207Smrg 276*4c3eb207Smrg label_text get_desc (bool can_colorize) const FINAL OVERRIDE; 277*4c3eb207Smrg 278*4c3eb207Smrg private: 279*4c3eb207Smrg label_text maybe_describe_condition (bool can_colorize) const; 280*4c3eb207Smrg 281*4c3eb207Smrg static label_text maybe_describe_condition (bool can_colorize, 282*4c3eb207Smrg tree lhs, 283*4c3eb207Smrg enum tree_code op, 284*4c3eb207Smrg tree rhs); 285*4c3eb207Smrg static bool should_print_expr_p (tree); 286*4c3eb207Smrg }; 287*4c3eb207Smrg 288*4c3eb207Smrg /* A concrete event subclass for the end of a CFG edge 289*4c3eb207Smrg e.g. "...to here'. */ 290*4c3eb207Smrg 291*4c3eb207Smrg class end_cfg_edge_event : public cfg_edge_event 292*4c3eb207Smrg { 293*4c3eb207Smrg public: end_cfg_edge_event(const exploded_edge & eedge,location_t loc,tree fndecl,int depth)294*4c3eb207Smrg end_cfg_edge_event (const exploded_edge &eedge, 295*4c3eb207Smrg location_t loc, tree fndecl, int depth) 296*4c3eb207Smrg : cfg_edge_event (EK_END_CFG_EDGE, eedge, loc, fndecl, depth) 297*4c3eb207Smrg { 298*4c3eb207Smrg } 299*4c3eb207Smrg get_desc(bool)300*4c3eb207Smrg label_text get_desc (bool /*can_colorize*/) const FINAL OVERRIDE 301*4c3eb207Smrg { 302*4c3eb207Smrg return label_text::borrow ("...to here"); 303*4c3eb207Smrg } 304*4c3eb207Smrg }; 305*4c3eb207Smrg 306*4c3eb207Smrg /* A concrete event subclass for an interprocedural call. */ 307*4c3eb207Smrg 308*4c3eb207Smrg class call_event : public superedge_event 309*4c3eb207Smrg { 310*4c3eb207Smrg public: 311*4c3eb207Smrg call_event (const exploded_edge &eedge, 312*4c3eb207Smrg location_t loc, tree fndecl, int depth); 313*4c3eb207Smrg 314*4c3eb207Smrg label_text get_desc (bool can_colorize) const FINAL OVERRIDE; 315*4c3eb207Smrg 316*4c3eb207Smrg bool is_call_p () const FINAL OVERRIDE; 317*4c3eb207Smrg }; 318*4c3eb207Smrg 319*4c3eb207Smrg /* A concrete event subclass for an interprocedural return. */ 320*4c3eb207Smrg 321*4c3eb207Smrg class return_event : public superedge_event 322*4c3eb207Smrg { 323*4c3eb207Smrg public: 324*4c3eb207Smrg return_event (const exploded_edge &eedge, 325*4c3eb207Smrg location_t loc, tree fndecl, int depth); 326*4c3eb207Smrg 327*4c3eb207Smrg label_text get_desc (bool can_colorize) const FINAL OVERRIDE; 328*4c3eb207Smrg 329*4c3eb207Smrg bool is_return_p () const FINAL OVERRIDE; 330*4c3eb207Smrg }; 331*4c3eb207Smrg 332*4c3eb207Smrg /* A concrete event subclass for a setjmp or sigsetjmp call. */ 333*4c3eb207Smrg 334*4c3eb207Smrg class setjmp_event : public checker_event 335*4c3eb207Smrg { 336*4c3eb207Smrg public: setjmp_event(location_t loc,const exploded_node * enode,tree fndecl,int depth,const gcall * setjmp_call)337*4c3eb207Smrg setjmp_event (location_t loc, const exploded_node *enode, 338*4c3eb207Smrg tree fndecl, int depth, const gcall *setjmp_call) 339*4c3eb207Smrg : checker_event (EK_SETJMP, loc, fndecl, depth), 340*4c3eb207Smrg m_enode (enode), m_setjmp_call (setjmp_call) 341*4c3eb207Smrg { 342*4c3eb207Smrg } 343*4c3eb207Smrg 344*4c3eb207Smrg label_text get_desc (bool can_colorize) const FINAL OVERRIDE; 345*4c3eb207Smrg 346*4c3eb207Smrg void prepare_for_emission (checker_path *path, 347*4c3eb207Smrg pending_diagnostic *pd, 348*4c3eb207Smrg diagnostic_event_id_t emission_id) FINAL OVERRIDE; 349*4c3eb207Smrg 350*4c3eb207Smrg private: 351*4c3eb207Smrg const exploded_node *m_enode; 352*4c3eb207Smrg const gcall *m_setjmp_call; 353*4c3eb207Smrg }; 354*4c3eb207Smrg 355*4c3eb207Smrg /* An abstract event subclass for rewinding from a longjmp to a setjmp 356*4c3eb207Smrg (or siglongjmp to sigsetjmp). 357*4c3eb207Smrg 358*4c3eb207Smrg Base class for two from/to subclasses, showing the two halves of the 359*4c3eb207Smrg rewind. */ 360*4c3eb207Smrg 361*4c3eb207Smrg class rewind_event : public checker_event 362*4c3eb207Smrg { 363*4c3eb207Smrg public: 364*4c3eb207Smrg tree get_longjmp_caller () const; 365*4c3eb207Smrg tree get_setjmp_caller () const; get_eedge()366*4c3eb207Smrg const exploded_edge *get_eedge () const { return m_eedge; } 367*4c3eb207Smrg 368*4c3eb207Smrg protected: 369*4c3eb207Smrg rewind_event (const exploded_edge *eedge, 370*4c3eb207Smrg enum event_kind kind, 371*4c3eb207Smrg location_t loc, tree fndecl, int depth, 372*4c3eb207Smrg const rewind_info_t *rewind_info); 373*4c3eb207Smrg const rewind_info_t *m_rewind_info; 374*4c3eb207Smrg 375*4c3eb207Smrg private: 376*4c3eb207Smrg const exploded_edge *m_eedge; 377*4c3eb207Smrg }; 378*4c3eb207Smrg 379*4c3eb207Smrg /* A concrete event subclass for rewinding from a longjmp to a setjmp, 380*4c3eb207Smrg showing the longjmp (or siglongjmp). */ 381*4c3eb207Smrg 382*4c3eb207Smrg class rewind_from_longjmp_event : public rewind_event 383*4c3eb207Smrg { 384*4c3eb207Smrg public: rewind_from_longjmp_event(const exploded_edge * eedge,location_t loc,tree fndecl,int depth,const rewind_info_t * rewind_info)385*4c3eb207Smrg rewind_from_longjmp_event (const exploded_edge *eedge, 386*4c3eb207Smrg location_t loc, tree fndecl, int depth, 387*4c3eb207Smrg const rewind_info_t *rewind_info) 388*4c3eb207Smrg : rewind_event (eedge, EK_REWIND_FROM_LONGJMP, loc, fndecl, depth, 389*4c3eb207Smrg rewind_info) 390*4c3eb207Smrg { 391*4c3eb207Smrg } 392*4c3eb207Smrg 393*4c3eb207Smrg label_text get_desc (bool can_colorize) const FINAL OVERRIDE; 394*4c3eb207Smrg }; 395*4c3eb207Smrg 396*4c3eb207Smrg /* A concrete event subclass for rewinding from a longjmp to a setjmp, 397*4c3eb207Smrg showing the setjmp (or sigsetjmp). */ 398*4c3eb207Smrg 399*4c3eb207Smrg class rewind_to_setjmp_event : public rewind_event 400*4c3eb207Smrg { 401*4c3eb207Smrg public: rewind_to_setjmp_event(const exploded_edge * eedge,location_t loc,tree fndecl,int depth,const rewind_info_t * rewind_info)402*4c3eb207Smrg rewind_to_setjmp_event (const exploded_edge *eedge, 403*4c3eb207Smrg location_t loc, tree fndecl, int depth, 404*4c3eb207Smrg const rewind_info_t *rewind_info) 405*4c3eb207Smrg : rewind_event (eedge, EK_REWIND_TO_SETJMP, loc, fndecl, depth, 406*4c3eb207Smrg rewind_info) 407*4c3eb207Smrg { 408*4c3eb207Smrg } 409*4c3eb207Smrg 410*4c3eb207Smrg label_text get_desc (bool can_colorize) const FINAL OVERRIDE; 411*4c3eb207Smrg 412*4c3eb207Smrg void prepare_for_emission (checker_path *path, 413*4c3eb207Smrg pending_diagnostic *pd, 414*4c3eb207Smrg diagnostic_event_id_t emission_id) FINAL OVERRIDE; 415*4c3eb207Smrg 416*4c3eb207Smrg private: 417*4c3eb207Smrg diagnostic_event_id_t m_original_setjmp_event_id; 418*4c3eb207Smrg }; 419*4c3eb207Smrg 420*4c3eb207Smrg /* Concrete subclass of checker_event for use at the end of a path: 421*4c3eb207Smrg a repeat of the warning message at the end of the path (perhaps with 422*4c3eb207Smrg references to pertinent events that occurred on the way), at the point 423*4c3eb207Smrg where the problem occurs. */ 424*4c3eb207Smrg 425*4c3eb207Smrg class warning_event : public checker_event 426*4c3eb207Smrg { 427*4c3eb207Smrg public: warning_event(location_t loc,tree fndecl,int depth,const state_machine * sm,tree var,state_machine::state_t state)428*4c3eb207Smrg warning_event (location_t loc, tree fndecl, int depth, 429*4c3eb207Smrg const state_machine *sm, 430*4c3eb207Smrg tree var, state_machine::state_t state) 431*4c3eb207Smrg : checker_event (EK_WARNING, loc, fndecl, depth), 432*4c3eb207Smrg m_sm (sm), m_var (var), m_state (state) 433*4c3eb207Smrg { 434*4c3eb207Smrg } 435*4c3eb207Smrg 436*4c3eb207Smrg label_text get_desc (bool can_colorize) const FINAL OVERRIDE; 437*4c3eb207Smrg 438*4c3eb207Smrg private: 439*4c3eb207Smrg const state_machine *m_sm; 440*4c3eb207Smrg tree m_var; 441*4c3eb207Smrg state_machine::state_t m_state; 442*4c3eb207Smrg }; 443*4c3eb207Smrg 444*4c3eb207Smrg /* Subclass of diagnostic_path for analyzer diagnostics. */ 445*4c3eb207Smrg 446*4c3eb207Smrg class checker_path : public diagnostic_path 447*4c3eb207Smrg { 448*4c3eb207Smrg public: checker_path()449*4c3eb207Smrg checker_path () : diagnostic_path () {} 450*4c3eb207Smrg 451*4c3eb207Smrg /* Implementation of diagnostic_path vfuncs. */ 452*4c3eb207Smrg num_events()453*4c3eb207Smrg unsigned num_events () const FINAL OVERRIDE 454*4c3eb207Smrg { 455*4c3eb207Smrg return m_events.length (); 456*4c3eb207Smrg } 457*4c3eb207Smrg get_event(int idx)458*4c3eb207Smrg const diagnostic_event & get_event (int idx) const FINAL OVERRIDE 459*4c3eb207Smrg { 460*4c3eb207Smrg return *m_events[idx]; 461*4c3eb207Smrg } 462*4c3eb207Smrg get_checker_event(int idx)463*4c3eb207Smrg checker_event *get_checker_event (int idx) 464*4c3eb207Smrg { 465*4c3eb207Smrg return m_events[idx]; 466*4c3eb207Smrg } 467*4c3eb207Smrg 468*4c3eb207Smrg void dump (pretty_printer *pp) const; 469*4c3eb207Smrg void debug () const; 470*4c3eb207Smrg 471*4c3eb207Smrg void maybe_log (logger *logger, const char *desc) const; 472*4c3eb207Smrg add_event(checker_event * event)473*4c3eb207Smrg void add_event (checker_event *event) 474*4c3eb207Smrg { 475*4c3eb207Smrg m_events.safe_push (event); 476*4c3eb207Smrg } 477*4c3eb207Smrg delete_event(int idx)478*4c3eb207Smrg void delete_event (int idx) 479*4c3eb207Smrg { 480*4c3eb207Smrg checker_event *event = m_events[idx]; 481*4c3eb207Smrg m_events.ordered_remove (idx); 482*4c3eb207Smrg delete event; 483*4c3eb207Smrg } 484*4c3eb207Smrg 485*4c3eb207Smrg void add_final_event (const state_machine *sm, 486*4c3eb207Smrg const exploded_node *enode, const gimple *stmt, 487*4c3eb207Smrg tree var, state_machine::state_t state); 488*4c3eb207Smrg 489*4c3eb207Smrg /* After all event-pruning, a hook for notifying each event what 490*4c3eb207Smrg its ID will be. The events are notified in order, allowing 491*4c3eb207Smrg for later events to refer to the IDs of earlier events in 492*4c3eb207Smrg their descriptions. */ prepare_for_emission(pending_diagnostic * pd)493*4c3eb207Smrg void prepare_for_emission (pending_diagnostic *pd) 494*4c3eb207Smrg { 495*4c3eb207Smrg checker_event *e; 496*4c3eb207Smrg int i; 497*4c3eb207Smrg FOR_EACH_VEC_ELT (m_events, i, e) 498*4c3eb207Smrg e->prepare_for_emission (this, pd, diagnostic_event_id_t (i)); 499*4c3eb207Smrg } 500*4c3eb207Smrg record_setjmp_event(const exploded_node * enode,diagnostic_event_id_t setjmp_emission_id)501*4c3eb207Smrg void record_setjmp_event (const exploded_node *enode, 502*4c3eb207Smrg diagnostic_event_id_t setjmp_emission_id) 503*4c3eb207Smrg { 504*4c3eb207Smrg m_setjmp_event_ids.put (enode, setjmp_emission_id); 505*4c3eb207Smrg } 506*4c3eb207Smrg get_setjmp_event(const exploded_node * enode,diagnostic_event_id_t * out_emission_id)507*4c3eb207Smrg bool get_setjmp_event (const exploded_node *enode, 508*4c3eb207Smrg diagnostic_event_id_t *out_emission_id) 509*4c3eb207Smrg { 510*4c3eb207Smrg if (diagnostic_event_id_t *emission_id = m_setjmp_event_ids.get (enode)) 511*4c3eb207Smrg { 512*4c3eb207Smrg *out_emission_id = *emission_id; 513*4c3eb207Smrg return true; 514*4c3eb207Smrg } 515*4c3eb207Smrg return false; 516*4c3eb207Smrg } 517*4c3eb207Smrg 518*4c3eb207Smrg private: 519*4c3eb207Smrg DISABLE_COPY_AND_ASSIGN(checker_path); 520*4c3eb207Smrg 521*4c3eb207Smrg /* The events that have occurred along this path. */ 522*4c3eb207Smrg auto_delete_vec<checker_event> m_events; 523*4c3eb207Smrg 524*4c3eb207Smrg /* During prepare_for_emission (and after), the setjmp_event for each 525*4c3eb207Smrg exploded_node *, so that rewind events can refer to them in their 526*4c3eb207Smrg descriptions. */ 527*4c3eb207Smrg hash_map <const exploded_node *, diagnostic_event_id_t> m_setjmp_event_ids; 528*4c3eb207Smrg }; 529*4c3eb207Smrg 530*4c3eb207Smrg } // namespace ana 531*4c3eb207Smrg 532*4c3eb207Smrg #endif /* GCC_ANALYZER_CHECKER_PATH_H */ 533