From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 53C3E3858439 for ; Fri, 11 Nov 2022 21:12:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 53C3E3858439 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1668201175; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=JUpMVMYxO3rIMoQUAJ4M2qbfjzHmC+VVH9YOYhop36k=; b=QewCb2RCJF80wudVsVASipQ3/AVIF5Bh+NGEviNUjVnNWmFYx68UWiAvuyex9cd9EObQBw /ZDJLnEUTvDX8o9y7AWWxy9Cr9ostA07XqK5hJNmvhc2vck77Rbww7zEb5Pd98lB/Tnlpd 2F6/NL2WFyIvHx6yMY7EdixxoJ16QL8= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-538-bE62APzRMcSyp1vtHo6Isg-1; Fri, 11 Nov 2022 16:12:53 -0500 X-MC-Unique: bE62APzRMcSyp1vtHo6Isg-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 653D529ABA17 for ; Fri, 11 Nov 2022 21:12:53 +0000 (UTC) Received: from t14s.localdomain.com (unknown [10.2.17.189]) by smtp.corp.redhat.com (Postfix) with ESMTP id 12F6B492B0A; Fri, 11 Nov 2022 21:12:53 +0000 (UTC) From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [committed] analyzer: split out checker_event classes to their own header Date: Fri, 11 Nov 2022 16:12:51 -0500 Message-Id: <20221111211251.2707146-1-dmalcolm@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to trunk as r13-3913-g65752c1f7c41c5. 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 --- gcc/analyzer/checker-event.h | 610 +++++++++++++++++++++++++++++++++++ gcc/analyzer/checker-path.h | 584 +-------------------------------- 2 files changed, 612 insertions(+), 582 deletions(-) create mode 100644 gcc/analyzer/checker-event.h diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h new file mode 100644 index 00000000000..18c44e600c8 --- /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 . + +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 +. */ + +#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 53e6bff03ec..55bf1e3e3b5 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 . @@ -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 -- 2.26.3