diff options
Diffstat (limited to 'gcc/analyzer/supergraph.h')
-rw-r--r-- | gcc/analyzer/supergraph.h | 197 |
1 files changed, 181 insertions, 16 deletions
diff --git a/gcc/analyzer/supergraph.h b/gcc/analyzer/supergraph.h index 6f94f99..f64a2f4 100644 --- a/gcc/analyzer/supergraph.h +++ b/gcc/analyzer/supergraph.h @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "gimple-iterator.h" #include "digraph.h" +#include "except.h" using namespace ana; @@ -42,6 +43,9 @@ class superedge; class return_superedge; class cfg_superedge; class switch_cfg_superedge; + class eh_dispatch_cfg_superedge; + class eh_dispatch_try_cfg_superedge; + class eh_dispatch_allowed_cfg_superedge; class supercluster; class dot_annotator; @@ -126,7 +130,7 @@ public: return *const_cast <bb_to_node_t &> (m_bb_to_initial_node).get (bb); } - /* Get the supernode containing the second half of the gcall * + /* Get the supernode containing the second half of the gcall & at an interprocedural call, within the caller. */ supernode *get_caller_next_node (cgraph_edge *edge) const { @@ -270,7 +274,7 @@ class supernode : public dnode<supergraph_traits> i.ptr = gimple_seq_first (*pseq); i.seq = pseq; - i.bb = i.ptr ? gimple_bb (i.ptr) : NULL; + i.bb = i.ptr ? gimple_bb (i.ptr) : nullptr; return i; } @@ -283,15 +287,15 @@ class supernode : public dnode<supergraph_traits> gimple *get_last_stmt () const { if (m_stmts.length () == 0) - return NULL; + return nullptr; return m_stmts[m_stmts.length () - 1]; } gcall *get_final_call () const { gimple *stmt = get_last_stmt (); - if (stmt == NULL) - return NULL; + if (stmt == nullptr) + return nullptr; return dyn_cast<gcall *> (stmt); } @@ -327,15 +331,18 @@ class superedge : public dedge<supergraph_traits> enum edge_kind get_kind () const { return m_kind; } - virtual cfg_superedge *dyn_cast_cfg_superedge () { return NULL; } - virtual const cfg_superedge *dyn_cast_cfg_superedge () const { return NULL; } - virtual const switch_cfg_superedge *dyn_cast_switch_cfg_superedge () const { return NULL; } - virtual callgraph_superedge *dyn_cast_callgraph_superedge () { return NULL; } - virtual const callgraph_superedge *dyn_cast_callgraph_superedge () const { return NULL; } - virtual call_superedge *dyn_cast_call_superedge () { return NULL; } - virtual const call_superedge *dyn_cast_call_superedge () const { return NULL; } - virtual return_superedge *dyn_cast_return_superedge () { return NULL; } - virtual const return_superedge *dyn_cast_return_superedge () const { return NULL; } + virtual cfg_superedge *dyn_cast_cfg_superedge () { return nullptr; } + virtual const cfg_superedge *dyn_cast_cfg_superedge () const { return nullptr; } + virtual const switch_cfg_superedge *dyn_cast_switch_cfg_superedge () const { return nullptr; } + virtual const eh_dispatch_cfg_superedge *dyn_cast_eh_dispatch_cfg_superedge () const { return nullptr; } + virtual const eh_dispatch_try_cfg_superedge *dyn_cast_eh_dispatch_try_cfg_superedge () const { return nullptr; } + virtual const eh_dispatch_allowed_cfg_superedge *dyn_cast_eh_dispatch_allowed_cfg_superedge () const { return nullptr; } + virtual callgraph_superedge *dyn_cast_callgraph_superedge () { return nullptr; } + virtual const callgraph_superedge *dyn_cast_callgraph_superedge () const { return nullptr; } + virtual call_superedge *dyn_cast_call_superedge () { return nullptr; } + virtual const call_superedge *dyn_cast_call_superedge () const { return nullptr; } + virtual return_superedge *dyn_cast_return_superedge () { return nullptr; } + virtual const return_superedge *dyn_cast_return_superedge () const { return nullptr; } ::edge get_any_cfg_edge () const; cgraph_edge *get_any_callgraph_edge () const; @@ -415,7 +422,7 @@ class callgraph_superedge : public superedge function *get_caller_function () const; tree get_callee_decl () const; tree get_caller_decl () const; - gcall *get_call_stmt () const; + const gcall &get_call_stmt () const; tree get_arg_for_parm (tree parm, callsite_expr *out) const; tree get_parm_for_arg (tree arg, callsite_expr *out) const; tree map_expr_from_caller_to_callee (tree caller_expr, @@ -587,11 +594,169 @@ template <> inline bool is_a_helper <const switch_cfg_superedge *>::test (const superedge *sedge) { - return sedge->dyn_cast_switch_cfg_superedge () != NULL; + return sedge->dyn_cast_switch_cfg_superedge () != nullptr; } namespace ana { +/* A subclass for edges from eh_dispatch statements, retaining enough + information to identify the various types being caught, vs the + "unhandled type" case, and for adding labels when rendering + via graphviz. + This is abstract; there are concrete subclasses based on the type + of the eh_region. */ + +class eh_dispatch_cfg_superedge : public cfg_superedge +{ + public: + static std::unique_ptr<eh_dispatch_cfg_superedge> + make (supernode *src, + supernode *dest, + ::edge e, + const geh_dispatch *eh_dispatch_stmt); + + const eh_dispatch_cfg_superedge *dyn_cast_eh_dispatch_cfg_superedge () const + final override + { + return this; + } + + const geh_dispatch * + get_eh_dispatch_stmt () const + { + return m_eh_dispatch_stmt; + } + + const eh_status &get_eh_status () const; + eh_region get_eh_region () const { return m_eh_region; } + + virtual bool + apply_constraints (region_model *model, + region_model_context *ctxt, + tree exception_type, + std::unique_ptr<rejected_constraint> *out) const = 0; + +protected: + eh_dispatch_cfg_superedge (supernode *src, supernode *dst, ::edge e, + const geh_dispatch *eh_dispatch_stmt, + eh_region eh_reg); + +private: + const geh_dispatch *m_eh_dispatch_stmt; + eh_region m_eh_region; +}; + +} // namespace ana + +template <> +template <> +inline bool +is_a_helper <const eh_dispatch_cfg_superedge *>::test (const superedge *sedge) +{ + return sedge->dyn_cast_eh_dispatch_cfg_superedge () != nullptr; +} + +namespace ana { + +/* A concrete subclass for edges from an eh_dispatch statements + for ERT_TRY regions. */ + +class eh_dispatch_try_cfg_superedge : public eh_dispatch_cfg_superedge +{ + public: + eh_dispatch_try_cfg_superedge (supernode *src, supernode *dst, ::edge e, + const geh_dispatch *eh_dispatch_stmt, + eh_region eh_reg, + eh_catch ehc) + : eh_dispatch_cfg_superedge (src, dst, e, eh_dispatch_stmt, eh_reg), + m_eh_catch (ehc) + { + gcc_assert (eh_reg->type == ERT_TRY); + } + + const eh_dispatch_try_cfg_superedge * + dyn_cast_eh_dispatch_try_cfg_superedge () const final override + { + return this; + } + + void dump_label_to_pp (pretty_printer *pp, + bool user_facing) const final override; + + eh_catch get_eh_catch () const { return m_eh_catch; } + + bool + apply_constraints (region_model *model, + region_model_context *ctxt, + tree exception_type, + std::unique_ptr<rejected_constraint> *out) + const final override; + +private: + eh_catch m_eh_catch; +}; + +} // namespace ana + +template <> +template <> +inline bool +is_a_helper <const eh_dispatch_try_cfg_superedge *>::test (const superedge *sedge) +{ + return sedge->dyn_cast_eh_dispatch_try_cfg_superedge () != nullptr; +} + +namespace ana { + +/* A concrete subclass for edges from an eh_dispatch statements + for ERT_ALLOWED_EXCEPTIONS regions. */ + +class eh_dispatch_allowed_cfg_superedge : public eh_dispatch_cfg_superedge +{ + public: + enum eh_kind + { + expected, + unexpected + }; + + eh_dispatch_allowed_cfg_superedge (supernode *src, supernode *dst, ::edge e, + const geh_dispatch *eh_dispatch_stmt, + eh_region eh_reg); + + const eh_dispatch_allowed_cfg_superedge * + dyn_cast_eh_dispatch_allowed_cfg_superedge () const final override + { + return this; + } + + void dump_label_to_pp (pretty_printer *pp, + bool user_facing) const final override; + + bool + apply_constraints (region_model *model, + region_model_context *ctxt, + tree exception_type, + std::unique_ptr<rejected_constraint> *out) + const final override; + + enum eh_kind get_eh_kind () const { return m_kind; } + +private: + enum eh_kind m_kind; +}; + +} // namespace ana + +template <> +template <> +inline bool +is_a_helper <const eh_dispatch_allowed_cfg_superedge *>::test (const superedge *sedge) +{ + return sedge->dyn_cast_eh_dispatch_allowed_cfg_superedge () != nullptr; +} + +namespace ana { /* Base class for adding additional content to the .dot output for a supergraph. */ |