xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/analyzer/checker-path.h (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
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