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