LCOV - code coverage report
Current view: top level - gcc/analyzer - checker-event.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.0 % 144 131
Test Date: 2026-05-11 19:44:49 Functions: 77.8 % 27 21
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Subclasses of diagnostics::paths::event for analyzer diagnostics.
       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_CHECKER_EVENT_H
      22              : #define GCC_ANALYZER_CHECKER_EVENT_H
      23              : 
      24              : #include "tree-logical-location.h"
      25              : #include "analyzer/program-state.h"
      26              : #include "analyzer/event-loc-info.h"
      27              : #include "diagnostics/digraphs.h"
      28              : 
      29              : namespace ana {
      30              : 
      31              : /* An enum for discriminating between the concrete subclasses of
      32              :    checker_event.  */
      33              : 
      34              : enum class event_kind
      35              : {
      36              :   debug,
      37              :   custom,
      38              :   stmt,
      39              :   region_creation,
      40              :   state_transition,
      41              :   function_entry,
      42              :   state_change,
      43              :   start_cfg_edge,
      44              :   end_cfg_edge,
      45              :   catch_,
      46              :   call_,
      47              :   return_,
      48              :   start_consolidated_cfg_edges,
      49              :   end_consolidated_cfg_edges,
      50              :   inlined_call,
      51              :   setjmp_,
      52              :   rewind_from_longjmp,
      53              :   rewind_to_setjmp,
      54              :   throw_,
      55              :   unwind,
      56              :   warning
      57              : };
      58              : 
      59              : extern const char *event_kind_to_string (enum event_kind ek);
      60              : 
      61              : /* Event subclasses.
      62              : 
      63              :    The class hierarchy looks like this (using indentation to show
      64              :    inheritance, and with event_kinds shown for the concrete subclasses):
      65              : 
      66              :    diagnostics::paths::event
      67              :      checker_event
      68              :        debug_event (event_kind::debug)
      69              :        custom_event (event_kind::custom)
      70              :          precanned_custom_event
      71              :        statement_event (event_kind::stmt)
      72              :        state_transition_event (event_kind::data_flow)
      73              :        region_creation_event (event_kind::region_creation)
      74              :        function_entry_event (event_kind::function_entry)
      75              :        state_change_event (event_kind::state_change)
      76              :        superedge_event
      77              :          cfg_edge_event
      78              :            start_cfg_edge_event (event_kind::start_cfg_edge)
      79              :            end_cfg_edge_event (event_kind::end_cfg_edge)
      80              :            catch_cfg_edge_event (event_kind::catch_cfg_edge)
      81              :          call_event (event_kind::call_)
      82              :        return_event (event_kind::return_)
      83              :        start_consolidated_cfg_edges_event (event_kind::start_consolidated_cfg_edges)
      84              :        end_consolidated_cfg_edges_event (event_kind::end_consolidated_cfg_edges)
      85              :        inlined_call_event (event_kind::inlined_call)
      86              :        setjmp_event (event_kind::setjmp_)
      87              :        rewind_event
      88              :          rewind_from_longjmp_event (event_kind::rewind_from_longjmp)
      89              :          rewind_to_setjmp_event (event_kind::rewind_to_setjmp)
      90              :        throw_event (event_kind:throw_)
      91              :          explicit_throw_event
      92              :          throw_from_call_to_external_fn_event
      93              :        unwind_event (event_kind::unwind)
      94              :        warning_event (event_kind::warning).  */
      95              : 
      96              : /* Abstract subclass of diagnostics::paths::event; the base class for use in
      97              :    checker_path (the analyzer's diagnostics::paths::path subclass).  */
      98              : 
      99           20 : class checker_event : public diagnostics::paths::event
     100              : {
     101              : public:
     102              :   /* Implementation of diagnostics::paths::event.  */
     103              : 
     104        60028 :   location_t get_location () const final override { return m_loc; }
     105        15999 :   int get_stack_depth () const final override { return m_effective_depth; }
     106              :   diagnostics::logical_locations::key
     107         5075 :   get_logical_location () const final override
     108              :   {
     109         5075 :     return m_logical_loc;
     110              :   }
     111              :   meaning get_meaning () const override;
     112         2873 :   bool connect_to_next_event_p () const override { return false; }
     113         3773 :   diagnostics::paths::thread_id_t get_thread_id () const final override
     114              :   {
     115         3773 :     return 0;
     116              :   }
     117              : 
     118              :   void
     119              :   maybe_add_sarif_properties (diagnostics::sarif_builder &,
     120              :                               diagnostics::sarif_object &thread_flow_loc_obj)
     121              :     const override;
     122              : 
     123              :   /* Additional functionality.  */
     124        70425 :   enum event_kind get_kind () const { return m_kind; }
     125        11211 :   tree get_fndecl () const { return m_effective_fndecl; }
     126              : 
     127         5701 :   int get_original_stack_depth () const { return m_original_depth; }
     128              : 
     129              :   virtual void prepare_for_emission (checker_path *,
     130              :                                      pending_diagnostic *pd,
     131              :                                      diagnostics::paths::event_id_t emission_id);
     132        21717 :   virtual bool is_call_p () const { return false; }
     133            8 :   virtual bool is_function_entry_p () const  { return false; }
     134        17403 :   virtual bool is_return_p () const  { return false; }
     135              : 
     136              :   std::unique_ptr<diagnostics::digraphs::digraph>
     137              :   maybe_make_diagnostic_state_graph (bool debug) const final override;
     138              : 
     139              :   virtual const program_state *
     140            0 :   get_program_state () const { return nullptr; }
     141              : 
     142              :   /* For use with %@.  */
     143          304 :   const diagnostics::paths::event_id_t *get_id_ptr () const
     144              :   {
     145          304 :     return &m_emission_id;
     146              :   }
     147              : 
     148              :   void dump (pretty_printer *pp) const;
     149              :   void debug () const;
     150              : 
     151        17355 :   void set_location (location_t loc) { m_loc = loc; }
     152              : 
     153              : protected:
     154              :   checker_event (enum event_kind kind,
     155              :                  const event_loc_info &loc_info);
     156              : 
     157              :  private:
     158              :   const checker_path *m_path;
     159              :   const enum event_kind m_kind;
     160              :  protected:
     161              :   location_t m_loc;
     162              :   tree m_original_fndecl;
     163              :   tree m_effective_fndecl;
     164              :   int m_original_depth;
     165              :   int m_effective_depth;
     166              :   pending_diagnostic *m_pending_diagnostic;
     167              :   diagnostics::paths::event_id_t m_emission_id; // only set once all pruning has occurred
     168              :   diagnostics::logical_locations::key m_logical_loc;
     169              : };
     170              : 
     171              : /* A concrete event subclass for a purely textual event, for use in
     172              :    debugging path creation and filtering.  */
     173              : 
     174              : class debug_event : public checker_event
     175              : {
     176              : public:
     177              : 
     178              :   debug_event (const event_loc_info &loc_info,
     179              :                const char *desc)
     180              :   : checker_event (event_kind::debug, loc_info),
     181              :     m_desc (xstrdup (desc))
     182              :   {
     183              :   }
     184            0 :   ~debug_event ()
     185              :   {
     186            0 :     free (m_desc);
     187            0 :   }
     188              : 
     189              :   void print_desc (pretty_printer &) const final override;
     190              : 
     191              : private:
     192              :   char *m_desc;
     193              : };
     194              : 
     195              : /* An abstract event subclass for custom events.  These are not filtered,
     196              :    as they are likely to be pertinent to the diagnostic.  */
     197              : 
     198           20 : class custom_event : public checker_event
     199              : {
     200              : protected:
     201          664 :   custom_event (const event_loc_info &loc_info)
     202          664 :   : checker_event (event_kind::custom, loc_info)
     203              :   {
     204              :   }
     205              : };
     206              : 
     207              : /* A concrete custom_event subclass with a precanned message.  */
     208              : 
     209              : class precanned_custom_event : public custom_event
     210              : {
     211              : public:
     212           20 :   precanned_custom_event (const event_loc_info &loc_info,
     213              :                           const char *desc)
     214           20 :   : custom_event (loc_info),
     215           20 :     m_desc (xstrdup (desc))
     216              :   {
     217           20 :   }
     218           20 :   ~precanned_custom_event ()
     219              :   {
     220           20 :     free (m_desc);
     221           20 :   }
     222              : 
     223              :   void print_desc (pretty_printer &) const final override;
     224              : 
     225              : private:
     226              :   char *m_desc;
     227              : };
     228              : 
     229              : /* A concrete event subclass describing the execution of a gimple statement,
     230              :    for use at high verbosity levels when debugging paths.  */
     231              : 
     232              : class statement_event : public checker_event
     233              : {
     234              : public:
     235              :   statement_event (const gimple *stmt, tree fndecl, int depth,
     236              :                    const program_state &dst_state);
     237              : 
     238              :   void print_desc (pretty_printer &) const final override;
     239              : 
     240              :   const program_state *
     241            0 :   get_program_state () const final override
     242              :   {
     243            0 :     return &m_dst_state;
     244              :   }
     245              : 
     246              :   const gimple * const m_stmt;
     247              :   const program_state m_dst_state;
     248              : };
     249              : 
     250              : /* A concrete checker_event subclass referencing a state_transition,
     251              :    for cases where the state_transition doesn't already have its own event.  */
     252              : 
     253              : class state_transition_event : public checker_event
     254              : {
     255              : public:
     256           44 :   state_transition_event (const event_loc_info &loc_info,
     257              :                           const state_transition *state_trans)
     258           44 :   : checker_event (event_kind::state_transition, loc_info),
     259           44 :     m_state_trans (state_trans)
     260              :   {
     261           44 :     gcc_assert (m_state_trans);
     262           44 :   }
     263              : 
     264              :   void print_desc (pretty_printer &) const final override;
     265              : 
     266              :   void prepare_for_emission (checker_path *path,
     267              :                              pending_diagnostic *pd,
     268              :                              diagnostics::paths::event_id_t emission_id) final override;
     269              : 
     270              : private:
     271              :   // borrowed from the exploded_path
     272              :   const state_transition *m_state_trans;
     273              : };
     274              : 
     275              : /* An abstract event subclass describing the creation of a region that
     276              :    is significant for a diagnostic.
     277              : 
     278              :    There are too many combinations to express region creation in one message,
     279              :    so we emit multiple region_creation_event instances when each pertinent
     280              :    region is created.
     281              : 
     282              :    The events are created by pending_diagnostic's add_region_creation_events
     283              :    vfunc, which by default creates a region_creation_event_memory_space, and
     284              :    if a capacity is known, a region_creation_event_capacity, giving e.g.:
     285              :      (1) region created on stack here
     286              :      (2) capacity: 100 bytes
     287              :    but this vfunc can be overridden to create other events if other wordings
     288              :    are more appropriate foa a given pending_diagnostic.  */
     289              : 
     290              : class region_creation_event : public checker_event
     291              : {
     292              : protected:
     293              :   region_creation_event (const event_loc_info &loc_info);
     294              : };
     295              : 
     296              : /* Concrete subclass of region_creation_event.
     297              :    Generates a message based on the memory space of the region
     298              :    e.g. "region created on stack here".  */
     299              : 
     300              : class region_creation_event_memory_space : public region_creation_event
     301              : {
     302              : public:
     303          601 :   region_creation_event_memory_space (enum memory_space mem_space,
     304              :                                       const event_loc_info &loc_info)
     305          601 :   : region_creation_event (loc_info),
     306          601 :     m_mem_space (mem_space)
     307              :   {
     308              :   }
     309              : 
     310              :   void print_desc (pretty_printer &pp) const final override;
     311              : 
     312              : private:
     313              :   enum memory_space m_mem_space;
     314              : };
     315              : 
     316              : /* Concrete subclass of region_creation_event.
     317              :    Generates a message based on the capacity of the region
     318              :    e.g. "capacity: 100 bytes".  */
     319              : 
     320              : class region_creation_event_capacity : public region_creation_event
     321              : {
     322              : public:
     323          815 :   region_creation_event_capacity (tree capacity,
     324              :                                   const event_loc_info &loc_info)
     325          815 :   : region_creation_event (loc_info),
     326          815 :     m_capacity (capacity)
     327              :   {
     328          815 :     gcc_assert (m_capacity);
     329          815 :   }
     330              : 
     331              :   void print_desc (pretty_printer &pp) const final override;
     332              : 
     333              : private:
     334              :   tree m_capacity;
     335              : };
     336              : 
     337              : /* Concrete subclass of region_creation_event.
     338              :    Generates a message based on the capacity of the region
     339              :    e.g. "allocated 100 bytes here".  */
     340              : 
     341              : class region_creation_event_allocation_size : public region_creation_event
     342              : {
     343              : public:
     344          107 :   region_creation_event_allocation_size (tree capacity,
     345              :                                          const event_loc_info &loc_info)
     346          107 :   : region_creation_event (loc_info),
     347          107 :     m_capacity (capacity)
     348              :   {}
     349              : 
     350              :   void print_desc (pretty_printer &pp) const final override;
     351              : 
     352              : private:
     353              :   tree m_capacity;
     354              : };
     355              : 
     356              : /* Concrete subclass of region_creation_event.
     357              :    Generates a debug message intended for analyzer developers.  */
     358              : 
     359              : class region_creation_event_debug : public region_creation_event
     360              : {
     361              : public:
     362            0 :   region_creation_event_debug (const region *reg, tree capacity,
     363              :                                const event_loc_info &loc_info)
     364            0 :   : region_creation_event (loc_info),
     365            0 :     m_reg (reg), m_capacity (capacity)
     366              :   {
     367              :   }
     368              : 
     369              :   void print_desc (pretty_printer &pp) const final override;
     370              : 
     371              : private:
     372              :   const region *m_reg;
     373              :   tree m_capacity;
     374              : };
     375              : 
     376              : /* An event subclass describing the entry to a function.  */
     377              : 
     378            0 : class function_entry_event : public checker_event
     379              : {
     380              : public:
     381         5322 :   function_entry_event (const event_loc_info &loc_info,
     382              :                         const program_state &state,
     383              :                         const state_transition_at_call *state_trans)
     384         5322 :   : checker_event (event_kind::function_entry, loc_info),
     385         5322 :     m_state (state),
     386         5322 :     m_state_trans (state_trans)
     387              :   {
     388              :   }
     389              : 
     390              :   void print_desc (pretty_printer &pp) const override;
     391              :   meaning get_meaning () const override;
     392              : 
     393          967 :   bool is_function_entry_p () const final override { return true; }
     394              : 
     395              :   const program_state *
     396            4 :   get_program_state () const final override
     397              :   {
     398            4 :     return &m_state;
     399              :   }
     400              : 
     401              :   void
     402              :   prepare_for_emission (checker_path *path,
     403              :                         pending_diagnostic *pd,
     404              :                         diagnostics::paths::event_id_t emission_id) final override;
     405              : 
     406              :   const state_transition_at_call *
     407           72 :   get_state_transition_at_call () const { return m_state_trans; }
     408              : 
     409              : private:
     410              :   const program_state &m_state;
     411              :   const state_transition_at_call *m_state_trans;
     412              : };
     413              : 
     414              : /* Subclass of checker_event describing a state change.  */
     415              : 
     416              : class state_change_event : public checker_event
     417              : {
     418              : public:
     419              :   state_change_event (const event_loc_info &loc_info,
     420              :                       const gimple *stmt,
     421              :                       const state_machine &sm,
     422              :                       const svalue *sval,
     423              :                       state_machine::state_t from,
     424              :                       state_machine::state_t to,
     425              :                       const svalue *origin,
     426              :                       const program_state &dst_state,
     427              :                       const exploded_node *enode);
     428              : 
     429              :   void print_desc (pretty_printer &pp) const final override;
     430              :   meaning get_meaning () const override;
     431              : 
     432              :   const program_state *
     433            3 :   get_program_state () const final override
     434              :   {
     435            3 :     return &m_dst_state;
     436              :   }
     437              : 
     438           22 :   const function *get_dest_function () const
     439              :   {
     440           22 :     return m_dst_state.get_current_function ();
     441              :   }
     442              : 
     443          161 :   const exploded_node *get_exploded_node () const { return m_enode; }
     444              : 
     445              :   const gimple *m_stmt;
     446              :   const state_machine &m_sm;
     447              :   const svalue *m_sval;
     448              :   state_machine::state_t m_from;
     449              :   state_machine::state_t m_to;
     450              :   const svalue *m_origin;
     451              :   program_state m_dst_state;
     452              :   const exploded_node *m_enode;
     453              : };
     454              : 
     455              : /* Subclass of checker_event; parent class for subclasses that relate to
     456              :    a superedge.  */
     457              : 
     458            0 : class superedge_event : public checker_event
     459              : {
     460              : public:
     461              :   void
     462              :   maybe_add_sarif_properties (diagnostics::sarif_builder &,
     463              :                               diagnostics::sarif_object &thread_flow_loc_obj)
     464              :     const override;
     465              : 
     466              :   bool should_filter_p (int verbosity) const;
     467              : 
     468              :   const program_state *
     469              :   get_program_state () const override;
     470              : 
     471              :   virtual const call_and_return_op *
     472              :   get_call_and_return_op () const;
     473              : 
     474              :  protected:
     475              :   superedge_event (enum event_kind kind, const exploded_edge &eedge,
     476              :                    const event_loc_info &loc_info);
     477              : 
     478              :  public:
     479              :   const exploded_edge &m_eedge;
     480              :   const superedge *m_sedge;
     481              : };
     482              : 
     483              : /* An abstract event subclass for when a CFG edge is followed; it has two
     484              :    subclasses, representing the start of the edge and the end of the
     485              :    edge, which come in pairs.  */
     486              : 
     487              : class cfg_edge_event : public superedge_event
     488              : {
     489              : public:
     490              :   meaning get_meaning () const override;
     491              : 
     492              :   ::edge get_cfg_edge () const;
     493              : 
     494              :   bool maybe_get_edge_sense (bool *out) const;
     495              : 
     496              :  protected:
     497              :   cfg_edge_event (enum event_kind kind,
     498              :                   const exploded_edge &eedge,
     499              :                   const event_loc_info &loc_info,
     500              :                   const control_flow_op *op);
     501              : 
     502              :   const control_flow_op *m_op;
     503              : };
     504              : 
     505              : /* A concrete event subclass for the start of a CFG edge
     506              :    e.g. "following 'false' branch...'.  */
     507              : 
     508              : class start_cfg_edge_event : public cfg_edge_event
     509              : {
     510              : public:
     511         2855 :   start_cfg_edge_event (const exploded_edge &eedge,
     512              :                         const event_loc_info &loc_info,
     513              :                         const control_flow_op *op)
     514         2855 :   : cfg_edge_event (event_kind::start_cfg_edge, eedge, loc_info, op)
     515              :   {
     516              :   }
     517              : 
     518              :   void print_desc (pretty_printer &pp) const override;
     519          482 :   bool connect_to_next_event_p () const final override { return true; }
     520              : 
     521              : private:
     522              :   static bool should_print_expr_p (tree);
     523              : };
     524              : 
     525              : /* A concrete event subclass for the end of a CFG edge
     526              :    e.g. "...to here'.  */
     527              : 
     528              : class end_cfg_edge_event : public cfg_edge_event
     529              : {
     530              : public:
     531         2855 :   end_cfg_edge_event (const exploded_edge &eedge,
     532              :                       const event_loc_info &loc_info,
     533              :                       const control_flow_op *op)
     534         2855 :   : cfg_edge_event (event_kind::end_cfg_edge, eedge, loc_info, op)
     535              :   {
     536              :   }
     537              : 
     538         4986 :   void print_desc (pretty_printer &pp) const final override
     539              :   {
     540         4986 :     pp_string (&pp, "...to here");
     541         4986 :   }
     542              : };
     543              : 
     544              : /* A concrete event subclass for catching an exception
     545              :    e.g. "...catching 'struct io_error' here".  */
     546              : 
     547              : class catch_cfg_edge_event : public cfg_edge_event
     548              : {
     549              : public:
     550           66 :   catch_cfg_edge_event (const exploded_edge &eedge,
     551              :                         const event_loc_info &loc_info,
     552              :                         const control_flow_op &op,
     553              :                         tree type)
     554           66 :   : cfg_edge_event (event_kind::catch_, eedge, loc_info, &op),
     555           66 :     m_type (type)
     556              :   {
     557              :   }
     558              : 
     559          144 :   void print_desc (pretty_printer &pp) const final override
     560              :   {
     561          144 :     if (m_type)
     562          114 :       pp_printf (&pp, "...catching exception of type %qT here", m_type);
     563              :     else
     564           30 :       pp_string (&pp, "...catching exception here");
     565          144 :   }
     566              : 
     567              :   meaning get_meaning () const override;
     568              : 
     569              : private:
     570              :   tree m_type;
     571              : };
     572              : 
     573              : struct critical_state
     574              : {
     575         1872 :   critical_state ()
     576         1872 :   : m_var (NULL_TREE),
     577          631 :     m_state (nullptr)
     578              :   {
     579              :   }
     580          312 :   critical_state (tree var, state_machine::state_t state)
     581              :   : m_var (var),
     582              :     m_state (state)
     583              :   {
     584              :   }
     585              : 
     586              :   tree m_var;
     587              :   state_machine::state_t m_state;
     588              : };
     589              : 
     590              : /* A concrete event subclass for an interprocedural call.  */
     591              : 
     592            0 : class call_event : public superedge_event
     593              : {
     594              : public:
     595              :   call_event (const exploded_edge &eedge,
     596              :               const event_loc_info &loc_info,
     597              :               const state_transition_at_call *state_trans);
     598              : 
     599              :   void print_desc (pretty_printer &pp) const override;
     600              :   meaning get_meaning () const override;
     601              : 
     602              :   bool is_call_p () const final override;
     603              : 
     604              :   const program_state *
     605              :   get_program_state () const final override;
     606              : 
     607              :   void
     608              :   prepare_for_emission (checker_path *path,
     609              :                         pending_diagnostic *pd,
     610              :                         diagnostics::paths::event_id_t emission_id) final override;
     611              : 
     612              :   /* Mark this edge event as being either an interprocedural call or
     613              :      return in which VAR is in STATE, and that this is critical to the
     614              :      diagnostic (so that print_desc can attempt to get a better description
     615              :      from any pending_diagnostic).  */
     616          218 :   void record_critical_state (tree var, state_machine::state_t state)
     617              :   {
     618          218 :     m_critical_state = critical_state (var, state);
     619          218 :   }
     620              : 
     621              :   const state_transition_at_call *
     622              :   get_state_transition_at_call () const { return m_state_trans; }
     623              : 
     624              : protected:
     625              :   tree get_caller_fndecl () const;
     626              :   tree get_callee_fndecl () const;
     627              : 
     628              :   const supernode *m_src_snode;
     629              :   const supernode *m_dest_snode;
     630              :   critical_state m_critical_state;
     631              :   const state_transition_at_call *m_state_trans;
     632              : };
     633              : 
     634              : /* A concrete event subclass for an interprocedural return.  */
     635              : 
     636              : class return_event : public checker_event
     637              : {
     638              : public:
     639              :   return_event (const exploded_edge &eedge,
     640              :                 const event_loc_info &loc_info,
     641              :                 const state_transition_at_return *state_trans);
     642              : 
     643              :   void print_desc (pretty_printer &pp) const final override;
     644              :   meaning get_meaning () const override;
     645              : 
     646              :   bool is_return_p () const final override;
     647              : 
     648              :   const call_and_return_op *
     649          443 :   get_call_and_return_op () const
     650              :   {
     651          443 :     return m_call_and_return_op;
     652              :   }
     653              : 
     654              :   const program_state *
     655              :   get_program_state () const override;
     656              : 
     657              :   void
     658              :   prepare_for_emission (checker_path *path,
     659              :                         pending_diagnostic *pd,
     660              :                         diagnostics::paths::event_id_t emission_id) final override;
     661              : 
     662              :   /* Mark this edge event as being either an interprocedural call or
     663              :      return in which VAR is in STATE, and that this is critical to the
     664              :      diagnostic (so that print_desc can attempt to get a better description
     665              :      from any pending_diagnostic).  */
     666           94 :   void record_critical_state (tree var, state_machine::state_t state)
     667              :   {
     668           94 :     m_critical_state = critical_state (var, state);
     669           94 :   }
     670              : 
     671              :   const exploded_edge &m_eedge;
     672              :   const supernode *m_src_snode;
     673              :   const supernode *m_dest_snode;
     674              :   const call_and_return_op *m_call_and_return_op;
     675              :   critical_state m_critical_state;
     676              :   const state_transition_at_return *m_state_trans;
     677              : };
     678              : 
     679              : /* A concrete event subclass for the start of a consolidated run of CFG
     680              :    edges all either TRUE or FALSE e.g. "following 'false' branch...'.  */
     681              : 
     682              : class start_consolidated_cfg_edges_event : public checker_event
     683              : {
     684              : public:
     685          111 :   start_consolidated_cfg_edges_event (const event_loc_info &loc_info,
     686              :                                       bool edge_sense)
     687          111 :   : checker_event (event_kind::start_consolidated_cfg_edges, loc_info),
     688          111 :     m_edge_sense (edge_sense)
     689              :   {
     690              :   }
     691              : 
     692              :   void print_desc (pretty_printer &pp) const final override;
     693              :   meaning get_meaning () const override;
     694            0 :   bool connect_to_next_event_p () const final override { return true; }
     695              : 
     696              :  private:
     697              :   bool m_edge_sense;
     698              : };
     699              : 
     700              : /* A concrete event subclass for the end of a consolidated run of
     701              :    CFG edges e.g. "...to here'.  */
     702              : 
     703              : class end_consolidated_cfg_edges_event : public checker_event
     704              : {
     705              : public:
     706          111 :   end_consolidated_cfg_edges_event (const event_loc_info &loc_info)
     707          111 :   : checker_event (event_kind::end_consolidated_cfg_edges, loc_info)
     708              :   {
     709              :   }
     710              : 
     711          206 :   void print_desc (pretty_printer &pp) const final override
     712              :   {
     713          206 :     pp_string (&pp, "...to here");
     714          206 :   }
     715              : };
     716              : 
     717              : /* A concrete event subclass for describing an inlined call event
     718              :    e.g. "inlined call to 'callee' from 'caller'".  */
     719              : 
     720              : class inlined_call_event : public checker_event
     721              : {
     722              : public:
     723          165 :   inlined_call_event (location_t loc,
     724              :                       tree apparent_callee_fndecl,
     725              :                       tree apparent_caller_fndecl,
     726              :                       int actual_depth,
     727              :                       int stack_depth_adjustment)
     728          165 :   : checker_event (event_kind::inlined_call,
     729          165 :                    event_loc_info (loc,
     730              :                                    apparent_caller_fndecl,
     731          165 :                                    actual_depth + stack_depth_adjustment)),
     732          165 :     m_apparent_callee_fndecl (apparent_callee_fndecl),
     733          165 :     m_apparent_caller_fndecl (apparent_caller_fndecl)
     734              :   {
     735          165 :     gcc_assert (LOCATION_BLOCK (loc) == NULL);
     736          165 :   }
     737              : 
     738              :   void print_desc (pretty_printer &) const final override;
     739              :   meaning get_meaning () const override;
     740              : 
     741              : private:
     742              :   tree m_apparent_callee_fndecl;
     743              :   tree m_apparent_caller_fndecl;
     744              : };
     745              : 
     746              : /* A concrete event subclass for a setjmp or sigsetjmp call.  */
     747              : 
     748              : class setjmp_event : public checker_event
     749              : {
     750              : public:
     751           20 :   setjmp_event (const event_loc_info &loc_info,
     752              :                 const exploded_node *enode,
     753              :                 const gcall &setjmp_call)
     754           20 :   : checker_event (event_kind::setjmp_, loc_info),
     755           20 :     m_enode (enode), m_setjmp_call (setjmp_call)
     756              :   {
     757              :   }
     758              : 
     759              :   void print_desc (pretty_printer &pp) const final override;
     760              : 
     761              :   meaning get_meaning () const override;
     762              : 
     763              :   void prepare_for_emission (checker_path *path,
     764              :                              pending_diagnostic *pd,
     765              :                              diagnostics::paths::event_id_t emission_id) final override;
     766              : 
     767              : private:
     768              :   const exploded_node *m_enode;
     769              :   const gcall &m_setjmp_call;
     770              : };
     771              : 
     772              : /* An abstract event subclass for rewinding from a longjmp to a setjmp
     773              :    (or siglongjmp to sigsetjmp).
     774              : 
     775              :    Base class for two from/to subclasses, showing the two halves of the
     776              :    rewind.  */
     777              : 
     778              : class rewind_event : public checker_event
     779              : {
     780              : public:
     781              :   tree get_longjmp_caller () const;
     782              :   tree get_setjmp_caller () const;
     783              :   const exploded_edge *get_eedge () const { return m_eedge; }
     784              : 
     785              :   meaning get_meaning () const override;
     786              : 
     787              :  protected:
     788              :   rewind_event (const exploded_edge *eedge,
     789              :                 enum event_kind kind,
     790              :                 const event_loc_info &loc_info,
     791              :                 const rewind_info_t *rewind_info);
     792              :   const rewind_info_t *m_rewind_info;
     793              : 
     794              :  private:
     795              :   const exploded_edge *m_eedge;
     796              : };
     797              : 
     798              : /* A concrete event subclass for rewinding from a longjmp to a setjmp,
     799              :    showing the longjmp (or siglongjmp).  */
     800              : 
     801              : class rewind_from_longjmp_event : public rewind_event
     802              : {
     803              : public:
     804           15 :   rewind_from_longjmp_event (const exploded_edge *eedge,
     805              :                              const event_loc_info &loc_info,
     806              :                              const rewind_info_t *rewind_info)
     807           15 :   : rewind_event (eedge, event_kind::rewind_from_longjmp, loc_info,
     808           15 :                   rewind_info)
     809              :   {
     810              :   }
     811              : 
     812              :   void print_desc (pretty_printer &pp) const final override;
     813              : };
     814              : 
     815              : /* A concrete event subclass for rewinding from a longjmp to a setjmp,
     816              :    showing the setjmp (or sigsetjmp).  */
     817              : 
     818              : class rewind_to_setjmp_event : public rewind_event
     819              : {
     820              : public:
     821           15 :   rewind_to_setjmp_event (const exploded_edge *eedge,
     822              :                           const event_loc_info &loc_info,
     823              :                           const rewind_info_t *rewind_info)
     824           15 :   : rewind_event (eedge, event_kind::rewind_to_setjmp, loc_info,
     825           15 :                   rewind_info)
     826              :   {
     827              :   }
     828              : 
     829              :   void print_desc (pretty_printer &pp) const final override;
     830              : 
     831              :   void prepare_for_emission (checker_path *path,
     832              :                              pending_diagnostic *pd,
     833              :                              diagnostics::paths::event_id_t emission_id) final override;
     834              : 
     835              : private:
     836              :   diagnostics::paths::event_id_t m_original_setjmp_event_id;
     837              : };
     838              : 
     839              : /* An abstract subclass for throwing/rethrowing an exception.  */
     840              : 
     841              : class throw_event : public checker_event
     842              : {
     843              : public:
     844           95 :   throw_event (const event_loc_info &loc_info,
     845              :                const exploded_node *enode,
     846              :                const gcall &throw_call)
     847           95 :   : checker_event (event_kind::throw_, loc_info),
     848           95 :     m_enode (enode),
     849          190 :     m_throw_call (throw_call)
     850              :   {
     851              :   }
     852              : 
     853              :   meaning get_meaning () const override;
     854              : 
     855              : protected:
     856              :   const exploded_node *m_enode;
     857              :   const gcall &m_throw_call;
     858              : };
     859              : 
     860              : /* A concrete event subclass for an explicit "throw EXC;"
     861              :    or "throw;"  (actually, a call to __cxa_throw or __cxa_rethrow).  */
     862              : 
     863              : class explicit_throw_event : public throw_event
     864              : {
     865              : public:
     866           69 :   explicit_throw_event (const event_loc_info &loc_info,
     867              :                         const exploded_node *enode,
     868              :                         const gcall &throw_call,
     869              :                         tree type,
     870              :                         bool is_rethrow)
     871           69 :   : throw_event (loc_info, enode, throw_call),
     872           69 :     m_type (type),
     873           69 :     m_is_rethrow (is_rethrow)
     874              :   {
     875              :   }
     876              : 
     877              :   void print_desc (pretty_printer &pp) const final override;
     878              : 
     879              : private:
     880              :   tree m_type;
     881              :   bool m_is_rethrow;
     882              : };
     883              : 
     884              : /* A concrete event subclass for an exception being thrown
     885              :    from within a call to a function we don't have the body of,
     886              :    or where we don't know what function was called.  */
     887              : 
     888              : class throw_from_call_to_external_fn_event : public throw_event
     889              : {
     890              : public:
     891           26 :   throw_from_call_to_external_fn_event (const event_loc_info &loc_info,
     892              :                                         const exploded_node *enode,
     893              :                                         const gcall &throw_call,
     894              :                                         tree fndecl)
     895           26 :   : throw_event (loc_info, enode, throw_call),
     896           26 :     m_fndecl (fndecl)
     897              :   {
     898              :   }
     899              : 
     900              :   void print_desc (pretty_printer &pp) const final override;
     901              : 
     902              : private:
     903              :   tree m_fndecl;
     904              : };
     905              : 
     906              : /* A concrete event subclass for unwinding a stack frame when
     907              :    processing an exception.  */
     908              : 
     909              : class unwind_event : public checker_event
     910              : {
     911              : public:
     912           16 :   unwind_event (const event_loc_info &loc_info)
     913           16 :   : checker_event (event_kind::unwind, loc_info),
     914           16 :     m_num_frames (1)
     915              :   {
     916              :   }
     917              : 
     918              :   meaning get_meaning () const override;
     919              : 
     920              :   void print_desc (pretty_printer &pp) const final override;
     921              : 
     922              :   int m_num_frames;
     923              : };
     924              : 
     925              : /* Concrete subclass of checker_event for use at the end of a path:
     926              :    a repeat of the warning message at the end of the path (perhaps with
     927              :    references to pertinent events that occurred on the way), at the point
     928              :    where the problem occurs.  */
     929              : 
     930              : class warning_event : public checker_event
     931              : {
     932              : public:
     933         4161 :   warning_event (const event_loc_info &loc_info,
     934              :                  const exploded_node *enode,
     935              :                  const state_machine *sm,
     936              :                  tree var, state_machine::state_t state,
     937              :                  const program_state *program_state_ = nullptr)
     938         4161 :   : checker_event (event_kind::warning, loc_info),
     939         4161 :     m_enode (enode),
     940         4161 :     m_sm (sm), m_var (var), m_state (state)
     941              :   {
     942         4161 :     if (program_state_)
     943          855 :       m_program_state = std::make_unique<program_state> (*program_state_);
     944         3923 :   }
     945              : 
     946              :   void print_desc (pretty_printer &pp) const final override;
     947              :   meaning get_meaning () const override;
     948              : 
     949              :   const program_state *
     950              :   get_program_state () const final override;
     951              : 
     952          165 :   const exploded_node *get_exploded_node () const { return m_enode; }
     953              : 
     954              : private:
     955              :   const exploded_node *m_enode;
     956              :   const state_machine *m_sm;
     957              :   tree m_var;
     958              :   state_machine::state_t m_state;
     959              :   /* Optional copy of program state, for when this is different from
     960              :      m_enode's state:  */
     961              :   std::unique_ptr<program_state> m_program_state;
     962              : };
     963              : 
     964              : } // namespace ana
     965              : 
     966              : #endif /* GCC_ANALYZER_CHECKER_EVENT_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.