991b592b82833adfb738ce2a5bf449bcd6d79054
[platform/upstream/gcc.git] / gcc / analyzer / engine.cc
1 /* The analysis "engine".
2    Copyright (C) 2019-2022 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 #include "config.h"
22 #define INCLUDE_MEMORY
23 #include "system.h"
24 #include "coretypes.h"
25 #include "make-unique.h"
26 #include "tree.h"
27 #include "fold-const.h"
28 #include "gcc-rich-location.h"
29 #include "diagnostic-core.h"
30 #include "diagnostic-event-id.h"
31 #include "diagnostic-path.h"
32 #include "function.h"
33 #include "pretty-print.h"
34 #include "sbitmap.h"
35 #include "bitmap.h"
36 #include "ordered-hash-map.h"
37 #include "analyzer/analyzer.h"
38 #include "analyzer/analyzer-logging.h"
39 #include "analyzer/call-string.h"
40 #include "analyzer/program-point.h"
41 #include "analyzer/store.h"
42 #include "analyzer/region-model.h"
43 #include "analyzer/constraint-manager.h"
44 #include "analyzer/sm.h"
45 #include "analyzer/pending-diagnostic.h"
46 #include "analyzer/diagnostic-manager.h"
47 #include "cfg.h"
48 #include "basic-block.h"
49 #include "gimple.h"
50 #include "gimple-iterator.h"
51 #include "gimple-pretty-print.h"
52 #include "cgraph.h"
53 #include "digraph.h"
54 #include "analyzer/supergraph.h"
55 #include "analyzer/program-state.h"
56 #include "analyzer/exploded-graph.h"
57 #include "analyzer/analysis-plan.h"
58 #include "analyzer/checker-path.h"
59 #include "analyzer/state-purge.h"
60 #include "analyzer/bar-chart.h"
61 #include "analyzer/call-info.h"
62 #include <zlib.h>
63 #include "plugin.h"
64 #include "target.h"
65 #include <memory>
66 #include "stringpool.h"
67 #include "attribs.h"
68 #include "tree-dfa.h"
69 #include "analyzer/known-function-manager.h"
70 #include "analyzer/call-summary.h"
71
72 /* For an overview, see gcc/doc/analyzer.texi.  */
73
74 #if ENABLE_ANALYZER
75
76 namespace ana {
77
78 /* class impl_region_model_context : public region_model_context.  */
79
80 impl_region_model_context::
81 impl_region_model_context (exploded_graph &eg,
82                            exploded_node *enode_for_diag,
83                            const program_state *old_state,
84                            program_state *new_state,
85                            uncertainty_t *uncertainty,
86                            path_context *path_ctxt,
87                            const gimple *stmt,
88                            stmt_finder *stmt_finder)
89 : m_eg (&eg), m_logger (eg.get_logger ()),
90   m_enode_for_diag (enode_for_diag),
91   m_old_state (old_state),
92   m_new_state (new_state),
93   m_stmt (stmt),
94   m_stmt_finder (stmt_finder),
95   m_ext_state (eg.get_ext_state ()),
96   m_uncertainty (uncertainty),
97   m_path_ctxt (path_ctxt)
98 {
99 }
100
101 impl_region_model_context::
102 impl_region_model_context (program_state *state,
103                            const extrinsic_state &ext_state,
104                            uncertainty_t *uncertainty,
105                            logger *logger)
106 : m_eg (NULL), m_logger (logger), m_enode_for_diag (NULL),
107   m_old_state (NULL),
108   m_new_state (state),
109   m_stmt (NULL),
110   m_stmt_finder (NULL),
111   m_ext_state (ext_state),
112   m_uncertainty (uncertainty),
113   m_path_ctxt (NULL)
114 {
115 }
116
117 bool
118 impl_region_model_context::warn (std::unique_ptr<pending_diagnostic> d)
119 {
120   LOG_FUNC (get_logger ());
121   if (m_stmt == NULL && m_stmt_finder == NULL)
122     {
123       if (get_logger ())
124         get_logger ()->log ("rejecting diagnostic: no stmt");
125       return false;
126     }
127   if (m_eg)
128     return m_eg->get_diagnostic_manager ().add_diagnostic
129       (m_enode_for_diag, m_enode_for_diag->get_supernode (),
130        m_stmt, m_stmt_finder, std::move (d));
131   else
132     return false;
133 }
134
135 void
136 impl_region_model_context::add_note (std::unique_ptr<pending_note> pn)
137 {
138   LOG_FUNC (get_logger ());
139   if (m_eg)
140     m_eg->get_diagnostic_manager ().add_note (std::move (pn));
141 }
142
143 void
144 impl_region_model_context::on_svalue_leak (const svalue *sval)
145
146 {
147   for (sm_state_map *smap : m_new_state->m_checker_states)
148     smap->on_svalue_leak (sval, this);
149 }
150
151 void
152 impl_region_model_context::
153 on_liveness_change (const svalue_set &live_svalues,
154                     const region_model *model)
155 {
156   for (sm_state_map *smap : m_new_state->m_checker_states)
157     smap->on_liveness_change (live_svalues, model, this);
158 }
159
160 void
161 impl_region_model_context::on_unknown_change (const svalue *sval,
162                                               bool is_mutable)
163 {
164   if (!sval->can_have_associated_state_p ())
165     return;
166   for (sm_state_map *smap : m_new_state->m_checker_states)
167     smap->on_unknown_change (sval, is_mutable, m_ext_state);
168 }
169
170 void
171 impl_region_model_context::on_escaped_function (tree fndecl)
172 {
173   m_eg->on_escaped_function (fndecl);
174 }
175
176 uncertainty_t *
177 impl_region_model_context::get_uncertainty ()
178 {
179   return m_uncertainty;
180 }
181
182 /* Purge state involving SVAL.  The region_model has already been purged,
183    so we only need to purge other state in the program_state:
184    the sm-state.  */
185
186 void
187 impl_region_model_context::purge_state_involving (const svalue *sval)
188 {
189   int i;
190   sm_state_map *smap;
191   FOR_EACH_VEC_ELT (m_new_state->m_checker_states, i, smap)
192     smap->purge_state_involving (sval, m_ext_state);
193 }
194
195 void
196 impl_region_model_context::bifurcate (std::unique_ptr<custom_edge_info> info)
197 {
198   if (m_path_ctxt)
199     m_path_ctxt->bifurcate (std::move (info));
200 }
201
202 void
203 impl_region_model_context::terminate_path ()
204 {
205   if (m_path_ctxt)
206     return m_path_ctxt->terminate_path ();
207 }
208
209 /* struct setjmp_record.  */
210
211 int
212 setjmp_record::cmp (const setjmp_record &rec1, const setjmp_record &rec2)
213 {
214   if (int cmp_enode = rec1.m_enode->m_index - rec2.m_enode->m_index)
215     return cmp_enode;
216   gcc_assert (&rec1 == &rec2);
217   return 0;
218 }
219
220 /* class setjmp_svalue : public svalue.  */
221
222 /* Implementation of svalue::accept vfunc for setjmp_svalue.  */
223
224 void
225 setjmp_svalue::accept (visitor *v) const
226 {
227   v->visit_setjmp_svalue (this);
228 }
229
230 /* Implementation of svalue::dump_to_pp vfunc for setjmp_svalue.  */
231
232 void
233 setjmp_svalue::dump_to_pp (pretty_printer *pp, bool simple) const
234 {
235   if (simple)
236     pp_printf (pp, "SETJMP(EN: %i)", get_enode_index ());
237   else
238     pp_printf (pp, "setjmp_svalue(EN%i)", get_enode_index ());
239 }
240
241 /* Get the index of the stored exploded_node.  */
242
243 int
244 setjmp_svalue::get_enode_index () const
245 {
246   return m_setjmp_record.m_enode->m_index;
247 }
248
249 /* Concrete implementation of sm_context, wiring it up to the rest of this
250    file.  */
251
252 class impl_sm_context : public sm_context
253 {
254 public:
255   impl_sm_context (exploded_graph &eg,
256                    int sm_idx,
257                    const state_machine &sm,
258                    exploded_node *enode_for_diag,
259                    const program_state *old_state,
260                    program_state *new_state,
261                    const sm_state_map *old_smap,
262                    sm_state_map *new_smap,
263                    path_context *path_ctxt,
264                    const stmt_finder *stmt_finder = NULL,
265                    bool unknown_side_effects = false)
266   : sm_context (sm_idx, sm),
267     m_logger (eg.get_logger ()),
268     m_eg (eg), m_enode_for_diag (enode_for_diag),
269     m_old_state (old_state), m_new_state (new_state),
270     m_old_smap (old_smap), m_new_smap (new_smap),
271     m_path_ctxt (path_ctxt),
272     m_stmt_finder (stmt_finder),
273     m_unknown_side_effects (unknown_side_effects)
274   {
275   }
276
277   logger *get_logger () const { return m_logger.get_logger (); }
278
279   tree get_fndecl_for_call (const gcall *call) final override
280   {
281     impl_region_model_context old_ctxt
282       (m_eg, m_enode_for_diag, NULL, NULL, NULL/*m_enode->get_state ()*/,
283        NULL, call);
284     region_model *model = m_new_state->m_region_model;
285     return model->get_fndecl_for_call (call, &old_ctxt);
286   }
287
288   state_machine::state_t get_state (const gimple *stmt ATTRIBUTE_UNUSED,
289                                     tree var) final override
290   {
291     logger * const logger = get_logger ();
292     LOG_FUNC (logger);
293     /* Use NULL ctxt on this get_rvalue call to avoid triggering
294        uninitialized value warnings.  */
295     const svalue *var_old_sval
296       = m_old_state->m_region_model->get_rvalue (var, NULL);
297
298     state_machine::state_t current
299       = m_old_smap->get_state (var_old_sval, m_eg.get_ext_state ());
300     return current;
301   }
302   state_machine::state_t get_state (const gimple *stmt ATTRIBUTE_UNUSED,
303                                     const svalue *sval) final override
304   {
305     logger * const logger = get_logger ();
306     LOG_FUNC (logger);
307     state_machine::state_t current
308       = m_old_smap->get_state (sval, m_eg.get_ext_state ());
309     return current;
310   }
311
312
313   void set_next_state (const gimple *,
314                        tree var,
315                        state_machine::state_t to,
316                        tree origin) final override
317   {
318     logger * const logger = get_logger ();
319     LOG_FUNC (logger);
320     const svalue *var_new_sval
321       = m_new_state->m_region_model->get_rvalue (var, NULL);
322     const svalue *origin_new_sval
323       = m_new_state->m_region_model->get_rvalue (origin, NULL);
324
325     /* We use the new sval here to avoid issues with uninitialized values.  */
326     state_machine::state_t current
327       = m_old_smap->get_state (var_new_sval, m_eg.get_ext_state ());
328     if (logger)
329       logger->log ("%s: state transition of %qE: %s -> %s",
330                    m_sm.get_name (),
331                    var,
332                    current->get_name (),
333                    to->get_name ());
334     m_new_smap->set_state (m_new_state->m_region_model, var_new_sval,
335                            to, origin_new_sval, m_eg.get_ext_state ());
336   }
337
338   void set_next_state (const gimple *stmt,
339                        const svalue *sval,
340                        state_machine::state_t to,
341                        tree origin) final override
342   {
343     logger * const logger = get_logger ();
344     LOG_FUNC (logger);
345     impl_region_model_context old_ctxt
346       (m_eg, m_enode_for_diag, NULL, NULL, NULL/*m_enode->get_state ()*/,
347        NULL, stmt);
348
349     const svalue *origin_new_sval
350       = m_new_state->m_region_model->get_rvalue (origin, NULL);
351
352     state_machine::state_t current
353       = m_old_smap->get_state (sval, m_eg.get_ext_state ());
354     if (logger)
355       {
356         logger->start_log_line ();
357         logger->log_partial ("%s: state transition of ",
358                              m_sm.get_name ());
359         sval->dump_to_pp (logger->get_printer (), true);
360         logger->log_partial (": %s -> %s",
361                              current->get_name (),
362                              to->get_name ());
363         logger->end_log_line ();
364       }
365     m_new_smap->set_state (m_new_state->m_region_model, sval,
366                            to, origin_new_sval, m_eg.get_ext_state ());
367   }
368
369   void warn (const supernode *snode, const gimple *stmt,
370              tree var,
371              std::unique_ptr<pending_diagnostic> d) final override
372   {
373     LOG_FUNC (get_logger ());
374     gcc_assert (d);
375     const svalue *var_old_sval
376       = m_old_state->m_region_model->get_rvalue (var, NULL);
377     state_machine::state_t current
378       = (var
379          ? m_old_smap->get_state (var_old_sval, m_eg.get_ext_state ())
380          : m_old_smap->get_global_state ());
381     m_eg.get_diagnostic_manager ().add_diagnostic
382       (&m_sm, m_enode_for_diag, snode, stmt, m_stmt_finder,
383        var, var_old_sval, current, std::move (d));
384   }
385
386   void warn (const supernode *snode, const gimple *stmt,
387              const svalue *sval,
388              std::unique_ptr<pending_diagnostic> d) final override
389   {
390     LOG_FUNC (get_logger ());
391     gcc_assert (d);
392     state_machine::state_t current
393       = (sval
394          ? m_old_smap->get_state (sval, m_eg.get_ext_state ())
395          : m_old_smap->get_global_state ());
396     m_eg.get_diagnostic_manager ().add_diagnostic
397       (&m_sm, m_enode_for_diag, snode, stmt, m_stmt_finder,
398        NULL_TREE, sval, current, std::move (d));
399   }
400
401   /* Hook for picking more readable trees for SSA names of temporaries,
402      so that rather than e.g.
403        "double-free of '<unknown>'"
404      we can print:
405        "double-free of 'inbuf.data'".  */
406
407   tree get_diagnostic_tree (tree expr) final override
408   {
409     /* Only for SSA_NAMEs of temporaries; otherwise, return EXPR, as it's
410        likely to be the least surprising tree to report.  */
411     if (TREE_CODE (expr) != SSA_NAME)
412       return expr;
413     if (SSA_NAME_VAR (expr) != NULL)
414       return expr;
415
416     gcc_assert (m_new_state);
417     const svalue *sval = m_new_state->m_region_model->get_rvalue (expr, NULL);
418     /* Find trees for all regions storing the value.  */
419     if (tree t = m_new_state->m_region_model->get_representative_tree (sval))
420       return t;
421     else
422       return expr;
423   }
424
425   tree get_diagnostic_tree (const svalue *sval) final override
426   {
427     return m_new_state->m_region_model->get_representative_tree (sval);
428   }
429
430   state_machine::state_t get_global_state () const final override
431   {
432     return m_old_state->m_checker_states[m_sm_idx]->get_global_state ();
433   }
434
435   void set_global_state (state_machine::state_t state) final override
436   {
437     m_new_state->m_checker_states[m_sm_idx]->set_global_state (state);
438   }
439
440   void on_custom_transition (custom_transition *transition) final override
441   {
442     transition->impl_transition (&m_eg,
443                                  const_cast<exploded_node *> (m_enode_for_diag),
444                                  m_sm_idx);
445   }
446
447   tree is_zero_assignment (const gimple *stmt) final override
448   {
449     const gassign *assign_stmt = dyn_cast <const gassign *> (stmt);
450     if (!assign_stmt)
451      return NULL_TREE;
452     impl_region_model_context old_ctxt
453       (m_eg, m_enode_for_diag, m_old_state, m_new_state, NULL, NULL, stmt);
454     if (const svalue *sval
455         = m_new_state->m_region_model->get_gassign_result (assign_stmt,
456                                                             &old_ctxt))
457       if (tree cst = sval->maybe_get_constant ())
458         if (::zerop(cst))
459           return gimple_assign_lhs (assign_stmt);
460     return NULL_TREE;
461   }
462
463   path_context *get_path_context () const final override
464   {
465     return m_path_ctxt;
466   }
467
468   bool unknown_side_effects_p () const final override
469   {
470     return m_unknown_side_effects;
471   }
472
473   const program_state *get_old_program_state () const final override
474   {
475     return m_old_state;
476   }
477
478   const program_state *get_new_program_state () const final override
479   {
480     return m_new_state;
481   }
482
483   log_user m_logger;
484   exploded_graph &m_eg;
485   exploded_node *m_enode_for_diag;
486   const program_state *m_old_state;
487   program_state *m_new_state;
488   const sm_state_map *m_old_smap;
489   sm_state_map *m_new_smap;
490   path_context *m_path_ctxt;
491   const stmt_finder *m_stmt_finder;
492
493   /* Are we handling an external function with unknown side effects?  */
494   bool m_unknown_side_effects;
495 };
496
497 bool
498 impl_region_model_context::
499 get_state_map_by_name (const char *name,
500                        sm_state_map **out_smap,
501                        const state_machine **out_sm,
502                        unsigned *out_sm_idx,
503                        std::unique_ptr<sm_context> *out_sm_context)
504 {
505   if (!m_new_state)
506     return false;
507
508   unsigned sm_idx;
509   if (!m_ext_state.get_sm_idx_by_name (name, &sm_idx))
510     return false;
511
512   const state_machine *sm = &m_ext_state.get_sm (sm_idx);
513   sm_state_map *new_smap = m_new_state->m_checker_states[sm_idx];
514
515   *out_smap = new_smap;
516   *out_sm = sm;
517   if (out_sm_idx)
518     *out_sm_idx = sm_idx;
519   if (out_sm_context)
520     {
521       const sm_state_map *old_smap = m_old_state->m_checker_states[sm_idx];
522       *out_sm_context
523         = make_unique<impl_sm_context> (*m_eg,
524                                         sm_idx,
525                                         *sm,
526                                         m_enode_for_diag,
527                                         m_old_state,
528                                         m_new_state,
529                                         old_smap,
530                                         new_smap,
531                                         m_path_ctxt,
532                                         m_stmt_finder,
533                                         false);
534     }
535   return true;
536 }
537
538 /* Subclass of stmt_finder for finding the best stmt to report the leak at,
539    given the emission path.  */
540
541 class leak_stmt_finder : public stmt_finder
542 {
543 public:
544   leak_stmt_finder (const exploded_graph &eg, tree var)
545   : m_eg (eg), m_var (var) {}
546
547   std::unique_ptr<stmt_finder> clone () const final override
548   {
549     return make_unique<leak_stmt_finder> (m_eg, m_var);
550   }
551
552   const gimple *find_stmt (const exploded_path &epath)
553     final override
554   {
555     logger * const logger = m_eg.get_logger ();
556     LOG_FUNC (logger);
557
558     if (m_var && TREE_CODE (m_var) == SSA_NAME)
559       {
560         /* Locate the final write to this SSA name in the path.  */
561         const gimple *def_stmt = SSA_NAME_DEF_STMT (m_var);
562
563         int idx_of_def_stmt;
564         bool found = epath.find_stmt_backwards (def_stmt, &idx_of_def_stmt);
565         if (!found)
566           goto not_found;
567
568         /* What was the next write to the underlying var
569            after the SSA name was set? (if any).  */
570
571         for (unsigned idx = idx_of_def_stmt + 1;
572              idx < epath.m_edges.length ();
573              ++idx)
574           {
575             const exploded_edge *eedge = epath.m_edges[idx];
576             if (logger)
577               logger->log ("eedge[%i]: EN %i -> EN %i",
578                            idx,
579                            eedge->m_src->m_index,
580                            eedge->m_dest->m_index);
581             const exploded_node *dst_node = eedge->m_dest;
582             const program_point &dst_point = dst_node->get_point ();
583             const gimple *stmt = dst_point.get_stmt ();
584             if (!stmt)
585               continue;
586             if (const gassign *assign = dyn_cast <const gassign *> (stmt))
587               {
588                 tree lhs = gimple_assign_lhs (assign);
589                 if (TREE_CODE (lhs) == SSA_NAME
590                     && SSA_NAME_VAR (lhs) == SSA_NAME_VAR (m_var))
591                   return assign;
592               }
593           }
594       }
595
596   not_found:
597
598     /* Look backwards for the first statement with a location.  */
599     int i;
600     const exploded_edge *eedge;
601     FOR_EACH_VEC_ELT_REVERSE (epath.m_edges, i, eedge)
602       {
603         if (logger)
604           logger->log ("eedge[%i]: EN %i -> EN %i",
605                        i,
606                        eedge->m_src->m_index,
607                        eedge->m_dest->m_index);
608         const exploded_node *dst_node = eedge->m_dest;
609         const program_point &dst_point = dst_node->get_point ();
610         const gimple *stmt = dst_point.get_stmt ();
611         if (stmt)
612           if (get_pure_location (stmt->location) != UNKNOWN_LOCATION)
613             return stmt;
614       }
615
616     gcc_unreachable ();
617     return NULL;
618   }
619
620 private:
621   const exploded_graph &m_eg;
622   tree m_var;
623 };
624
625 /* A measurement of how good EXPR is for presenting to the user, so
626    that e.g. we can say prefer printing
627      "leak of 'tmp.m_ptr'"
628    over:
629      "leak of '<unknown>'".  */
630
631 static int
632 readability (const_tree expr)
633 {
634   /* Arbitrarily-chosen "high readability" value.  */
635   const int HIGH_READABILITY = 65536;
636
637   gcc_assert (expr);
638   switch (TREE_CODE (expr))
639     {
640     case COMPONENT_REF:
641     case MEM_REF:
642       /* Impose a slight readability penalty relative to that of
643          operand 0.  */
644       return readability (TREE_OPERAND (expr, 0)) - 16;
645
646     case SSA_NAME:
647       {
648         if (tree var = SSA_NAME_VAR (expr))
649           {
650             if (DECL_ARTIFICIAL (var))
651               {
652                 /* If we have an SSA name for an artificial var,
653                    only use it if it has a debug expr associated with
654                    it that fixup_tree_for_diagnostic can use.  */
655                 if (VAR_P (var) && DECL_HAS_DEBUG_EXPR_P (var))
656                   return readability (DECL_DEBUG_EXPR (var)) - 1;
657               }
658             else
659               {
660                 /* Slightly favor the underlying var over the SSA name to
661                    avoid having them compare equal.  */
662                 return readability (var) - 1;
663               }
664           }
665         /* Avoid printing '<unknown>' for SSA names for temporaries.  */
666         return -1;
667       }
668       break;
669
670     case PARM_DECL:
671     case VAR_DECL:
672       if (DECL_NAME (expr))
673         return HIGH_READABILITY;
674       else
675         /* We don't want to print temporaries.  For example, the C FE
676            prints them as e.g. "<Uxxxx>" where "xxxx" is the low 16 bits
677            of the tree pointer (see pp_c_tree_decl_identifier).  */
678         return -1;
679
680     case RESULT_DECL:
681       /* Printing "<return-value>" isn't ideal, but is less awful than
682          trying to print a temporary.  */
683       return HIGH_READABILITY / 2;
684
685     case NOP_EXPR:
686       {
687         /* Impose a moderate readability penalty for casts.  */
688         const int CAST_PENALTY = 32;
689         return readability (TREE_OPERAND (expr, 0)) - CAST_PENALTY;
690       }
691
692     case INTEGER_CST:
693       return HIGH_READABILITY;
694
695     default:
696       return 0;
697     }
698
699   return 0;
700 }
701
702 /* A qsort comparator for trees to sort them into most user-readable to
703    least user-readable.  */
704
705 int
706 readability_comparator (const void *p1, const void *p2)
707 {
708   path_var pv1 = *(path_var const *)p1;
709   path_var pv2 = *(path_var const *)p2;
710
711   const int tree_r1 = readability (pv1.m_tree);
712   const int tree_r2 = readability (pv2.m_tree);
713
714   /* Favor items that are deeper on the stack and hence more recent;
715      this also favors locals over globals.  */
716   const int COST_PER_FRAME = 64;
717   const int depth_r1 = pv1.m_stack_depth * COST_PER_FRAME;
718   const int depth_r2 = pv2.m_stack_depth * COST_PER_FRAME;
719
720   /* Combine the scores from the tree and from the stack depth.
721      This e.g. lets us have a slightly penalized cast in the most
722      recent stack frame "beat" an uncast value in an older stack frame.  */
723   const int sum_r1 = tree_r1 + depth_r1;
724   const int sum_r2 = tree_r2 + depth_r2;
725   if (int cmp = sum_r2 - sum_r1)
726     return cmp;
727
728   /* Otherwise, more readable trees win.  */
729   if (int cmp = tree_r2 - tree_r1)
730     return cmp;
731
732   /* Otherwise, if they have the same readability, then impose an
733      arbitrary deterministic ordering on them.  */
734
735   if (int cmp = TREE_CODE (pv1.m_tree) - TREE_CODE (pv2.m_tree))
736     return cmp;
737
738   switch (TREE_CODE (pv1.m_tree))
739     {
740     default:
741       break;
742     case SSA_NAME:
743       if (int cmp = (SSA_NAME_VERSION (pv1.m_tree)
744                      - SSA_NAME_VERSION (pv2.m_tree)))
745         return cmp;
746       break;
747     case PARM_DECL:
748     case VAR_DECL:
749     case RESULT_DECL:
750       if (int cmp = DECL_UID (pv1.m_tree) - DECL_UID (pv2.m_tree))
751         return cmp;
752       break;
753     }
754
755   /* TODO: We ought to find ways of sorting such cases.  */
756   return 0;
757 }
758
759 /* Return true is SNODE is the EXIT node of a function, or is one
760    of the final snodes within its function.
761
762    Specifically, handle the final supernodes before the EXIT node,
763    for the case of clobbers that happen immediately before exiting.
764    We need a run of snodes leading to the return_p snode, where all edges are
765    intraprocedural, and every snode has just one successor.
766
767    We use this when suppressing leak reports at the end of "main".  */
768
769 static bool
770 returning_from_function_p (const supernode *snode)
771 {
772   if (!snode)
773     return false;
774
775   unsigned count = 0;
776   const supernode *iter = snode;
777   while (true)
778     {
779       if (iter->return_p ())
780         return true;
781       if (iter->m_succs.length () != 1)
782         return false;
783       const superedge *sedge = iter->m_succs[0];
784       if (sedge->get_kind () != SUPEREDGE_CFG_EDGE)
785         return false;
786       iter = sedge->m_dest;
787
788       /* Impose a limit to ensure we terminate for pathological cases.
789
790          We only care about the final 3 nodes, due to cases like:
791            BB:
792              (clobber causing leak)
793
794            BB:
795            <label>:
796            return _val;
797
798            EXIT BB.*/
799       if (++count > 3)
800         return false;
801     }
802 }
803
804 /* Find the best tree for SVAL and call SM's on_leak vfunc with it.
805    If on_leak returns a pending_diagnostic, queue it up to be reported,
806    so that we potentially complain about a leak of SVAL in the given STATE.  */
807
808 void
809 impl_region_model_context::on_state_leak (const state_machine &sm,
810                                           const svalue *sval,
811                                           state_machine::state_t state)
812 {
813   logger * const logger = get_logger ();
814   LOG_SCOPE (logger);
815   if (logger)
816     {
817       logger->start_log_line ();
818       logger->log_partial ("considering leak of ");
819       sval->dump_to_pp (logger->get_printer (), true);
820       logger->end_log_line ();
821     }
822
823   if (!m_eg)
824     return;
825
826   /* m_old_state also needs to be non-NULL so that the sm_ctxt can look
827      up the old state of SVAL.  */
828   gcc_assert (m_old_state);
829
830   /* SVAL has leaked within the new state: it is not used by any reachable
831      regions.
832      We need to convert it back to a tree, but since it's likely no regions
833      use it, we have to find the "best" tree for it in the old_state.  */
834   svalue_set visited;
835   path_var leaked_pv
836     = m_old_state->m_region_model->get_representative_path_var (sval,
837                                                                 &visited);
838
839   /* Strip off top-level casts  */
840   if (leaked_pv.m_tree && TREE_CODE (leaked_pv.m_tree) == NOP_EXPR)
841     leaked_pv.m_tree = TREE_OPERAND (leaked_pv.m_tree, 0);
842
843   /* This might be NULL; the pending_diagnostic subclasses need to cope
844      with this.  */
845   tree leaked_tree = leaked_pv.m_tree;
846   if (logger)
847     {
848       if (leaked_tree)
849         logger->log ("best leaked_tree: %qE", leaked_tree);
850       else
851         logger->log ("best leaked_tree: NULL");
852     }
853
854   leak_stmt_finder stmt_finder (*m_eg, leaked_tree);
855   gcc_assert (m_enode_for_diag);
856
857   /* Don't complain about leaks when returning from "main".  */
858   if (returning_from_function_p (m_enode_for_diag->get_supernode ()))
859     {
860       tree fndecl = m_enode_for_diag->get_function ()->decl;
861       if (id_equal (DECL_NAME (fndecl), "main"))
862         {
863           if (logger)
864             logger->log ("not reporting leak from main");
865           return;
866         }
867     }
868
869   tree leaked_tree_for_diag = fixup_tree_for_diagnostic (leaked_tree);
870   std::unique_ptr<pending_diagnostic> pd = sm.on_leak (leaked_tree_for_diag);
871   if (pd)
872     m_eg->get_diagnostic_manager ().add_diagnostic
873       (&sm, m_enode_for_diag, m_enode_for_diag->get_supernode (),
874        m_stmt, &stmt_finder,
875        leaked_tree_for_diag, sval, state, std::move (pd));
876 }
877
878 /* Implementation of region_model_context::on_condition vfunc.
879    Notify all state machines about the condition, which could lead to
880    state transitions.  */
881
882 void
883 impl_region_model_context::on_condition (const svalue *lhs,
884                                          enum tree_code op,
885                                          const svalue *rhs)
886 {
887   int sm_idx;
888   sm_state_map *smap;
889   FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
890     {
891       const state_machine &sm = m_ext_state.get_sm (sm_idx);
892       impl_sm_context sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
893                                m_old_state, m_new_state,
894                                m_old_state->m_checker_states[sm_idx],
895                                m_new_state->m_checker_states[sm_idx],
896                                m_path_ctxt);
897       sm.on_condition (&sm_ctxt,
898                        (m_enode_for_diag
899                         ? m_enode_for_diag->get_supernode ()
900                         : NULL),
901                        m_stmt,
902                        lhs, op, rhs);
903     }
904 }
905
906 /* Implementation of region_model_context::on_bounded_ranges vfunc.
907    Notify all state machines about the ranges, which could lead to
908    state transitions.  */
909
910 void
911 impl_region_model_context::on_bounded_ranges (const svalue &sval,
912                                               const bounded_ranges &ranges)
913 {
914   int sm_idx;
915   sm_state_map *smap;
916   FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
917     {
918       const state_machine &sm = m_ext_state.get_sm (sm_idx);
919       impl_sm_context sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
920                                m_old_state, m_new_state,
921                                m_old_state->m_checker_states[sm_idx],
922                                m_new_state->m_checker_states[sm_idx],
923                                m_path_ctxt);
924       sm.on_bounded_ranges (&sm_ctxt,
925                             (m_enode_for_diag
926                              ? m_enode_for_diag->get_supernode ()
927                              : NULL),
928                             m_stmt, sval, ranges);
929     }
930 }
931
932 /* Implementation of region_model_context::on_pop_frame vfunc.
933    Notify all state machines about the frame being popped, which
934    could lead to states being discarded.  */
935
936 void
937 impl_region_model_context::on_pop_frame (const frame_region *frame_reg)
938 {
939   int sm_idx;
940   sm_state_map *smap;
941   FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
942     {
943       const state_machine &sm = m_ext_state.get_sm (sm_idx);
944       sm.on_pop_frame (smap, frame_reg);
945     }
946 }
947
948 /* Implementation of region_model_context::on_phi vfunc.
949    Notify all state machines about the phi, which could lead to
950    state transitions.  */
951
952 void
953 impl_region_model_context::on_phi (const gphi *phi, tree rhs)
954 {
955   int sm_idx;
956   sm_state_map *smap;
957   FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
958     {
959       const state_machine &sm = m_ext_state.get_sm (sm_idx);
960       impl_sm_context sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
961                                m_old_state, m_new_state,
962                                m_old_state->m_checker_states[sm_idx],
963                                m_new_state->m_checker_states[sm_idx],
964                                m_path_ctxt);
965       sm.on_phi (&sm_ctxt, m_enode_for_diag->get_supernode (), phi, rhs);
966     }
967 }
968
969 /* Implementation of region_model_context::on_unexpected_tree_code vfunc.
970    Mark the new state as being invalid for further exploration.
971    TODO(stage1): introduce a warning for when this occurs.  */
972
973 void
974 impl_region_model_context::on_unexpected_tree_code (tree t,
975                                                     const dump_location_t &loc)
976 {
977   logger * const logger = get_logger ();
978   if (logger)
979     logger->log ("unhandled tree code: %qs in %qs at %s:%i",
980                  get_tree_code_name (TREE_CODE (t)),
981                  loc.get_impl_location ().m_function,
982                  loc.get_impl_location ().m_file,
983                  loc.get_impl_location ().m_line);
984   if (m_new_state)
985     m_new_state->m_valid = false;
986 }
987
988 /* struct point_and_state.  */
989
990 /* Assert that this object is sane.  */
991
992 void
993 point_and_state::validate (const extrinsic_state &ext_state) const
994 {
995   /* Skip this in a release build.  */
996 #if !CHECKING_P
997   return;
998 #endif
999
1000   m_point.validate ();
1001
1002   m_state.validate (ext_state);
1003
1004   /* Verify that the callstring's model of the stack corresponds to that
1005      of the region_model.  */
1006   /* They should have the same depth.  */
1007   gcc_assert (m_point.get_stack_depth ()
1008               == m_state.m_region_model->get_stack_depth ());
1009   /* Check the functions in the callstring vs those in the frames
1010      at each depth.  */
1011   for (const frame_region *iter_frame
1012          = m_state.m_region_model->get_current_frame ();
1013        iter_frame; iter_frame = iter_frame->get_calling_frame ())
1014     {
1015       int index = iter_frame->get_index ();
1016       gcc_assert (m_point.get_function_at_depth (index)
1017                   == iter_frame->get_function ());
1018     }
1019 }
1020
1021 /* Subroutine of print_enode_indices: print a run of indices from START_IDX
1022    to END_IDX to PP, using and updating *FIRST_RUN.  */
1023
1024 static void
1025 print_run (pretty_printer *pp, int start_idx, int end_idx,
1026            bool *first_run)
1027 {
1028   if (!(*first_run))
1029     pp_string (pp, ", ");
1030   *first_run = false;
1031   if (start_idx == end_idx)
1032     pp_printf (pp, "EN: %i", start_idx);
1033   else
1034     pp_printf (pp, "EN: %i-%i", start_idx, end_idx);
1035 }
1036
1037 /* Print the indices within ENODES to PP, collecting them as
1038    runs/singletons e.g. "EN: 4-7, EN: 20-23, EN: 42".  */
1039
1040 static void
1041 print_enode_indices (pretty_printer *pp,
1042                      const auto_vec<exploded_node *> &enodes)
1043 {
1044   int cur_start_idx = -1;
1045   int cur_finish_idx = -1;
1046   bool first_run = true;
1047   unsigned i;
1048   exploded_node *enode;
1049   FOR_EACH_VEC_ELT (enodes, i, enode)
1050     {
1051       if (cur_start_idx == -1)
1052         {
1053           gcc_assert (cur_finish_idx == -1);
1054           cur_start_idx = cur_finish_idx = enode->m_index;
1055         }
1056       else
1057         {
1058           if (enode->m_index == cur_finish_idx + 1)
1059             /* Continuation of a run.  */
1060             cur_finish_idx = enode->m_index;
1061           else
1062             {
1063               /* Finish existing run, start a new one.  */
1064               gcc_assert (cur_start_idx >= 0);
1065               gcc_assert (cur_finish_idx >= 0);
1066               print_run (pp, cur_start_idx, cur_finish_idx,
1067                          &first_run);
1068               cur_start_idx = cur_finish_idx = enode->m_index;
1069             }
1070         }
1071     }
1072   /* Finish any existing run.  */
1073   if (cur_start_idx >= 0)
1074     {
1075       gcc_assert (cur_finish_idx >= 0);
1076       print_run (pp, cur_start_idx, cur_finish_idx,
1077                  &first_run);
1078     }
1079 }
1080
1081 /* struct eg_traits::dump_args_t.  */
1082
1083 /* The <FILENAME>.eg.dot output can quickly become unwieldy if we show
1084    full details for all enodes (both in terms of CPU time to render it,
1085    and in terms of being meaningful to a human viewing it).
1086
1087    If we show just the IDs then the resulting graph is usually viewable,
1088    but then we have to keep switching back and forth between the .dot
1089    view and other dumps.
1090
1091    This function implements a heuristic for showing detail at the enodes
1092    that (we hope) matter, and just the ID at other enodes, fixing the CPU
1093    usage of the .dot viewer, and drawing the attention of the viewer
1094    to these enodes.
1095
1096    Return true if ENODE should be shown in detail in .dot output.
1097    Return false if no detail should be shown for ENODE.  */
1098
1099 bool
1100 eg_traits::dump_args_t::show_enode_details_p (const exploded_node &enode) const
1101 {
1102   /* If the number of exploded nodes isn't too large, we may as well show
1103      all enodes in full detail in the .dot output.  */
1104   if (m_eg.m_nodes.length ()
1105         <= (unsigned) param_analyzer_max_enodes_for_full_dump)
1106     return true;
1107
1108   /* Otherwise, assume that what's most interesting are state explosions,
1109      and thus the places where this happened.
1110      Expand enodes at program points where we hit the per-enode limit, so we
1111      can investigate what exploded.  */
1112   const per_program_point_data *per_point_data
1113     = m_eg.get_per_program_point_data (enode.get_point ());
1114   return per_point_data->m_excess_enodes > 0;
1115 }
1116
1117 /* class exploded_node : public dnode<eg_traits>.  */
1118
1119 const char *
1120 exploded_node::status_to_str (enum status s)
1121 {
1122   switch (s)
1123     {
1124     default: gcc_unreachable ();
1125     case STATUS_WORKLIST: return "WORKLIST";
1126     case STATUS_PROCESSED: return "PROCESSED";
1127     case STATUS_MERGER: return "MERGER";
1128     case STATUS_BULK_MERGED: return "BULK_MERGED";
1129     }
1130 }
1131
1132 /* exploded_node's ctor.  */
1133
1134 exploded_node::exploded_node (const point_and_state &ps,
1135                               int index)
1136 : m_ps (ps), m_status (STATUS_WORKLIST), m_index (index),
1137   m_num_processed_stmts (0)
1138 {
1139   gcc_checking_assert (ps.get_state ().m_region_model->canonicalized_p ());
1140 }
1141
1142 /* Get the stmt that was processed in this enode at index IDX.
1143    IDX is an index within the stmts processed at this enode, rather
1144    than within those of the supernode.  */
1145
1146 const gimple *
1147 exploded_node::get_processed_stmt (unsigned idx) const
1148 {
1149   gcc_assert (idx < m_num_processed_stmts);
1150   const program_point &point = get_point ();
1151   gcc_assert (point.get_kind () == PK_BEFORE_STMT);
1152   const supernode *snode = get_supernode ();
1153   const unsigned int point_stmt_idx = point.get_stmt_idx ();
1154   const unsigned int idx_within_snode = point_stmt_idx + idx;
1155   const gimple *stmt = snode->m_stmts[idx_within_snode];
1156   return stmt;
1157 }
1158
1159 /* For use by dump_dot, get a value for the .dot "fillcolor" attribute.
1160    Colorize by sm-state, to make it easier to see how sm-state propagates
1161    through the exploded_graph.  */
1162
1163 const char *
1164 exploded_node::get_dot_fillcolor () const
1165 {
1166   const program_state &state = get_state ();
1167
1168   /* We want to be able to easily distinguish the no-sm-state case,
1169      and to be able to distinguish cases where there's a single state
1170      from each other.
1171
1172      Sum the sm_states, and use the result to choose from a table,
1173      modulo table-size, special-casing the "no sm-state" case.   */
1174   int total_sm_state = 0;
1175   int i;
1176   sm_state_map *smap;
1177   FOR_EACH_VEC_ELT (state.m_checker_states, i, smap)
1178     {
1179       for (sm_state_map::iterator_t iter = smap->begin ();
1180            iter != smap->end ();
1181            ++iter)
1182         total_sm_state += (*iter).second.m_state->get_id ();
1183       total_sm_state += smap->get_global_state ()->get_id ();
1184     }
1185
1186   if (total_sm_state > 0)
1187     {
1188       /* An arbitrarily-picked collection of light colors.  */
1189       const char * const colors[]
1190         = {"azure", "coral", "cornsilk", "lightblue", "yellow",
1191            "honeydew", "lightpink", "lightsalmon", "palegreen1",
1192            "wheat", "seashell"};
1193       const int num_colors = ARRAY_SIZE (colors);
1194       return colors[total_sm_state % num_colors];
1195     }
1196   else
1197     /* No sm-state.   */
1198     return "lightgrey";
1199 }
1200
1201 /* Implementation of dnode::dump_dot vfunc for exploded_node.  */
1202
1203 void
1204 exploded_node::dump_dot (graphviz_out *gv, const dump_args_t &args) const
1205 {
1206   pretty_printer *pp = gv->get_pp ();
1207
1208   dump_dot_id (pp);
1209   pp_printf (pp, " [shape=none,margin=0,style=filled,fillcolor=%s,label=\"",
1210              get_dot_fillcolor ());
1211   pp_write_text_to_stream (pp);
1212
1213   pp_printf (pp, "EN: %i", m_index);
1214   if (m_status == STATUS_MERGER)
1215     pp_string (pp, " (merger)");
1216   else if (m_status == STATUS_BULK_MERGED)
1217     pp_string (pp, " (bulk merged)");
1218   pp_newline (pp);
1219
1220   if (args.show_enode_details_p (*this))
1221     {
1222       format f (true);
1223       m_ps.get_point ().print (pp, f);
1224       pp_newline (pp);
1225
1226       const extrinsic_state &ext_state = args.m_eg.get_ext_state ();
1227       const program_state &state = m_ps.get_state ();
1228       state.dump_to_pp (ext_state, false, true, pp);
1229       pp_newline (pp);
1230
1231       dump_processed_stmts (pp);
1232     }
1233
1234   dump_saved_diagnostics (pp);
1235
1236   args.dump_extra_info (this, pp);
1237
1238   pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
1239
1240   pp_string (pp, "\"];\n\n");
1241
1242   /* It can be hard to locate the saved diagnostics as text within the
1243      enode nodes, so add extra nodes to the graph for each saved_diagnostic,
1244      highlighted in red.
1245      Compare with dump_saved_diagnostics.  */
1246   {
1247     unsigned i;
1248     const saved_diagnostic *sd;
1249     FOR_EACH_VEC_ELT (m_saved_diagnostics, i, sd)
1250       {
1251         sd->dump_as_dot_node (pp);
1252
1253         /* Add edge connecting this enode to the saved_diagnostic.  */
1254         dump_dot_id (pp);
1255         pp_string (pp, " -> ");
1256         sd->dump_dot_id (pp);
1257         pp_string (pp, " [style=\"dotted\" arrowhead=\"none\"];");
1258         pp_newline (pp);
1259       }
1260   }
1261
1262   pp_flush (pp);
1263 }
1264
1265 /* Show any stmts that were processed within this enode,
1266    and their index within the supernode.  */
1267 void
1268 exploded_node::dump_processed_stmts (pretty_printer *pp) const
1269 {
1270   if (m_num_processed_stmts > 0)
1271     {
1272       const program_point &point = get_point ();
1273       gcc_assert (point.get_kind () == PK_BEFORE_STMT);
1274       const supernode *snode = get_supernode ();
1275       const unsigned int point_stmt_idx = point.get_stmt_idx ();
1276
1277       pp_printf (pp, "stmts: %i", m_num_processed_stmts);
1278       pp_newline (pp);
1279       for (unsigned i = 0; i < m_num_processed_stmts; i++)
1280         {
1281           const unsigned int idx_within_snode = point_stmt_idx + i;
1282           const gimple *stmt = snode->m_stmts[idx_within_snode];
1283           pp_printf (pp, "  %i: ", idx_within_snode);
1284           pp_gimple_stmt_1 (pp, stmt, 0, (dump_flags_t)0);
1285           pp_newline (pp);
1286         }
1287     }
1288 }
1289
1290 /* Dump any saved_diagnostics at this enode to PP.  */
1291
1292 void
1293 exploded_node::dump_saved_diagnostics (pretty_printer *pp) const
1294 {
1295   unsigned i;
1296   const saved_diagnostic *sd;
1297   FOR_EACH_VEC_ELT (m_saved_diagnostics, i, sd)
1298     {
1299       pp_printf (pp, "DIAGNOSTIC: %s (sd: %i)",
1300                  sd->m_d->get_kind (), sd->get_index ());
1301       pp_newline (pp);
1302     }
1303 }
1304
1305 /* Dump this to PP in a form suitable for use as an id in .dot output.  */
1306
1307 void
1308 exploded_node::dump_dot_id (pretty_printer *pp) const
1309 {
1310   pp_printf (pp, "exploded_node_%i", m_index);
1311 }
1312
1313 /* Dump a multiline representation of this node to PP.  */
1314
1315 void
1316 exploded_node::dump_to_pp (pretty_printer *pp,
1317                            const extrinsic_state &ext_state) const
1318 {
1319   pp_printf (pp, "EN: %i", m_index);
1320   pp_newline (pp);
1321
1322   format f (true);
1323   m_ps.get_point ().print (pp, f);
1324   pp_newline (pp);
1325
1326   m_ps.get_state ().dump_to_pp (ext_state, false, true, pp);
1327   pp_newline (pp);
1328 }
1329
1330 /* Dump a multiline representation of this node to FILE.  */
1331
1332 void
1333 exploded_node::dump (FILE *fp,
1334                      const extrinsic_state &ext_state) const
1335 {
1336   pretty_printer pp;
1337   pp_format_decoder (&pp) = default_tree_printer;
1338   pp_show_color (&pp) = pp_show_color (global_dc->printer);
1339   pp.buffer->stream = fp;
1340   dump_to_pp (&pp, ext_state);
1341   pp_flush (&pp);
1342 }
1343
1344 /* Dump a multiline representation of this node to stderr.  */
1345
1346 DEBUG_FUNCTION void
1347 exploded_node::dump (const extrinsic_state &ext_state) const
1348 {
1349   dump (stderr, ext_state);
1350 }
1351
1352 /* Return a new json::object of the form
1353    {"point"  : object for program_point,
1354     "state"  : object for program_state,
1355     "status" : str,
1356     "idx"    : int,
1357     "processed_stmts" : int}.  */
1358
1359 json::object *
1360 exploded_node::to_json (const extrinsic_state &ext_state) const
1361 {
1362   json::object *enode_obj = new json::object ();
1363
1364   enode_obj->set ("point", get_point ().to_json ());
1365   enode_obj->set ("state", get_state ().to_json (ext_state));
1366   enode_obj->set ("status", new json::string (status_to_str (m_status)));
1367   enode_obj->set ("idx", new json::integer_number (m_index));
1368   enode_obj->set ("processed_stmts",
1369                   new json::integer_number (m_num_processed_stmts));
1370
1371   return enode_obj;
1372 }
1373
1374 } // namespace ana
1375
1376 /* Return true if FNDECL has a gimple body.  */
1377 // TODO: is there a pre-canned way to do this?
1378
1379 bool
1380 fndecl_has_gimple_body_p (tree fndecl)
1381 {
1382   if (fndecl == NULL_TREE)
1383     return false;
1384
1385   cgraph_node *n = cgraph_node::get (fndecl);
1386   if (!n)
1387     return false;
1388
1389   return n->has_gimple_body_p ();
1390 }
1391
1392 namespace ana {
1393
1394 /* Modify STATE in place, applying the effects of the stmt at this node's
1395    point.  */
1396
1397 exploded_node::on_stmt_flags
1398 exploded_node::on_stmt (exploded_graph &eg,
1399                         const supernode *snode,
1400                         const gimple *stmt,
1401                         program_state *state,
1402                         uncertainty_t *uncertainty,
1403                         path_context *path_ctxt)
1404 {
1405   logger *logger = eg.get_logger ();
1406   LOG_SCOPE (logger);
1407   if (logger)
1408     {
1409       logger->start_log_line ();
1410       pp_gimple_stmt_1 (logger->get_printer (), stmt, 0, (dump_flags_t)0);
1411       logger->end_log_line ();
1412     }
1413
1414   /* Update input_location in case of ICE: make it easier to track down which
1415      source construct we're failing to handle.  */
1416   input_location = stmt->location;
1417
1418   gcc_assert (state->m_region_model);
1419
1420   /* Preserve the old state.  It is used here for looking
1421      up old checker states, for determining state transitions, and
1422      also within impl_region_model_context and impl_sm_context for
1423      going from tree to svalue_id.  */
1424   const program_state old_state (*state);
1425
1426   impl_region_model_context ctxt (eg, this,
1427                                   &old_state, state, uncertainty,
1428                                   path_ctxt, stmt);
1429
1430   /* Handle call summaries here.  */
1431   if (cgraph_edge *cgedge
1432           = supergraph_call_edge (snode->get_function (), stmt))
1433     if (eg.get_analysis_plan ().use_summary_p (cgedge))
1434       {
1435         function *called_fn = get_ultimate_function_for_cgraph_edge (cgedge);
1436         per_function_data *called_fn_data
1437           = eg.get_per_function_data (called_fn);
1438         if (called_fn_data)
1439           return replay_call_summaries (eg,
1440                                         snode,
1441                                         as_a <const gcall *> (stmt),
1442                                         state,
1443                                         path_ctxt,
1444                                         called_fn,
1445                                         called_fn_data,
1446                                         &ctxt);
1447       }
1448
1449   bool unknown_side_effects = false;
1450   bool terminate_path = false;
1451
1452   on_stmt_pre (eg, stmt, state, &terminate_path,
1453                &unknown_side_effects, &ctxt);
1454
1455   if (terminate_path)
1456     return on_stmt_flags::terminate_path ();
1457
1458   int sm_idx;
1459   sm_state_map *smap;
1460   FOR_EACH_VEC_ELT (old_state.m_checker_states, sm_idx, smap)
1461     {
1462       const state_machine &sm = eg.get_ext_state ().get_sm (sm_idx);
1463       const sm_state_map *old_smap
1464         = old_state.m_checker_states[sm_idx];
1465       sm_state_map *new_smap = state->m_checker_states[sm_idx];
1466       impl_sm_context sm_ctxt (eg, sm_idx, sm, this, &old_state, state,
1467                                old_smap, new_smap, path_ctxt, NULL,
1468                                unknown_side_effects);
1469
1470       /* Allow the state_machine to handle the stmt.  */
1471       if (sm.on_stmt (&sm_ctxt, snode, stmt))
1472         unknown_side_effects = false;
1473     }
1474
1475   if (path_ctxt->terminate_path_p ())
1476     return on_stmt_flags::terminate_path ();
1477
1478   on_stmt_post (stmt, state, unknown_side_effects, &ctxt);
1479
1480   return on_stmt_flags ();
1481 }
1482
1483 /* Handle the pre-sm-state part of STMT, modifying STATE in-place.
1484    Write true to *OUT_TERMINATE_PATH if the path should be terminated.
1485    Write true to *OUT_UNKNOWN_SIDE_EFFECTS if the stmt has unknown
1486    side effects.  */
1487
1488 void
1489 exploded_node::on_stmt_pre (exploded_graph &eg,
1490                             const gimple *stmt,
1491                             program_state *state,
1492                             bool *out_terminate_path,
1493                             bool *out_unknown_side_effects,
1494                             region_model_context *ctxt)
1495 {
1496   /* Handle special-case calls that require the full program_state.  */
1497   if (const gcall *call = dyn_cast <const gcall *> (stmt))
1498     {
1499       if (is_special_named_call_p (call, "__analyzer_dump", 0))
1500         {
1501           /* Handle the builtin "__analyzer_dump" by dumping state
1502              to stderr.  */
1503           state->dump (eg.get_ext_state (), true);
1504           return;
1505         }
1506       else if (is_special_named_call_p (call, "__analyzer_dump_state", 2))
1507         {
1508           state->impl_call_analyzer_dump_state (call, eg.get_ext_state (),
1509                                                 ctxt);
1510           return;
1511         }
1512       else if (is_setjmp_call_p (call))
1513         {
1514           state->m_region_model->on_setjmp (call, this, ctxt);
1515           return;
1516         }
1517       else if (is_longjmp_call_p (call))
1518         {
1519           on_longjmp (eg, call, state, ctxt);
1520           *out_terminate_path = true;
1521           return;
1522         }
1523     }
1524
1525   /* Otherwise, defer to m_region_model.  */
1526   state->m_region_model->on_stmt_pre (stmt,
1527                                       out_unknown_side_effects,
1528                                       ctxt);
1529 }
1530
1531 /* Handle the post-sm-state part of STMT, modifying STATE in-place.  */
1532
1533 void
1534 exploded_node::on_stmt_post (const gimple *stmt,
1535                              program_state *state,
1536                              bool unknown_side_effects,
1537                              region_model_context *ctxt)
1538 {
1539   if (const gcall *call = dyn_cast <const gcall *> (stmt))
1540     state->m_region_model->on_call_post (call, unknown_side_effects, ctxt);
1541 }
1542
1543 /* A concrete call_info subclass representing a replay of a call summary.  */
1544
1545 class call_summary_edge_info : public call_info
1546 {
1547 public:
1548   call_summary_edge_info (const call_details &cd,
1549                           function *called_fn,
1550                           call_summary *summary,
1551                           const extrinsic_state &ext_state)
1552   : call_info (cd),
1553     m_called_fn (called_fn),
1554     m_summary (summary),
1555     m_ext_state (ext_state)
1556   {}
1557
1558   bool update_state (program_state *state,
1559                      const exploded_edge *,
1560                      region_model_context *ctxt) const final override
1561   {
1562     /* Update STATE based on summary_end_state.  */
1563     call_details cd (get_call_details (state->m_region_model, ctxt));
1564     call_summary_replay r (cd, m_called_fn, m_summary, m_ext_state);
1565     const program_state &summary_end_state = m_summary->get_state ();
1566     return state->replay_call_summary (r, summary_end_state);
1567   }
1568
1569   bool update_model (region_model *model,
1570                      const exploded_edge *,
1571                      region_model_context *ctxt) const final override
1572   {
1573     /* Update STATE based on summary_end_state.  */
1574     call_details cd (get_call_details (model, ctxt));
1575     call_summary_replay r (cd, m_called_fn, m_summary, m_ext_state);
1576     const program_state &summary_end_state = m_summary->get_state ();
1577     model->replay_call_summary (r, *summary_end_state.m_region_model);
1578     return true;
1579   }
1580
1581   label_text get_desc (bool /*can_colorize*/) const final override
1582   {
1583     return m_summary->get_desc ();
1584   }
1585
1586 private:
1587   function *m_called_fn;
1588   call_summary *m_summary;
1589   const extrinsic_state &m_ext_state;
1590 };
1591
1592 /* Use PATH_CTXT to bifurcate, which when handled will add custom edges
1593    for a replay of the various feasible summaries in CALLED_FN_DATA.  */
1594
1595 exploded_node::on_stmt_flags
1596 exploded_node::replay_call_summaries (exploded_graph &eg,
1597                                       const supernode *snode,
1598                                       const gcall *call_stmt,
1599                                       program_state *state,
1600                                       path_context *path_ctxt,
1601                                       function *called_fn,
1602                                       per_function_data *called_fn_data,
1603                                       region_model_context *ctxt)
1604 {
1605   logger *logger = eg.get_logger ();
1606   LOG_SCOPE (logger);
1607
1608   gcc_assert (called_fn);
1609   gcc_assert (called_fn_data);
1610
1611   /* Each summary will call bifurcate on the PATH_CTXT.  */
1612   for (auto summary : called_fn_data->m_summaries)
1613     replay_call_summary (eg, snode, call_stmt, state,
1614                          path_ctxt, called_fn, summary, ctxt);
1615   path_ctxt->terminate_path ();
1616
1617   return on_stmt_flags ();
1618 }
1619
1620 /* Use PATH_CTXT to bifurcate, which when handled will add a
1621    custom edge for a replay of SUMMARY, if the summary's
1622    conditions are feasible based on the current state.  */
1623
1624 void
1625 exploded_node::replay_call_summary (exploded_graph &eg,
1626                                     const supernode *snode,
1627                                     const gcall *call_stmt,
1628                                     program_state *old_state,
1629                                     path_context *path_ctxt,
1630                                     function *called_fn,
1631                                     call_summary *summary,
1632                                     region_model_context *ctxt)
1633 {
1634   logger *logger = eg.get_logger ();
1635   LOG_SCOPE (logger);
1636   gcc_assert (snode);
1637   gcc_assert (call_stmt);
1638   gcc_assert (old_state);
1639   gcc_assert (called_fn);
1640   gcc_assert (summary);
1641
1642   if (logger)
1643     logger->log ("using %s as summary for call to %qE from %qE",
1644                  summary->get_desc ().get (),
1645                  called_fn->decl,
1646                  snode->get_function ()->decl);
1647   const extrinsic_state &ext_state = eg.get_ext_state ();
1648   const program_state &summary_end_state = summary->get_state ();
1649   if (logger)
1650     {
1651       pretty_printer *pp = logger->get_printer ();
1652
1653       logger->start_log_line ();
1654       pp_string (pp, "callsite state: ");
1655       old_state->dump_to_pp (ext_state, true, false, pp);
1656       logger->end_log_line ();
1657
1658       logger->start_log_line ();
1659       pp_string (pp, "summary end state: ");
1660       summary_end_state.dump_to_pp (ext_state, true, false, pp);
1661       logger->end_log_line ();
1662     }
1663
1664   program_state new_state (*old_state);
1665
1666   call_details cd (call_stmt, new_state.m_region_model, ctxt);
1667   call_summary_replay r (cd, called_fn, summary, ext_state);
1668
1669   if (path_ctxt)
1670     path_ctxt->bifurcate (make_unique<call_summary_edge_info> (cd,
1671                                                                called_fn,
1672                                                                summary,
1673                                                                ext_state));
1674 }
1675
1676
1677 /* Consider the effect of following superedge SUCC from this node.
1678
1679    Return true if it's feasible to follow the edge, or false
1680    if it's infeasible.
1681
1682    Examples: if it's the "true" branch within
1683    a CFG and we know the conditional is false, we know it's infeasible.
1684    If it's one of multiple interprocedual "return" edges, then only
1685    the edge back to the most recent callsite is feasible.
1686
1687    Update NEXT_STATE accordingly (e.g. to record that a condition was
1688    true or false, or that the NULL-ness of a pointer has been checked,
1689    pushing/popping stack frames, etc).
1690
1691    Update NEXT_POINT accordingly (updating the call string).  */
1692
1693 bool
1694 exploded_node::on_edge (exploded_graph &eg,
1695                         const superedge *succ,
1696                         program_point *next_point,
1697                         program_state *next_state,
1698                         uncertainty_t *uncertainty)
1699 {
1700   LOG_FUNC (eg.get_logger ());
1701
1702   if (!next_point->on_edge (eg, succ))
1703     return false;
1704
1705   if (!next_state->on_edge (eg, this, succ, uncertainty))
1706     return false;
1707
1708   return true;
1709 }
1710
1711 /* Verify that the stack at LONGJMP_POINT is still valid, given a call
1712    to "setjmp" at SETJMP_POINT - the stack frame that "setjmp" was
1713    called in must still be valid.
1714
1715    Caveat: this merely checks the call_strings in the points; it doesn't
1716    detect the case where a frame returns and is then called again.  */
1717
1718 static bool
1719 valid_longjmp_stack_p (const program_point &longjmp_point,
1720                        const program_point &setjmp_point)
1721 {
1722   const call_string &cs_at_longjmp = longjmp_point.get_call_string ();
1723   const call_string &cs_at_setjmp = setjmp_point.get_call_string ();
1724
1725   if (cs_at_longjmp.length () < cs_at_setjmp.length ())
1726     return false;
1727
1728   /* Check that the call strings match, up to the depth of the
1729      setjmp point.  */
1730   for (unsigned depth = 0; depth < cs_at_setjmp.length (); depth++)
1731     if (cs_at_longjmp[depth] != cs_at_setjmp[depth])
1732       return false;
1733
1734   return true;
1735 }
1736
1737 /* A pending_diagnostic subclass for complaining about bad longjmps,
1738    where the enclosing function of the "setjmp" has returned (and thus
1739    the stack frame no longer exists).  */
1740
1741 class stale_jmp_buf : public pending_diagnostic_subclass<stale_jmp_buf>
1742 {
1743 public:
1744   stale_jmp_buf (const gcall *setjmp_call, const gcall *longjmp_call,
1745                  const program_point &setjmp_point)
1746   : m_setjmp_call (setjmp_call), m_longjmp_call (longjmp_call),
1747     m_setjmp_point (setjmp_point), m_stack_pop_event (NULL)
1748   {}
1749
1750   int get_controlling_option () const final override
1751   {
1752     return OPT_Wanalyzer_stale_setjmp_buffer;
1753   }
1754
1755   bool emit (rich_location *richloc) final override
1756   {
1757     return warning_at
1758       (richloc, get_controlling_option (),
1759        "%qs called after enclosing function of %qs has returned",
1760        get_user_facing_name (m_longjmp_call),
1761        get_user_facing_name (m_setjmp_call));
1762   }
1763
1764   const char *get_kind () const final override
1765   { return "stale_jmp_buf"; }
1766
1767   bool operator== (const stale_jmp_buf &other) const
1768   {
1769     return (m_setjmp_call == other.m_setjmp_call
1770             && m_longjmp_call == other.m_longjmp_call);
1771   }
1772
1773   bool
1774   maybe_add_custom_events_for_superedge (const exploded_edge &eedge,
1775                                          checker_path *emission_path)
1776     final override
1777   {
1778     /* Detect exactly when the stack first becomes invalid,
1779        and issue an event then.  */
1780     if (m_stack_pop_event)
1781       return false;
1782     const exploded_node *src_node = eedge.m_src;
1783     const program_point &src_point = src_node->get_point ();
1784     const exploded_node *dst_node = eedge.m_dest;
1785     const program_point &dst_point = dst_node->get_point ();
1786     if (valid_longjmp_stack_p (src_point, m_setjmp_point)
1787         && !valid_longjmp_stack_p (dst_point, m_setjmp_point))
1788       {
1789         /* Compare with diagnostic_manager::add_events_for_superedge.  */
1790         const int src_stack_depth = src_point.get_stack_depth ();
1791         m_stack_pop_event = new precanned_custom_event
1792           (src_point.get_location (),
1793            src_point.get_fndecl (),
1794            src_stack_depth,
1795            "stack frame is popped here, invalidating saved environment");
1796         emission_path->add_event
1797           (std::unique_ptr<custom_event> (m_stack_pop_event));
1798         return false;
1799       }
1800     return false;
1801   }
1802
1803   label_text describe_final_event (const evdesc::final_event &ev) final override
1804   {
1805     if (m_stack_pop_event)
1806       return ev.formatted_print
1807         ("%qs called after enclosing function of %qs returned at %@",
1808          get_user_facing_name (m_longjmp_call),
1809          get_user_facing_name (m_setjmp_call),
1810          m_stack_pop_event->get_id_ptr ());
1811     else
1812       return ev.formatted_print
1813         ("%qs called after enclosing function of %qs has returned",
1814          get_user_facing_name (m_longjmp_call),
1815          get_user_facing_name (m_setjmp_call));;
1816   }
1817
1818
1819 private:
1820   const gcall *m_setjmp_call;
1821   const gcall *m_longjmp_call;
1822   program_point m_setjmp_point;
1823   custom_event *m_stack_pop_event;
1824 };
1825
1826 /* Handle LONGJMP_CALL, a call to longjmp or siglongjmp.
1827
1828    Attempt to locate where setjmp/sigsetjmp was called on the jmp_buf and build
1829    an exploded_node and exploded_edge to it representing a rewind to that frame,
1830    handling the various kinds of failure that can occur.  */
1831
1832 void
1833 exploded_node::on_longjmp (exploded_graph &eg,
1834                            const gcall *longjmp_call,
1835                            program_state *new_state,
1836                            region_model_context *ctxt)
1837 {
1838   tree buf_ptr = gimple_call_arg (longjmp_call, 0);
1839   gcc_assert (POINTER_TYPE_P (TREE_TYPE (buf_ptr)));
1840
1841   region_model *new_region_model = new_state->m_region_model;
1842   const svalue *buf_ptr_sval = new_region_model->get_rvalue (buf_ptr, ctxt);
1843   const region *buf = new_region_model->deref_rvalue (buf_ptr_sval, buf_ptr,
1844                                                        ctxt);
1845
1846   const svalue *buf_content_sval
1847     = new_region_model->get_store_value (buf, ctxt);
1848   const setjmp_svalue *setjmp_sval
1849     = buf_content_sval->dyn_cast_setjmp_svalue ();
1850   if (!setjmp_sval)
1851     return;
1852
1853   const setjmp_record tmp_setjmp_record = setjmp_sval->get_setjmp_record ();
1854
1855   /* Build a custom enode and eedge for rewinding from the longjmp/siglongjmp
1856      call back to the setjmp/sigsetjmp.  */
1857   rewind_info_t rewind_info (tmp_setjmp_record, longjmp_call);
1858
1859   const gcall *setjmp_call = rewind_info.get_setjmp_call ();
1860   const program_point &setjmp_point = rewind_info.get_setjmp_point ();
1861
1862   const program_point &longjmp_point = get_point ();
1863
1864   /* Verify that the setjmp's call_stack hasn't been popped.  */
1865   if (!valid_longjmp_stack_p (longjmp_point, setjmp_point))
1866     {
1867       ctxt->warn (make_unique<stale_jmp_buf> (setjmp_call,
1868                                               longjmp_call,
1869                                               setjmp_point));
1870       return;
1871     }
1872
1873   gcc_assert (longjmp_point.get_stack_depth ()
1874               >= setjmp_point.get_stack_depth ());
1875
1876   /* Update the state for use by the destination node.  */
1877
1878   /* Stash the current number of diagnostics so that we can update
1879      any that this adds to show where the longjmp is rewinding to.  */
1880
1881   diagnostic_manager *dm = &eg.get_diagnostic_manager ();
1882   unsigned prev_num_diagnostics = dm->get_num_diagnostics ();
1883
1884   new_region_model->on_longjmp (longjmp_call, setjmp_call,
1885                                 setjmp_point.get_stack_depth (), ctxt);
1886
1887   /* Detect leaks in the new state relative to the old state.  */
1888   program_state::detect_leaks (get_state (), *new_state, NULL,
1889                                 eg.get_ext_state (), ctxt);
1890
1891   program_point next_point
1892     = program_point::after_supernode (setjmp_point.get_supernode (),
1893                                       setjmp_point.get_call_string ());
1894
1895   exploded_node *next
1896     = eg.get_or_create_node (next_point, *new_state, this);
1897
1898   /* Create custom exploded_edge for a longjmp.  */
1899   if (next)
1900     {
1901       exploded_edge *eedge
1902         = eg.add_edge (const_cast<exploded_node *> (this), next, NULL,
1903                        make_unique<rewind_info_t> (tmp_setjmp_record, longjmp_call));
1904
1905       /* For any diagnostics that were queued here (such as leaks) we want
1906          the checker_path to show the rewinding events after the "final event"
1907          so that the user sees where the longjmp is rewinding to (otherwise the
1908          path is meaningless).
1909
1910          For example, we want to emit something like:
1911                         |   NN | {
1912                         |   NN |   longjmp (env, 1);
1913                         |      |   ~~~~~~~~~~~~~~~~
1914                         |      |   |
1915                         |      |   (10) 'ptr' leaks here; was allocated at (7)
1916                         |      |   (11) rewinding from 'longjmp' in 'inner'...
1917                         |
1918           <-------------+
1919           |
1920         'outer': event 12
1921           |
1922           |   NN |   i = setjmp(env);
1923           |      |       ^~~~~~
1924           |      |       |
1925           |      |       (12) ...to 'setjmp' in 'outer' (saved at (2))
1926
1927          where the "final" event above is event (10), but we want to append
1928          events (11) and (12) afterwards.
1929
1930          Do this by setting m_trailing_eedge on any diagnostics that were
1931          just saved.  */
1932       unsigned num_diagnostics = dm->get_num_diagnostics ();
1933       for (unsigned i = prev_num_diagnostics; i < num_diagnostics; i++)
1934         {
1935           saved_diagnostic *sd = dm->get_saved_diagnostic (i);
1936           sd->m_trailing_eedge = eedge;
1937         }
1938     }
1939 }
1940
1941 /* Subroutine of exploded_graph::process_node for finding the successors
1942    of the supernode for a function exit basic block.
1943
1944    Ensure that pop_frame is called, potentially queuing diagnostics about
1945    leaks.  */
1946
1947 void
1948 exploded_node::detect_leaks (exploded_graph &eg)
1949 {
1950   LOG_FUNC_1 (eg.get_logger (), "EN: %i", m_index);
1951
1952   gcc_assert (get_point ().get_supernode ()->return_p ());
1953
1954   /* If we're not a "top-level" function, do nothing; pop_frame
1955      will be called when handling the return superedge.  */
1956   if (get_point ().get_stack_depth () > 1)
1957     return;
1958
1959   /* We have a "top-level" function.  */
1960   gcc_assert (get_point ().get_stack_depth () == 1);
1961
1962   const program_state &old_state = get_state ();
1963
1964   /* Work with a temporary copy of the state: pop the frame, and see
1965      what leaks (via purge_unused_svalues).  */
1966   program_state new_state (old_state);
1967
1968   gcc_assert (new_state.m_region_model);
1969
1970   uncertainty_t uncertainty;
1971   impl_region_model_context ctxt (eg, this,
1972                                   &old_state, &new_state, &uncertainty, NULL,
1973                                   get_stmt ());
1974   const svalue *result = NULL;
1975   new_state.m_region_model->pop_frame (NULL, &result, &ctxt);
1976   program_state::detect_leaks (old_state, new_state, result,
1977                                eg.get_ext_state (), &ctxt);
1978 }
1979
1980 /* Dump the successors and predecessors of this enode to OUTF.  */
1981
1982 void
1983 exploded_node::dump_succs_and_preds (FILE *outf) const
1984 {
1985   unsigned i;
1986   exploded_edge *e;
1987   {
1988     auto_vec<exploded_node *> preds (m_preds.length ());
1989     FOR_EACH_VEC_ELT (m_preds, i, e)
1990       preds.quick_push (e->m_src);
1991     pretty_printer pp;
1992     print_enode_indices (&pp, preds);
1993     fprintf (outf, "preds: %s\n",
1994              pp_formatted_text (&pp));
1995   }
1996   {
1997     auto_vec<exploded_node *> succs (m_succs.length ());
1998     FOR_EACH_VEC_ELT (m_succs, i, e)
1999       succs.quick_push (e->m_dest);
2000     pretty_printer pp;
2001     print_enode_indices (&pp, succs);
2002     fprintf (outf, "succs: %s\n",
2003              pp_formatted_text (&pp));
2004   }
2005 }
2006
2007 /* class dynamic_call_info_t : public custom_edge_info.  */
2008
2009 /* Implementation of custom_edge_info::update_model vfunc
2010    for dynamic_call_info_t.
2011
2012    Update state for a dynamically discovered call (or return), by pushing
2013    or popping the a frame for the appropriate function.  */
2014
2015 bool
2016 dynamic_call_info_t::update_model (region_model *model,
2017                                    const exploded_edge *eedge,
2018                                    region_model_context *ctxt) const
2019 {
2020   gcc_assert (eedge);
2021   if (m_is_returning_call)
2022     model->update_for_return_gcall (m_dynamic_call, ctxt);
2023   else
2024     {
2025       function *callee = eedge->m_dest->get_function ();
2026       model->update_for_gcall (m_dynamic_call, ctxt, callee);
2027     }
2028   return true;
2029 }
2030
2031 /* Implementation of custom_edge_info::add_events_to_path vfunc
2032    for dynamic_call_info_t.  */
2033
2034 void
2035 dynamic_call_info_t::add_events_to_path (checker_path *emission_path,
2036                                    const exploded_edge &eedge) const
2037 {
2038   const exploded_node *src_node = eedge.m_src;
2039   const program_point &src_point = src_node->get_point ();
2040   const int src_stack_depth = src_point.get_stack_depth ();
2041   const exploded_node *dest_node = eedge.m_dest;
2042   const program_point &dest_point = dest_node->get_point ();
2043   const int dest_stack_depth = dest_point.get_stack_depth ();
2044
2045   if (m_is_returning_call)
2046     emission_path->add_event
2047       (make_unique<return_event> (eedge,
2048                                   (m_dynamic_call
2049                                    ? m_dynamic_call->location
2050                                    : UNKNOWN_LOCATION),
2051                                   dest_point.get_fndecl (),
2052                                   dest_stack_depth));
2053   else
2054     emission_path->add_event
2055       (make_unique<call_event> (eedge,
2056                                 (m_dynamic_call
2057                                  ? m_dynamic_call->location
2058                                  : UNKNOWN_LOCATION),
2059                                 src_point.get_fndecl (),
2060                                 src_stack_depth));
2061 }
2062
2063 /* class rewind_info_t : public custom_edge_info.  */
2064
2065 /* Implementation of custom_edge_info::update_model vfunc
2066    for rewind_info_t.
2067
2068    Update state for the special-case of a rewind of a longjmp
2069    to a setjmp (which doesn't have a superedge, but does affect
2070    state).  */
2071
2072 bool
2073 rewind_info_t::update_model (region_model *model,
2074                              const exploded_edge *eedge,
2075                              region_model_context *) const
2076 {
2077   gcc_assert (eedge);
2078   const program_point &longjmp_point = eedge->m_src->get_point ();
2079   const program_point &setjmp_point = eedge->m_dest->get_point ();
2080
2081   gcc_assert (longjmp_point.get_stack_depth ()
2082               >= setjmp_point.get_stack_depth ());
2083
2084   model->on_longjmp (get_longjmp_call (),
2085                      get_setjmp_call (),
2086                      setjmp_point.get_stack_depth (), NULL);
2087   return true;
2088 }
2089
2090 /* Implementation of custom_edge_info::add_events_to_path vfunc
2091    for rewind_info_t.  */
2092
2093 void
2094 rewind_info_t::add_events_to_path (checker_path *emission_path,
2095                                    const exploded_edge &eedge) const
2096 {
2097   const exploded_node *src_node = eedge.m_src;
2098   const program_point &src_point = src_node->get_point ();
2099   const int src_stack_depth = src_point.get_stack_depth ();
2100   const exploded_node *dst_node = eedge.m_dest;
2101   const program_point &dst_point = dst_node->get_point ();
2102   const int dst_stack_depth = dst_point.get_stack_depth ();
2103
2104   emission_path->add_event
2105     (make_unique<rewind_from_longjmp_event>
2106      (&eedge, get_longjmp_call ()->location,
2107       src_point.get_fndecl (),
2108       src_stack_depth, this));
2109   emission_path->add_event
2110     (make_unique<rewind_to_setjmp_event>
2111      (&eedge, get_setjmp_call ()->location,
2112       dst_point.get_fndecl (),
2113       dst_stack_depth, this));
2114 }
2115
2116 /* class exploded_edge : public dedge<eg_traits>.  */
2117
2118 /* exploded_edge's ctor.  */
2119
2120 exploded_edge::exploded_edge (exploded_node *src, exploded_node *dest,
2121                               const superedge *sedge,
2122                               std::unique_ptr<custom_edge_info> custom_info)
2123 : dedge<eg_traits> (src, dest), m_sedge (sedge),
2124   m_custom_info (std::move (custom_info))
2125 {
2126 }
2127
2128 /* Implementation of dedge::dump_dot vfunc for exploded_edge.
2129    Use the label of the underlying superedge, if any.  */
2130
2131 void
2132 exploded_edge::dump_dot (graphviz_out *gv, const dump_args_t &) const
2133 {
2134   pretty_printer *pp = gv->get_pp ();
2135
2136   m_src->dump_dot_id (pp);
2137   pp_string (pp, " -> ");
2138   m_dest->dump_dot_id (pp);
2139   dump_dot_label (pp);
2140 }
2141
2142 /* Second half of exploded_edge::dump_dot.  This is split out
2143    for use by trimmed_graph::dump_dot and base_feasible_edge::dump_dot.  */
2144
2145 void
2146 exploded_edge::dump_dot_label (pretty_printer *pp) const
2147 {
2148   const char *style = "\"solid,bold\"";
2149   const char *color = "black";
2150   int weight = 10;
2151   const char *constraint = "true";
2152
2153   if (m_sedge)
2154     switch (m_sedge->m_kind)
2155       {
2156       default:
2157         gcc_unreachable ();
2158       case SUPEREDGE_CFG_EDGE:
2159         break;
2160       case SUPEREDGE_CALL:
2161         color = "red";
2162         //constraint = "false";
2163         break;
2164       case SUPEREDGE_RETURN:
2165         color = "green";
2166         //constraint = "false";
2167         break;
2168       case SUPEREDGE_INTRAPROCEDURAL_CALL:
2169         style = "\"dotted\"";
2170         break;
2171       }
2172   if (m_custom_info)
2173     {
2174       color = "red";
2175       style = "\"dotted\"";
2176     }
2177
2178   pp_printf (pp,
2179              (" [style=%s, color=%s, weight=%d, constraint=%s,"
2180               " headlabel=\""),
2181              style, color, weight, constraint);
2182
2183   if (m_sedge)
2184     m_sedge->dump_label_to_pp (pp, false);
2185   else if (m_custom_info)
2186     m_custom_info->print (pp);
2187
2188   //pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/false);
2189
2190   pp_printf (pp, "\"];\n");
2191 }
2192
2193 /* Return a new json::object of the form
2194    {"src_idx": int, the index of the source exploded edge,
2195     "dst_idx": int, the index of the destination exploded edge,
2196     "sedge": (optional) object for the superedge, if any,
2197     "custom": (optional) str, a description, if this is a custom edge}.  */
2198
2199 json::object *
2200 exploded_edge::to_json () const
2201 {
2202   json::object *eedge_obj = new json::object ();
2203   eedge_obj->set ("src_idx", new json::integer_number (m_src->m_index));
2204   eedge_obj->set ("dst_idx", new json::integer_number (m_dest->m_index));
2205   if (m_sedge)
2206     eedge_obj->set ("sedge", m_sedge->to_json ());
2207   if (m_custom_info)
2208     {
2209       pretty_printer pp;
2210       pp_format_decoder (&pp) = default_tree_printer;
2211       m_custom_info->print (&pp);
2212       eedge_obj->set ("custom", new json::string (pp_formatted_text (&pp)));
2213     }
2214   return eedge_obj;
2215 }
2216
2217 /* struct stats.  */
2218
2219 /* stats' ctor.  */
2220
2221 stats::stats (int num_supernodes)
2222 : m_node_reuse_count (0),
2223   m_node_reuse_after_merge_count (0),
2224   m_num_supernodes (num_supernodes)
2225 {
2226   for (int i = 0; i < NUM_POINT_KINDS; i++)
2227     m_num_nodes[i] = 0;
2228 }
2229
2230 /* Log these stats in multiline form to LOGGER.  */
2231
2232 void
2233 stats::log (logger *logger) const
2234 {
2235   gcc_assert (logger);
2236   for (int i = 0; i < NUM_POINT_KINDS; i++)
2237     if (m_num_nodes[i] > 0)
2238       logger->log ("m_num_nodes[%s]: %i",
2239                    point_kind_to_string (static_cast <enum point_kind> (i)),
2240                    m_num_nodes[i]);
2241   logger->log ("m_node_reuse_count: %i", m_node_reuse_count);
2242   logger->log ("m_node_reuse_after_merge_count: %i",
2243                m_node_reuse_after_merge_count);
2244 }
2245
2246 /* Dump these stats in multiline form to OUT.  */
2247
2248 void
2249 stats::dump (FILE *out) const
2250 {
2251   for (int i = 0; i < NUM_POINT_KINDS; i++)
2252     if (m_num_nodes[i] > 0)
2253       fprintf (out, "m_num_nodes[%s]: %i\n",
2254                point_kind_to_string (static_cast <enum point_kind> (i)),
2255                m_num_nodes[i]);
2256   fprintf (out, "m_node_reuse_count: %i\n", m_node_reuse_count);
2257   fprintf (out, "m_node_reuse_after_merge_count: %i\n",
2258            m_node_reuse_after_merge_count);
2259
2260   if (m_num_supernodes > 0)
2261     fprintf (out, "PK_AFTER_SUPERNODE nodes per supernode: %.2f\n",
2262              (float)m_num_nodes[PK_AFTER_SUPERNODE] / (float)m_num_supernodes);
2263 }
2264
2265 /* Return the total number of enodes recorded within this object.  */
2266
2267 int
2268 stats::get_total_enodes () const
2269 {
2270   int result = 0;
2271   for (int i = 0; i < NUM_POINT_KINDS; i++)
2272     result += m_num_nodes[i];
2273   return result;
2274 }
2275
2276 /* struct per_function_data.  */
2277
2278 per_function_data::~per_function_data ()
2279 {
2280   for (auto iter : m_summaries)
2281     delete iter;
2282 }
2283
2284 void
2285 per_function_data::add_call_summary (exploded_node *node)
2286 {
2287   m_summaries.safe_push (new call_summary (this, node));
2288 }
2289
2290 /* strongly_connected_components's ctor.  Tarjan's SCC algorithm.  */
2291
2292 strongly_connected_components::
2293 strongly_connected_components (const supergraph &sg, logger *logger)
2294 : m_sg (sg), m_per_node (m_sg.num_nodes ())
2295 {
2296   LOG_SCOPE (logger);
2297   auto_timevar tv (TV_ANALYZER_SCC);
2298
2299   for (int i = 0; i < m_sg.num_nodes (); i++)
2300     m_per_node.quick_push (per_node_data ());
2301
2302   for (int i = 0; i < m_sg.num_nodes (); i++)
2303     if (m_per_node[i].m_index == -1)
2304       strong_connect (i);
2305
2306   if (0)
2307     dump ();
2308 }
2309
2310 /* Dump this object to stderr.  */
2311
2312 DEBUG_FUNCTION void
2313 strongly_connected_components::dump () const
2314 {
2315   for (int i = 0; i < m_sg.num_nodes (); i++)
2316     {
2317       const per_node_data &v = m_per_node[i];
2318       fprintf (stderr, "SN %i: index: %i lowlink: %i on_stack: %i\n",
2319                i, v.m_index, v.m_lowlink, v.m_on_stack);
2320     }
2321 }
2322
2323 /* Return a new json::array of per-snode SCC ids.  */
2324
2325 json::array *
2326 strongly_connected_components::to_json () const
2327 {
2328   json::array *scc_arr = new json::array ();
2329   for (int i = 0; i < m_sg.num_nodes (); i++)
2330     scc_arr->append (new json::integer_number (get_scc_id (i)));
2331   return scc_arr;
2332 }
2333
2334 /* Subroutine of strongly_connected_components's ctor, part of Tarjan's
2335    SCC algorithm.  */
2336
2337 void
2338 strongly_connected_components::strong_connect (unsigned index)
2339 {
2340   supernode *v_snode = m_sg.get_node_by_index (index);
2341
2342   /* Set the depth index for v to the smallest unused index.  */
2343   per_node_data *v = &m_per_node[index];
2344   v->m_index = index;
2345   v->m_lowlink = index;
2346   m_stack.safe_push (index);
2347   v->m_on_stack = true;
2348   index++;
2349
2350   /* Consider successors of v.  */
2351   unsigned i;
2352   superedge *sedge;
2353   FOR_EACH_VEC_ELT (v_snode->m_succs, i, sedge)
2354     {
2355       if (sedge->get_kind () != SUPEREDGE_CFG_EDGE
2356           && sedge->get_kind () != SUPEREDGE_INTRAPROCEDURAL_CALL)
2357         continue;
2358       supernode *w_snode = sedge->m_dest;
2359       per_node_data *w = &m_per_node[w_snode->m_index];
2360       if (w->m_index == -1)
2361         {
2362           /* Successor w has not yet been visited; recurse on it.  */
2363           strong_connect (w_snode->m_index);
2364           v->m_lowlink = MIN (v->m_lowlink, w->m_lowlink);
2365         }
2366       else if (w->m_on_stack)
2367         {
2368           /* Successor w is in stack S and hence in the current SCC
2369              If w is not on stack, then (v, w) is a cross-edge in the DFS
2370              tree and must be ignored.  */
2371           v->m_lowlink = MIN (v->m_lowlink, w->m_index);
2372         }
2373     }
2374
2375   /* If v is a root node, pop the stack and generate an SCC.  */
2376
2377   if (v->m_lowlink == v->m_index)
2378     {
2379       per_node_data *w;
2380       do {
2381         int idx = m_stack.pop ();
2382         w = &m_per_node[idx];
2383         w->m_on_stack = false;
2384       } while (w != v);
2385     }
2386 }
2387
2388 /* worklist's ctor.  */
2389
2390 worklist::worklist (const exploded_graph &eg, const analysis_plan &plan)
2391 : m_scc (eg.get_supergraph (), eg.get_logger ()),
2392   m_plan (plan),
2393   m_queue (key_t (*this, NULL))
2394 {
2395 }
2396
2397 /* Return the number of nodes in the worklist.  */
2398
2399 unsigned
2400 worklist::length () const
2401 {
2402   return m_queue.nodes ();
2403 }
2404
2405 /* Return the next node in the worklist, removing it.  */
2406
2407 exploded_node *
2408 worklist::take_next ()
2409 {
2410   return m_queue.extract_min ();
2411 }
2412
2413 /* Return the next node in the worklist without removing it.  */
2414
2415 exploded_node *
2416 worklist::peek_next ()
2417 {
2418   return m_queue.min ();
2419 }
2420
2421 /* Add ENODE to the worklist.  */
2422
2423 void
2424 worklist::add_node (exploded_node *enode)
2425 {
2426   gcc_assert (enode->get_status () == exploded_node::STATUS_WORKLIST);
2427   m_queue.insert (key_t (*this, enode), enode);
2428 }
2429
2430 /* Comparator for implementing worklist::key_t comparison operators.
2431    Return negative if KA is before KB
2432    Return positive if KA is after KB
2433    Return 0 if they are equal.
2434
2435    The ordering of the worklist is critical for performance and for
2436    avoiding node explosions.  Ideally we want all enodes at a CFG join-point
2437    with the same callstring to be sorted next to each other in the worklist
2438    so that a run of consecutive enodes can be merged and processed "in bulk"
2439    rather than individually or pairwise, minimizing the number of new enodes
2440    created.  */
2441
2442 int
2443 worklist::key_t::cmp (const worklist::key_t &ka, const worklist::key_t &kb)
2444 {
2445   const program_point &point_a = ka.m_enode->get_point ();
2446   const program_point &point_b = kb.m_enode->get_point ();
2447   const call_string &call_string_a = point_a.get_call_string ();
2448   const call_string &call_string_b = point_b.get_call_string ();
2449
2450   /* Order empty-callstring points with different functions based on the
2451      analysis_plan, so that we generate summaries before they are used.  */
2452   if (flag_analyzer_call_summaries
2453       && call_string_a.empty_p ()
2454       && call_string_b.empty_p ()
2455       && point_a.get_function () != NULL
2456       && point_b.get_function () != NULL
2457       && point_a.get_function () != point_b.get_function ())
2458     {
2459       if (int cmp = ka.m_worklist.m_plan.cmp_function (point_a.get_function (),
2460                                                        point_b.get_function ()))
2461         return cmp;
2462     }
2463
2464   /* Sort by callstring, so that nodes with deeper call strings are processed
2465      before those with shallower call strings.
2466      If we have
2467          splitting BB
2468              /  \
2469             /    \
2470        fn call   no fn call
2471             \    /
2472              \  /
2473             join BB
2474      then we want the path inside the function call to be fully explored up
2475      to the return to the join BB before we explore on the "no fn call" path,
2476      so that both enodes at the join BB reach the front of the worklist at
2477      the same time and thus have a chance of being merged.  */
2478   int cs_cmp = call_string::cmp (call_string_a, call_string_b);
2479   if (cs_cmp)
2480     return cs_cmp;
2481
2482   /* Order by SCC.  */
2483   int scc_id_a = ka.get_scc_id (ka.m_enode);
2484   int scc_id_b = kb.get_scc_id (kb.m_enode);
2485   if (scc_id_a != scc_id_b)
2486     return scc_id_a - scc_id_b;
2487
2488   /* If in same SCC, order by supernode index (an arbitrary but stable
2489      ordering).  */
2490   const supernode *snode_a = ka.m_enode->get_supernode ();
2491   const supernode *snode_b = kb.m_enode->get_supernode ();
2492   if (snode_a == NULL)
2493     {
2494       if (snode_b != NULL)
2495         /* One is NULL.  */
2496         return -1;
2497       else
2498         /* Both are NULL.  */
2499         return 0;
2500     }
2501   if (snode_b == NULL)
2502     /* One is NULL.  */
2503     return 1;
2504   /* Neither are NULL.  */
2505   gcc_assert (snode_a && snode_b);
2506   if (snode_a->m_index != snode_b->m_index)
2507     return snode_a->m_index - snode_b->m_index;
2508
2509   gcc_assert (snode_a == snode_b);
2510
2511   /* Order within supernode via program point.  */
2512   int within_snode_cmp
2513     = function_point::cmp_within_supernode (point_a.get_function_point (),
2514                                             point_b.get_function_point ());
2515   if (within_snode_cmp)
2516     return within_snode_cmp;
2517
2518   /* Otherwise, we ought to have the same program_point.  */
2519   gcc_assert (point_a == point_b);
2520
2521   const program_state &state_a = ka.m_enode->get_state ();
2522   const program_state &state_b = kb.m_enode->get_state ();
2523
2524   /* Sort by sm-state, so that identical sm-states are grouped
2525      together in the worklist.  */
2526   for (unsigned sm_idx = 0; sm_idx < state_a.m_checker_states.length ();
2527        ++sm_idx)
2528     {
2529       sm_state_map *smap_a = state_a.m_checker_states[sm_idx];
2530       sm_state_map *smap_b = state_b.m_checker_states[sm_idx];
2531
2532       if (int smap_cmp = sm_state_map::cmp (*smap_a, *smap_b))
2533         return smap_cmp;
2534     }
2535
2536   /* Otherwise, we have two enodes at the same program point but with
2537      different states.  We don't have a good total ordering on states,
2538      so order them by enode index, so that we have at least have a
2539      stable sort.  */
2540   return ka.m_enode->m_index - kb.m_enode->m_index;
2541 }
2542
2543 /* Return a new json::object of the form
2544    {"scc" : [per-snode-IDs]},  */
2545
2546 json::object *
2547 worklist::to_json () const
2548 {
2549   json::object *worklist_obj = new json::object ();
2550
2551   worklist_obj->set ("scc", m_scc.to_json ());
2552
2553   /* The following field isn't yet being JSONified:
2554      queue_t m_queue;  */
2555
2556   return worklist_obj;
2557 }
2558
2559 /* exploded_graph's ctor.  */
2560
2561 exploded_graph::exploded_graph (const supergraph &sg, logger *logger,
2562                                 const extrinsic_state &ext_state,
2563                                 const state_purge_map *purge_map,
2564                                 const analysis_plan &plan,
2565                                 int verbosity)
2566 : m_sg (sg), m_logger (logger),
2567   m_worklist (*this, plan),
2568   m_ext_state (ext_state),
2569   m_purge_map (purge_map),
2570   m_plan (plan),
2571   m_diagnostic_manager (logger, ext_state.get_engine (), verbosity),
2572   m_global_stats (m_sg.num_nodes ()),
2573   m_functionless_stats (m_sg.num_nodes ()),
2574   m_PK_AFTER_SUPERNODE_per_snode (m_sg.num_nodes ())
2575 {
2576   m_origin = get_or_create_node
2577     (program_point::origin (*ext_state.get_model_manager ()),
2578      program_state (ext_state), NULL);
2579   for (int i = 0; i < m_sg.num_nodes (); i++)
2580     m_PK_AFTER_SUPERNODE_per_snode.quick_push (i);
2581 }
2582
2583 /* exploded_graph's dtor.  */
2584
2585 exploded_graph::~exploded_graph ()
2586 {
2587   for (auto iter : m_per_point_data)
2588     delete iter.second;
2589   for (auto iter : m_per_function_data)
2590     delete iter.second;
2591   for (auto iter : m_per_function_stats)
2592     delete iter.second;
2593   for (auto iter : m_per_call_string_data)
2594     delete iter.second;
2595 }
2596
2597 /* Subroutine for use when implementing __attribute__((tainted_args))
2598    on functions and on function pointer fields in structs.
2599
2600    Called on STATE representing a call to FNDECL.
2601    Mark all params of FNDECL in STATE as "tainted".  Mark the value of all
2602    regions pointed to by params of FNDECL as "tainted".
2603
2604    Return true if successful; return false if the "taint" state machine
2605    was not found.  */
2606
2607 static bool
2608 mark_params_as_tainted (program_state *state, tree fndecl,
2609                         const extrinsic_state &ext_state)
2610 {
2611   unsigned taint_sm_idx;
2612   if (!ext_state.get_sm_idx_by_name ("taint", &taint_sm_idx))
2613     return false;
2614   sm_state_map *smap = state->m_checker_states[taint_sm_idx];
2615
2616   const state_machine &sm = ext_state.get_sm (taint_sm_idx);
2617   state_machine::state_t tainted = sm.get_state_by_name ("tainted");
2618
2619   region_model_manager *mgr = ext_state.get_model_manager ();
2620
2621   function *fun = DECL_STRUCT_FUNCTION (fndecl);
2622   gcc_assert (fun);
2623
2624   for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm;
2625        iter_parm = DECL_CHAIN (iter_parm))
2626     {
2627       tree param = iter_parm;
2628       if (tree parm_default_ssa = ssa_default_def (fun, iter_parm))
2629         param = parm_default_ssa;
2630       const region *param_reg = state->m_region_model->get_lvalue (param, NULL);
2631       const svalue *init_sval = mgr->get_or_create_initial_value (param_reg);
2632       smap->set_state (state->m_region_model, init_sval,
2633                        tainted, NULL /*origin_new_sval*/, ext_state);
2634       if (POINTER_TYPE_P (TREE_TYPE (param)))
2635         {
2636           const region *pointee_reg = mgr->get_symbolic_region (init_sval);
2637           /* Mark "*param" as tainted.  */
2638           const svalue *init_pointee_sval
2639             = mgr->get_or_create_initial_value (pointee_reg);
2640           smap->set_state (state->m_region_model, init_pointee_sval,
2641                            tainted, NULL /*origin_new_sval*/, ext_state);
2642         }
2643     }
2644
2645   return true;
2646 }
2647
2648 /* Custom event for use by tainted_args_function_info when a function
2649    has been marked with __attribute__((tainted_args)).  */
2650
2651 class tainted_args_function_custom_event : public custom_event
2652 {
2653 public:
2654   tainted_args_function_custom_event (location_t loc, tree fndecl, int depth)
2655   : custom_event (loc, fndecl, depth),
2656     m_fndecl (fndecl)
2657   {
2658   }
2659
2660   label_text get_desc (bool can_colorize) const final override
2661   {
2662     return make_label_text
2663       (can_colorize,
2664        "function %qE marked with %<__attribute__((tainted_args))%>",
2665        m_fndecl);
2666   }
2667
2668 private:
2669   tree m_fndecl;
2670 };
2671
2672 /* Custom exploded_edge info for top-level calls to a function
2673    marked with __attribute__((tainted_args)).  */
2674
2675 class tainted_args_function_info : public custom_edge_info
2676 {
2677 public:
2678   tainted_args_function_info (tree fndecl)
2679   : m_fndecl (fndecl)
2680   {}
2681
2682   void print (pretty_printer *pp) const final override
2683   {
2684     pp_string (pp, "call to tainted_args function");
2685   };
2686
2687   bool update_model (region_model *,
2688                      const exploded_edge *,
2689                      region_model_context *) const final override
2690   {
2691     /* No-op.  */
2692     return true;
2693   }
2694
2695   void add_events_to_path (checker_path *emission_path,
2696                            const exploded_edge &) const final override
2697   {
2698     emission_path->add_event
2699       (make_unique<tainted_args_function_custom_event>
2700        (DECL_SOURCE_LOCATION (m_fndecl), m_fndecl, 0));
2701   }
2702
2703 private:
2704   tree m_fndecl;
2705 };
2706
2707 /* Ensure that there is an exploded_node representing an external call to
2708    FUN, adding it to the worklist if creating it.
2709
2710    Add an edge from the origin exploded_node to the function entrypoint
2711    exploded_node.
2712
2713    Return the exploded_node for the entrypoint to the function.  */
2714
2715 exploded_node *
2716 exploded_graph::add_function_entry (function *fun)
2717 {
2718   gcc_assert (gimple_has_body_p (fun->decl));
2719
2720   /* Be idempotent.  */
2721   if (m_functions_with_enodes.contains (fun))
2722     {
2723       logger * const logger = get_logger ();
2724        if (logger)
2725         logger->log ("entrypoint for %qE already exists", fun->decl);
2726       return NULL;
2727     }
2728
2729   program_point point
2730     = program_point::from_function_entry (*m_ext_state.get_model_manager (),
2731                                           m_sg, fun);
2732   program_state state (m_ext_state);
2733   state.push_frame (m_ext_state, fun);
2734
2735   std::unique_ptr<custom_edge_info> edge_info = NULL;
2736
2737   if (lookup_attribute ("tainted_args", DECL_ATTRIBUTES (fun->decl)))
2738     {
2739       if (mark_params_as_tainted (&state, fun->decl, m_ext_state))
2740         edge_info = make_unique<tainted_args_function_info> (fun->decl);
2741     }
2742
2743   if (!state.m_valid)
2744     return NULL;
2745
2746   exploded_node *enode = get_or_create_node (point, state, NULL);
2747   if (!enode)
2748     return NULL;
2749
2750   add_edge (m_origin, enode, NULL, std::move (edge_info));
2751
2752   m_functions_with_enodes.add (fun);
2753
2754   return enode;
2755 }
2756
2757 /* Get or create an exploded_node for (POINT, STATE).
2758    If a new node is created, it is added to the worklist.
2759
2760    Use ENODE_FOR_DIAG, a pre-existing enode, for any diagnostics
2761    that need to be emitted (e.g. when purging state *before* we have
2762    a new enode).  */
2763
2764 exploded_node *
2765 exploded_graph::get_or_create_node (const program_point &point,
2766                                     const program_state &state,
2767                                     exploded_node *enode_for_diag)
2768 {
2769   logger * const logger = get_logger ();
2770   LOG_FUNC (logger);
2771   if (logger)
2772     {
2773       format f (false);
2774       pretty_printer *pp = logger->get_printer ();
2775       logger->start_log_line ();
2776       pp_string (pp, "point: ");
2777       point.print (pp, f);
2778       logger->end_log_line ();
2779       logger->start_log_line ();
2780       pp_string (pp, "state: ");
2781       state.dump_to_pp (m_ext_state, true, false, pp);
2782       logger->end_log_line ();
2783     }
2784
2785   /* Stop exploring paths for which we don't know how to effectively
2786      model the state.  */
2787   if (!state.m_valid)
2788     {
2789       if (logger)
2790         logger->log ("invalid state; not creating node");
2791       return NULL;
2792     }
2793
2794   auto_cfun sentinel (point.get_function ());
2795
2796   state.validate (get_ext_state ());
2797
2798   //state.dump (get_ext_state ());
2799
2800   /* Prune state to try to improve the chances of a cache hit,
2801      avoiding generating redundant nodes.  */
2802   uncertainty_t uncertainty;
2803   program_state pruned_state
2804     = state.prune_for_point (*this, point, enode_for_diag, &uncertainty);
2805
2806   pruned_state.validate (get_ext_state ());
2807
2808   //pruned_state.dump (get_ext_state ());
2809
2810   if (logger)
2811     {
2812       pretty_printer *pp = logger->get_printer ();
2813       logger->start_log_line ();
2814       pp_string (pp, "pruned_state: ");
2815       pruned_state.dump_to_pp (m_ext_state, true, false, pp);
2816       logger->end_log_line ();
2817       pruned_state.m_region_model->dump_to_pp (logger->get_printer (), true,
2818                                                 false);
2819     }
2820
2821   stats *per_fn_stats = get_or_create_function_stats (point.get_function ());
2822
2823   stats *per_cs_stats
2824     = &get_or_create_per_call_string_data (point.get_call_string ())->m_stats;
2825
2826   point_and_state ps (point, pruned_state);
2827   ps.validate (m_ext_state);
2828   if (exploded_node **slot = m_point_and_state_to_node.get (&ps))
2829     {
2830       /* An exploded_node for PS already exists.  */
2831       if (logger)
2832         logger->log ("reused EN: %i", (*slot)->m_index);
2833       m_global_stats.m_node_reuse_count++;
2834       per_fn_stats->m_node_reuse_count++;
2835       per_cs_stats->m_node_reuse_count++;
2836       return *slot;
2837     }
2838
2839   per_program_point_data *per_point_data
2840     = get_or_create_per_program_point_data (point);
2841
2842   /* Consider merging state with another enode at this program_point.  */
2843   if (flag_analyzer_state_merge)
2844     {
2845       exploded_node *existing_enode;
2846       unsigned i;
2847       FOR_EACH_VEC_ELT (per_point_data->m_enodes, i, existing_enode)
2848         {
2849           if (logger)
2850             logger->log ("considering merging with existing EN: %i for point",
2851                          existing_enode->m_index);
2852           gcc_assert (existing_enode->get_point () == point);
2853           const program_state &existing_state = existing_enode->get_state ();
2854
2855           /* This merges successfully within the loop.  */
2856
2857           program_state merged_state (m_ext_state);
2858           if (pruned_state.can_merge_with_p (existing_state, m_ext_state, point,
2859                                              &merged_state))
2860             {
2861               merged_state.validate (m_ext_state);
2862               if (logger)
2863                 logger->log ("merging new state with that of EN: %i",
2864                              existing_enode->m_index);
2865
2866               /* Try again for a cache hit.
2867                  Whether we get one or not, merged_state's value_ids have no
2868                  relationship to those of the input state, and thus to those
2869                  of CHANGE, so we must purge any svalue_ids from *CHANGE.  */
2870               ps.set_state (merged_state);
2871
2872               if (exploded_node **slot = m_point_and_state_to_node.get (&ps))
2873                 {
2874                   /* An exploded_node for PS already exists.  */
2875                   if (logger)
2876                     logger->log ("reused EN: %i", (*slot)->m_index);
2877                   m_global_stats.m_node_reuse_after_merge_count++;
2878                   per_fn_stats->m_node_reuse_after_merge_count++;
2879                   per_cs_stats->m_node_reuse_after_merge_count++;
2880                   return *slot;
2881                 }
2882             }
2883           else
2884             if (logger)
2885               logger->log ("not merging new state with that of EN: %i",
2886                            existing_enode->m_index);
2887         }
2888     }
2889
2890   /* Impose a limit on the number of enodes per program point, and
2891      simply stop if we exceed it.  */
2892   if ((int)per_point_data->m_enodes.length ()
2893       >= param_analyzer_max_enodes_per_program_point)
2894     {
2895       pretty_printer pp;
2896       point.print (&pp, format (false));
2897       print_enode_indices (&pp, per_point_data->m_enodes);
2898       if (logger)
2899         logger->log ("not creating enode; too many at program point: %s",
2900                      pp_formatted_text (&pp));
2901       warning_at (point.get_location (), OPT_Wanalyzer_too_complex,
2902                   "terminating analysis for this program point: %s",
2903                   pp_formatted_text (&pp));
2904       per_point_data->m_excess_enodes++;
2905       return NULL;
2906     }
2907
2908   ps.validate (m_ext_state);
2909
2910   /* An exploded_node for "ps" doesn't already exist; create one.  */
2911   exploded_node *node = new exploded_node (ps, m_nodes.length ());
2912   add_node (node);
2913   m_point_and_state_to_node.put (node->get_ps_key (), node);
2914
2915   /* Update per-program_point data.  */
2916   per_point_data->m_enodes.safe_push (node);
2917
2918   const enum point_kind node_pk = node->get_point ().get_kind ();
2919   m_global_stats.m_num_nodes[node_pk]++;
2920   per_fn_stats->m_num_nodes[node_pk]++;
2921   per_cs_stats->m_num_nodes[node_pk]++;
2922
2923   if (node_pk == PK_AFTER_SUPERNODE)
2924     m_PK_AFTER_SUPERNODE_per_snode[point.get_supernode ()->m_index]++;
2925
2926   if (logger)
2927     {
2928       format f (false);
2929       pretty_printer *pp = logger->get_printer ();
2930       logger->log ("created EN: %i", node->m_index);
2931       logger->start_log_line ();
2932       pp_string (pp, "point: ");
2933       point.print (pp, f);
2934       logger->end_log_line ();
2935       logger->start_log_line ();
2936       pp_string (pp, "pruned_state: ");
2937       pruned_state.dump_to_pp (m_ext_state, true, false, pp);
2938       logger->end_log_line ();
2939     }
2940
2941   /* Add the new node to the worlist.  */
2942   m_worklist.add_node (node);
2943   return node;
2944 }
2945
2946 /* Add an exploded_edge from SRC to DEST, recording its association
2947    with SEDGE (which may be NULL), and, if non-NULL, taking ownership
2948    of CUSTOM_INFO.
2949    Return the newly-created eedge.  */
2950
2951 exploded_edge *
2952 exploded_graph::add_edge (exploded_node *src, exploded_node *dest,
2953                           const superedge *sedge,
2954                             std::unique_ptr<custom_edge_info> custom_info)
2955 {
2956   if (get_logger ())
2957     get_logger ()->log ("creating edge EN: %i -> EN: %i",
2958                         src->m_index, dest->m_index);
2959   exploded_edge *e = new exploded_edge (src, dest, sedge,
2960                                         std::move (custom_info));
2961   digraph<eg_traits>::add_edge (e);
2962   return e;
2963 }
2964
2965 /* Ensure that this graph has per-program_point-data for POINT;
2966    borrow a pointer to it.  */
2967
2968 per_program_point_data *
2969 exploded_graph::
2970 get_or_create_per_program_point_data (const program_point &point)
2971 {
2972   if (per_program_point_data **slot = m_per_point_data.get (&point))
2973     return *slot;
2974
2975   per_program_point_data *per_point_data = new per_program_point_data (point);
2976   m_per_point_data.put (&per_point_data->m_key, per_point_data);
2977   return per_point_data;
2978 }
2979
2980 /* Get this graph's per-program-point-data for POINT if there is any,
2981    otherwise NULL.  */
2982
2983 per_program_point_data *
2984 exploded_graph::get_per_program_point_data (const program_point &point) const
2985 {
2986   if (per_program_point_data **slot
2987       = const_cast <point_map_t &> (m_per_point_data).get (&point))
2988     return *slot;
2989
2990   return NULL;
2991 }
2992
2993 /* Ensure that this graph has per-call_string-data for CS;
2994    borrow a pointer to it.  */
2995
2996 per_call_string_data *
2997 exploded_graph::get_or_create_per_call_string_data (const call_string &cs)
2998 {
2999   if (per_call_string_data **slot = m_per_call_string_data.get (&cs))
3000     return *slot;
3001
3002   per_call_string_data *data = new per_call_string_data (cs, m_sg.num_nodes ());
3003   m_per_call_string_data.put (&data->m_key,
3004                               data);
3005   return data;
3006 }
3007
3008 /* Ensure that this graph has per-function-data for FUN;
3009    borrow a pointer to it.  */
3010
3011 per_function_data *
3012 exploded_graph::get_or_create_per_function_data (function *fun)
3013 {
3014   if (per_function_data **slot = m_per_function_data.get (fun))
3015     return *slot;
3016
3017   per_function_data *data = new per_function_data ();
3018   m_per_function_data.put (fun, data);
3019   return data;
3020 }
3021
3022 /* Get this graph's per-function-data for FUN if there is any,
3023    otherwise NULL.  */
3024
3025 per_function_data *
3026 exploded_graph::get_per_function_data (function *fun) const
3027 {
3028   if (per_function_data **slot
3029         = const_cast <per_function_data_t &> (m_per_function_data).get (fun))
3030     return *slot;
3031
3032   return NULL;
3033 }
3034
3035 /* Return true if FUN should be traversed directly, rather than only as
3036    called via other functions.  */
3037
3038 static bool
3039 toplevel_function_p (function *fun, logger *logger)
3040 {
3041   /* Don't directly traverse into functions that have an "__analyzer_"
3042      prefix.  Doing so is useful for the analyzer test suite, allowing
3043      us to have functions that are called in traversals, but not directly
3044      explored, thus testing how the analyzer handles calls and returns.
3045      With this, we can have DejaGnu directives that cover just the case
3046      of where a function is called by another function, without generating
3047      excess messages from the case of the first function being traversed
3048      directly.  */
3049 #define ANALYZER_PREFIX "__analyzer_"
3050   if (!strncmp (IDENTIFIER_POINTER (DECL_NAME (fun->decl)), ANALYZER_PREFIX,
3051                 strlen (ANALYZER_PREFIX)))
3052     {
3053       if (logger)
3054         logger->log ("not traversing %qE (starts with %qs)",
3055                      fun->decl, ANALYZER_PREFIX);
3056       return false;
3057     }
3058
3059   if (logger)
3060     logger->log ("traversing %qE (all checks passed)", fun->decl);
3061
3062   return true;
3063 }
3064
3065 /* Custom event for use by tainted_call_info when a callback field has been
3066    marked with __attribute__((tainted_args)), for labelling the field.  */
3067
3068 class tainted_args_field_custom_event : public custom_event
3069 {
3070 public:
3071   tainted_args_field_custom_event (tree field)
3072   : custom_event (DECL_SOURCE_LOCATION (field), NULL_TREE, 0),
3073     m_field (field)
3074   {
3075   }
3076
3077   label_text get_desc (bool can_colorize) const final override
3078   {
3079     return make_label_text (can_colorize,
3080                             "field %qE of %qT"
3081                             " is marked with %<__attribute__((tainted_args))%>",
3082                             m_field, DECL_CONTEXT (m_field));
3083   }
3084
3085 private:
3086   tree m_field;
3087 };
3088
3089 /* Custom event for use by tainted_call_info when a callback field has been
3090    marked with __attribute__((tainted_args)), for labelling the function used
3091    in that callback.  */
3092
3093 class tainted_args_callback_custom_event : public custom_event
3094 {
3095 public:
3096   tainted_args_callback_custom_event (location_t loc, tree fndecl, int depth,
3097                                  tree field)
3098   : custom_event (loc, fndecl, depth),
3099     m_field (field)
3100   {
3101   }
3102
3103   label_text get_desc (bool can_colorize) const final override
3104   {
3105     return make_label_text (can_colorize,
3106                             "function %qE used as initializer for field %qE"
3107                             " marked with %<__attribute__((tainted_args))%>",
3108                             get_fndecl (), m_field);
3109   }
3110
3111 private:
3112   tree m_field;
3113 };
3114
3115 /* Custom edge info for use when adding a function used by a callback field
3116    marked with '__attribute__((tainted_args))'.   */
3117
3118 class tainted_args_call_info : public custom_edge_info
3119 {
3120 public:
3121   tainted_args_call_info (tree field, tree fndecl, location_t loc)
3122   : m_field (field), m_fndecl (fndecl), m_loc (loc)
3123   {}
3124
3125   void print (pretty_printer *pp) const final override
3126   {
3127     pp_string (pp, "call to tainted field");
3128   };
3129
3130   bool update_model (region_model *,
3131                      const exploded_edge *,
3132                      region_model_context *) const final override
3133   {
3134     /* No-op.  */
3135     return true;
3136   }
3137
3138   void add_events_to_path (checker_path *emission_path,
3139                            const exploded_edge &) const final override
3140   {
3141     /* Show the field in the struct declaration, e.g.
3142        "(1) field 'store' is marked with '__attribute__((tainted_args))'"  */
3143     emission_path->add_event
3144       (make_unique<tainted_args_field_custom_event> (m_field));
3145
3146     /* Show the callback in the initializer
3147        e.g.
3148        "(2) function 'gadget_dev_desc_UDC_store' used as initializer
3149        for field 'store' marked with '__attribute__((tainted_args))'".  */
3150     emission_path->add_event
3151       (make_unique<tainted_args_callback_custom_event> (m_loc, m_fndecl,
3152                                                         0, m_field));
3153   }
3154
3155 private:
3156   tree m_field;
3157   tree m_fndecl;
3158   location_t m_loc;
3159 };
3160
3161 /* Given an initializer at LOC for FIELD marked with
3162    '__attribute__((tainted_args))' initialized with FNDECL, add an
3163    entrypoint to FNDECL to EG (and to its worklist) where the params to
3164    FNDECL are marked as tainted.  */
3165
3166 static void
3167 add_tainted_args_callback (exploded_graph *eg, tree field, tree fndecl,
3168                            location_t loc)
3169 {
3170   logger *logger = eg->get_logger ();
3171
3172   LOG_SCOPE (logger);
3173
3174   if (!gimple_has_body_p (fndecl))
3175     return;
3176
3177   const extrinsic_state &ext_state = eg->get_ext_state ();
3178
3179   function *fun = DECL_STRUCT_FUNCTION (fndecl);
3180   gcc_assert (fun);
3181
3182   program_point point
3183     = program_point::from_function_entry (*ext_state.get_model_manager (),
3184                                           eg->get_supergraph (), fun);
3185   program_state state (ext_state);
3186   state.push_frame (ext_state, fun);
3187
3188   if (!mark_params_as_tainted (&state, fndecl, ext_state))
3189     return;
3190
3191   if (!state.m_valid)
3192     return;
3193
3194   exploded_node *enode = eg->get_or_create_node (point, state, NULL);
3195   if (logger)
3196     {
3197       if (enode)
3198         logger->log ("created EN %i for tainted_args %qE entrypoint",
3199                      enode->m_index, fndecl);
3200       else
3201         {
3202           logger->log ("did not create enode for tainted_args %qE entrypoint",
3203                        fndecl);
3204           return;
3205         }
3206     }
3207
3208   eg->add_edge (eg->get_origin (), enode, NULL,
3209                 make_unique<tainted_args_call_info> (field, fndecl, loc));
3210 }
3211
3212 /* Callback for walk_tree for finding callbacks within initializers;
3213    ensure that any callback initializer where the corresponding field is
3214    marked with '__attribute__((tainted_args))' is treated as an entrypoint
3215    to the analysis, special-casing that the inputs to the callback are
3216    untrustworthy.  */
3217
3218 static tree
3219 add_any_callbacks (tree *tp, int *, void *data)
3220 {
3221   exploded_graph *eg = (exploded_graph *)data;
3222   if (TREE_CODE (*tp) == CONSTRUCTOR)
3223     {
3224       /* Find fields with the "tainted_args" attribute.
3225          walk_tree only walks the values, not the index values;
3226          look at the index values.  */
3227       unsigned HOST_WIDE_INT idx;
3228       constructor_elt *ce;
3229
3230       for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (*tp), idx, &ce);
3231            idx++)
3232         if (ce->index && TREE_CODE (ce->index) == FIELD_DECL)
3233           if (lookup_attribute ("tainted_args", DECL_ATTRIBUTES (ce->index)))
3234             {
3235               tree value = ce->value;
3236               if (TREE_CODE (value) == ADDR_EXPR
3237                   && TREE_CODE (TREE_OPERAND (value, 0)) == FUNCTION_DECL)
3238                 add_tainted_args_callback (eg, ce->index,
3239                                            TREE_OPERAND (value, 0),
3240                                            EXPR_LOCATION (value));
3241             }
3242     }
3243
3244   return NULL_TREE;
3245 }
3246
3247 /* Add initial nodes to EG, with entrypoints for externally-callable
3248    functions.  */
3249
3250 void
3251 exploded_graph::build_initial_worklist ()
3252 {
3253   logger * const logger = get_logger ();
3254   LOG_SCOPE (logger);
3255
3256   cgraph_node *node;
3257   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
3258   {
3259     function *fun = node->get_fun ();
3260     if (!toplevel_function_p (fun, logger))
3261       continue;
3262     exploded_node *enode = add_function_entry (fun);
3263     if (logger)
3264       {
3265         if (enode)
3266           logger->log ("created EN %i for %qE entrypoint",
3267                        enode->m_index, fun->decl);
3268         else
3269           logger->log ("did not create enode for %qE entrypoint", fun->decl);
3270       }
3271   }
3272
3273   /* Find callbacks that are reachable from global initializers.  */
3274   varpool_node *vpnode;
3275   FOR_EACH_VARIABLE (vpnode)
3276     {
3277       tree decl = vpnode->decl;
3278       tree init = DECL_INITIAL (decl);
3279       if (!init)
3280         continue;
3281       walk_tree (&init, add_any_callbacks, this, NULL);
3282     }
3283 }
3284
3285 /* The main loop of the analysis.
3286    Take freshly-created exploded_nodes from the worklist, calling
3287    process_node on them to explore the <point, state> graph.
3288    Add edges to their successors, potentially creating new successors
3289    (which are also added to the worklist).  */
3290
3291 void
3292 exploded_graph::process_worklist ()
3293 {
3294   logger * const logger = get_logger ();
3295   LOG_SCOPE (logger);
3296   auto_timevar tv (TV_ANALYZER_WORKLIST);
3297
3298   while (m_worklist.length () > 0)
3299     {
3300       exploded_node *node = m_worklist.take_next ();
3301       gcc_assert (node->get_status () == exploded_node::STATUS_WORKLIST);
3302       gcc_assert (node->m_succs.length () == 0
3303                   || node == m_origin);
3304
3305       if (logger)
3306         logger->log ("next to process: EN: %i", node->m_index);
3307
3308       /* If we have a run of nodes that are before-supernode, try merging and
3309          processing them together, rather than pairwise or individually.  */
3310       if (flag_analyzer_state_merge && node != m_origin)
3311         if (maybe_process_run_of_before_supernode_enodes (node))
3312           goto handle_limit;
3313
3314       /* Avoid exponential explosions of nodes by attempting to merge
3315          nodes that are at the same program point and which have
3316          sufficiently similar state.  */
3317       if (flag_analyzer_state_merge && node != m_origin)
3318         if (exploded_node *node_2 = m_worklist.peek_next ())
3319           {
3320             gcc_assert (node_2->get_status ()
3321                         == exploded_node::STATUS_WORKLIST);
3322             gcc_assert (node->m_succs.length () == 0);
3323             gcc_assert (node_2->m_succs.length () == 0);
3324
3325             gcc_assert (node != node_2);
3326
3327             if (logger)
3328               logger->log ("peek worklist: EN: %i", node_2->m_index);
3329
3330             if (node->get_point () == node_2->get_point ())
3331               {
3332                 const program_point &point = node->get_point ();
3333                 if (logger)
3334                   {
3335                     format f (false);
3336                     pretty_printer *pp = logger->get_printer ();
3337                     logger->start_log_line ();
3338                     logger->log_partial
3339                       ("got potential merge EN: %i and EN: %i at ",
3340                        node->m_index, node_2->m_index);
3341                     point.print (pp, f);
3342                     logger->end_log_line ();
3343                   }
3344                 const program_state &state = node->get_state ();
3345                 const program_state &state_2 = node_2->get_state ();
3346
3347                 /* They shouldn't be equal, or we wouldn't have two
3348                    separate nodes.  */
3349                 gcc_assert (state != state_2);
3350
3351                 program_state merged_state (m_ext_state);
3352                 if (state.can_merge_with_p (state_2, m_ext_state,
3353                                             point, &merged_state))
3354                   {
3355                     if (logger)
3356                       logger->log ("merging EN: %i and EN: %i",
3357                                    node->m_index, node_2->m_index);
3358
3359                     if (merged_state == state)
3360                       {
3361                         /* Then merge node_2 into node by adding an edge.  */
3362                         add_edge (node_2, node, NULL);
3363
3364                         /* Remove node_2 from the worklist.  */
3365                         m_worklist.take_next ();
3366                         node_2->set_status (exploded_node::STATUS_MERGER);
3367
3368                         /* Continue processing "node" below.  */
3369                       }
3370                     else if (merged_state == state_2)
3371                       {
3372                         /* Then merge node into node_2, and leave node_2
3373                            in the worklist, to be processed on the next
3374                            iteration.  */
3375                         add_edge (node, node_2, NULL);
3376                         node->set_status (exploded_node::STATUS_MERGER);
3377                         continue;
3378                       }
3379                     else
3380                       {
3381                         /* We have a merged state that differs from
3382                            both state and state_2.  */
3383
3384                         /* Remove node_2 from the worklist.  */
3385                         m_worklist.take_next ();
3386
3387                         /* Create (or get) an exploded node for the merged
3388                            states, adding to the worklist.  */
3389                         exploded_node *merged_enode
3390                           = get_or_create_node (node->get_point (),
3391                                                 merged_state, node);
3392                         if (merged_enode == NULL)
3393                           continue;
3394
3395                         if (logger)
3396                           logger->log ("merged EN: %i and EN: %i into EN: %i",
3397                                        node->m_index, node_2->m_index,
3398                                        merged_enode->m_index);
3399
3400                         /* "node" and "node_2" have both now been removed
3401                            from the worklist; we should not process them.
3402
3403                            "merged_enode" may be a new node; if so it will be
3404                            processed in a subsequent iteration.
3405                            Alternatively, "merged_enode" could be an existing
3406                            node; one way the latter can
3407                            happen is if we end up merging a succession of
3408                            similar nodes into one.  */
3409
3410                         /* If merged_node is one of the two we were merging,
3411                            add it back to the worklist to ensure it gets
3412                            processed.
3413
3414                            Add edges from the merged nodes to it (but not a
3415                            self-edge).  */
3416                         if (merged_enode == node)
3417                           m_worklist.add_node (merged_enode);
3418                         else
3419                           {
3420                             add_edge (node, merged_enode, NULL);
3421                             node->set_status (exploded_node::STATUS_MERGER);
3422                           }
3423
3424                         if (merged_enode == node_2)
3425                           m_worklist.add_node (merged_enode);
3426                         else
3427                           {
3428                             add_edge (node_2, merged_enode, NULL);
3429                             node_2->set_status (exploded_node::STATUS_MERGER);
3430                           }
3431
3432                         continue;
3433                       }
3434                   }
3435
3436                 /* TODO: should we attempt more than two nodes,
3437                    or just do pairs of nodes?  (and hope that we get
3438                    a cascade of mergers).  */
3439               }
3440         }
3441
3442       process_node (node);
3443
3444     handle_limit:
3445       /* Impose a hard limit on the number of exploded nodes, to ensure
3446          that the analysis terminates in the face of pathological state
3447          explosion (or bugs).
3448
3449          Specifically, the limit is on the number of PK_AFTER_SUPERNODE
3450          exploded nodes, looking at supernode exit events.
3451
3452          We use exit rather than entry since there can be multiple
3453          entry ENs, one per phi; the number of PK_AFTER_SUPERNODE ought
3454          to be equivalent to the number of supernodes multiplied by the
3455          number of states.  */
3456       const int limit = m_sg.num_nodes () * param_analyzer_bb_explosion_factor;
3457       if (m_global_stats.m_num_nodes[PK_AFTER_SUPERNODE] > limit)
3458         {
3459           if (logger)
3460             logger->log ("bailing out; too many nodes");
3461           warning_at (node->get_point ().get_location (),
3462                       OPT_Wanalyzer_too_complex,
3463                       "analysis bailed out early"
3464                       " (%i 'after-snode' enodes; %i enodes)",
3465                       m_global_stats.m_num_nodes[PK_AFTER_SUPERNODE],
3466                       m_nodes.length ());
3467           return;
3468         }
3469     }
3470 }
3471
3472 /* Attempt to process a consecutive run of sufficiently-similar nodes in
3473    the worklist at a CFG join-point (having already popped ENODE from the
3474    head of the worklist).
3475
3476    If ENODE's point is of the form (before-supernode, SNODE) and the next
3477    nodes in the worklist are a consecutive run of enodes of the same form,
3478    for the same supernode as ENODE (but potentially from different in-edges),
3479    process them all together, setting their status to STATUS_BULK_MERGED,
3480    and return true.
3481    Otherwise, return false, in which case ENODE must be processed in the
3482    normal way.
3483
3484    When processing them all together, generate successor states based
3485    on phi nodes for the appropriate CFG edges, and then attempt to merge
3486    these states into a minimal set of merged successor states, partitioning
3487    the inputs by merged successor state.
3488
3489    Create new exploded nodes for all of the merged states, and add edges
3490    connecting the input enodes to the corresponding merger exploded nodes.
3491
3492    We hope we have a much smaller number of merged successor states
3493    compared to the number of input enodes - ideally just one,
3494    if all successor states can be merged.
3495
3496    Processing and merging many together as one operation rather than as
3497    pairs avoids scaling issues where per-pair mergers could bloat the
3498    graph with merger nodes (especially so after switch statements).  */
3499
3500 bool
3501 exploded_graph::
3502 maybe_process_run_of_before_supernode_enodes (exploded_node *enode)
3503 {
3504   /* A struct for tracking per-input state.  */
3505   struct item
3506   {
3507     item (exploded_node *input_enode)
3508     : m_input_enode (input_enode),
3509       m_processed_state (input_enode->get_state ()),
3510       m_merger_idx (-1)
3511     {}
3512
3513     exploded_node *m_input_enode;
3514     program_state m_processed_state;
3515     int m_merger_idx;
3516   };
3517
3518   gcc_assert (enode->get_status () == exploded_node::STATUS_WORKLIST);
3519   gcc_assert (enode->m_succs.length () == 0);
3520
3521   const program_point &point = enode->get_point ();
3522
3523   if (point.get_kind () != PK_BEFORE_SUPERNODE)
3524     return false;
3525
3526   const supernode *snode = point.get_supernode ();
3527
3528   logger * const logger = get_logger ();
3529   LOG_SCOPE (logger);
3530
3531   /* Find a run of enodes in the worklist that are before the same supernode,
3532      but potentially from different in-edges.  */
3533   auto_vec <exploded_node *> enodes;
3534   enodes.safe_push (enode);
3535   while (exploded_node *enode_2 = m_worklist.peek_next ())
3536     {
3537       gcc_assert (enode_2->get_status ()
3538                   == exploded_node::STATUS_WORKLIST);
3539       gcc_assert (enode_2->m_succs.length () == 0);
3540
3541       const program_point &point_2 = enode_2->get_point ();
3542
3543       if (point_2.get_kind () == PK_BEFORE_SUPERNODE
3544           && point_2.get_supernode () == snode
3545           && &point_2.get_call_string () == &point.get_call_string ())
3546         {
3547           enodes.safe_push (enode_2);
3548           m_worklist.take_next ();
3549         }
3550       else
3551         break;
3552     }
3553
3554   /* If the only node is ENODE, then give up.  */
3555   if (enodes.length () == 1)
3556     return false;
3557
3558   if (logger)
3559     logger->log ("got run of %i enodes for SN: %i",
3560                  enodes.length (), snode->m_index);
3561
3562   /* All of these enodes have a shared successor point (even if they
3563      were for different in-edges).  */
3564   program_point next_point (point.get_next ());
3565
3566   /* Calculate the successor state for each enode in enodes.  */
3567   auto_delete_vec<item> items (enodes.length ());
3568   unsigned i;
3569   exploded_node *iter_enode;
3570   FOR_EACH_VEC_ELT (enodes, i, iter_enode)
3571     {
3572       item *it = new item (iter_enode);
3573       items.quick_push (it);
3574       const program_state &state = iter_enode->get_state ();
3575       program_state *next_state = &it->m_processed_state;
3576       next_state->validate (m_ext_state);
3577       const program_point &iter_point = iter_enode->get_point ();
3578       if (const superedge *iter_sedge = iter_point.get_from_edge ())
3579         {
3580           uncertainty_t uncertainty;
3581           impl_region_model_context ctxt (*this, iter_enode,
3582                                           &state, next_state,
3583                                           &uncertainty, NULL, NULL);
3584           const cfg_superedge *last_cfg_superedge
3585             = iter_sedge->dyn_cast_cfg_superedge ();
3586           if (last_cfg_superedge)
3587             next_state->m_region_model->update_for_phis
3588               (snode, last_cfg_superedge, &ctxt);
3589         }
3590       next_state->validate (m_ext_state);
3591     }
3592
3593   /* Attempt to partition the items into a set of merged states.
3594      We hope we have a much smaller number of merged states
3595      compared to the number of input enodes - ideally just one,
3596      if all can be merged.  */
3597   auto_delete_vec <program_state> merged_states;
3598   auto_vec<item *> first_item_for_each_merged_state;
3599   item *it;
3600   FOR_EACH_VEC_ELT (items, i, it)
3601     {
3602       const program_state &it_state = it->m_processed_state;
3603       program_state *merged_state;
3604       unsigned iter_merger_idx;
3605       FOR_EACH_VEC_ELT (merged_states, iter_merger_idx, merged_state)
3606         {
3607           merged_state->validate (m_ext_state);
3608           program_state merge (m_ext_state);
3609           if (it_state.can_merge_with_p (*merged_state, m_ext_state,
3610                                          next_point, &merge))
3611             {
3612               *merged_state = merge;
3613               merged_state->validate (m_ext_state);
3614               it->m_merger_idx = iter_merger_idx;
3615               if (logger)
3616                 logger->log ("reusing merger state %i for item %i (EN: %i)",
3617                              it->m_merger_idx, i, it->m_input_enode->m_index);
3618               goto got_merger;
3619             }
3620         }
3621       /* If it couldn't be merged with any existing merged_states,
3622          create a new one.  */
3623       if (it->m_merger_idx == -1)
3624         {
3625           it->m_merger_idx = merged_states.length ();
3626           merged_states.safe_push (new program_state (it_state));
3627           first_item_for_each_merged_state.safe_push (it);
3628           if (logger)
3629             logger->log ("using new merger state %i for item %i (EN: %i)",
3630                          it->m_merger_idx, i, it->m_input_enode->m_index);
3631         }
3632     got_merger:
3633       gcc_assert (it->m_merger_idx >= 0);
3634       gcc_assert ((unsigned)it->m_merger_idx < merged_states.length ());
3635     }
3636
3637   /* Create merger nodes.  */
3638   auto_vec<exploded_node *> next_enodes (merged_states.length ());
3639   program_state *merged_state;
3640   FOR_EACH_VEC_ELT (merged_states, i, merged_state)
3641     {
3642       exploded_node *src_enode
3643         = first_item_for_each_merged_state[i]->m_input_enode;
3644       exploded_node *next
3645         = get_or_create_node (next_point, *merged_state, src_enode);
3646       /* "next" could be NULL; we handle that when adding the edges below.  */
3647       next_enodes.quick_push (next);
3648       if (logger)
3649         {
3650           if (next)
3651             logger->log ("using EN: %i for merger state %i", next->m_index, i);
3652           else
3653             logger->log ("using NULL enode for merger state %i", i);
3654         }
3655     }
3656
3657   /* Create edges from each input enode to the appropriate successor enode.
3658      Update the status of the now-processed input enodes.  */
3659   FOR_EACH_VEC_ELT (items, i, it)
3660     {
3661       exploded_node *next = next_enodes[it->m_merger_idx];
3662       if (next)
3663         add_edge (it->m_input_enode, next, NULL);
3664       it->m_input_enode->set_status (exploded_node::STATUS_BULK_MERGED);
3665     }
3666
3667   if (logger)
3668     logger->log ("merged %i in-enodes into %i out-enode(s) at SN: %i",
3669                  items.length (), merged_states.length (), snode->m_index);
3670
3671   return true;
3672 }
3673
3674 /* Return true if STMT must appear at the start of its exploded node, and
3675    thus we can't consolidate its effects within a run of other statements,
3676    where PREV_STMT was the previous statement.  */
3677
3678 static bool
3679 stmt_requires_new_enode_p (const gimple *stmt,
3680                            const gimple *prev_stmt)
3681 {
3682   if (const gcall *call = dyn_cast <const gcall *> (stmt))
3683     {
3684       /* Stop consolidating at calls to
3685          "__analyzer_dump_exploded_nodes", so they always appear at the
3686          start of an exploded_node.  */
3687       if (is_special_named_call_p (call, "__analyzer_dump_exploded_nodes",
3688                                    1))
3689         return true;
3690
3691       /* sm-signal.cc injects an additional custom eedge at "signal" calls
3692          from the registration enode to the handler enode, separate from the
3693          regular next state, which defeats the "detect state change" logic
3694          in process_node.  Work around this via special-casing, to ensure
3695          we split the enode immediately before any "signal" call.  */
3696       if (is_special_named_call_p (call, "signal", 2))
3697         return true;
3698     }
3699
3700   /* If we had a PREV_STMT with an unknown location, and this stmt
3701      has a known location, then if a state change happens here, it
3702      could be consolidated into PREV_STMT, giving us an event with
3703      no location.  Ensure that STMT gets its own exploded_node to
3704      avoid this.  */
3705   if (get_pure_location (prev_stmt->location) == UNKNOWN_LOCATION
3706       && get_pure_location (stmt->location) != UNKNOWN_LOCATION)
3707     return true;
3708
3709   return false;
3710 }
3711
3712 /* Return true if OLD_STATE and NEW_STATE are sufficiently different that
3713    we should split enodes and create an exploded_edge separating them
3714    (which makes it easier to identify state changes of intereset when
3715    constructing checker_paths).  */
3716
3717 static bool
3718 state_change_requires_new_enode_p (const program_state &old_state,
3719                                    const program_state &new_state)
3720 {
3721   /* Changes in dynamic extents signify creations of heap/alloca regions
3722      and resizings of heap regions; likely to be of interest in
3723      diagnostic paths.  */
3724   if (old_state.m_region_model->get_dynamic_extents ()
3725       != new_state.m_region_model->get_dynamic_extents ())
3726     return true;
3727
3728   /* Changes in sm-state are of interest.  */
3729   int sm_idx;
3730   sm_state_map *smap;
3731   FOR_EACH_VEC_ELT (old_state.m_checker_states, sm_idx, smap)
3732     {
3733       const sm_state_map *old_smap = old_state.m_checker_states[sm_idx];
3734       const sm_state_map *new_smap = new_state.m_checker_states[sm_idx];
3735       if (*old_smap != *new_smap)
3736         return true;
3737     }
3738
3739   return false;
3740 }
3741
3742 /* Create enodes and eedges for the function calls that doesn't have an
3743    underlying call superedge.
3744
3745    Such case occurs when GCC's middle end didn't know which function to
3746    call but the analyzer does (with the help of current state).
3747
3748    Some example such calls are dynamically dispatched calls to virtual
3749    functions or calls that happen via function pointer.  */
3750
3751 bool
3752 exploded_graph::maybe_create_dynamic_call (const gcall *call,
3753                                            tree fn_decl,
3754                                            exploded_node *node,
3755                                            program_state next_state,
3756                                            program_point &next_point,
3757                                            uncertainty_t *uncertainty,
3758                                            logger *logger)
3759 {
3760   LOG_FUNC (logger);
3761
3762   const program_point *this_point = &node->get_point ();
3763   function *fun = DECL_STRUCT_FUNCTION (fn_decl);
3764   if (fun)
3765     {
3766       const supergraph &sg = this->get_supergraph ();
3767       supernode *sn_entry = sg.get_node_for_function_entry (fun);
3768       supernode *sn_exit = sg.get_node_for_function_exit (fun);
3769
3770       program_point new_point
3771         = program_point::before_supernode (sn_entry,
3772                                            NULL,
3773                                            this_point->get_call_string ());
3774
3775       new_point.push_to_call_stack (sn_exit,
3776                                     next_point.get_supernode());
3777
3778       /* Impose a maximum recursion depth and don't analyze paths
3779          that exceed it further.
3780          This is something of a blunt workaround, but it only
3781          applies to recursion (and mutual recursion), not to
3782          general call stacks.  */
3783       if (new_point.get_call_string ().calc_recursion_depth ()
3784           > param_analyzer_max_recursion_depth)
3785       {
3786         if (logger)
3787           logger->log ("rejecting call edge: recursion limit exceeded");
3788         return false;
3789       }
3790
3791       next_state.push_call (*this, node, call, uncertainty);
3792
3793       if (next_state.m_valid)
3794         {
3795           if (logger)
3796             logger->log ("Discovered call to %s [SN: %i -> SN: %i]",
3797                          function_name(fun),
3798                          this_point->get_supernode ()->m_index,
3799                          sn_entry->m_index);
3800
3801           exploded_node *enode = get_or_create_node (new_point,
3802                                                      next_state,
3803                                                      node);
3804           if (enode)
3805             add_edge (node,enode, NULL,
3806                       make_unique<dynamic_call_info_t> (call));
3807           return true;
3808         }
3809     }
3810   return false;
3811 }
3812
3813 /* Subclass of path_context for use within exploded_graph::process_node,
3814    so that we can split states e.g. at "realloc" calls.  */
3815
3816 class impl_path_context : public path_context
3817 {
3818 public:
3819   impl_path_context (const program_state *cur_state)
3820   : m_cur_state (cur_state),
3821     m_terminate_path (false)
3822   {
3823   }
3824
3825   bool bifurcation_p () const
3826   {
3827     return m_custom_eedge_infos.length () > 0;
3828   }
3829
3830   const program_state &get_state_at_bifurcation () const
3831   {
3832     gcc_assert (m_state_at_bifurcation);
3833     return *m_state_at_bifurcation;
3834   }
3835
3836   void
3837   bifurcate (std::unique_ptr<custom_edge_info> info) final override
3838   {
3839     if (m_state_at_bifurcation)
3840       /* Verify that the state at bifurcation is consistent when we
3841          split into multiple out-edges.  */
3842       gcc_assert (*m_state_at_bifurcation == *m_cur_state);
3843     else
3844       /* Take a copy of the cur_state at the moment when bifurcation
3845          happens.  */
3846       m_state_at_bifurcation
3847         = std::unique_ptr<program_state> (new program_state (*m_cur_state));
3848
3849     /* Take ownership of INFO.  */
3850     m_custom_eedge_infos.safe_push (info.release ());
3851   }
3852
3853   void terminate_path () final override
3854   {
3855     m_terminate_path = true;
3856   }
3857
3858   bool terminate_path_p () const final override
3859   {
3860     return m_terminate_path;
3861   }
3862
3863   const vec<custom_edge_info *> & get_custom_eedge_infos ()
3864   {
3865     return m_custom_eedge_infos;
3866   }
3867
3868 private:
3869   const program_state *m_cur_state;
3870
3871   /* Lazily-created copy of the state before the split.  */
3872   std::unique_ptr<program_state> m_state_at_bifurcation;
3873
3874   auto_vec <custom_edge_info *> m_custom_eedge_infos;
3875
3876   bool m_terminate_path;
3877 };
3878
3879 /* A subclass of pending_diagnostic for complaining about jumps through NULL
3880    function pointers.  */
3881
3882 class jump_through_null : public pending_diagnostic_subclass<jump_through_null>
3883 {
3884 public:
3885   jump_through_null (const gcall *call)
3886   : m_call (call)
3887   {}
3888
3889   const char *get_kind () const final override
3890   {
3891     return "jump_through_null";
3892   }
3893
3894   bool operator== (const jump_through_null &other) const
3895   {
3896     return m_call == other.m_call;
3897   }
3898
3899   int get_controlling_option () const final override
3900   {
3901     return OPT_Wanalyzer_jump_through_null;
3902   }
3903
3904   bool emit (rich_location *rich_loc) final override
3905   {
3906     return warning_at (rich_loc, get_controlling_option (),
3907                        "jump through null pointer");
3908   }
3909
3910   label_text describe_final_event (const evdesc::final_event &ev) final override
3911   {
3912     return ev.formatted_print ("jump through null pointer here");
3913   }
3914
3915 private:
3916   const gcall *m_call;
3917 };
3918
3919 /* The core of exploded_graph::process_worklist (the main analysis loop),
3920    handling one node in the worklist.
3921
3922    Get successor <point, state> pairs for NODE, calling get_or_create on
3923    them, and adding an exploded_edge to each successors.
3924
3925    Freshly-created nodes will be added to the worklist.  */
3926
3927 void
3928 exploded_graph::process_node (exploded_node *node)
3929 {
3930   logger * const logger = get_logger ();
3931   LOG_FUNC_1 (logger, "EN: %i", node->m_index);
3932
3933   node->set_status (exploded_node::STATUS_PROCESSED);
3934
3935   const program_point &point = node->get_point ();
3936
3937   /* Update cfun and input_location in case of an ICE: make it easier to
3938      track down which source construct we're failing to handle.  */
3939   auto_cfun sentinel (node->get_function ());
3940   const gimple *stmt = point.get_stmt ();
3941   if (stmt)
3942     input_location = stmt->location;
3943
3944   const program_state &state = node->get_state ();
3945   if (logger)
3946     {
3947       pretty_printer *pp = logger->get_printer ();
3948       logger->start_log_line ();
3949       pp_string (pp, "point: ");
3950       point.print (pp, format (false));
3951       pp_string (pp, ", state: ");
3952       state.dump_to_pp (m_ext_state, true, false, pp);
3953       logger->end_log_line ();
3954     }
3955
3956   switch (point.get_kind ())
3957     {
3958     default:
3959       gcc_unreachable ();
3960     case PK_ORIGIN:
3961       /* This node exists to simplify finding the shortest path
3962          to an exploded_node.  */
3963       break;
3964
3965     case PK_BEFORE_SUPERNODE:
3966       {
3967         program_state next_state (state);
3968         uncertainty_t uncertainty;
3969
3970         if (point.get_from_edge ())
3971           {
3972             impl_region_model_context ctxt (*this, node,
3973                                             &state, &next_state,
3974                                             &uncertainty, NULL, NULL);
3975             const cfg_superedge *last_cfg_superedge
3976               = point.get_from_edge ()->dyn_cast_cfg_superedge ();
3977             if (last_cfg_superedge)
3978               next_state.m_region_model->update_for_phis
3979                 (node->get_supernode (),
3980                  last_cfg_superedge,
3981                  &ctxt);
3982             program_state::detect_leaks (state, next_state, NULL,
3983                                          get_ext_state (), &ctxt);
3984           }
3985
3986         program_point next_point (point.get_next ());
3987         exploded_node *next = get_or_create_node (next_point, next_state, node);
3988         if (next)
3989           add_edge (node, next, NULL);
3990       }
3991       break;
3992     case PK_BEFORE_STMT:
3993       {
3994         /* Determine the effect of a run of one or more statements
3995            within one supernode, generating an edge to the program_point
3996            after the last statement that's processed.
3997
3998            Stop iterating statements and thus consolidating into one enode
3999            when:
4000            - reaching the end of the statements in the supernode
4001            - if an sm-state-change occurs (so that it gets its own
4002              exploded_node)
4003            - if "-fanalyzer-fine-grained" is active
4004            - encountering certain statements must appear at the start of
4005            their enode (for which stmt_requires_new_enode_p returns true)
4006
4007            Update next_state in-place, to get the result of the one
4008            or more stmts that are processed.
4009
4010            Split the node in-place if an sm-state-change occurs, so that
4011            the sm-state-change occurs on an edge where the src enode has
4012            exactly one stmt, the one that caused the change. */
4013         program_state next_state (state);
4014
4015         impl_path_context path_ctxt (&next_state);
4016
4017         uncertainty_t uncertainty;
4018         const supernode *snode = point.get_supernode ();
4019         unsigned stmt_idx;
4020         const gimple *prev_stmt = NULL;
4021         for (stmt_idx = point.get_stmt_idx ();
4022              stmt_idx < snode->m_stmts.length ();
4023              stmt_idx++)
4024           {
4025             const gimple *stmt = snode->m_stmts[stmt_idx];
4026
4027             if (stmt_idx > point.get_stmt_idx ())
4028               if (stmt_requires_new_enode_p (stmt, prev_stmt))
4029                 {
4030                   stmt_idx--;
4031                   break;
4032                 }
4033             prev_stmt = stmt;
4034
4035             program_state old_state (next_state);
4036
4037             /* Process the stmt.  */
4038             exploded_node::on_stmt_flags flags
4039               = node->on_stmt (*this, snode, stmt, &next_state, &uncertainty,
4040                                &path_ctxt);
4041             node->m_num_processed_stmts++;
4042
4043             /* If flags.m_terminate_path, stop analyzing; any nodes/edges
4044                will have been added by on_stmt (e.g. for handling longjmp).  */
4045             if (flags.m_terminate_path)
4046               return;
4047
4048             if (next_state.m_region_model)
4049               {
4050                 impl_region_model_context ctxt (*this, node,
4051                                                 &old_state, &next_state,
4052                                                 &uncertainty, NULL, stmt);
4053                 program_state::detect_leaks (old_state, next_state, NULL,
4054                                              get_ext_state (), &ctxt);
4055               }
4056
4057             unsigned next_idx = stmt_idx + 1;
4058             program_point next_point
4059               = (next_idx < point.get_supernode ()->m_stmts.length ()
4060                  ? program_point::before_stmt (point.get_supernode (), next_idx,
4061                                                point.get_call_string ())
4062                  : program_point::after_supernode (point.get_supernode (),
4063                                                    point.get_call_string ()));
4064             next_state = next_state.prune_for_point (*this, next_point, node,
4065                                                      &uncertainty);
4066
4067             if (flag_analyzer_fine_grained
4068                 || state_change_requires_new_enode_p (old_state, next_state)
4069                 || path_ctxt.bifurcation_p ()
4070                 || path_ctxt.terminate_path_p ())
4071               {
4072                 program_point split_point
4073                   = program_point::before_stmt (point.get_supernode (),
4074                                                 stmt_idx,
4075                                                 point.get_call_string ());
4076                 if (split_point != node->get_point ())
4077                   {
4078                     /* If we're not at the start of NODE, split the enode at
4079                        this stmt, so we have:
4080                          node -> split_enode
4081                        so that when split_enode is processed the next edge
4082                        we add will be:
4083                          split_enode -> next
4084                        and any state change will effectively occur on that
4085                        latter edge, and split_enode will contain just stmt.  */
4086                     if (logger)
4087                       logger->log ("getting split_enode");
4088                     exploded_node *split_enode
4089                       = get_or_create_node (split_point, old_state, node);
4090                     if (!split_enode)
4091                       return;
4092                     /* "stmt" will be reprocessed when split_enode is
4093                        processed.  */
4094                     node->m_num_processed_stmts--;
4095                     if (logger)
4096                       logger->log ("creating edge to split_enode");
4097                     add_edge (node, split_enode, NULL);
4098                     return;
4099                   }
4100                 else
4101                   /* If we're at the start of NODE, stop iterating,
4102                      so that an edge will be created from NODE to
4103                      (next_point, next_state) below. */
4104                   break;
4105               }
4106           }
4107         unsigned next_idx = stmt_idx + 1;
4108         program_point next_point
4109           = (next_idx < point.get_supernode ()->m_stmts.length ()
4110              ? program_point::before_stmt (point.get_supernode (), next_idx,
4111                                            point.get_call_string ())
4112              : program_point::after_supernode (point.get_supernode (),
4113                                                point.get_call_string ()));
4114         if (path_ctxt.terminate_path_p ())
4115           {
4116             if (logger)
4117               logger->log ("not adding node: terminating path");
4118           }
4119         else
4120           {
4121             exploded_node *next
4122               = get_or_create_node (next_point, next_state, node);
4123             if (next)
4124               add_edge (node, next, NULL);
4125           }
4126
4127         /* If we have custom edge infos, "bifurcate" the state
4128            accordingly, potentially creating a new state/enode/eedge
4129            instances.  For example, to handle a "realloc" call, we
4130            might split into 3 states, for the "failure",
4131            "resizing in place", and "moving to a new buffer" cases.  */
4132         for (auto edge_info_iter : path_ctxt.get_custom_eedge_infos ())
4133           {
4134             /* Take ownership of the edge infos from the path_ctxt.  */
4135             std::unique_ptr<custom_edge_info> edge_info (edge_info_iter);
4136             if (logger)
4137               {
4138                 logger->start_log_line ();
4139                 logger->log_partial ("bifurcating for edge: ");
4140                 edge_info->print (logger->get_printer ());
4141                 logger->end_log_line ();
4142               }
4143             program_state bifurcated_new_state
4144               (path_ctxt.get_state_at_bifurcation ());
4145
4146             /* Apply edge_info to state.  */
4147             impl_region_model_context
4148               bifurcation_ctxt (*this,
4149                                 node, // enode_for_diag
4150                                 &path_ctxt.get_state_at_bifurcation (),
4151                                 &bifurcated_new_state,
4152                                 NULL, // uncertainty_t *uncertainty
4153                                 NULL, // path_context *path_ctxt
4154                                 stmt);
4155             if (edge_info->update_state (&bifurcated_new_state,
4156                                          NULL, /* no exploded_edge yet.  */
4157                                          &bifurcation_ctxt))
4158               {
4159                 exploded_node *next2
4160                   = get_or_create_node (next_point, bifurcated_new_state, node);
4161                 if (next2)
4162                   add_edge (node, next2, NULL, std::move (edge_info));
4163               }
4164             else
4165               {
4166                 if (logger)
4167                   logger->log ("infeasible state, not adding node");
4168               }
4169           }
4170       }
4171       break;
4172     case PK_AFTER_SUPERNODE:
4173       {
4174         bool found_a_superedge = false;
4175         bool is_an_exit_block = false;
4176         /* If this is an EXIT BB, detect leaks, and potentially
4177            create a function summary.  */
4178         if (point.get_supernode ()->return_p ())
4179           {
4180             is_an_exit_block = true;
4181             node->detect_leaks (*this);
4182             if (flag_analyzer_call_summaries
4183                 && point.get_call_string ().empty_p ())
4184               {
4185                 /* TODO: create function summary
4186                    There can be more than one; each corresponds to a different
4187                    final enode in the function.  */
4188                 if (logger)
4189                   {
4190                     pretty_printer *pp = logger->get_printer ();
4191                     logger->start_log_line ();
4192                     logger->log_partial
4193                       ("would create function summary for %qE; state: ",
4194                        point.get_fndecl ());
4195                     state.dump_to_pp (m_ext_state, true, false, pp);
4196                     logger->end_log_line ();
4197                   }
4198                 per_function_data *per_fn_data
4199                   = get_or_create_per_function_data (point.get_function ());
4200                 per_fn_data->add_call_summary (node);
4201               }
4202           }
4203         /* Traverse into successors of the supernode.  */
4204         int i;
4205         superedge *succ;
4206         FOR_EACH_VEC_ELT (point.get_supernode ()->m_succs, i, succ)
4207           {
4208             found_a_superedge = true;
4209             if (logger)
4210               {
4211                 label_text succ_desc (succ->get_description (false));
4212                 logger->log ("considering SN: %i -> SN: %i (%s)",
4213                              succ->m_src->m_index, succ->m_dest->m_index,
4214                              succ_desc.get ());
4215               }
4216
4217             program_point next_point
4218               = program_point::before_supernode (succ->m_dest, succ,
4219                                                  point.get_call_string ());
4220             program_state next_state (state);
4221             uncertainty_t uncertainty;
4222
4223             /* Make use the current state and try to discover and analyse
4224                indirect function calls (a call that doesn't have an underlying
4225                cgraph edge representing call).
4226
4227                Some examples of such calls are virtual function calls
4228                and calls that happen via a function pointer.  */
4229             if (succ->m_kind == SUPEREDGE_INTRAPROCEDURAL_CALL
4230                 && !(succ->get_any_callgraph_edge ()))
4231               {
4232                 const gcall *call
4233                   = point.get_supernode ()->get_final_call ();
4234
4235                 impl_region_model_context ctxt (*this,
4236                                                 node,
4237                                                 &state,
4238                                                 &next_state,
4239                                                 &uncertainty,
4240                                                 NULL,
4241                                                 point.get_stmt());
4242
4243                 region_model *model = state.m_region_model;
4244                 bool call_discovered = false;
4245
4246                 if (tree fn_decl = model->get_fndecl_for_call (call, &ctxt))
4247                   call_discovered = maybe_create_dynamic_call (call,
4248                                                                fn_decl,
4249                                                                node,
4250                                                                next_state,
4251                                                                next_point,
4252                                                                &uncertainty,
4253                                                                logger);
4254                 if (!call_discovered)
4255                   {
4256                     /* Check for jump through NULL.  */
4257                     if (tree fn_ptr = gimple_call_fn (call))
4258                       {
4259                         const svalue *fn_ptr_sval
4260                           = model->get_rvalue (fn_ptr, &ctxt);
4261                         if (fn_ptr_sval->all_zeroes_p ())
4262                           ctxt.warn (make_unique<jump_through_null> (call));
4263                       }
4264
4265                     /* An unknown function or a special function was called
4266                        at this point, in such case, don't terminate the
4267                        analysis of the current function.
4268
4269                        The analyzer handles calls to such functions while
4270                        analysing the stmt itself, so the function call
4271                        must have been handled by the anlyzer till now.  */
4272                     exploded_node *next
4273                       = get_or_create_node (next_point,
4274                                             next_state,
4275                                             node);
4276                     if (next)
4277                       add_edge (node, next, succ);
4278                   }
4279               }
4280
4281             if (!node->on_edge (*this, succ, &next_point, &next_state,
4282                                 &uncertainty))
4283               {
4284                 if (logger)
4285                   logger->log ("skipping impossible edge to SN: %i",
4286                                succ->m_dest->m_index);
4287                 continue;
4288               }
4289             exploded_node *next = get_or_create_node (next_point, next_state,
4290                                                       node);
4291             if (next)
4292               {
4293                 add_edge (node, next, succ);
4294
4295                 /* We might have a function entrypoint.  */
4296                 detect_infinite_recursion (next);
4297               }
4298           }
4299
4300         /* Return from the calls which doesn't have a return superedge.
4301            Such case occurs when GCC's middle end didn't knew which function to
4302            call but analyzer did.  */
4303         if ((is_an_exit_block && !found_a_superedge)
4304             && (!point.get_call_string ().empty_p ()))
4305           {
4306             const call_string &cs = point.get_call_string ();
4307             program_point next_point
4308               = program_point::before_supernode (cs.get_caller_node (),
4309                                                  NULL,
4310                                                  cs);
4311             program_state next_state (state);
4312             uncertainty_t uncertainty;
4313
4314             const gcall *call
4315               = next_point.get_supernode ()->get_returning_call ();
4316
4317             if (call)
4318               next_state.returning_call (*this, node, call, &uncertainty);
4319
4320             if (next_state.m_valid)
4321               {
4322                 next_point.pop_from_call_stack ();
4323                 exploded_node *enode = get_or_create_node (next_point,
4324                                                            next_state,
4325                                                            node);
4326                 if (enode)
4327                   add_edge (node, enode, NULL,
4328                             make_unique<dynamic_call_info_t> (call, true));
4329               }
4330           }
4331       }
4332       break;
4333     }
4334 }
4335
4336 /* Ensure that this graph has a stats instance for FN, return it.
4337    FN can be NULL, in which case a stats instances is returned covering
4338    "functionless" parts of the graph (the origin node).  */
4339
4340 stats *
4341 exploded_graph::get_or_create_function_stats (function *fn)
4342 {
4343   if (!fn)
4344     return &m_functionless_stats;
4345
4346   if (stats **slot = m_per_function_stats.get (fn))
4347     return *slot;
4348   else
4349     {
4350       int num_supernodes = fn ? n_basic_blocks_for_fn (fn) : 0;
4351       /* not quite the num supernodes, but nearly.  */
4352       stats *new_stats = new stats (num_supernodes);
4353       m_per_function_stats.put (fn, new_stats);
4354       return new_stats;
4355     }
4356 }
4357
4358 /* Print bar charts to PP showing:
4359    - the number of enodes per function, and
4360    - for each function:
4361      - the number of enodes per supernode/BB
4362      - the number of excess enodes per supernode/BB beyond the
4363        per-program-point limit, if there were any.  */
4364
4365 void
4366 exploded_graph::print_bar_charts (pretty_printer *pp) const
4367 {
4368   cgraph_node *cgnode;
4369
4370   pp_string (pp, "enodes per function:");
4371   pp_newline (pp);
4372   bar_chart enodes_per_function;
4373   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (cgnode)
4374     {
4375       function *fn = cgnode->get_fun ();
4376       const stats * const *s_ptr
4377         = const_cast <function_stat_map_t &> (m_per_function_stats).get (fn);
4378       enodes_per_function.add_item (function_name (fn),
4379                                     s_ptr ? (*s_ptr)->get_total_enodes () : 0);
4380     }
4381   enodes_per_function.print (pp);
4382
4383   /* Accumulate number of enodes per supernode.  */
4384   auto_vec<unsigned> enodes_per_supernode (m_sg.num_nodes ());
4385   for (int i = 0; i < m_sg.num_nodes (); i++)
4386     enodes_per_supernode.quick_push (0);
4387   int i;
4388   exploded_node *enode;
4389   FOR_EACH_VEC_ELT (m_nodes, i, enode)
4390     {
4391       const supernode *iter_snode = enode->get_supernode ();
4392       if (!iter_snode)
4393         continue;
4394       enodes_per_supernode[iter_snode->m_index]++;
4395     }
4396
4397   /* Accumulate excess enodes per supernode.  */
4398   auto_vec<unsigned> excess_enodes_per_supernode (m_sg.num_nodes ());
4399   for (int i = 0; i < m_sg.num_nodes (); i++)
4400     excess_enodes_per_supernode.quick_push (0);
4401   for (point_map_t::iterator iter = m_per_point_data.begin ();
4402        iter != m_per_point_data.end (); ++iter)
4403     {
4404       const program_point *point = (*iter).first;
4405       const supernode *iter_snode = point->get_supernode ();
4406       if (!iter_snode)
4407         continue;
4408       const per_program_point_data *point_data = (*iter).second;
4409       excess_enodes_per_supernode[iter_snode->m_index]
4410         += point_data->m_excess_enodes;
4411     }
4412
4413   /* Show per-function bar_charts of enodes per supernode/BB.  */
4414   pp_string (pp, "per-function enodes per supernode/BB:");
4415   pp_newline (pp);
4416   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (cgnode)
4417     {
4418       function *fn = cgnode->get_fun ();
4419       pp_printf (pp, "function: %qs", function_name (fn));
4420       pp_newline (pp);
4421
4422       bar_chart enodes_per_snode;
4423       bar_chart excess_enodes_per_snode;
4424       bool have_excess_enodes = false;
4425       for (int i = 0; i < m_sg.num_nodes (); i++)
4426         {
4427           const supernode *iter_snode = m_sg.get_node_by_index (i);
4428           if (iter_snode->get_function () != fn)
4429             continue;
4430           pretty_printer tmp_pp;
4431           pp_printf (&tmp_pp, "sn %i (bb %i)",
4432                      iter_snode->m_index, iter_snode->m_bb->index);
4433           enodes_per_snode.add_item (pp_formatted_text (&tmp_pp),
4434                                      enodes_per_supernode[iter_snode->m_index]);
4435           const int num_excess
4436             = excess_enodes_per_supernode[iter_snode->m_index];
4437           excess_enodes_per_snode.add_item (pp_formatted_text (&tmp_pp),
4438                                             num_excess);
4439           if (num_excess)
4440             have_excess_enodes = true;
4441         }
4442       enodes_per_snode.print (pp);
4443       if (have_excess_enodes)
4444         {
4445           pp_printf (pp, "EXCESS ENODES:");
4446           pp_newline (pp);
4447           excess_enodes_per_snode.print (pp);
4448         }
4449     }
4450 }
4451
4452 /* Write all stats information to this graph's logger, if any.  */
4453
4454 void
4455 exploded_graph::log_stats () const
4456 {
4457   logger * const logger = get_logger ();
4458   if (!logger)
4459     return;
4460
4461   LOG_SCOPE (logger);
4462
4463   m_ext_state.get_engine ()->log_stats (logger);
4464
4465   logger->log ("m_sg.num_nodes (): %i", m_sg.num_nodes ());
4466   logger->log ("m_nodes.length (): %i", m_nodes.length ());
4467   logger->log ("m_edges.length (): %i", m_edges.length ());
4468   logger->log ("remaining enodes in worklist: %i", m_worklist.length ());
4469
4470   logger->log ("global stats:");
4471   m_global_stats.log (logger);
4472
4473   for (function_stat_map_t::iterator iter = m_per_function_stats.begin ();
4474        iter != m_per_function_stats.end ();
4475        ++iter)
4476     {
4477       function *fn = (*iter).first;
4478       log_scope s (logger, function_name (fn));
4479       (*iter).second->log (logger);
4480     }
4481
4482   print_bar_charts (logger->get_printer ());
4483 }
4484
4485 /* Dump all stats information to OUT.  */
4486
4487 void
4488 exploded_graph::dump_stats (FILE *out) const
4489 {
4490   fprintf (out, "m_sg.num_nodes (): %i\n", m_sg.num_nodes ());
4491   fprintf (out, "m_nodes.length (): %i\n", m_nodes.length ());
4492   fprintf (out, "m_edges.length (): %i\n", m_edges.length ());
4493   fprintf (out, "remaining enodes in worklist: %i", m_worklist.length ());
4494
4495   fprintf (out, "global stats:\n");
4496   m_global_stats.dump (out);
4497
4498   for (function_stat_map_t::iterator iter = m_per_function_stats.begin ();
4499        iter != m_per_function_stats.end ();
4500        ++iter)
4501     {
4502       function *fn = (*iter).first;
4503       fprintf (out, "function: %s\n", function_name (fn));
4504       (*iter).second->dump (out);
4505     }
4506
4507   fprintf (out, "PK_AFTER_SUPERNODE per supernode:\n");
4508   for (unsigned i = 0; i < m_PK_AFTER_SUPERNODE_per_snode.length (); i++)
4509     fprintf (out, "  SN %i: %3i\n", i, m_PK_AFTER_SUPERNODE_per_snode[i]);
4510 }
4511
4512 void
4513 exploded_graph::dump_states_for_supernode (FILE *out,
4514                                            const supernode *snode) const
4515 {
4516   fprintf (out, "PK_AFTER_SUPERNODE nodes for SN: %i\n", snode->m_index);
4517   int i;
4518   exploded_node *enode;
4519   int state_idx = 0;
4520   FOR_EACH_VEC_ELT (m_nodes, i, enode)
4521     {
4522       const supernode *iter_snode = enode->get_supernode ();
4523       if (enode->get_point ().get_kind () == PK_AFTER_SUPERNODE
4524           && iter_snode == snode)
4525         {
4526           pretty_printer pp;
4527           pp_format_decoder (&pp) = default_tree_printer;
4528           enode->get_state ().dump_to_pp (m_ext_state, true, false, &pp);
4529           fprintf (out, "state %i: EN: %i\n  %s\n",
4530                    state_idx++, enode->m_index,
4531                    pp_formatted_text (&pp));
4532         }
4533     }
4534   fprintf (out, "#exploded_node for PK_AFTER_SUPERNODE for SN: %i = %i\n",
4535            snode->m_index, state_idx);
4536 }
4537
4538 /* Return a new json::object of the form
4539    {"nodes" : [objs for enodes],
4540     "edges" : [objs for eedges],
4541     "ext_state": object for extrinsic_state,
4542     "diagnostic_manager": object for diagnostic_manager}.  */
4543
4544 json::object *
4545 exploded_graph::to_json () const
4546 {
4547   json::object *egraph_obj = new json::object ();
4548
4549   /* Nodes.  */
4550   {
4551     json::array *nodes_arr = new json::array ();
4552     unsigned i;
4553     exploded_node *n;
4554     FOR_EACH_VEC_ELT (m_nodes, i, n)
4555       nodes_arr->append (n->to_json (m_ext_state));
4556     egraph_obj->set ("nodes", nodes_arr);
4557   }
4558
4559   /* Edges.  */
4560   {
4561     json::array *edges_arr = new json::array ();
4562     unsigned i;
4563     exploded_edge *n;
4564     FOR_EACH_VEC_ELT (m_edges, i, n)
4565       edges_arr->append (n->to_json ());
4566     egraph_obj->set ("edges", edges_arr);
4567   }
4568
4569   /* m_sg is JSONified at the top-level.  */
4570
4571   egraph_obj->set ("ext_state", m_ext_state.to_json ());
4572   egraph_obj->set ("worklist", m_worklist.to_json ());
4573   egraph_obj->set ("diagnostic_manager", m_diagnostic_manager.to_json ());
4574
4575   /* The following fields aren't yet being JSONified:
4576      const state_purge_map *const m_purge_map;
4577      const analysis_plan &m_plan;
4578      stats m_global_stats;
4579      function_stat_map_t m_per_function_stats;
4580      stats m_functionless_stats;
4581      call_string_data_map_t m_per_call_string_data;
4582      auto_vec<int> m_PK_AFTER_SUPERNODE_per_snode;  */
4583
4584   return egraph_obj;
4585 }
4586
4587 /* class exploded_path.  */
4588
4589 /* Copy ctor.  */
4590
4591 exploded_path::exploded_path (const exploded_path &other)
4592 : m_edges (other.m_edges.length ())
4593 {
4594   int i;
4595   const exploded_edge *eedge;
4596   FOR_EACH_VEC_ELT (other.m_edges, i, eedge)
4597     m_edges.quick_push (eedge);
4598 }
4599
4600 /* Look for the last use of SEARCH_STMT within this path.
4601    If found write the edge's index to *OUT_IDX and return true, otherwise
4602    return false.  */
4603
4604 bool
4605 exploded_path::find_stmt_backwards (const gimple *search_stmt,
4606                                     int *out_idx) const
4607 {
4608   int i;
4609   const exploded_edge *eedge;
4610   FOR_EACH_VEC_ELT_REVERSE (m_edges, i, eedge)
4611     {
4612       const exploded_node *dst_node = eedge->m_dest;
4613       const program_point &dst_point = dst_node->get_point ();
4614       const gimple *stmt = dst_point.get_stmt ();
4615       if (stmt == search_stmt)
4616         {
4617           *out_idx = i;
4618           return true;
4619         }
4620     }
4621   return false;
4622 }
4623
4624 /* Get the final exploded_node in this path, which must be non-empty.  */
4625
4626 exploded_node *
4627 exploded_path::get_final_enode () const
4628 {
4629   gcc_assert (m_edges.length () > 0);
4630   return m_edges[m_edges.length () - 1]->m_dest;
4631 }
4632
4633 /* Check state along this path, returning true if it is feasible.
4634    If OUT is non-NULL, and the path is infeasible, write a new
4635    feasibility_problem to *OUT.  */
4636
4637 bool
4638 exploded_path::feasible_p (logger *logger,
4639                            std::unique_ptr<feasibility_problem> *out,
4640                            engine *eng, const exploded_graph *eg) const
4641 {
4642   LOG_SCOPE (logger);
4643
4644   feasibility_state state (eng->get_model_manager (),
4645                            eg->get_supergraph ());
4646
4647   /* Traverse the path, updating this state.  */
4648   for (unsigned edge_idx = 0; edge_idx < m_edges.length (); edge_idx++)
4649     {
4650       const exploded_edge *eedge = m_edges[edge_idx];
4651       if (logger)
4652         logger->log ("considering edge %i: EN:%i -> EN:%i",
4653                      edge_idx,
4654                      eedge->m_src->m_index,
4655                      eedge->m_dest->m_index);
4656
4657       rejected_constraint *rc = NULL;
4658       if (!state.maybe_update_for_edge (logger, eedge, &rc))
4659         {
4660           gcc_assert (rc);
4661           if (out)
4662             {
4663               const exploded_node &src_enode = *eedge->m_src;
4664               const program_point &src_point = src_enode.get_point ();
4665               const gimple *last_stmt
4666                 = src_point.get_supernode ()->get_last_stmt ();
4667               *out = make_unique<feasibility_problem> (edge_idx, *eedge,
4668                                                        last_stmt, rc);
4669             }
4670           else
4671             delete rc;
4672           return false;
4673         }
4674
4675       if (logger)
4676         {
4677           logger->log ("state after edge %i: EN:%i -> EN:%i",
4678                        edge_idx,
4679                        eedge->m_src->m_index,
4680                        eedge->m_dest->m_index);
4681           logger->start_log_line ();
4682           state.get_model ().dump_to_pp (logger->get_printer (), true, false);
4683           logger->end_log_line ();
4684         }
4685     }
4686
4687   return true;
4688 }
4689
4690 /* Dump this path in multiline form to PP.
4691    If EXT_STATE is non-NULL, then show the nodes.  */
4692
4693 void
4694 exploded_path::dump_to_pp (pretty_printer *pp,
4695                            const extrinsic_state *ext_state) const
4696 {
4697   for (unsigned i = 0; i < m_edges.length (); i++)
4698     {
4699       const exploded_edge *eedge = m_edges[i];
4700       pp_printf (pp, "m_edges[%i]: EN %i -> EN %i",
4701                  i,
4702                  eedge->m_src->m_index,
4703                  eedge->m_dest->m_index);
4704       pp_newline (pp);
4705
4706       if (ext_state)
4707         eedge->m_dest->dump_to_pp (pp, *ext_state);
4708     }
4709 }
4710
4711 /* Dump this path in multiline form to FP.  */
4712
4713 void
4714 exploded_path::dump (FILE *fp, const extrinsic_state *ext_state) const
4715 {
4716   pretty_printer pp;
4717   pp_format_decoder (&pp) = default_tree_printer;
4718   pp_show_color (&pp) = pp_show_color (global_dc->printer);
4719   pp.buffer->stream = fp;
4720   dump_to_pp (&pp, ext_state);
4721   pp_flush (&pp);
4722 }
4723
4724 /* Dump this path in multiline form to stderr.  */
4725
4726 DEBUG_FUNCTION void
4727 exploded_path::dump (const extrinsic_state *ext_state) const
4728 {
4729   dump (stderr, ext_state);
4730 }
4731
4732 /* Dump this path verbosely to FILENAME.  */
4733
4734 void
4735 exploded_path::dump_to_file (const char *filename,
4736                              const extrinsic_state &ext_state) const
4737 {
4738   FILE *fp = fopen (filename, "w");
4739   if (!fp)
4740     return;
4741   pretty_printer pp;
4742   pp_format_decoder (&pp) = default_tree_printer;
4743   pp.buffer->stream = fp;
4744   dump_to_pp (&pp, &ext_state);
4745   pp_flush (&pp);
4746   fclose (fp);
4747 }
4748
4749 /* class feasibility_problem.  */
4750
4751 void
4752 feasibility_problem::dump_to_pp (pretty_printer *pp) const
4753 {
4754   pp_printf (pp, "edge from EN: %i to EN: %i",
4755              m_eedge.m_src->m_index, m_eedge.m_dest->m_index);
4756   if (m_rc)
4757     {
4758       pp_string (pp, "; rejected constraint: ");
4759       m_rc->dump_to_pp (pp);
4760       pp_string (pp, "; rmodel: ");
4761       m_rc->get_model ().dump_to_pp (pp, true, false);
4762     }
4763 }
4764
4765 /* class feasibility_state.  */
4766
4767 /* Ctor for feasibility_state, at the beginning of a path.  */
4768
4769 feasibility_state::feasibility_state (region_model_manager *manager,
4770                                       const supergraph &sg)
4771 : m_model (manager),
4772   m_snodes_visited (sg.m_nodes.length ())
4773 {
4774   bitmap_clear (m_snodes_visited);
4775 }
4776
4777 /* Copy ctor for feasibility_state, for extending a path.  */
4778
4779 feasibility_state::feasibility_state (const feasibility_state &other)
4780 : m_model (other.m_model),
4781   m_snodes_visited (const_sbitmap (other.m_snodes_visited)->n_bits)
4782 {
4783   bitmap_copy (m_snodes_visited, other.m_snodes_visited);
4784 }
4785
4786 /* The heart of feasibility-checking.
4787
4788    Attempt to update this state in-place based on traversing EEDGE
4789    in a path.
4790    Update the model for the stmts in the src enode.
4791    Attempt to add constraints for EEDGE.
4792
4793    If feasible, return true.
4794    Otherwise, return false and write to *OUT_RC.  */
4795
4796 bool
4797 feasibility_state::maybe_update_for_edge (logger *logger,
4798                                           const exploded_edge *eedge,
4799                                           rejected_constraint **out_rc)
4800 {
4801   const exploded_node &src_enode = *eedge->m_src;
4802   const program_point &src_point = src_enode.get_point ();
4803   if (logger)
4804     {
4805       logger->start_log_line ();
4806       src_point.print (logger->get_printer (), format (false));
4807       logger->end_log_line ();
4808     }
4809
4810   /* Update state for the stmts that were processed in each enode.  */
4811   for (unsigned stmt_idx = 0; stmt_idx < src_enode.m_num_processed_stmts;
4812        stmt_idx++)
4813     {
4814       const gimple *stmt = src_enode.get_processed_stmt (stmt_idx);
4815
4816       /* Update cfun and input_location in case of ICE: make it easier to
4817          track down which source construct we're failing to handle.  */
4818       auto_cfun sentinel (src_point.get_function ());
4819       input_location = stmt->location;
4820
4821       if (const gassign *assign = dyn_cast <const gassign *> (stmt))
4822         m_model.on_assignment (assign, NULL);
4823       else if (const gasm *asm_stmt = dyn_cast <const gasm *> (stmt))
4824         m_model.on_asm_stmt (asm_stmt, NULL);
4825       else if (const gcall *call = dyn_cast <const gcall *> (stmt))
4826         {
4827           bool unknown_side_effects = m_model.on_call_pre (call, NULL);
4828           m_model.on_call_post (call, unknown_side_effects, NULL);
4829         }
4830       else if (const greturn *return_ = dyn_cast <const greturn *> (stmt))
4831         m_model.on_return (return_, NULL);
4832     }
4833
4834   const superedge *sedge = eedge->m_sedge;
4835   if (sedge)
4836     {
4837       if (logger)
4838         {
4839           label_text desc (sedge->get_description (false));
4840           logger->log ("  sedge: SN:%i -> SN:%i %s",
4841                        sedge->m_src->m_index,
4842                        sedge->m_dest->m_index,
4843                        desc.get ());
4844         }
4845
4846       const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
4847       if (!m_model.maybe_update_for_edge (*sedge, last_stmt, NULL, out_rc))
4848         {
4849           if (logger)
4850             {
4851               logger->log ("rejecting due to region model");
4852               m_model.dump_to_pp (logger->get_printer (), true, false);
4853             }
4854           return false;
4855         }
4856     }
4857   else
4858     {
4859       /* Special-case the initial eedge from the origin node to the
4860          initial function by pushing a frame for it.  */
4861       if (src_point.get_kind () == PK_ORIGIN)
4862         {
4863           gcc_assert (eedge->m_src->m_index == 0);
4864           gcc_assert (eedge->m_dest->get_point ().get_kind ()
4865                       == PK_BEFORE_SUPERNODE);
4866           function *fun = eedge->m_dest->get_function ();
4867           gcc_assert (fun);
4868           m_model.push_frame (fun, NULL, NULL);
4869           if (logger)
4870             logger->log ("  pushing frame for %qD", fun->decl);
4871         }
4872       else if (eedge->m_custom_info)
4873         {
4874           eedge->m_custom_info->update_model (&m_model, eedge, NULL);
4875         }
4876     }
4877
4878   /* Handle phi nodes on an edge leaving a PK_BEFORE_SUPERNODE (to
4879      a PK_BEFORE_STMT, or a PK_AFTER_SUPERNODE if no stmts).
4880      This will typically not be associated with a superedge.  */
4881   if (src_point.get_from_edge ())
4882     {
4883       const cfg_superedge *last_cfg_superedge
4884         = src_point.get_from_edge ()->dyn_cast_cfg_superedge ();
4885       const exploded_node &dst_enode = *eedge->m_dest;
4886       const unsigned dst_snode_idx = dst_enode.get_supernode ()->m_index;
4887       if (last_cfg_superedge)
4888         {
4889           if (logger)
4890             logger->log ("  update for phis");
4891           m_model.update_for_phis (src_enode.get_supernode (),
4892                                   last_cfg_superedge,
4893                                   NULL);
4894           /* If we've entering an snode that we've already visited on this
4895              epath, then we need do fix things up for loops; see the
4896              comment for store::loop_replay_fixup.
4897              Perhaps we should probably also verify the callstring,
4898              and track program_points,  but hopefully doing it by supernode
4899              is good enough.  */
4900           if (bitmap_bit_p (m_snodes_visited, dst_snode_idx))
4901             m_model.loop_replay_fixup (dst_enode.get_state ().m_region_model);
4902         }
4903       bitmap_set_bit (m_snodes_visited, dst_snode_idx);
4904     }
4905   return true;
4906 }
4907
4908 /* Dump this object to PP.  */
4909
4910 void
4911 feasibility_state::dump_to_pp (pretty_printer *pp,
4912                                bool simple, bool multiline) const
4913 {
4914   m_model.dump_to_pp (pp, simple, multiline);
4915 }
4916
4917 /* A family of cluster subclasses for use when generating .dot output for
4918    exploded graphs (-fdump-analyzer-exploded-graph), for grouping the
4919    enodes into hierarchical boxes.
4920
4921    All functionless enodes appear in the top-level graph.
4922    Every (function, call_string) pair gets its own cluster.  Within that
4923    cluster, each supernode gets its own cluster.
4924
4925    Hence all enodes relating to a particular function with a particular
4926    callstring will be in a cluster together; all enodes for the same
4927    function but with a different callstring will be in a different
4928    cluster.  */
4929
4930 /* Base class of cluster for clustering exploded_node instances in .dot
4931    output, based on various subclass-specific criteria.  */
4932
4933 class exploded_cluster : public cluster<eg_traits>
4934 {
4935 };
4936
4937 /* Cluster containing all exploded_node instances for one supernode.  */
4938
4939 class supernode_cluster : public exploded_cluster
4940 {
4941 public:
4942   supernode_cluster (const supernode *supernode) : m_supernode (supernode) {}
4943
4944   // TODO: dtor?
4945
4946   void dump_dot (graphviz_out *gv, const dump_args_t &args) const final override
4947   {
4948     gv->println ("subgraph \"cluster_supernode_%i\" {", m_supernode->m_index);
4949     gv->indent ();
4950     gv->println ("style=\"dashed\";");
4951     gv->println ("label=\"SN: %i (bb: %i; scc: %i)\";",
4952                  m_supernode->m_index, m_supernode->m_bb->index,
4953                  args.m_eg.get_scc_id (*m_supernode));
4954
4955     int i;
4956     exploded_node *enode;
4957     FOR_EACH_VEC_ELT (m_enodes, i, enode)
4958       enode->dump_dot (gv, args);
4959
4960     /* Terminate subgraph.  */
4961     gv->outdent ();
4962     gv->println ("}");
4963   }
4964
4965   void add_node (exploded_node *en) final override
4966   {
4967     m_enodes.safe_push (en);
4968   }
4969
4970   /* Comparator for use by auto_vec<supernode_cluster *>::qsort.  */
4971
4972   static int cmp_ptr_ptr (const void *p1, const void *p2)
4973   {
4974     const supernode_cluster *c1
4975       = *(const supernode_cluster * const *)p1;
4976     const supernode_cluster *c2
4977       = *(const supernode_cluster * const *)p2;
4978     return c1->m_supernode->m_index - c2->m_supernode->m_index;
4979   }
4980
4981 private:
4982   const supernode *m_supernode;
4983   auto_vec <exploded_node *> m_enodes;
4984 };
4985
4986 /* Cluster containing all supernode_cluster instances for one
4987    (function, call_string) pair.  */
4988
4989 class function_call_string_cluster : public exploded_cluster
4990 {
4991 public:
4992   function_call_string_cluster (function *fun, const call_string &cs)
4993   : m_fun (fun), m_cs (cs) {}
4994
4995   ~function_call_string_cluster ()
4996   {
4997     for (map_t::iterator iter = m_map.begin ();
4998          iter != m_map.end ();
4999          ++iter)
5000       delete (*iter).second;
5001   }
5002
5003   void dump_dot (graphviz_out *gv, const dump_args_t &args) const final override
5004   {
5005     const char *funcname = function_name (m_fun);
5006
5007     gv->println ("subgraph \"cluster_function_%s\" {",
5008                  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (m_fun->decl)));
5009     gv->indent ();
5010     gv->write_indent ();
5011     gv->print ("label=\"call string: ");
5012     m_cs.print (gv->get_pp ());
5013     gv->print (" function: %s \";", funcname);
5014     gv->print ("\n");
5015
5016     /* Dump m_map, sorting it to avoid churn when comparing dumps.  */
5017     auto_vec<supernode_cluster *> child_clusters (m_map.elements ());
5018     for (map_t::iterator iter = m_map.begin ();
5019          iter != m_map.end ();
5020          ++iter)
5021       child_clusters.quick_push ((*iter).second);
5022
5023     child_clusters.qsort (supernode_cluster::cmp_ptr_ptr);
5024
5025     unsigned i;
5026     supernode_cluster *child_cluster;
5027     FOR_EACH_VEC_ELT (child_clusters, i, child_cluster)
5028       child_cluster->dump_dot (gv, args);
5029
5030     /* Terminate subgraph.  */
5031     gv->outdent ();
5032     gv->println ("}");
5033   }
5034
5035   void add_node (exploded_node *en) final override
5036   {
5037     const supernode *supernode = en->get_supernode ();
5038     gcc_assert (supernode);
5039     supernode_cluster **slot = m_map.get (supernode);
5040     if (slot)
5041       (*slot)->add_node (en);
5042     else
5043       {
5044         supernode_cluster *child = new supernode_cluster (supernode);
5045         m_map.put (supernode, child);
5046         child->add_node (en);
5047       }
5048   }
5049
5050   /* Comparator for use by auto_vec<function_call_string_cluster *>.  */
5051
5052   static int cmp_ptr_ptr (const void *p1, const void *p2)
5053   {
5054     const function_call_string_cluster *c1
5055       = *(const function_call_string_cluster * const *)p1;
5056     const function_call_string_cluster *c2
5057       = *(const function_call_string_cluster * const *)p2;
5058     if (int cmp_names
5059         = strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (c1->m_fun->decl)),
5060                   IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (c2->m_fun->decl))))
5061       return cmp_names;
5062     return call_string::cmp (c1->m_cs, c2->m_cs);
5063   }
5064
5065 private:
5066   function *m_fun;
5067   const call_string &m_cs;
5068   typedef ordered_hash_map<const supernode *, supernode_cluster *> map_t;
5069   map_t m_map;
5070 };
5071
5072 /* Keys for root_cluster.  */
5073
5074 struct function_call_string
5075 {
5076   function_call_string (function *fun, const call_string *cs)
5077   : m_fun (fun), m_cs (cs)
5078   {
5079     gcc_assert (fun);
5080     gcc_assert (cs);
5081   }
5082
5083   function *m_fun;
5084   const call_string *m_cs;
5085 };
5086
5087 } // namespace ana
5088
5089 template <> struct default_hash_traits<function_call_string>
5090 : public pod_hash_traits<function_call_string>
5091 {
5092   static const bool empty_zero_p = false;
5093 };
5094
5095 template <>
5096 inline hashval_t
5097 pod_hash_traits<function_call_string>::hash (value_type v)
5098 {
5099   return (pointer_hash <function>::hash (v.m_fun)
5100           ^ pointer_hash <const call_string>::hash (v.m_cs));
5101 }
5102
5103 template <>
5104 inline bool
5105 pod_hash_traits<function_call_string>::equal (const value_type &existing,
5106                                               const value_type &candidate)
5107 {
5108   return existing.m_fun == candidate.m_fun && &existing.m_cs == &candidate.m_cs;
5109 }
5110 template <>
5111 inline void
5112 pod_hash_traits<function_call_string>::mark_deleted (value_type &v)
5113 {
5114   v.m_fun = reinterpret_cast<function *> (1);
5115 }
5116 template <>
5117 inline void
5118 pod_hash_traits<function_call_string>::mark_empty (value_type &v)
5119 {
5120   v.m_fun = NULL;
5121 }
5122 template <>
5123 inline bool
5124 pod_hash_traits<function_call_string>::is_deleted (value_type v)
5125 {
5126   return v.m_fun == reinterpret_cast<function *> (1);
5127 }
5128 template <>
5129 inline bool
5130 pod_hash_traits<function_call_string>::is_empty (value_type v)
5131 {
5132   return v.m_fun == NULL;
5133 }
5134
5135 namespace ana {
5136
5137 /* Top-level cluster for generating .dot output for exploded graphs,
5138    handling the functionless nodes, and grouping the remaining nodes by
5139    callstring.  */
5140
5141 class root_cluster : public exploded_cluster
5142 {
5143 public:
5144   ~root_cluster ()
5145   {
5146     for (map_t::iterator iter = m_map.begin ();
5147          iter != m_map.end ();
5148          ++iter)
5149       delete (*iter).second;
5150   }
5151
5152   void dump_dot (graphviz_out *gv, const dump_args_t &args) const final override
5153   {
5154     int i;
5155     exploded_node *enode;
5156     FOR_EACH_VEC_ELT (m_functionless_enodes, i, enode)
5157       enode->dump_dot (gv, args);
5158
5159     /* Dump m_map, sorting it to avoid churn when comparing dumps.  */
5160     auto_vec<function_call_string_cluster *> child_clusters (m_map.elements ());
5161     for (map_t::iterator iter = m_map.begin ();
5162          iter != m_map.end ();
5163          ++iter)
5164       child_clusters.quick_push ((*iter).second);
5165
5166     child_clusters.qsort (function_call_string_cluster::cmp_ptr_ptr);
5167
5168     function_call_string_cluster *child_cluster;
5169     FOR_EACH_VEC_ELT (child_clusters, i, child_cluster)
5170       child_cluster->dump_dot (gv, args);
5171   }
5172
5173   void add_node (exploded_node *en) final override
5174   {
5175     function *fun = en->get_function ();
5176     if (!fun)
5177       {
5178         m_functionless_enodes.safe_push (en);
5179         return;
5180       }
5181
5182     const call_string &cs = en->get_point ().get_call_string ();
5183     function_call_string key (fun, &cs);
5184     function_call_string_cluster **slot = m_map.get (key);
5185     if (slot)
5186       (*slot)->add_node (en);
5187     else
5188       {
5189         function_call_string_cluster *child
5190           = new function_call_string_cluster (fun, cs);
5191         m_map.put (key, child);
5192         child->add_node (en);
5193       }
5194   }
5195
5196 private:
5197   typedef hash_map<function_call_string, function_call_string_cluster *> map_t;
5198   map_t m_map;
5199
5200   /* This should just be the origin exploded_node.  */
5201   auto_vec <exploded_node *> m_functionless_enodes;
5202 };
5203
5204 /* Subclass of range_label for use within
5205    exploded_graph::dump_exploded_nodes for implementing
5206    -fdump-analyzer-exploded-nodes: a label for a specific
5207    exploded_node.  */
5208
5209 class enode_label : public range_label
5210 {
5211  public:
5212   enode_label (const extrinsic_state &ext_state,
5213                exploded_node *enode)
5214   : m_ext_state (ext_state), m_enode (enode) {}
5215
5216   label_text get_text (unsigned) const final override
5217   {
5218     pretty_printer pp;
5219     pp_format_decoder (&pp) = default_tree_printer;
5220     m_enode->get_state ().dump_to_pp (m_ext_state, true, false, &pp);
5221     return make_label_text (false, "EN: %i: %s",
5222                             m_enode->m_index, pp_formatted_text (&pp));
5223   }
5224
5225 private:
5226   const extrinsic_state &m_ext_state;
5227   exploded_node *m_enode;
5228 };
5229
5230 /* Postprocessing support for dumping the exploded nodes.
5231    Handle -fdump-analyzer-exploded-nodes,
5232    -fdump-analyzer-exploded-nodes-2, and the
5233    "__analyzer_dump_exploded_nodes" builtin.  */
5234
5235 void
5236 exploded_graph::dump_exploded_nodes () const
5237 {
5238   // TODO
5239   /* Locate calls to __analyzer_dump_exploded_nodes.  */
5240   // Print how many egs there are for them?
5241   /* Better: log them as we go, and record the exploded nodes
5242      in question.  */
5243
5244   /* Show every enode.  */
5245
5246   /* Gather them by stmt, so that we can more clearly see the
5247      "hotspots" requiring numerous exploded nodes.  */
5248
5249   /* Alternatively, simply throw them all into one big rich_location
5250      and see if the label-printing will sort it out...
5251      This requires them all to be in the same source file.  */
5252
5253   if (flag_dump_analyzer_exploded_nodes)
5254     {
5255       auto_timevar tv (TV_ANALYZER_DUMP);
5256       gcc_rich_location richloc (UNKNOWN_LOCATION);
5257       unsigned i;
5258       exploded_node *enode;
5259       FOR_EACH_VEC_ELT (m_nodes, i, enode)
5260         {
5261           if (const gimple *stmt = enode->get_stmt ())
5262             {
5263               if (get_pure_location (richloc.get_loc ()) == UNKNOWN_LOCATION)
5264                 richloc.set_range (0, stmt->location, SHOW_RANGE_WITH_CARET);
5265               else
5266                 richloc.add_range (stmt->location,
5267                                    SHOW_RANGE_WITHOUT_CARET,
5268                                    new enode_label (m_ext_state, enode));
5269             }
5270         }
5271       warning_at (&richloc, 0, "%i exploded nodes", m_nodes.length ());
5272
5273       /* Repeat the warning without all the labels, so that message is visible
5274          (the other one may well have scrolled past the terminal limit).  */
5275       warning_at (richloc.get_loc (), 0,
5276                   "%i exploded nodes", m_nodes.length ());
5277
5278       if (m_worklist.length () > 0)
5279         warning_at (richloc.get_loc (), 0,
5280                     "worklist still contains %i nodes", m_worklist.length ());
5281     }
5282
5283   /* Dump the egraph in textual form to a dump file.  */
5284   if (flag_dump_analyzer_exploded_nodes_2)
5285     {
5286       auto_timevar tv (TV_ANALYZER_DUMP);
5287       char *filename
5288         = concat (dump_base_name, ".eg.txt", NULL);
5289       FILE *outf = fopen (filename, "w");
5290       if (!outf)
5291         error_at (UNKNOWN_LOCATION, "unable to open %qs for writing", filename);
5292       free (filename);
5293
5294       fprintf (outf, "exploded graph for %s\n", dump_base_name);
5295       fprintf (outf, "  nodes: %i\n", m_nodes.length ());
5296       fprintf (outf, "  edges: %i\n", m_edges.length ());
5297
5298       unsigned i;
5299       exploded_node *enode;
5300       FOR_EACH_VEC_ELT (m_nodes, i, enode)
5301         {
5302           fprintf (outf, "\nEN %i:\n", enode->m_index);
5303           enode->dump_succs_and_preds (outf);
5304           pretty_printer pp;
5305           enode->get_point ().print (&pp, format (true));
5306           fprintf (outf, "%s\n", pp_formatted_text (&pp));
5307           enode->get_state ().dump_to_file (m_ext_state, false, true, outf);
5308         }
5309
5310       fclose (outf);
5311     }
5312
5313   /* Dump the egraph in textual form to multiple dump files, one per enode.  */
5314   if (flag_dump_analyzer_exploded_nodes_3)
5315     {
5316       auto_timevar tv (TV_ANALYZER_DUMP);
5317
5318       unsigned i;
5319       exploded_node *enode;
5320       FOR_EACH_VEC_ELT (m_nodes, i, enode)
5321         {
5322           char *filename
5323             = xasprintf ("%s.en-%i.txt", dump_base_name, i);
5324           FILE *outf = fopen (filename, "w");
5325           if (!outf)
5326             error_at (UNKNOWN_LOCATION, "unable to open %qs for writing", filename);
5327           free (filename);
5328
5329           fprintf (outf, "EN %i:\n", enode->m_index);
5330           enode->dump_succs_and_preds (outf);
5331           pretty_printer pp;
5332           enode->get_point ().print (&pp, format (true));
5333           fprintf (outf, "%s\n", pp_formatted_text (&pp));
5334           enode->get_state ().dump_to_file (m_ext_state, false, true, outf);
5335
5336           fclose (outf);
5337         }
5338     }
5339
5340   /* Emit a warning at any call to "__analyzer_dump_exploded_nodes",
5341      giving the number of processed exploded nodes for "before-stmt",
5342      and the IDs of processed, merger, and worklist enodes.
5343
5344      We highlight the count of *processed* enodes since this is of most
5345      interest in DejaGnu tests for ensuring that state merger has
5346      happened.
5347
5348      We don't show the count of merger and worklist enodes, as this is
5349      more of an implementation detail of the merging/worklist that we
5350      don't want to bake into our expected DejaGnu messages.  */
5351
5352   unsigned i;
5353   exploded_node *enode;
5354   hash_set<const gimple *> seen;
5355   FOR_EACH_VEC_ELT (m_nodes, i, enode)
5356     {
5357       if (enode->get_point ().get_kind () != PK_BEFORE_STMT)
5358         continue;
5359
5360       if (const gimple *stmt = enode->get_stmt ())
5361         if (const gcall *call = dyn_cast <const gcall *> (stmt))
5362           if (is_special_named_call_p (call, "__analyzer_dump_exploded_nodes",
5363                                        1))
5364             {
5365               if (seen.contains (stmt))
5366                 continue;
5367
5368               auto_vec<exploded_node *> processed_enodes;
5369               auto_vec<exploded_node *> merger_enodes;
5370               auto_vec<exploded_node *> worklist_enodes;
5371               /* This is O(N^2).  */
5372               unsigned j;
5373               exploded_node *other_enode;
5374               FOR_EACH_VEC_ELT (m_nodes, j, other_enode)
5375                 {
5376                   if (other_enode->get_point ().get_kind () != PK_BEFORE_STMT)
5377                     continue;
5378                   if (other_enode->get_stmt () == stmt)
5379                     switch (other_enode->get_status ())
5380                       {
5381                       default:
5382                         gcc_unreachable ();
5383                       case exploded_node::STATUS_WORKLIST:
5384                         worklist_enodes.safe_push (other_enode);
5385                         break;
5386                       case exploded_node::STATUS_PROCESSED:
5387                         processed_enodes.safe_push (other_enode);
5388                         break;
5389                       case exploded_node::STATUS_MERGER:
5390                         merger_enodes.safe_push (other_enode);
5391                         break;
5392                       }
5393                 }
5394
5395               pretty_printer pp;
5396               pp_character (&pp, '[');
5397               print_enode_indices (&pp, processed_enodes);
5398               if (merger_enodes.length () > 0)
5399                 {
5400                   pp_string (&pp, "] merger(s): [");
5401                   print_enode_indices (&pp, merger_enodes);
5402                 }
5403               if (worklist_enodes.length () > 0)
5404                 {
5405                   pp_string (&pp, "] worklist: [");
5406                   print_enode_indices (&pp, worklist_enodes);
5407                 }
5408               pp_character (&pp, ']');
5409
5410               warning_n (stmt->location, 0, processed_enodes.length (),
5411                          "%i processed enode: %s",
5412                          "%i processed enodes: %s",
5413                          processed_enodes.length (), pp_formatted_text (&pp));
5414               seen.add (stmt);
5415
5416               /* If the argument is non-zero, then print all of the states
5417                  of the various enodes.  */
5418               tree t_arg = fold (gimple_call_arg (call, 0));
5419               if (TREE_CODE (t_arg) != INTEGER_CST)
5420                 {
5421                   error_at (call->location,
5422                             "integer constant required for arg 1");
5423                   return;
5424                 }
5425               int i_arg = TREE_INT_CST_LOW (t_arg);
5426               if (i_arg)
5427                 {
5428                   exploded_node *other_enode;
5429                   FOR_EACH_VEC_ELT (processed_enodes, j, other_enode)
5430                     {
5431                       fprintf (stderr, "%i of %i: EN %i:\n",
5432                                j + 1, processed_enodes.length (),
5433                                other_enode->m_index);
5434                       other_enode->dump_succs_and_preds (stderr);
5435                       /* Dump state.  */
5436                       other_enode->get_state ().dump (m_ext_state, false);
5437                     }
5438                 }
5439             }
5440     }
5441 }
5442
5443 DEBUG_FUNCTION exploded_node *
5444 exploded_graph::get_node_by_index (int idx) const
5445 {
5446   exploded_node *enode = m_nodes[idx];
5447   gcc_assert (enode->m_index == idx);
5448   return enode;
5449 }
5450
5451 /* Ensure that there is an exploded_node for a top-level call to FNDECL.  */
5452
5453 void
5454 exploded_graph::on_escaped_function (tree fndecl)
5455 {
5456   logger * const logger = get_logger ();
5457   LOG_FUNC_1 (logger, "%qE", fndecl);
5458
5459   cgraph_node *cgnode = cgraph_node::get (fndecl);
5460   if (!cgnode)
5461     return;
5462
5463   function *fun = cgnode->get_fun ();
5464   if (!fun)
5465     return;
5466
5467   if (!gimple_has_body_p (fndecl))
5468     return;
5469
5470   exploded_node *enode = add_function_entry (fun);
5471   if (logger)
5472     {
5473       if (enode)
5474         logger->log ("created EN %i for %qE entrypoint",
5475                      enode->m_index, fun->decl);
5476       else
5477         logger->log ("did not create enode for %qE entrypoint", fun->decl);
5478     }
5479 }
5480
5481 /* A collection of classes for visualizing the callgraph in .dot form
5482    (as represented in the supergraph).  */
5483
5484 /* Forward decls.  */
5485 class viz_callgraph_node;
5486 class viz_callgraph_edge;
5487 class viz_callgraph;
5488 class viz_callgraph_cluster;
5489
5490 /* Traits for using "digraph.h" to visualize the callgraph.  */
5491
5492 struct viz_callgraph_traits
5493 {
5494   typedef viz_callgraph_node node_t;
5495   typedef viz_callgraph_edge edge_t;
5496   typedef viz_callgraph graph_t;
5497   struct dump_args_t
5498   {
5499     dump_args_t (const exploded_graph *eg) : m_eg (eg) {}
5500     const exploded_graph *m_eg;
5501   };
5502   typedef viz_callgraph_cluster cluster_t;
5503 };
5504
5505 /* Subclass of dnode representing a function within the callgraph.  */
5506
5507 class viz_callgraph_node : public dnode<viz_callgraph_traits>
5508 {
5509   friend class viz_callgraph;
5510
5511 public:
5512   viz_callgraph_node (function *fun, int index)
5513   : m_fun (fun), m_index (index), m_num_supernodes (0), m_num_superedges (0)
5514   {
5515     gcc_assert (fun);
5516   }
5517
5518   void dump_dot (graphviz_out *gv, const dump_args_t &args) const final override
5519   {
5520     pretty_printer *pp = gv->get_pp ();
5521
5522     dump_dot_id (pp);
5523     pp_printf (pp, " [shape=none,margin=0,style=filled,fillcolor=%s,label=\"",
5524                "lightgrey");
5525     pp_write_text_to_stream (pp);
5526
5527     pp_printf (pp, "VCG: %i: %s", m_index, function_name (m_fun));
5528     pp_newline (pp);
5529
5530     pp_printf (pp, "supernodes: %i\n", m_num_supernodes);
5531     pp_newline (pp);
5532
5533     pp_printf (pp, "superedges: %i\n", m_num_superedges);
5534     pp_newline (pp);
5535
5536     if (args.m_eg)
5537       {
5538         unsigned i;
5539         exploded_node *enode;
5540         unsigned num_enodes = 0;
5541         FOR_EACH_VEC_ELT (args.m_eg->m_nodes, i, enode)
5542           {
5543             if (enode->get_point ().get_function () == m_fun)
5544               num_enodes++;
5545           }
5546         pp_printf (pp, "enodes: %i\n", num_enodes);
5547         pp_newline (pp);
5548
5549         // TODO: also show the per-callstring breakdown
5550         const exploded_graph::call_string_data_map_t *per_cs_data
5551           = args.m_eg->get_per_call_string_data ();
5552         for (exploded_graph::call_string_data_map_t::iterator iter
5553                = per_cs_data->begin ();
5554              iter != per_cs_data->end ();
5555              ++iter)
5556           {
5557             const call_string *cs = (*iter).first;
5558             //per_call_string_data *data = (*iter).second;
5559             num_enodes = 0;
5560             FOR_EACH_VEC_ELT (args.m_eg->m_nodes, i, enode)
5561               {
5562                 if (enode->get_point ().get_function () == m_fun
5563                     && &enode->get_point ().get_call_string () == cs)
5564                   num_enodes++;
5565               }
5566             if (num_enodes > 0)
5567               {
5568                 cs->print (pp);
5569                 pp_printf (pp, ": %i\n", num_enodes);
5570               }
5571           }
5572
5573         /* Show any summaries.  */
5574         per_function_data *data = args.m_eg->get_per_function_data (m_fun);
5575         if (data)
5576           {
5577             pp_newline (pp);
5578             pp_printf (pp, "summaries: %i\n", data->m_summaries.length ());
5579             for (auto summary : data->m_summaries)
5580               {
5581                 pp_printf (pp, "\nsummary: %s:\n", summary->get_desc ().get ());
5582                 const extrinsic_state &ext_state = args.m_eg->get_ext_state ();
5583                 const program_state &state = summary->get_state ();
5584                 state.dump_to_pp (ext_state, false, true, pp);
5585                 pp_newline (pp);
5586               }
5587           }
5588       }
5589
5590     pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
5591     pp_string (pp, "\"];\n\n");
5592     pp_flush (pp);
5593   }
5594
5595   void dump_dot_id (pretty_printer *pp) const
5596   {
5597     pp_printf (pp, "vcg_%i", m_index);
5598   }
5599
5600 private:
5601   function *m_fun;
5602   int m_index;
5603   int m_num_supernodes;
5604   int m_num_superedges;
5605 };
5606
5607 /* Subclass of dedge representing a callgraph edge.  */
5608
5609 class viz_callgraph_edge : public dedge<viz_callgraph_traits>
5610 {
5611 public:
5612   viz_callgraph_edge (viz_callgraph_node *src, viz_callgraph_node *dest)
5613   : dedge<viz_callgraph_traits> (src, dest)
5614   {}
5615
5616   void dump_dot (graphviz_out *gv, const dump_args_t &) const
5617     final override
5618   {
5619     pretty_printer *pp = gv->get_pp ();
5620
5621     const char *style = "\"solid,bold\"";
5622     const char *color = "black";
5623     int weight = 10;
5624     const char *constraint = "true";
5625
5626     m_src->dump_dot_id (pp);
5627     pp_string (pp, " -> ");
5628     m_dest->dump_dot_id (pp);
5629     pp_printf (pp,
5630                (" [style=%s, color=%s, weight=%d, constraint=%s,"
5631                 " headlabel=\""),
5632                style, color, weight, constraint);
5633     pp_printf (pp, "\"];\n");
5634   }
5635 };
5636
5637 /* Subclass of digraph representing the callgraph.  */
5638
5639 class viz_callgraph : public digraph<viz_callgraph_traits>
5640 {
5641 public:
5642   viz_callgraph (const supergraph &sg);
5643
5644   viz_callgraph_node *get_vcg_node_for_function (function *fun)
5645   {
5646     return *m_map.get (fun);
5647   }
5648
5649   viz_callgraph_node *get_vcg_node_for_snode (supernode *snode)
5650   {
5651     return get_vcg_node_for_function (snode->m_fun);
5652   }
5653
5654 private:
5655   hash_map<function *, viz_callgraph_node *> m_map;
5656 };
5657
5658 /* Placeholder subclass of cluster.  */
5659
5660 class viz_callgraph_cluster : public cluster<viz_callgraph_traits>
5661 {
5662 };
5663
5664 /* viz_callgraph's ctor.  */
5665
5666 viz_callgraph::viz_callgraph (const supergraph &sg)
5667 {
5668   cgraph_node *node;
5669   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
5670     {
5671       function *fun = node->get_fun ();
5672       viz_callgraph_node *vcg_node
5673         = new viz_callgraph_node (fun, m_nodes.length ());
5674       m_map.put (fun, vcg_node);
5675       add_node (vcg_node);
5676     }
5677
5678   unsigned i;
5679   superedge *sedge;
5680   FOR_EACH_VEC_ELT (sg.m_edges, i, sedge)
5681     {
5682       viz_callgraph_node *vcg_src = get_vcg_node_for_snode (sedge->m_src);
5683       if (vcg_src->m_fun)
5684         get_vcg_node_for_function (vcg_src->m_fun)->m_num_superedges++;
5685       if (sedge->dyn_cast_call_superedge ())
5686         {
5687           viz_callgraph_node *vcg_dest = get_vcg_node_for_snode (sedge->m_dest);
5688           viz_callgraph_edge *vcg_edge
5689             = new viz_callgraph_edge (vcg_src, vcg_dest);
5690           add_edge (vcg_edge);
5691         }
5692     }
5693
5694   supernode *snode;
5695   FOR_EACH_VEC_ELT (sg.m_nodes, i, snode)
5696     {
5697       if (snode->m_fun)
5698         get_vcg_node_for_function (snode->m_fun)->m_num_supernodes++;
5699     }
5700 }
5701
5702 /* Dump the callgraph to FILENAME.  */
5703
5704 static void
5705 dump_callgraph (const supergraph &sg, const char *filename,
5706                 const exploded_graph *eg)
5707 {
5708   FILE *outf = fopen (filename, "w");
5709   if (!outf)
5710     return;
5711
5712   // TODO
5713   viz_callgraph vcg (sg);
5714   vcg.dump_dot (filename, NULL, viz_callgraph_traits::dump_args_t (eg));
5715
5716   fclose (outf);
5717 }
5718
5719 /* Dump the callgraph to "<srcfile>.callgraph.dot".  */
5720
5721 static void
5722 dump_callgraph (const supergraph &sg, const exploded_graph *eg)
5723 {
5724   auto_timevar tv (TV_ANALYZER_DUMP);
5725   char *filename = concat (dump_base_name, ".callgraph.dot", NULL);
5726   dump_callgraph (sg, filename, eg);
5727   free (filename);
5728 }
5729
5730 /* Subclass of dot_annotator for implementing
5731    DUMP_BASE_NAME.supergraph-eg.dot, a post-analysis dump of the supergraph.
5732
5733    Annotate the supergraph nodes by printing the exploded nodes in concise
5734    form within them, next to their pertinent statements where appropriate,
5735    colorizing the exploded nodes based on sm-state.
5736    Also show saved diagnostics within the exploded nodes, giving information
5737    on whether they were feasible, and, if infeasible, where the problem
5738    was.  */
5739
5740 class exploded_graph_annotator : public dot_annotator
5741 {
5742 public:
5743   exploded_graph_annotator (const exploded_graph &eg)
5744   : m_eg (eg)
5745   {
5746     /* Avoid O(N^2) by prepopulating m_enodes_per_snodes.  */
5747     unsigned i;
5748     supernode *snode;
5749     FOR_EACH_VEC_ELT (eg.get_supergraph ().m_nodes, i, snode)
5750       m_enodes_per_snodes.safe_push (new auto_vec <exploded_node *> ());
5751     exploded_node *enode;
5752     FOR_EACH_VEC_ELT (m_eg.m_nodes, i, enode)
5753       if (enode->get_supernode ())
5754         m_enodes_per_snodes[enode->get_supernode ()->m_index]->safe_push (enode);
5755   }
5756
5757   /* Show exploded nodes for BEFORE_SUPERNODE points before N.  */
5758   bool add_node_annotations (graphviz_out *gv, const supernode &n,
5759                              bool within_table)
5760     const final override
5761   {
5762     if (!within_table)
5763       return false;
5764     gv->begin_tr ();
5765     pretty_printer *pp = gv->get_pp ();
5766
5767     gv->begin_td ();
5768     pp_string (pp, "BEFORE");
5769     pp_printf (pp, " (scc: %i)", m_eg.get_scc_id (n));
5770     gv->end_td ();
5771
5772     unsigned i;
5773     exploded_node *enode;
5774     bool had_enode = false;
5775     FOR_EACH_VEC_ELT (*m_enodes_per_snodes[n.m_index], i, enode)
5776       {
5777         gcc_assert (enode->get_supernode () == &n);
5778         const program_point &point = enode->get_point ();
5779         if (point.get_kind () != PK_BEFORE_SUPERNODE)
5780           continue;
5781         print_enode (gv, enode);
5782         had_enode = true;
5783       }
5784     if (!had_enode)
5785       pp_string (pp, "<TD BGCOLOR=\"red\">UNREACHED</TD>");
5786     pp_flush (pp);
5787     gv->end_tr ();
5788     return true;
5789   }
5790
5791   /* Show exploded nodes for STMT.  */
5792   void add_stmt_annotations (graphviz_out *gv, const gimple *stmt,
5793                              bool within_row)
5794     const final override
5795   {
5796     if (!within_row)
5797       return;
5798     pretty_printer *pp = gv->get_pp ();
5799
5800     const supernode *snode
5801       = m_eg.get_supergraph ().get_supernode_for_stmt (stmt);
5802     unsigned i;
5803     exploded_node *enode;
5804     bool had_td = false;
5805     FOR_EACH_VEC_ELT (*m_enodes_per_snodes[snode->m_index], i, enode)
5806       {
5807         const program_point &point = enode->get_point ();
5808         if (point.get_kind () != PK_BEFORE_STMT)
5809           continue;
5810         if (point.get_stmt () != stmt)
5811           continue;
5812         print_enode (gv, enode);
5813         had_td = true;
5814       }
5815     pp_flush (pp);
5816     if (!had_td)
5817       {
5818         gv->begin_td ();
5819         gv->end_td ();
5820       }
5821   }
5822
5823   /* Show exploded nodes for AFTER_SUPERNODE points after N.  */
5824   bool add_after_node_annotations (graphviz_out *gv, const supernode &n)
5825     const final override
5826   {
5827     gv->begin_tr ();
5828     pretty_printer *pp = gv->get_pp ();
5829
5830     gv->begin_td ();
5831     pp_string (pp, "AFTER");
5832     gv->end_td ();
5833
5834     unsigned i;
5835     exploded_node *enode;
5836     FOR_EACH_VEC_ELT (*m_enodes_per_snodes[n.m_index], i, enode)
5837       {
5838         gcc_assert (enode->get_supernode () == &n);
5839         const program_point &point = enode->get_point ();
5840         if (point.get_kind () != PK_AFTER_SUPERNODE)
5841           continue;
5842         print_enode (gv, enode);
5843       }
5844     pp_flush (pp);
5845     gv->end_tr ();
5846     return true;
5847   }
5848
5849 private:
5850   /* Concisely print a TD element for ENODE, showing the index, status,
5851      and any saved_diagnostics at the enode.  Colorize it to show sm-state.
5852
5853      Ideally we'd dump ENODE's state here, hidden behind some kind of
5854      interactive disclosure method like a tooltip, so that the states
5855      can be explored without overwhelming the graph.
5856      However, I wasn't able to get graphviz/xdot to show tooltips on
5857      individual elements within a HTML-like label.  */
5858   void print_enode (graphviz_out *gv, const exploded_node *enode) const
5859   {
5860     pretty_printer *pp = gv->get_pp ();
5861     pp_printf (pp, "<TD BGCOLOR=\"%s\">",
5862                enode->get_dot_fillcolor ());
5863     pp_printf (pp, "<TABLE BORDER=\"0\">");
5864     gv->begin_trtd ();
5865     pp_printf (pp, "EN: %i", enode->m_index);
5866     switch (enode->get_status ())
5867       {
5868       default:
5869         gcc_unreachable ();
5870       case exploded_node::STATUS_WORKLIST:
5871         pp_string (pp, "(W)");
5872         break;
5873       case exploded_node::STATUS_PROCESSED:
5874         break;
5875       case exploded_node::STATUS_MERGER:
5876         pp_string (pp, "(M)");
5877         break;
5878       case exploded_node::STATUS_BULK_MERGED:
5879         pp_string (pp, "(BM)");
5880         break;
5881       }
5882     gv->end_tdtr ();
5883
5884     /* Dump any saved_diagnostics at this enode.  */
5885     for (unsigned i = 0; i < enode->get_num_diagnostics (); i++)
5886       {
5887         const saved_diagnostic *sd = enode->get_saved_diagnostic (i);
5888         print_saved_diagnostic (gv, sd);
5889       }
5890     pp_printf (pp, "</TABLE>");
5891     pp_printf (pp, "</TD>");
5892   }
5893
5894   /* Print a TABLE element for SD, showing the kind, the length of the
5895      exploded_path, whether the path was feasible, and if infeasible,
5896      what the problem was.  */
5897   void print_saved_diagnostic (graphviz_out *gv,
5898                                const saved_diagnostic *sd) const
5899   {
5900     pretty_printer *pp = gv->get_pp ();
5901     gv->begin_trtd ();
5902     pp_printf (pp, "<TABLE BORDER=\"0\">");
5903     gv->begin_tr ();
5904     pp_string (pp, "<TD BGCOLOR=\"green\">");
5905     pp_printf (pp, "DIAGNOSTIC: %s", sd->m_d->get_kind ());
5906     gv->end_tdtr ();
5907     gv->begin_trtd ();
5908     if (sd->get_best_epath ())
5909       pp_printf (pp, "epath length: %i", sd->get_epath_length ());
5910     else
5911       pp_printf (pp, "no best epath");
5912     gv->end_tdtr ();
5913     if (const feasibility_problem *p = sd->get_feasibility_problem ())
5914       {
5915         gv->begin_trtd ();
5916         pp_printf (pp, "INFEASIBLE at eedge %i: EN:%i -> EN:%i",
5917                    p->m_eedge_idx,
5918                    p->m_eedge.m_src->m_index,
5919                    p->m_eedge.m_dest->m_index);
5920         pp_write_text_as_html_like_dot_to_stream (pp);
5921         gv->end_tdtr ();
5922         gv->begin_trtd ();
5923         p->m_eedge.m_sedge->dump (pp);
5924         pp_write_text_as_html_like_dot_to_stream (pp);
5925         gv->end_tdtr ();
5926         gv->begin_trtd ();
5927         pp_gimple_stmt_1 (pp, p->m_last_stmt, 0, (dump_flags_t)0);
5928         pp_write_text_as_html_like_dot_to_stream (pp);
5929         gv->end_tdtr ();
5930         /* Ideally we'd print p->m_model here; see the notes above about
5931            tooltips.  */
5932       }
5933     pp_printf (pp, "</TABLE>");
5934     gv->end_tdtr ();
5935   }
5936
5937   const exploded_graph &m_eg;
5938   auto_delete_vec<auto_vec <exploded_node *> > m_enodes_per_snodes;
5939 };
5940
5941 /* Implement -fdump-analyzer-json.  */
5942
5943 static void
5944 dump_analyzer_json (const supergraph &sg,
5945                     const exploded_graph &eg)
5946 {
5947   auto_timevar tv (TV_ANALYZER_DUMP);
5948   char *filename = concat (dump_base_name, ".analyzer.json.gz", NULL);
5949   gzFile output = gzopen (filename, "w");
5950   if (!output)
5951     {
5952       error_at (UNKNOWN_LOCATION, "unable to open %qs for writing", filename);
5953       free (filename);
5954       return;
5955     }
5956
5957   json::object *toplev_obj = new json::object ();
5958   toplev_obj->set ("sgraph", sg.to_json ());
5959   toplev_obj->set ("egraph", eg.to_json ());
5960
5961   pretty_printer pp;
5962   toplev_obj->print (&pp);
5963   pp_formatted_text (&pp);
5964
5965   delete toplev_obj;
5966
5967   if (gzputs (output, pp_formatted_text (&pp)) == EOF
5968       || gzclose (output))
5969     error_at (UNKNOWN_LOCATION, "error writing %qs", filename);
5970
5971   free (filename);
5972 }
5973
5974 /* Concrete subclass of plugin_analyzer_init_iface, allowing plugins
5975    to register new state machines.  */
5976
5977 class plugin_analyzer_init_impl : public plugin_analyzer_init_iface
5978 {
5979 public:
5980   plugin_analyzer_init_impl (auto_delete_vec <state_machine> *checkers,
5981                              known_function_manager *known_fn_mgr,
5982                              logger *logger)
5983   : m_checkers (checkers),
5984     m_known_fn_mgr (known_fn_mgr),
5985     m_logger (logger)
5986   {}
5987
5988   void register_state_machine (std::unique_ptr<state_machine> sm) final override
5989   {
5990     LOG_SCOPE (m_logger);
5991     m_checkers->safe_push (sm.release ());
5992   }
5993
5994   void register_known_function (const char *name,
5995                                 std::unique_ptr<known_function> kf) final override
5996   {
5997     LOG_SCOPE (m_logger);
5998     m_known_fn_mgr->add (name, std::move (kf));
5999   }
6000
6001   logger *get_logger () const final override
6002   {
6003     return m_logger;
6004   }
6005
6006 private:
6007   auto_delete_vec <state_machine> *m_checkers;
6008   known_function_manager *m_known_fn_mgr;
6009   logger *m_logger;
6010 };
6011
6012 /* Run the analysis "engine".  */
6013
6014 void
6015 impl_run_checkers (logger *logger)
6016 {
6017   LOG_SCOPE (logger);
6018
6019   if (logger)
6020     {
6021       logger->log ("BITS_BIG_ENDIAN: %i", BITS_BIG_ENDIAN ? 1 : 0);
6022       logger->log ("BYTES_BIG_ENDIAN: %i", BYTES_BIG_ENDIAN ? 1 : 0);
6023       logger->log ("WORDS_BIG_ENDIAN: %i", WORDS_BIG_ENDIAN ? 1 : 0);
6024       log_stashed_constants (logger);
6025     }
6026
6027   /* If using LTO, ensure that the cgraph nodes have function bodies.  */
6028   cgraph_node *node;
6029   FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
6030     node->get_untransformed_body ();
6031
6032   /* Create the supergraph.  */
6033   supergraph sg (logger);
6034
6035   engine eng (&sg, logger);
6036
6037   state_purge_map *purge_map = NULL;
6038
6039   if (flag_analyzer_state_purge)
6040     purge_map = new state_purge_map (sg, eng.get_model_manager (), logger);
6041
6042   if (flag_dump_analyzer_supergraph)
6043     {
6044       /* Dump supergraph pre-analysis.  */
6045       auto_timevar tv (TV_ANALYZER_DUMP);
6046       char *filename = concat (dump_base_name, ".supergraph.dot", NULL);
6047       supergraph::dump_args_t args ((enum supergraph_dot_flags)0, NULL);
6048       sg.dump_dot (filename, args);
6049       free (filename);
6050     }
6051
6052   if (flag_dump_analyzer_state_purge)
6053     {
6054       auto_timevar tv (TV_ANALYZER_DUMP);
6055       state_purge_annotator a (purge_map);
6056       char *filename = concat (dump_base_name, ".state-purge.dot", NULL);
6057       supergraph::dump_args_t args ((enum supergraph_dot_flags)0, &a);
6058       sg.dump_dot (filename, args);
6059       free (filename);
6060     }
6061
6062   auto_delete_vec <state_machine> checkers;
6063   make_checkers (checkers, logger);
6064
6065   register_known_functions (*eng.get_known_function_manager ());
6066
6067   plugin_analyzer_init_impl data (&checkers,
6068                                   eng.get_known_function_manager (),
6069                                   logger);
6070   invoke_plugin_callbacks (PLUGIN_ANALYZER_INIT, &data);
6071
6072   if (logger)
6073     {
6074       int i;
6075       state_machine *sm;
6076       FOR_EACH_VEC_ELT (checkers, i, sm)
6077         logger->log ("checkers[%i]: %s", i, sm->get_name ());
6078     }
6079
6080   /* Extrinsic state shared by nodes in the graph.  */
6081   const extrinsic_state ext_state (checkers, &eng, logger);
6082
6083   const analysis_plan plan (sg, logger);
6084
6085   /* The exploded graph.  */
6086   exploded_graph eg (sg, logger, ext_state, purge_map, plan,
6087                      analyzer_verbosity);
6088
6089   /* Add entrypoints to the graph for externally-callable functions.  */
6090   eg.build_initial_worklist ();
6091
6092   /* Now process the worklist, exploring the <point, state> graph.  */
6093   eg.process_worklist ();
6094
6095   if (flag_dump_analyzer_exploded_graph)
6096     {
6097       auto_timevar tv (TV_ANALYZER_DUMP);
6098       char *filename
6099         = concat (dump_base_name, ".eg.dot", NULL);
6100       exploded_graph::dump_args_t args (eg);
6101       root_cluster c;
6102       eg.dump_dot (filename, &c, args);
6103       free (filename);
6104     }
6105
6106   /* Now emit any saved diagnostics.  */
6107   eg.get_diagnostic_manager ().emit_saved_diagnostics (eg);
6108
6109   eg.dump_exploded_nodes ();
6110
6111   eg.log_stats ();
6112
6113   if (flag_dump_analyzer_callgraph)
6114     dump_callgraph (sg, &eg);
6115
6116   if (flag_dump_analyzer_supergraph)
6117     {
6118       /* Dump post-analysis form of supergraph.  */
6119       auto_timevar tv (TV_ANALYZER_DUMP);
6120       char *filename = concat (dump_base_name, ".supergraph-eg.dot", NULL);
6121       exploded_graph_annotator a (eg);
6122       supergraph::dump_args_t args ((enum supergraph_dot_flags)0, &a);
6123       sg.dump_dot (filename, args);
6124       free (filename);
6125     }
6126
6127   if (flag_dump_analyzer_json)
6128     dump_analyzer_json (sg, eg);
6129
6130   if (flag_dump_analyzer_untracked)
6131     eng.get_model_manager ()->dump_untracked_regions ();
6132
6133   delete purge_map;
6134 }
6135
6136 /* Handle -fdump-analyzer and -fdump-analyzer-stderr.  */
6137 static FILE *dump_fout = NULL;
6138
6139 /* Track if we're responsible for closing dump_fout.  */
6140 static bool owns_dump_fout = false;
6141
6142 /* If dumping is enabled, attempt to create dump_fout if it hasn't already
6143    been opened.  Return it.  */
6144
6145 FILE *
6146 get_or_create_any_logfile ()
6147 {
6148   if (!dump_fout)
6149     {
6150       if (flag_dump_analyzer_stderr)
6151         dump_fout = stderr;
6152       else if (flag_dump_analyzer)
6153         {
6154           char *dump_filename = concat (dump_base_name, ".analyzer.txt", NULL);
6155           dump_fout = fopen (dump_filename, "w");
6156           free (dump_filename);
6157           if (dump_fout)
6158             owns_dump_fout = true;
6159         }
6160      }
6161   return dump_fout;
6162 }
6163
6164 /* External entrypoint to the analysis "engine".
6165    Set up any dumps, then call impl_run_checkers.  */
6166
6167 void
6168 run_checkers ()
6169 {
6170   /* Save input_location.  */
6171   location_t saved_input_location = input_location;
6172
6173   {
6174     log_user the_logger (NULL);
6175     get_or_create_any_logfile ();
6176     if (dump_fout)
6177       the_logger.set_logger (new logger (dump_fout, 0, 0,
6178                                          *global_dc->printer));
6179     LOG_SCOPE (the_logger.get_logger ());
6180
6181     impl_run_checkers (the_logger.get_logger ());
6182
6183     /* end of lifetime of the_logger (so that dump file is closed after the
6184        various dtors run).  */
6185   }
6186
6187   if (owns_dump_fout)
6188     {
6189       fclose (dump_fout);
6190       owns_dump_fout = false;
6191       dump_fout = NULL;
6192     }
6193
6194   /* Restore input_location.  Subsequent passes may assume that input_location
6195      is some arbitrary value *not* in the block tree, which might be violated
6196      if we didn't restore it.  */
6197   input_location = saved_input_location;
6198 }
6199
6200 } // namespace ana
6201
6202 #endif /* #if ENABLE_ANALYZER */