aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2022-11-11 16:06:32 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2022-11-11 16:06:32 -0500
commit65752c1f7c41c5641eef298454825910a57146e4 (patch)
tree82f14437cd1306fedff94396879be04a2451cd27 /gcc
parent12c583a2a3da798e82737c2d0e11fd686636cfeb (diff)
downloadgcc-65752c1f7c41c5641eef298454825910a57146e4.zip
gcc-65752c1f7c41c5641eef298454825910a57146e4.tar.gz
gcc-65752c1f7c41c5641eef298454825910a57146e4.tar.bz2
analyzer: split out checker_event classes to their own header
gcc/analyzer/ChangeLog: * checker-path.h: Split out checker_event and its subclasses to... * checker-event.h: ...this new header. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/analyzer/checker-event.h610
-rw-r--r--gcc/analyzer/checker-path.h584
2 files changed, 612 insertions, 582 deletions
diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h
new file mode 100644
index 0000000..18c44e6
--- /dev/null
+++ b/gcc/analyzer/checker-event.h
@@ -0,0 +1,610 @@
+/* Subclasses of diagnostic_event for analyzer diagnostics.
+ Copyright (C) 2019-2022 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_ANALYZER_CHECKER_EVENT_H
+#define GCC_ANALYZER_CHECKER_EVENT_H
+
+#include "tree-logical-location.h"
+
+namespace ana {
+
+/* An enum for discriminating between the concrete subclasses of
+ checker_event. */
+
+enum event_kind
+{
+ EK_DEBUG,
+ EK_CUSTOM,
+ EK_STMT,
+ EK_REGION_CREATION,
+ EK_FUNCTION_ENTRY,
+ EK_STATE_CHANGE,
+ EK_START_CFG_EDGE,
+ EK_END_CFG_EDGE,
+ EK_CALL_EDGE,
+ EK_RETURN_EDGE,
+ EK_START_CONSOLIDATED_CFG_EDGES,
+ EK_END_CONSOLIDATED_CFG_EDGES,
+ EK_INLINED_CALL,
+ EK_SETJMP,
+ EK_REWIND_FROM_LONGJMP,
+ EK_REWIND_TO_SETJMP,
+ EK_WARNING
+};
+
+extern const char *event_kind_to_string (enum event_kind ek);
+
+/* Event subclasses.
+
+ The class hierarchy looks like this (using indentation to show
+ inheritance, and with event_kinds shown for the concrete subclasses):
+
+ diagnostic_event
+ checker_event
+ debug_event (EK_DEBUG)
+ custom_event (EK_CUSTOM)
+ precanned_custom_event
+ statement_event (EK_STMT)
+ region_creation_event (EK_REGION_CREATION)
+ function_entry_event (EK_FUNCTION_ENTRY)
+ state_change_event (EK_STATE_CHANGE)
+ superedge_event
+ cfg_edge_event
+ start_cfg_edge_event (EK_START_CFG_EDGE)
+ end_cfg_edge_event (EK_END_CFG_EDGE)
+ call_event (EK_CALL_EDGE)
+ return_edge (EK_RETURN_EDGE)
+ start_consolidated_cfg_edges_event (EK_START_CONSOLIDATED_CFG_EDGES)
+ end_consolidated_cfg_edges_event (EK_END_CONSOLIDATED_CFG_EDGES)
+ inlined_call_event (EK_INLINED_CALL)
+ setjmp_event (EK_SETJMP)
+ rewind_event
+ rewind_from_longjmp_event (EK_REWIND_FROM_LONGJMP)
+ rewind_to_setjmp_event (EK_REWIND_TO_SETJMP)
+ warning_event (EK_WARNING). */
+
+/* Abstract subclass of diagnostic_event; the base class for use in
+ checker_path (the analyzer's diagnostic_path subclass). */
+
+class checker_event : public diagnostic_event
+{
+public:
+ /* Implementation of diagnostic_event. */
+
+ location_t get_location () const final override { return m_loc; }
+ tree get_fndecl () const final override { return m_effective_fndecl; }
+ int get_stack_depth () const final override { return m_effective_depth; }
+ const logical_location *get_logical_location () const final override
+ {
+ if (m_effective_fndecl)
+ return &m_logical_loc;
+ else
+ return NULL;
+ }
+ meaning get_meaning () const override;
+
+ /* Additional functionality. */
+
+ int get_original_stack_depth () const { return m_original_depth; }
+
+ virtual void prepare_for_emission (checker_path *,
+ pending_diagnostic *pd,
+ diagnostic_event_id_t emission_id);
+ virtual bool is_call_p () const { return false; }
+ virtual bool is_function_entry_p () const { return false; }
+ virtual bool is_return_p () const { return false; }
+
+ /* For use with %@. */
+ const diagnostic_event_id_t *get_id_ptr () const
+ {
+ return &m_emission_id;
+ }
+
+ void dump (pretty_printer *pp) const;
+ void debug () const;
+
+ void set_location (location_t loc) { m_loc = loc; }
+
+protected:
+ checker_event (enum event_kind kind,
+ location_t loc, tree fndecl, int depth);
+
+ public:
+ const enum event_kind m_kind;
+ protected:
+ location_t m_loc;
+ tree m_original_fndecl;
+ tree m_effective_fndecl;
+ int m_original_depth;
+ int m_effective_depth;
+ pending_diagnostic *m_pending_diagnostic;
+ diagnostic_event_id_t m_emission_id; // only set once all pruning has occurred
+ tree_logical_location m_logical_loc;
+};
+
+/* A concrete event subclass for a purely textual event, for use in
+ debugging path creation and filtering. */
+
+class debug_event : public checker_event
+{
+public:
+ debug_event (location_t loc, tree fndecl, int depth,
+ const char *desc)
+ : checker_event (EK_DEBUG, loc, fndecl, depth),
+ m_desc (xstrdup (desc))
+ {
+ }
+ ~debug_event ()
+ {
+ free (m_desc);
+ }
+
+ label_text get_desc (bool) const final override;
+
+private:
+ char *m_desc;
+};
+
+/* An abstract event subclass for custom events. These are not filtered,
+ as they are likely to be pertinent to the diagnostic. */
+
+class custom_event : public checker_event
+{
+protected:
+ custom_event (location_t loc, tree fndecl, int depth)
+ : checker_event (EK_CUSTOM, loc, fndecl, depth)
+ {
+ }
+};
+
+/* A concrete custom_event subclass with a precanned message. */
+
+class precanned_custom_event : public custom_event
+{
+public:
+ precanned_custom_event (location_t loc, tree fndecl, int depth,
+ const char *desc)
+ : custom_event (loc, fndecl, depth),
+ m_desc (xstrdup (desc))
+ {
+ }
+ ~precanned_custom_event ()
+ {
+ free (m_desc);
+ }
+
+ label_text get_desc (bool) const final override;
+
+private:
+ char *m_desc;
+};
+
+/* A concrete event subclass describing the execution of a gimple statement,
+ for use at high verbosity levels when debugging paths. */
+
+class statement_event : public checker_event
+{
+public:
+ statement_event (const gimple *stmt, tree fndecl, int depth,
+ const program_state &dst_state);
+
+ label_text get_desc (bool) const final override;
+
+ const gimple * const m_stmt;
+ const program_state m_dst_state;
+};
+
+/* There are too many combinations to express region creation in one message,
+ so we emit multiple region_creation_event instances when each pertinent
+ region is created.
+
+ This enum distinguishes between the different messages. */
+
+enum rce_kind
+{
+ /* Generate a message based on the memory space of the region
+ e.g. "region created on stack here". */
+ RCE_MEM_SPACE,
+
+ /* Generate a message based on the capacity of the region
+ e.g. "capacity: 100 bytes". */
+ RCE_CAPACITY,
+
+ /* Generate a debug message. */
+ RCE_DEBUG
+};
+
+/* A concrete event subclass describing the creation of a region that
+ is significant for a diagnostic. */
+
+class region_creation_event : public checker_event
+{
+public:
+ region_creation_event (const region *reg,
+ tree capacity,
+ enum rce_kind kind,
+ location_t loc, tree fndecl, int depth);
+
+ label_text get_desc (bool can_colorize) const final override;
+
+private:
+ const region *m_reg;
+ tree m_capacity;
+ enum rce_kind m_rce_kind;
+};
+
+/* An event subclass describing the entry to a function. */
+
+class function_entry_event : public checker_event
+{
+public:
+ function_entry_event (location_t loc, tree fndecl, int depth)
+ : checker_event (EK_FUNCTION_ENTRY, loc, fndecl, depth)
+ {
+ }
+
+ function_entry_event (const program_point &dst_point);
+
+ label_text get_desc (bool can_colorize) const override;
+ meaning get_meaning () const override;
+
+ bool is_function_entry_p () const final override { return true; }
+};
+
+/* Subclass of checker_event describing a state change. */
+
+class state_change_event : public checker_event
+{
+public:
+ state_change_event (const supernode *node, const gimple *stmt,
+ int stack_depth,
+ const state_machine &sm,
+ const svalue *sval,
+ state_machine::state_t from,
+ state_machine::state_t to,
+ const svalue *origin,
+ const program_state &dst_state);
+
+ label_text get_desc (bool can_colorize) const final override;
+ meaning get_meaning () const override;
+
+ function *get_dest_function () const
+ {
+ return m_dst_state.get_current_function ();
+ }
+
+ const supernode *m_node;
+ const gimple *m_stmt;
+ const state_machine &m_sm;
+ const svalue *m_sval;
+ state_machine::state_t m_from;
+ state_machine::state_t m_to;
+ const svalue *m_origin;
+ program_state m_dst_state;
+};
+
+/* Subclass of checker_event; parent class for subclasses that relate to
+ a superedge. */
+
+class superedge_event : public checker_event
+{
+public:
+ /* Mark this edge event as being either an interprocedural call or
+ return in which VAR is in STATE, and that this is critical to the
+ diagnostic (so that get_desc can attempt to get a better description
+ from any pending_diagnostic). */
+ void record_critical_state (tree var, state_machine::state_t state)
+ {
+ m_var = var;
+ m_critical_state = state;
+ }
+
+ const callgraph_superedge& get_callgraph_superedge () const;
+
+ bool should_filter_p (int verbosity) const;
+
+ protected:
+ superedge_event (enum event_kind kind, const exploded_edge &eedge,
+ location_t loc, tree fndecl, int depth);
+
+ public:
+ const exploded_edge &m_eedge;
+ const superedge *m_sedge;
+ tree m_var;
+ state_machine::state_t m_critical_state;
+};
+
+/* An abstract event subclass for when a CFG edge is followed; it has two
+ subclasses, representing the start of the edge and the end of the
+ edge, which come in pairs. */
+
+class cfg_edge_event : public superedge_event
+{
+public:
+ meaning get_meaning () const override;
+
+ const cfg_superedge& get_cfg_superedge () const;
+
+ protected:
+ cfg_edge_event (enum event_kind kind, const exploded_edge &eedge,
+ location_t loc, tree fndecl, int depth);
+};
+
+/* A concrete event subclass for the start of a CFG edge
+ e.g. "following 'false' branch...'. */
+
+class start_cfg_edge_event : public cfg_edge_event
+{
+public:
+ start_cfg_edge_event (const exploded_edge &eedge,
+ location_t loc, tree fndecl, int depth)
+ : cfg_edge_event (EK_START_CFG_EDGE, eedge, loc, fndecl, depth)
+ {
+ }
+
+ label_text get_desc (bool can_colorize) const final override;
+
+ private:
+ label_text maybe_describe_condition (bool can_colorize) const;
+
+ static label_text maybe_describe_condition (bool can_colorize,
+ tree lhs,
+ enum tree_code op,
+ tree rhs);
+ static bool should_print_expr_p (tree);
+};
+
+/* A concrete event subclass for the end of a CFG edge
+ e.g. "...to here'. */
+
+class end_cfg_edge_event : public cfg_edge_event
+{
+public:
+ end_cfg_edge_event (const exploded_edge &eedge,
+ location_t loc, tree fndecl, int depth)
+ : cfg_edge_event (EK_END_CFG_EDGE, eedge, loc, fndecl, depth)
+ {
+ }
+
+ label_text get_desc (bool /*can_colorize*/) const final override
+ {
+ return label_text::borrow ("...to here");
+ }
+};
+
+/* A concrete event subclass for an interprocedural call. */
+
+class call_event : public superedge_event
+{
+public:
+ call_event (const exploded_edge &eedge,
+ location_t loc, tree fndecl, int depth);
+
+ label_text get_desc (bool can_colorize) const override;
+ meaning get_meaning () const override;
+
+ bool is_call_p () const final override;
+
+protected:
+ tree get_caller_fndecl () const;
+ tree get_callee_fndecl () const;
+
+ const supernode *m_src_snode;
+ const supernode *m_dest_snode;
+};
+
+/* A concrete event subclass for an interprocedural return. */
+
+class return_event : public superedge_event
+{
+public:
+ return_event (const exploded_edge &eedge,
+ location_t loc, tree fndecl, int depth);
+
+ label_text get_desc (bool can_colorize) const final override;
+ meaning get_meaning () const override;
+
+ bool is_return_p () const final override;
+
+ const supernode *m_src_snode;
+ const supernode *m_dest_snode;
+};
+
+/* A concrete event subclass for the start of a consolidated run of CFG
+ edges all either TRUE or FALSE e.g. "following 'false' branch...'. */
+
+class start_consolidated_cfg_edges_event : public checker_event
+{
+public:
+ start_consolidated_cfg_edges_event (location_t loc, tree fndecl, int depth,
+ bool edge_sense)
+ : checker_event (EK_START_CONSOLIDATED_CFG_EDGES, loc, fndecl, depth),
+ m_edge_sense (edge_sense)
+ {
+ }
+
+ label_text get_desc (bool can_colorize) const final override;
+ meaning get_meaning () const override;
+
+ private:
+ bool m_edge_sense;
+};
+
+/* A concrete event subclass for the end of a consolidated run of
+ CFG edges e.g. "...to here'. */
+
+class end_consolidated_cfg_edges_event : public checker_event
+{
+public:
+ end_consolidated_cfg_edges_event (location_t loc, tree fndecl, int depth)
+ : checker_event (EK_END_CONSOLIDATED_CFG_EDGES, loc, fndecl, depth)
+ {
+ }
+
+ label_text get_desc (bool /*can_colorize*/) const final override
+ {
+ return label_text::borrow ("...to here");
+ }
+};
+
+/* A concrete event subclass for describing an inlined call event
+ e.g. "inlined call to 'callee' from 'caller'". */
+
+class inlined_call_event : public checker_event
+{
+public:
+ inlined_call_event (location_t loc,
+ tree apparent_callee_fndecl,
+ tree apparent_caller_fndecl,
+ int actual_depth,
+ int stack_depth_adjustment)
+ : checker_event (EK_INLINED_CALL, loc,
+ apparent_caller_fndecl,
+ actual_depth + stack_depth_adjustment),
+ m_apparent_callee_fndecl (apparent_callee_fndecl),
+ m_apparent_caller_fndecl (apparent_caller_fndecl)
+ {
+ gcc_assert (LOCATION_BLOCK (loc) == NULL);
+ }
+
+ label_text get_desc (bool /*can_colorize*/) const final override;
+ meaning get_meaning () const override;
+
+private:
+ tree m_apparent_callee_fndecl;
+ tree m_apparent_caller_fndecl;
+};
+
+/* A concrete event subclass for a setjmp or sigsetjmp call. */
+
+class setjmp_event : public checker_event
+{
+public:
+ setjmp_event (location_t loc, const exploded_node *enode,
+ tree fndecl, int depth, const gcall *setjmp_call)
+ : checker_event (EK_SETJMP, loc, fndecl, depth),
+ m_enode (enode), m_setjmp_call (setjmp_call)
+ {
+ }
+
+ label_text get_desc (bool can_colorize) const final override;
+
+ void prepare_for_emission (checker_path *path,
+ pending_diagnostic *pd,
+ diagnostic_event_id_t emission_id) final override;
+
+private:
+ const exploded_node *m_enode;
+ const gcall *m_setjmp_call;
+};
+
+/* An abstract event subclass for rewinding from a longjmp to a setjmp
+ (or siglongjmp to sigsetjmp).
+
+ Base class for two from/to subclasses, showing the two halves of the
+ rewind. */
+
+class rewind_event : public checker_event
+{
+public:
+ tree get_longjmp_caller () const;
+ tree get_setjmp_caller () const;
+ const exploded_edge *get_eedge () const { return m_eedge; }
+
+ protected:
+ rewind_event (const exploded_edge *eedge,
+ enum event_kind kind,
+ location_t loc, tree fndecl, int depth,
+ const rewind_info_t *rewind_info);
+ const rewind_info_t *m_rewind_info;
+
+ private:
+ const exploded_edge *m_eedge;
+};
+
+/* A concrete event subclass for rewinding from a longjmp to a setjmp,
+ showing the longjmp (or siglongjmp). */
+
+class rewind_from_longjmp_event : public rewind_event
+{
+public:
+ rewind_from_longjmp_event (const exploded_edge *eedge,
+ location_t loc, tree fndecl, int depth,
+ const rewind_info_t *rewind_info)
+ : rewind_event (eedge, EK_REWIND_FROM_LONGJMP, loc, fndecl, depth,
+ rewind_info)
+ {
+ }
+
+ label_text get_desc (bool can_colorize) const final override;
+};
+
+/* A concrete event subclass for rewinding from a longjmp to a setjmp,
+ showing the setjmp (or sigsetjmp). */
+
+class rewind_to_setjmp_event : public rewind_event
+{
+public:
+ rewind_to_setjmp_event (const exploded_edge *eedge,
+ location_t loc, tree fndecl, int depth,
+ const rewind_info_t *rewind_info)
+ : rewind_event (eedge, EK_REWIND_TO_SETJMP, loc, fndecl, depth,
+ rewind_info)
+ {
+ }
+
+ label_text get_desc (bool can_colorize) const final override;
+
+ void prepare_for_emission (checker_path *path,
+ pending_diagnostic *pd,
+ diagnostic_event_id_t emission_id) final override;
+
+private:
+ diagnostic_event_id_t m_original_setjmp_event_id;
+};
+
+/* Concrete subclass of checker_event for use at the end of a path:
+ a repeat of the warning message at the end of the path (perhaps with
+ references to pertinent events that occurred on the way), at the point
+ where the problem occurs. */
+
+class warning_event : public checker_event
+{
+public:
+ warning_event (location_t loc, tree fndecl, int depth,
+ const state_machine *sm,
+ tree var, state_machine::state_t state)
+ : checker_event (EK_WARNING, loc, fndecl, depth),
+ m_sm (sm), m_var (var), m_state (state)
+ {
+ }
+
+ label_text get_desc (bool can_colorize) const final override;
+ meaning get_meaning () const override;
+
+private:
+ const state_machine *m_sm;
+ tree m_var;
+ state_machine::state_t m_state;
+};
+
+} // namespace ana
+
+#endif /* GCC_ANALYZER_CHECKER_EVENT_H */
diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h
index 53e6bff..55bf1e3 100644
--- a/gcc/analyzer/checker-path.h
+++ b/gcc/analyzer/checker-path.h
@@ -1,4 +1,4 @@
-/* Subclasses of diagnostic_path and diagnostic_event for analyzer diagnostics.
+/* Subclass of diagnostic_path for analyzer diagnostics.
Copyright (C) 2019-2022 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
@@ -21,590 +21,10 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_ANALYZER_CHECKER_PATH_H
#define GCC_ANALYZER_CHECKER_PATH_H
-#include "tree-logical-location.h"
+#include "analyzer/checker-event.h"
namespace ana {
-/* An enum for discriminating between the concrete subclasses of
- checker_event. */
-
-enum event_kind
-{
- EK_DEBUG,
- EK_CUSTOM,
- EK_STMT,
- EK_REGION_CREATION,
- EK_FUNCTION_ENTRY,
- EK_STATE_CHANGE,
- EK_START_CFG_EDGE,
- EK_END_CFG_EDGE,
- EK_CALL_EDGE,
- EK_RETURN_EDGE,
- EK_START_CONSOLIDATED_CFG_EDGES,
- EK_END_CONSOLIDATED_CFG_EDGES,
- EK_INLINED_CALL,
- EK_SETJMP,
- EK_REWIND_FROM_LONGJMP,
- EK_REWIND_TO_SETJMP,
- EK_WARNING
-};
-
-extern const char *event_kind_to_string (enum event_kind ek);
-
-/* Event subclasses.
-
- The class hierarchy looks like this (using indentation to show
- inheritance, and with event_kinds shown for the concrete subclasses):
-
- diagnostic_event
- checker_event
- debug_event (EK_DEBUG)
- custom_event (EK_CUSTOM)
- precanned_custom_event
- statement_event (EK_STMT)
- region_creation_event (EK_REGION_CREATION)
- function_entry_event (EK_FUNCTION_ENTRY)
- state_change_event (EK_STATE_CHANGE)
- superedge_event
- cfg_edge_event
- start_cfg_edge_event (EK_START_CFG_EDGE)
- end_cfg_edge_event (EK_END_CFG_EDGE)
- call_event (EK_CALL_EDGE)
- return_edge (EK_RETURN_EDGE)
- start_consolidated_cfg_edges_event (EK_START_CONSOLIDATED_CFG_EDGES)
- end_consolidated_cfg_edges_event (EK_END_CONSOLIDATED_CFG_EDGES)
- inlined_call_event (EK_INLINED_CALL)
- setjmp_event (EK_SETJMP)
- rewind_event
- rewind_from_longjmp_event (EK_REWIND_FROM_LONGJMP)
- rewind_to_setjmp_event (EK_REWIND_TO_SETJMP)
- warning_event (EK_WARNING). */
-
-/* Abstract subclass of diagnostic_event; the base class for use in
- checker_path (the analyzer's diagnostic_path subclass). */
-
-class checker_event : public diagnostic_event
-{
-public:
- /* Implementation of diagnostic_event. */
-
- location_t get_location () const final override { return m_loc; }
- tree get_fndecl () const final override { return m_effective_fndecl; }
- int get_stack_depth () const final override { return m_effective_depth; }
- const logical_location *get_logical_location () const final override
- {
- if (m_effective_fndecl)
- return &m_logical_loc;
- else
- return NULL;
- }
- meaning get_meaning () const override;
-
- /* Additional functionality. */
-
- int get_original_stack_depth () const { return m_original_depth; }
-
- virtual void prepare_for_emission (checker_path *,
- pending_diagnostic *pd,
- diagnostic_event_id_t emission_id);
- virtual bool is_call_p () const { return false; }
- virtual bool is_function_entry_p () const { return false; }
- virtual bool is_return_p () const { return false; }
-
- /* For use with %@. */
- const diagnostic_event_id_t *get_id_ptr () const
- {
- return &m_emission_id;
- }
-
- void dump (pretty_printer *pp) const;
- void debug () const;
-
- void set_location (location_t loc) { m_loc = loc; }
-
-protected:
- checker_event (enum event_kind kind,
- location_t loc, tree fndecl, int depth);
-
- public:
- const enum event_kind m_kind;
- protected:
- location_t m_loc;
- tree m_original_fndecl;
- tree m_effective_fndecl;
- int m_original_depth;
- int m_effective_depth;
- pending_diagnostic *m_pending_diagnostic;
- diagnostic_event_id_t m_emission_id; // only set once all pruning has occurred
- tree_logical_location m_logical_loc;
-};
-
-/* A concrete event subclass for a purely textual event, for use in
- debugging path creation and filtering. */
-
-class debug_event : public checker_event
-{
-public:
- debug_event (location_t loc, tree fndecl, int depth,
- const char *desc)
- : checker_event (EK_DEBUG, loc, fndecl, depth),
- m_desc (xstrdup (desc))
- {
- }
- ~debug_event ()
- {
- free (m_desc);
- }
-
- label_text get_desc (bool) const final override;
-
-private:
- char *m_desc;
-};
-
-/* An abstract event subclass for custom events. These are not filtered,
- as they are likely to be pertinent to the diagnostic. */
-
-class custom_event : public checker_event
-{
-protected:
- custom_event (location_t loc, tree fndecl, int depth)
- : checker_event (EK_CUSTOM, loc, fndecl, depth)
- {
- }
-};
-
-/* A concrete custom_event subclass with a precanned message. */
-
-class precanned_custom_event : public custom_event
-{
-public:
- precanned_custom_event (location_t loc, tree fndecl, int depth,
- const char *desc)
- : custom_event (loc, fndecl, depth),
- m_desc (xstrdup (desc))
- {
- }
- ~precanned_custom_event ()
- {
- free (m_desc);
- }
-
- label_text get_desc (bool) const final override;
-
-private:
- char *m_desc;
-};
-
-/* A concrete event subclass describing the execution of a gimple statement,
- for use at high verbosity levels when debugging paths. */
-
-class statement_event : public checker_event
-{
-public:
- statement_event (const gimple *stmt, tree fndecl, int depth,
- const program_state &dst_state);
-
- label_text get_desc (bool) const final override;
-
- const gimple * const m_stmt;
- const program_state m_dst_state;
-};
-
-/* There are too many combinations to express region creation in one message,
- so we emit multiple region_creation_event instances when each pertinent
- region is created.
-
- This enum distinguishes between the different messages. */
-
-enum rce_kind
-{
- /* Generate a message based on the memory space of the region
- e.g. "region created on stack here". */
- RCE_MEM_SPACE,
-
- /* Generate a message based on the capacity of the region
- e.g. "capacity: 100 bytes". */
- RCE_CAPACITY,
-
- /* Generate a debug message. */
- RCE_DEBUG
-};
-
-/* A concrete event subclass describing the creation of a region that
- is significant for a diagnostic. */
-
-class region_creation_event : public checker_event
-{
-public:
- region_creation_event (const region *reg,
- tree capacity,
- enum rce_kind kind,
- location_t loc, tree fndecl, int depth);
-
- label_text get_desc (bool can_colorize) const final override;
-
-private:
- const region *m_reg;
- tree m_capacity;
- enum rce_kind m_rce_kind;
-};
-
-/* An event subclass describing the entry to a function. */
-
-class function_entry_event : public checker_event
-{
-public:
- function_entry_event (location_t loc, tree fndecl, int depth)
- : checker_event (EK_FUNCTION_ENTRY, loc, fndecl, depth)
- {
- }
-
- function_entry_event (const program_point &dst_point);
-
- label_text get_desc (bool can_colorize) const override;
- meaning get_meaning () const override;
-
- bool is_function_entry_p () const final override { return true; }
-};
-
-/* Subclass of checker_event describing a state change. */
-
-class state_change_event : public checker_event
-{
-public:
- state_change_event (const supernode *node, const gimple *stmt,
- int stack_depth,
- const state_machine &sm,
- const svalue *sval,
- state_machine::state_t from,
- state_machine::state_t to,
- const svalue *origin,
- const program_state &dst_state);
-
- label_text get_desc (bool can_colorize) const final override;
- meaning get_meaning () const override;
-
- function *get_dest_function () const
- {
- return m_dst_state.get_current_function ();
- }
-
- const supernode *m_node;
- const gimple *m_stmt;
- const state_machine &m_sm;
- const svalue *m_sval;
- state_machine::state_t m_from;
- state_machine::state_t m_to;
- const svalue *m_origin;
- program_state m_dst_state;
-};
-
-/* Subclass of checker_event; parent class for subclasses that relate to
- a superedge. */
-
-class superedge_event : public checker_event
-{
-public:
- /* Mark this edge event as being either an interprocedural call or
- return in which VAR is in STATE, and that this is critical to the
- diagnostic (so that get_desc can attempt to get a better description
- from any pending_diagnostic). */
- void record_critical_state (tree var, state_machine::state_t state)
- {
- m_var = var;
- m_critical_state = state;
- }
-
- const callgraph_superedge& get_callgraph_superedge () const;
-
- bool should_filter_p (int verbosity) const;
-
- protected:
- superedge_event (enum event_kind kind, const exploded_edge &eedge,
- location_t loc, tree fndecl, int depth);
-
- public:
- const exploded_edge &m_eedge;
- const superedge *m_sedge;
- tree m_var;
- state_machine::state_t m_critical_state;
-};
-
-/* An abstract event subclass for when a CFG edge is followed; it has two
- subclasses, representing the start of the edge and the end of the
- edge, which come in pairs. */
-
-class cfg_edge_event : public superedge_event
-{
-public:
- meaning get_meaning () const override;
-
- const cfg_superedge& get_cfg_superedge () const;
-
- protected:
- cfg_edge_event (enum event_kind kind, const exploded_edge &eedge,
- location_t loc, tree fndecl, int depth);
-};
-
-/* A concrete event subclass for the start of a CFG edge
- e.g. "following 'false' branch...'. */
-
-class start_cfg_edge_event : public cfg_edge_event
-{
-public:
- start_cfg_edge_event (const exploded_edge &eedge,
- location_t loc, tree fndecl, int depth)
- : cfg_edge_event (EK_START_CFG_EDGE, eedge, loc, fndecl, depth)
- {
- }
-
- label_text get_desc (bool can_colorize) const final override;
-
- private:
- label_text maybe_describe_condition (bool can_colorize) const;
-
- static label_text maybe_describe_condition (bool can_colorize,
- tree lhs,
- enum tree_code op,
- tree rhs);
- static bool should_print_expr_p (tree);
-};
-
-/* A concrete event subclass for the end of a CFG edge
- e.g. "...to here'. */
-
-class end_cfg_edge_event : public cfg_edge_event
-{
-public:
- end_cfg_edge_event (const exploded_edge &eedge,
- location_t loc, tree fndecl, int depth)
- : cfg_edge_event (EK_END_CFG_EDGE, eedge, loc, fndecl, depth)
- {
- }
-
- label_text get_desc (bool /*can_colorize*/) const final override
- {
- return label_text::borrow ("...to here");
- }
-};
-
-/* A concrete event subclass for an interprocedural call. */
-
-class call_event : public superedge_event
-{
-public:
- call_event (const exploded_edge &eedge,
- location_t loc, tree fndecl, int depth);
-
- label_text get_desc (bool can_colorize) const override;
- meaning get_meaning () const override;
-
- bool is_call_p () const final override;
-
-protected:
- tree get_caller_fndecl () const;
- tree get_callee_fndecl () const;
-
- const supernode *m_src_snode;
- const supernode *m_dest_snode;
-};
-
-/* A concrete event subclass for an interprocedural return. */
-
-class return_event : public superedge_event
-{
-public:
- return_event (const exploded_edge &eedge,
- location_t loc, tree fndecl, int depth);
-
- label_text get_desc (bool can_colorize) const final override;
- meaning get_meaning () const override;
-
- bool is_return_p () const final override;
-
- const supernode *m_src_snode;
- const supernode *m_dest_snode;
-};
-
-/* A concrete event subclass for the start of a consolidated run of CFG
- edges all either TRUE or FALSE e.g. "following 'false' branch...'. */
-
-class start_consolidated_cfg_edges_event : public checker_event
-{
-public:
- start_consolidated_cfg_edges_event (location_t loc, tree fndecl, int depth,
- bool edge_sense)
- : checker_event (EK_START_CONSOLIDATED_CFG_EDGES, loc, fndecl, depth),
- m_edge_sense (edge_sense)
- {
- }
-
- label_text get_desc (bool can_colorize) const final override;
- meaning get_meaning () const override;
-
- private:
- bool m_edge_sense;
-};
-
-/* A concrete event subclass for the end of a consolidated run of
- CFG edges e.g. "...to here'. */
-
-class end_consolidated_cfg_edges_event : public checker_event
-{
-public:
- end_consolidated_cfg_edges_event (location_t loc, tree fndecl, int depth)
- : checker_event (EK_END_CONSOLIDATED_CFG_EDGES, loc, fndecl, depth)
- {
- }
-
- label_text get_desc (bool /*can_colorize*/) const final override
- {
- return label_text::borrow ("...to here");
- }
-};
-
-/* A concrete event subclass for describing an inlined call event
- e.g. "inlined call to 'callee' from 'caller'". */
-
-class inlined_call_event : public checker_event
-{
-public:
- inlined_call_event (location_t loc,
- tree apparent_callee_fndecl,
- tree apparent_caller_fndecl,
- int actual_depth,
- int stack_depth_adjustment)
- : checker_event (EK_INLINED_CALL, loc,
- apparent_caller_fndecl,
- actual_depth + stack_depth_adjustment),
- m_apparent_callee_fndecl (apparent_callee_fndecl),
- m_apparent_caller_fndecl (apparent_caller_fndecl)
- {
- gcc_assert (LOCATION_BLOCK (loc) == NULL);
- }
-
- label_text get_desc (bool /*can_colorize*/) const final override;
- meaning get_meaning () const override;
-
-private:
- tree m_apparent_callee_fndecl;
- tree m_apparent_caller_fndecl;
-};
-
-/* A concrete event subclass for a setjmp or sigsetjmp call. */
-
-class setjmp_event : public checker_event
-{
-public:
- setjmp_event (location_t loc, const exploded_node *enode,
- tree fndecl, int depth, const gcall *setjmp_call)
- : checker_event (EK_SETJMP, loc, fndecl, depth),
- m_enode (enode), m_setjmp_call (setjmp_call)
- {
- }
-
- label_text get_desc (bool can_colorize) const final override;
-
- void prepare_for_emission (checker_path *path,
- pending_diagnostic *pd,
- diagnostic_event_id_t emission_id) final override;
-
-private:
- const exploded_node *m_enode;
- const gcall *m_setjmp_call;
-};
-
-/* An abstract event subclass for rewinding from a longjmp to a setjmp
- (or siglongjmp to sigsetjmp).
-
- Base class for two from/to subclasses, showing the two halves of the
- rewind. */
-
-class rewind_event : public checker_event
-{
-public:
- tree get_longjmp_caller () const;
- tree get_setjmp_caller () const;
- const exploded_edge *get_eedge () const { return m_eedge; }
-
- protected:
- rewind_event (const exploded_edge *eedge,
- enum event_kind kind,
- location_t loc, tree fndecl, int depth,
- const rewind_info_t *rewind_info);
- const rewind_info_t *m_rewind_info;
-
- private:
- const exploded_edge *m_eedge;
-};
-
-/* A concrete event subclass for rewinding from a longjmp to a setjmp,
- showing the longjmp (or siglongjmp). */
-
-class rewind_from_longjmp_event : public rewind_event
-{
-public:
- rewind_from_longjmp_event (const exploded_edge *eedge,
- location_t loc, tree fndecl, int depth,
- const rewind_info_t *rewind_info)
- : rewind_event (eedge, EK_REWIND_FROM_LONGJMP, loc, fndecl, depth,
- rewind_info)
- {
- }
-
- label_text get_desc (bool can_colorize) const final override;
-};
-
-/* A concrete event subclass for rewinding from a longjmp to a setjmp,
- showing the setjmp (or sigsetjmp). */
-
-class rewind_to_setjmp_event : public rewind_event
-{
-public:
- rewind_to_setjmp_event (const exploded_edge *eedge,
- location_t loc, tree fndecl, int depth,
- const rewind_info_t *rewind_info)
- : rewind_event (eedge, EK_REWIND_TO_SETJMP, loc, fndecl, depth,
- rewind_info)
- {
- }
-
- label_text get_desc (bool can_colorize) const final override;
-
- void prepare_for_emission (checker_path *path,
- pending_diagnostic *pd,
- diagnostic_event_id_t emission_id) final override;
-
-private:
- diagnostic_event_id_t m_original_setjmp_event_id;
-};
-
-/* Concrete subclass of checker_event for use at the end of a path:
- a repeat of the warning message at the end of the path (perhaps with
- references to pertinent events that occurred on the way), at the point
- where the problem occurs. */
-
-class warning_event : public checker_event
-{
-public:
- warning_event (location_t loc, tree fndecl, int depth,
- const state_machine *sm,
- tree var, state_machine::state_t state)
- : checker_event (EK_WARNING, loc, fndecl, depth),
- m_sm (sm), m_var (var), m_state (state)
- {
- }
-
- label_text get_desc (bool can_colorize) const final override;
- meaning get_meaning () const override;
-
-private:
- const state_machine *m_sm;
- tree m_var;
- state_machine::state_t m_state;
-};
-
/* Subclass of diagnostic_path for analyzer diagnostics. */
class checker_path : public diagnostic_path