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