LCOV - code coverage report
Current view: top level - gcc/analyzer - ops.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 61.1 % 131 80
Test Date: 2026-02-28 14:20:25 Functions: 47.1 % 34 16
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Operations within the code being analyzed.
       2              :    Copyright (C) 2019-2026 Free Software Foundation, Inc.
       3              :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it
       8              : under the terms of the GNU General Public License as published by
       9              : the Free Software Foundation; either version 3, or (at your option)
      10              : any later version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but
      13              : WITHOUT ANY WARRANTY; without even the implied warranty of
      14              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15              : General Public License for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #ifndef GCC_ANALYZER_OPS_H
      22              : #define GCC_ANALYZER_OPS_H
      23              : 
      24              : #include "except.h"
      25              : #include "gimple-walk.h"
      26              : 
      27              : namespace ana {
      28              : 
      29              : class operation;
      30              :   class control_flow_op;
      31              :   class call_and_return_op;
      32              :   class phis_for_edge_op;
      33              : 
      34              : class callsite_expr;
      35              : 
      36              : struct operation_context
      37              : {
      38       360582 :   operation_context (exploded_graph &eg,
      39              :                      exploded_node &src_enode,
      40              :                      const superedge &sedge)
      41       360582 :   : m_eg (eg),
      42       360582 :     m_src_enode (src_enode),
      43       360582 :     m_sedge (sedge)
      44              :   {
      45              :   }
      46              : 
      47              :   void DEBUG_FUNCTION dump () const;
      48              : 
      49              :   logger *get_logger () const;
      50              : 
      51              :   const extrinsic_state &get_ext_state () const;
      52              : 
      53              :   const program_point &
      54              :   get_initial_point () const;
      55              : 
      56              :   const program_state &
      57              :   get_initial_state () const;
      58              : 
      59              :   const supergraph &
      60              :   get_supergraph () const;
      61              : 
      62              :   program_point
      63              :   get_next_intraprocedural_point () const;
      64              : 
      65              :   void
      66              :   add_outcome (const program_point &dst_point,
      67              :                program_state dst_state,
      68              :                bool could_do_work,
      69              :                uncertainty_t *uncertainty,
      70              :                std::unique_ptr<custom_edge_info> info = nullptr);
      71              : 
      72              :   exploded_graph &m_eg;
      73              :   exploded_node &m_src_enode;
      74              :   const superedge &m_sedge;
      75              : };
      76              : 
      77              : /* Abstract base class for an operation along a superedge.  */
      78              : 
      79            0 : class operation
      80              : {
      81              :  public:
      82              :   // Discriminator for concrete subclasses
      83              :   enum kind
      84              :   {
      85              :     asm_stmt,
      86              :     assignment,
      87              :     predict_stmt,
      88              :     return_stmt,
      89              :     resx,
      90              :     cond_edge,
      91              :     goto_edge,
      92              :     switch_edge,
      93              :     eh_dispatch_try_edge,
      94              :     eh_dispatch_allowed_edge,
      95              :     phis,
      96              :     call_and_return
      97              :   };
      98              : 
      99              :   virtual ~operation () {}
     100              : 
     101              :   void
     102              :   dump () const;
     103              : 
     104              :   virtual std::unique_ptr<operation>
     105              :   clone () const = 0;
     106              : 
     107              :   virtual void
     108              :   print_as_edge_label (pretty_printer *pp, bool user_facing) const = 0;
     109              : 
     110              :   virtual bool
     111              :   defines_ssa_name_p (const_tree ssa_name) const = 0;
     112              : 
     113              :   virtual void
     114              :   walk_load_store_addr_ops (void *,
     115              :                             walk_stmt_load_store_addr_fn,
     116              :                             walk_stmt_load_store_addr_fn,
     117              :                             walk_stmt_load_store_addr_fn) const = 0;
     118              : 
     119              :   virtual const gimple *
     120         2756 :   maybe_get_stmt () const
     121              :   {
     122         2756 :     return nullptr;
     123              :   }
     124              : 
     125              :   virtual void
     126              :   execute (operation_context &op_ctxt) const = 0;
     127              : 
     128              :   virtual bool
     129            0 :   execute_for_feasibility (const exploded_edge &,
     130              :                            feasibility_state &,
     131              :                            region_model_context *,
     132              :                            std::unique_ptr<rejected_constraint> */*out_rc*/) const
     133              :   {
     134              :     // no-op
     135            0 :     return true;
     136              :   }
     137              : 
     138              :   /* Is this op suitable for bulk-merging?
     139              :      It must have a single outcome, at the intraprocedural
     140              :      next point, with some state.  */
     141              :   virtual bool
     142              :   supports_bulk_merge_p () const = 0;
     143              :   virtual void
     144            0 :   update_state_for_bulk_merger (const program_state &,
     145              :                                 program_state &) const
     146              :   {
     147              :     /* Must be implemented for any subclasses that return true
     148              :        for supports_bulk_merge_p.  */
     149            0 :     gcc_unreachable ();
     150              :   }
     151              :   virtual void
     152              :   add_any_events_for_eedge (const exploded_edge &eedge,
     153              :                             checker_path &out_path) const = 0;
     154              : 
     155              :   virtual const control_flow_op *
     156         1444 :   dyn_cast_control_flow_op () const { return nullptr; }
     157              : 
     158              :   virtual const call_and_return_op *
     159       200803 :   dyn_cast_call_and_return_op () const { return nullptr; }
     160              : 
     161              :   virtual const phis_for_edge_op *
     162          788 :   dyn_cast_phis_for_edge_op () const { return nullptr; }
     163              : 
     164         2001 :   enum kind get_kind () const { return m_kind; }
     165              : 
     166              : protected:
     167       136282 :   operation (enum kind kind_)
     168       136282 :   : m_kind (kind_)
     169              :   {
     170              :   }
     171              : 
     172              :   static void
     173              :   handle_on_stmt_for_state_machines (operation_context &op_ctxt,
     174              :                                      program_state &dst_state,
     175              :                                      path_context *path_ctxt,
     176              :                                      bool &unknown_side_effects,
     177              :                                      const gimple &stmt);
     178              : 
     179              : private:
     180              :   enum kind m_kind;
     181              : };
     182              : 
     183              : /* Subclass for an operation representing a specific gimple stmt
     184              :    that isn't control flow.  */
     185              : 
     186              : class gimple_stmt_op : public operation
     187              : {
     188              : public:
     189       225612 :   const gimple &get_stmt () const { return m_stmt; }
     190              : 
     191              :   void
     192              :   print_as_edge_label (pretty_printer *pp, bool user_facing) const override;
     193              : 
     194              :   bool
     195              :   defines_ssa_name_p (const_tree ssa_name) const final override;
     196              : 
     197              :   void
     198              :   walk_load_store_addr_ops (void *,
     199              :                             walk_stmt_load_store_addr_fn,
     200              :                             walk_stmt_load_store_addr_fn,
     201              :                             walk_stmt_load_store_addr_fn) const final override;
     202              : 
     203              :   const gimple *
     204        46855 :   maybe_get_stmt () const final override
     205              :   {
     206        46855 :     return &m_stmt;
     207              :   }
     208              : 
     209              :   void
     210              :   execute (operation_context &op_ctxt) const override;
     211              : 
     212              :   void
     213              :   execute_on_state (operation_context &op_ctxt,
     214              :                     program_state dst_state) const;
     215              : 
     216              :   bool
     217              :   execute_for_feasibility (const exploded_edge &,
     218              :                            feasibility_state &,
     219              :                            region_model_context *,
     220              :                            std::unique_ptr<rejected_constraint> *out_rc) const override;
     221              : 
     222              :   virtual bool
     223              :   supports_bulk_merge_p () const override;
     224              : 
     225              :   void
     226              :   add_any_events_for_eedge (const exploded_edge &eedge,
     227              :                             checker_path &out_path) const override;
     228              : 
     229              : protected:
     230       108970 :   gimple_stmt_op (enum kind kind_, const gimple &stmt)
     231       108970 :   : operation (kind_), m_stmt (stmt)
     232              :   {}
     233              : 
     234              : private:
     235              :   const gimple &m_stmt;
     236              : };
     237              : 
     238              : /* Various subclasses of gimple_stmt_op.  */
     239              : 
     240              : /* An operation subclass representing the effect of a GIMPLE_ASM stmt.  */
     241              : 
     242              : class gasm_op : public gimple_stmt_op
     243              : {
     244              : public:
     245          210 :   gasm_op (const gasm &asm_stmt)
     246          210 :   : gimple_stmt_op (kind::asm_stmt, asm_stmt)
     247              :   {
     248              :   }
     249              : 
     250              :   std::unique_ptr<operation>
     251            0 :   clone () const final override
     252              :   {
     253            0 :     return std::make_unique<gasm_op> (get_gasm ());
     254              :   }
     255              : 
     256            0 :   const gasm &get_gasm () const
     257              :   {
     258            0 :     return *as_a <const gasm *> (&get_stmt ());
     259              :   }
     260              : };
     261              : 
     262              : /* An operation subclass representing the effect of a GIMPLE_ASSIGN stmt.  */
     263              : 
     264              : class gassign_op : public gimple_stmt_op
     265              : {
     266              : public:
     267        54554 :   gassign_op (const gassign &assign_stmt)
     268        54554 :   : gimple_stmt_op (kind::assignment, assign_stmt)
     269              :   {
     270              :   }
     271              : 
     272              :   std::unique_ptr<operation>
     273            0 :   clone () const final override
     274              :   {
     275            0 :     return std::make_unique<gassign_op> (get_gassign ());
     276              :   }
     277              : 
     278            0 :   const gassign &get_gassign () const
     279              :   {
     280            0 :     return *as_a <const gassign *> (&get_stmt ());
     281              :   }
     282              : };
     283              : 
     284              : /* An operation subclass for a GIMPLE_PREDICT stmt.
     285              :    They have no effect on state, but can be useful for reconstructing
     286              :    where "return" statements were in the code the user originally wrote,
     287              :    to improve the reported locations in diagnostics.  */
     288              : 
     289              : class predict_op : public gimple_stmt_op
     290              : {
     291              : public:
     292         1761 :   predict_op (const gimple &predict_stmt)
     293         1761 :   : gimple_stmt_op (kind::predict_stmt, predict_stmt)
     294              :   {
     295         1761 :     gcc_assert (predict_stmt.code == GIMPLE_PREDICT);
     296         1761 :   }
     297              : 
     298              :   std::unique_ptr<operation>
     299            0 :   clone () const final override
     300              :   {
     301            0 :     return std::make_unique<predict_op> (get_stmt ());
     302              :   }
     303              : };
     304              : 
     305              : /* An operation subclass representing both:
     306              :    (a) the effect of a GIMPLE_RETURN stmt: copying a value into the
     307              :    RESULT_DECL of the current frame, and
     308              :    (b) a hint when reporting diagnostics that this is the return
     309              :    path from the function (rather than say, throwing an exception).  */
     310              : 
     311              : class greturn_op : public gimple_stmt_op
     312              : {
     313              : public:
     314        10002 :   greturn_op (const greturn &return_stmt)
     315        10002 :   : gimple_stmt_op (kind::return_stmt, return_stmt)
     316              :   {
     317              :   }
     318              : 
     319              :   std::unique_ptr<operation>
     320            0 :   clone () const final override
     321              :   {
     322            0 :     return std::make_unique<greturn_op> (get_greturn ());
     323              :   }
     324              : 
     325              :   void
     326              :   execute (operation_context &op_ctxt) const final override;
     327              : 
     328              :   bool
     329              :   execute_for_feasibility (const exploded_edge &,
     330              :                            feasibility_state &,
     331              :                            region_model_context *ctxt,
     332              :                            std::unique_ptr<rejected_constraint> *out_rc) const override;
     333              : 
     334              :   bool
     335        11286 :   supports_bulk_merge_p () const final override
     336              :   {
     337        11286 :     return false;
     338              :   }
     339              : 
     340              :   void
     341              :   add_any_events_for_eedge (const exploded_edge &eedge,
     342              :                             checker_path &out_path) const final override;
     343              : 
     344        21501 :   const greturn &get_greturn () const
     345              :   {
     346          714 :     return *as_a <const greturn *> (&get_stmt ());
     347              :   }
     348              : 
     349        20787 :   tree get_retval () const
     350              :   {
     351        20787 :     return gimple_return_retval (&get_greturn ());
     352              :   }
     353              : };
     354              : 
     355              : /* A concrete operation subclass representing the effect of a GIMPLE_CALL stmt.
     356              : 
     357              :    If the function is identified and has a known body, either simulate
     358              :    it interprocedurally by pushing a stack frame and transitioning to the
     359              :    callee, or simulate it intraprocedurally by replaying a summary of the
     360              :    effects of the call.
     361              : 
     362              :    If the function is identified but has an unknown body,
     363              :    simulate it intraprocedurally, either using a known_function
     364              :    subclass for precision, or following conservative rules that
     365              :    assume various side-effects.
     366              : 
     367              :    If the function is unidentified (for some kinds of dynamic calls),
     368              :    simulate it intraprocedurally, following conservative rules that
     369              :    assume various side-effects.
     370              : 
     371              :    In the various intraprocedural simulation cases, the exploded edge will
     372              :    correspond to the underlying superedge.
     373              : 
     374              :    In the interprocedural simulation case, the exploded edge will
     375              :    link two supernodes in different functions, and thus will require
     376              :    custom edge info.
     377              : 
     378              :    Various subclasses exist for handling awkward special cases,
     379              :    such as longjmp.  */
     380              : 
     381              : class call_and_return_op : public gimple_stmt_op
     382              : {
     383              : public:
     384              :   static std::unique_ptr<operation>
     385              :   make (const gcall &call_stmt);
     386              : 
     387              :   std::unique_ptr<operation>
     388            0 :   clone () const override
     389              :   {
     390            0 :     return std::make_unique<call_and_return_op> (get_gcall ());
     391              :   }
     392              : 
     393       257103 :   const gcall &get_gcall () const
     394              :   {
     395       203309 :     return *as_a <const gcall *> (&get_stmt ());
     396              :   }
     397              : 
     398              :   void
     399              :   execute (operation_context &op_ctxt) const override;
     400              : 
     401              :   bool
     402        15834 :   supports_bulk_merge_p () const final override
     403              :   {
     404        15834 :     return false;
     405              :   }
     406              : 
     407              :   void
     408              :   add_any_events_for_eedge (const exploded_edge &eedge,
     409              :                             checker_path &out_path) const override;
     410              : 
     411              :   const call_and_return_op *
     412        62785 :   dyn_cast_call_and_return_op () const final override { return this; }
     413              : 
     414              :   tree
     415              :   map_expr_from_caller_to_callee (tree callee_fndecl,
     416              :                                   tree caller_expr,
     417              :                                   callsite_expr *out) const;
     418              :   tree
     419              :   map_expr_from_callee_to_caller (tree callee_fndecl,
     420              :                                   tree callee_expr,
     421              :                                   callsite_expr *out) const;
     422              : 
     423        41878 :   call_and_return_op (const gcall &call_stmt)
     424        41878 :   : gimple_stmt_op (kind::call_and_return, call_stmt)
     425              :   {
     426              :   }
     427              : 
     428              :   const known_function *
     429              :   maybe_get_known_function (const call_details &cd) const;
     430              : 
     431              : private:
     432              :   cgraph_edge *
     433              :   get_any_cgraph_edge (operation_context &op_ctxt) const;
     434              : 
     435              :   void
     436              :   replay_call_summaries (operation_context &op_ctxt,
     437              :                          function &called_fn,
     438              :                          per_function_data &called_fn_data,
     439              :                          region_model_context *ctxt) const;
     440              : 
     441              :   void
     442              :   replay_call_summary (operation_context &op_ctxt,
     443              :                        function &called_fn,
     444              :                        call_summary &summary,
     445              :                        region_model_context *ctxt) const;
     446              : 
     447              :   tree
     448              :   get_arg_for_parm (tree callee_fndecl,
     449              :                     tree parm,
     450              :                     callsite_expr *out) const;
     451              :   tree
     452              :   get_parm_for_arg (tree callee_fndecl,
     453              :                     tree arg,
     454              :                     callsite_expr *out) const;
     455              : };
     456              : 
     457              : /* A call to one of the various __analyzer_dump* functions.
     458              :    These have no effect on state.  */
     459              : 
     460              : class dump_op : public call_and_return_op
     461              : {
     462              : public:
     463              :   enum dump_kind
     464              :   {
     465              :    state,
     466              :    sarif,
     467              :    dot,
     468              :    state_2
     469              :   };
     470              : 
     471          309 :   dump_op (const gcall &call_stmt, enum dump_kind dump_kind_)
     472          309 :   : call_and_return_op (call_stmt),
     473          309 :     m_dump_kind (dump_kind_)
     474              :   {
     475              :   }
     476              : 
     477              :   std::unique_ptr<operation>
     478            0 :   clone () const final override
     479              :   {
     480            0 :     return std::make_unique<dump_op> (get_gcall (), m_dump_kind);
     481              :   }
     482              : 
     483              :   void
     484              :   execute (operation_context &op_ctxt) const final override;
     485              : 
     486              : private:
     487              :   enum dump_kind m_dump_kind;
     488              : };
     489              : 
     490              : class setjmp_op : public call_and_return_op
     491              : {
     492              : public:
     493           29 :   setjmp_op (const gcall &call_stmt)
     494           29 :   : call_and_return_op (call_stmt)
     495              :   {
     496              :   }
     497              : 
     498              :   std::unique_ptr<operation>
     499            0 :   clone () const final override
     500              :   {
     501            0 :     return std::make_unique<setjmp_op> (get_gcall ());
     502              :   }
     503              : 
     504              :   void
     505              :   execute (operation_context &op_ctxt) const final override;
     506              : 
     507              :   void
     508              :   add_any_events_for_eedge (const exploded_edge &eedge,
     509              :                             checker_path &out_path) const final override;
     510              : };
     511              : 
     512              : class longjmp_op : public call_and_return_op
     513              : {
     514              : public:
     515           41 :   longjmp_op (const gcall &call_stmt)
     516           41 :   : call_and_return_op (call_stmt)
     517              :   {
     518              :   }
     519              : 
     520              :   std::unique_ptr<operation>
     521            0 :   clone () const final override
     522              :   {
     523            0 :     return std::make_unique<longjmp_op> (get_gcall ());
     524              :   }
     525              : 
     526              :   void
     527              :   execute (operation_context &op_ctxt) const final override;
     528              : };
     529              : 
     530              : class cxa_throw_op : public call_and_return_op
     531              : {
     532              : public:
     533          112 :   cxa_throw_op (const gcall &call_stmt, bool is_rethrow)
     534          112 :   : call_and_return_op (call_stmt),
     535          112 :     m_is_rethrow (is_rethrow)
     536              :   {
     537              :   }
     538              : 
     539              :   std::unique_ptr<operation>
     540            0 :   clone () const final override
     541              :   {
     542            0 :     return std::make_unique<cxa_throw_op> (get_gcall (), m_is_rethrow);
     543              :   }
     544              : 
     545              :   void
     546              :   execute (operation_context &op_ctxt) const final override;
     547              : 
     548              : private:
     549              :   bool m_is_rethrow;
     550              : };
     551              : 
     552              : class resx_op : public gimple_stmt_op
     553              : {
     554              : public:
     555          565 :   resx_op (const gresx &resx_stmt)
     556          565 :   : gimple_stmt_op (kind::resx, resx_stmt)
     557              :   {
     558              :   }
     559              : 
     560              :   std::unique_ptr<operation>
     561            0 :   clone () const final override
     562              :   {
     563            0 :     return std::make_unique<resx_op> (get_gresx ());
     564              :   }
     565              : 
     566            0 :   const gresx &get_gresx () const
     567              :   {
     568            0 :     return *as_a <const gresx *> (&get_stmt ());
     569              :   }
     570              : 
     571              :   void
     572              :   execute (operation_context &op_ctxt) const final override;
     573              : 
     574              :   bool
     575           47 :   supports_bulk_merge_p () const final override
     576              :   {
     577           47 :     return false;
     578              :   }
     579              : 
     580              :   void
     581              :   add_any_events_for_eedge (const exploded_edge &eedge,
     582              :                             checker_path &out_path) const final override;
     583              : };
     584              : 
     585              : /* An abstract subclass of operation representing the filtering effect on
     586              :    state of a gimple control-flow statement at the end of a BB, for
     587              :    a specific CFG out-edge from that BB.  */
     588              : 
     589            0 : class control_flow_op : public operation
     590              : {
     591              : public:
     592              :   void
     593              :   add_any_events_for_eedge (const exploded_edge &eedge,
     594              :                             checker_path &out_path) const override;
     595              : 
     596              :   bool
     597        27846 :   defines_ssa_name_p (const_tree) const final override
     598              :   {
     599        27846 :     return false;
     600              :   }
     601              : 
     602              :   void
     603              :   walk_load_store_addr_ops (void *,
     604              :                             walk_stmt_load_store_addr_fn,
     605              :                             walk_stmt_load_store_addr_fn,
     606              :                             walk_stmt_load_store_addr_fn) const final override;
     607              : 
     608              :   const gimple *
     609         8196 :   maybe_get_stmt () const final override
     610              :   {
     611         8196 :     return &m_ctrlflow_stmt;
     612              :   }
     613              : 
     614              :   virtual label_text
     615              :   maybe_describe_condition (bool can_colorize) const;
     616              : 
     617              :   void
     618              :   execute (operation_context &op_ctxt) const final override;
     619              : 
     620              :   bool
     621           66 :   supports_bulk_merge_p () const final override
     622              :   {
     623           66 :     return false;
     624              :   }
     625              : 
     626              :   bool
     627              :   execute_for_feasibility (const exploded_edge &,
     628              :                            feasibility_state &,
     629              :                            region_model_context *,
     630              :                            std::unique_ptr<rejected_constraint> *out_rc) const override;
     631              : 
     632              :   const control_flow_op *
     633          565 :   dyn_cast_control_flow_op () const final override { return this; }
     634              : 
     635            0 :   ::edge get_cfg_edge () const { return m_cfg_edge; }
     636        14898 :   int get_flags () const { return m_cfg_edge->flags; }
     637              :   int back_edge_p () const { return get_flags () & EDGE_DFS_BACK; }
     638              : 
     639          715 :   const gimple &get_ctrlflow_stmt () const { return m_ctrlflow_stmt; }
     640              : 
     641              : protected:
     642        18104 :   control_flow_op (enum kind kind_,
     643              :                    ::edge cfg_edge,
     644              :                    const gimple &ctrlflow_stmt)
     645        18104 :   : operation (kind_),
     646        18104 :     m_cfg_edge (cfg_edge),
     647        17881 :     m_ctrlflow_stmt (ctrlflow_stmt)
     648              :   {}
     649              : 
     650              : private:
     651              :   virtual bool
     652              :   apply_constraints (const superedge *sedge,
     653              :                      region_model &model,
     654              :                      region_model_context *ctxt,
     655              :                      std::unique_ptr<rejected_constraint> *out) const = 0;
     656              : 
     657              :   ::edge m_cfg_edge;
     658              :   const gimple &m_ctrlflow_stmt;
     659              : };
     660              : 
     661              : /* Concrete operation subclass representing filtering/applying state
     662              :    transitions on a specific CFG edge after a GIMPLE_COND stmt, either the
     663              :    "if (cond) is true" or the "if (cond) is false" branch.  */
     664              : 
     665              : class gcond_edge_op : public control_flow_op
     666              : {
     667              : public:
     668              :   gcond_edge_op (::edge cfg_edge,
     669              :                  const gcond &cond_stmt);
     670              : 
     671              :   std::unique_ptr<operation>
     672            0 :   clone () const final override
     673              :   {
     674            0 :     return std::make_unique<gcond_edge_op> (get_cfg_edge (),
     675            0 :                                             get_gcond ());
     676              :   }
     677              : 
     678              :   void
     679              :   print_as_edge_label (pretty_printer *pp,
     680              :                        bool user_facing) const final override;
     681              : 
     682              :   label_text
     683              :   maybe_describe_condition (bool can_colorize) const final override;
     684              : 
     685        79176 :   const gcond &get_gcond () const
     686              :   {
     687        79176 :     return *as_a <const gcond *> (&get_ctrlflow_stmt ());
     688              :   }
     689              : 
     690              : private:
     691              :   static label_text
     692              :   maybe_describe_condition (bool can_colorize,
     693              :                             tree lhs,
     694              :                             enum tree_code op,
     695              :                             tree rhs);
     696              :   static bool should_print_expr_p (tree expr);
     697              : 
     698              :   bool
     699              :   apply_constraints (const superedge *sedge,
     700              :                      region_model &model,
     701              :                      region_model_context *ctxt,
     702              :                      std::unique_ptr<rejected_constraint> *out)
     703              :     const final override;
     704              : 
     705              :   bool m_true_value;
     706              : };
     707              : 
     708              : /* Concrete operation subclass representing filtering/applying state
     709              :    transitions on a specific CFG edge after a GIMPLE_GOTO stmt, thus
     710              :    handling computed gotos.  */
     711              : 
     712              : class ggoto_edge_op : public control_flow_op
     713              : {
     714              : public:
     715              :   ggoto_edge_op (::edge cfg_edge,
     716              :                  const ggoto &goto_stmt,
     717              :                  tree dst_label);
     718              : 
     719              :   std::unique_ptr<operation>
     720            0 :   clone () const final override
     721              :   {
     722            0 :     return std::make_unique<ggoto_edge_op> (get_cfg_edge (),
     723              :                                             get_ggoto (),
     724            0 :                                             m_dst_label);
     725              :   }
     726              : 
     727              :   void
     728              :   print_as_edge_label (pretty_printer *pp,
     729              :                        bool user_facing) const final override;
     730              : 
     731              :   label_text
     732              :   maybe_describe_condition (bool can_colorize) const final override;
     733              : 
     734           79 :   const ggoto &get_ggoto () const
     735              :   {
     736           79 :     return *as_a <const ggoto *> (&get_ctrlflow_stmt ());
     737              :   }
     738              : 
     739              : private:
     740              :   bool
     741              :   apply_constraints (const superedge *sedge,
     742              :                      region_model &model,
     743              :                      region_model_context *ctxt,
     744              :                      std::unique_ptr<rejected_constraint> *out)
     745              :     const final override;
     746              : 
     747              :   tree m_dst_label;
     748              : };
     749              : 
     750              : /* Concrete operation subclass representing filtering/applying state
     751              :    transitions on a specific CFG edge after a GIMPLE_SWITCH stmt, thus
     752              :    handling a cluster of cases/default value.  */
     753              : 
     754              : class switch_case_op : public control_flow_op
     755              : {
     756              :  public:
     757              :   switch_case_op (function &fun,
     758              :                   ::edge cfg_edge,
     759              :                   const gswitch &switch_stmt,
     760              :                   bounded_ranges_manager &mgr);
     761              : 
     762              :   std::unique_ptr<operation>
     763            0 :   clone () const final override
     764              :   {
     765            0 :     return std::make_unique<switch_case_op> (*this);
     766              :   }
     767              : 
     768              :   void
     769              :   print_as_edge_label (pretty_printer *pp,
     770              :                        bool user_facing) const final override;
     771              : 
     772              :   bool implicitly_created_default_p () const;
     773              : 
     774         8072 :   const gswitch &get_gswitch () const
     775              :   {
     776         8072 :     return *as_a <const gswitch *> (&get_ctrlflow_stmt ());
     777              :   }
     778              : 
     779              :  private:
     780              :   bool
     781              :   apply_constraints (const superedge *sedge,
     782              :                      region_model &model,
     783              :                      region_model_context *ctxt,
     784              :                      std::unique_ptr<rejected_constraint> *out)
     785              :     const final override;
     786              : 
     787              :   std::vector<tree> m_case_labels;
     788              :   const bounded_ranges *m_all_cases_ranges;
     789              : };
     790              : 
     791              : /* Abstract subclass for edges from eh_dispatch statements.  */
     792              : 
     793            0 : class eh_dispatch_edge_op : public control_flow_op
     794              : {
     795              : public:
     796              :   static std::unique_ptr<eh_dispatch_edge_op>
     797              :   make (supernode *src,
     798              :         supernode *dest,
     799              :         ::edge cfg_edge,
     800              :         const geh_dispatch &geh_dispatch_stmt);
     801              : 
     802              :   const geh_dispatch &
     803              :   get_geh_dispatch () const
     804              :   {
     805              :     return *as_a <const geh_dispatch *> (&get_ctrlflow_stmt ());
     806              :   }
     807              : 
     808              :   eh_region
     809           13 :   get_eh_region () const { return m_eh_region; }
     810              : 
     811              : protected:
     812              :   eh_dispatch_edge_op (supernode *src_snode,
     813              :                        enum kind kind_,
     814              :                        ::edge cfg_edge,
     815              :                        const geh_dispatch &geh_dispatch_stmt,
     816              :                        eh_region eh_reg);
     817              : 
     818          230 :   supernode *get_src_snode () const { return m_src_snode; }
     819              : 
     820              : private:
     821              :   bool
     822              :   apply_constraints (const superedge *sedge,
     823              :                      region_model &model,
     824              :                      region_model_context *ctxt,
     825              :                      std::unique_ptr<rejected_constraint> *out)
     826              :     const final override;
     827              : 
     828              :   virtual bool
     829              :   apply_eh_constraints (const superedge *sedge,
     830              :                         region_model &model,
     831              :                         region_model_context *ctxt,
     832              :                         tree exception_type,
     833              :                         std::unique_ptr<rejected_constraint> *out) const = 0;
     834              : 
     835              :   supernode *m_src_snode;
     836              :   eh_region m_eh_region;
     837              : };
     838              : 
     839              : /* Concrete operation for edges from an eh_dispatch statement
     840              :    for ERT_TRY regions.  */
     841              : 
     842            0 : class eh_dispatch_try_edge_op : public eh_dispatch_edge_op
     843              : {
     844              : public:
     845              :   eh_dispatch_try_edge_op (supernode *src_snode,
     846              :                            ::edge cfg_edge,
     847              :                            const geh_dispatch &geh_dispatch_stmt,
     848              :                            eh_region eh_reg,
     849              :                            eh_catch ehc);
     850              : 
     851              :   std::unique_ptr<operation>
     852            0 :   clone () const final override
     853              :   {
     854            0 :     return std::make_unique<eh_dispatch_try_edge_op> (*this);
     855              :   }
     856              : 
     857              :   void
     858              :   print_as_edge_label (pretty_printer *pp,
     859              :                        bool user_facing) const final override;
     860              : 
     861              :   void
     862              :   add_any_events_for_eedge (const exploded_edge &eedge,
     863              :                             checker_path &out_path) const final override;
     864              : 
     865              : private:
     866              :   bool
     867              :   apply_eh_constraints (const superedge *sedge,
     868              :                         region_model &model,
     869              :                         region_model_context *ctxt,
     870              :                         tree exception_type,
     871              :                         std::unique_ptr<rejected_constraint> *out)
     872              :     const final override;
     873              : 
     874              :   eh_catch m_eh_catch;
     875              : };
     876              : 
     877              : /* Concrete operation for edges from an eh_dispatch statement
     878              :    for ERT_ALLOWED_EXCEPTIONS regions.  */
     879              : 
     880            0 : class eh_dispatch_allowed_edge_op : public eh_dispatch_edge_op
     881              : {
     882              : public:
     883              :   enum eh_kind
     884              :   {
     885              :     expected,
     886              :     unexpected
     887              :   };
     888              : 
     889              :   eh_dispatch_allowed_edge_op (supernode *src_snode,
     890              :                                supernode *dst_snode,
     891              :                                ::edge cfg_edge,
     892              :                                const geh_dispatch &geh_dispatch_stmt,
     893              :                                eh_region eh_reg);
     894              : 
     895              :   std::unique_ptr<operation>
     896            0 :   clone () const final override
     897              :   {
     898            0 :     return std::make_unique<eh_dispatch_allowed_edge_op> (*this);
     899              :   }
     900              : 
     901              :   void
     902              :   print_as_edge_label (pretty_printer *pp,
     903              :                        bool user_facing) const final override;
     904              : 
     905           13 :   enum eh_kind get_eh_kind () const { return m_kind; }
     906              : 
     907              : private:
     908              :   bool
     909              :   apply_eh_constraints (const superedge *sedge,
     910              :                         region_model &model,
     911              :                         region_model_context *ctxt,
     912              :                         tree exception_type,
     913              :                         std::unique_ptr<rejected_constraint> *out)
     914              :     const final override;
     915              : 
     916              :   enum eh_kind m_kind;
     917              : };
     918              : 
     919              : /* Concrete operation subclass representing the state transition
     920              :    for simultaneously handling all of the phi nodes at the entry to a BB,
     921              :    after following a specific CFG in-edge.
     922              :    Note that this covers multiple gimple stmts: all of the gphi stmts
     923              :    at a basic block entry (albeit for just one in-edge).
     924              :    This can be thought of as handling one column of the entries in the
     925              :    phi nodes of a BB (for a specific in-edge).
     926              :    We ignore MEM entries, and discard phi nodes purely affecting them.  */
     927              : 
     928            0 : class phis_for_edge_op : public operation
     929              : {
     930              : public:
     931              :   /* A "dst=src;" pair within a phi node.  */
     932              :   struct pair
     933              :   {
     934              :     tree m_dst;
     935              :     tree m_src;
     936              :   };
     937              : 
     938              :   static std::unique_ptr<operation>
     939              :   maybe_make (::edge cfg_in_edge);
     940              : 
     941              :   std::unique_ptr<operation>
     942            0 :   clone () const final override
     943              :   {
     944            0 :     return std::make_unique<phis_for_edge_op> (*this);
     945              :   }
     946              : 
     947              :   phis_for_edge_op (std::vector<pair> &&pairs);
     948              : 
     949              :   const phis_for_edge_op *
     950          180 :   dyn_cast_phis_for_edge_op () const final override { return this; }
     951              : 
     952              :   void
     953              :   print_as_edge_label (pretty_printer *pp,
     954              :                        bool user_facing) const final override;
     955              : 
     956              :   bool
     957              :   defines_ssa_name_p (const_tree ssa_name) const final override;
     958              : 
     959              :   void
     960              :   walk_load_store_addr_ops (void *,
     961              :                             walk_stmt_load_store_addr_fn,
     962              :                             walk_stmt_load_store_addr_fn,
     963              :                             walk_stmt_load_store_addr_fn) const final override;
     964              :   void
     965              :   execute (operation_context &op_ctxt) const final override;
     966              : 
     967              :   bool
     968              :   execute_for_feasibility (const exploded_edge &,
     969              :                            feasibility_state &,
     970              :                            region_model_context *,
     971              :                            std::unique_ptr<rejected_constraint> *out_rc) const override;
     972              : 
     973              :   bool
     974         1136 :   supports_bulk_merge_p () const final override
     975              :   {
     976         1136 :     return true;
     977              :   }
     978              :   void
     979              :   update_state_for_bulk_merger (const program_state &src_state,
     980              :                                 program_state &dst_state) const final override;
     981              : 
     982              :   void
     983              :   add_any_events_for_eedge (const exploded_edge &eedge,
     984              :                             checker_path &out_path) const final override;
     985              : 
     986           92 :   const std::vector<pair> &get_pairs () const { return m_pairs; }
     987              : 
     988              : private:
     989              :   static std::vector<pair>
     990              :   get_pairs_for_phi_along_in_edge (::edge cfg_in_edge);
     991              : 
     992              :   void
     993              :   update_state (const program_state &src_state,
     994              :                 program_state &dst_state,
     995              :                 region_model_context *ctxt) const;
     996              : 
     997              :   std::vector<pair> m_pairs;
     998              : };
     999              : 
    1000              : } // namespace ana
    1001              : 
    1002              : #endif /* GCC_ANALYZER_OPS_H */
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.