From 5b1bc5c14c9b0d401b5f42190c5062ed939deddc Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 6 May 2020 17:42:40 -0400 Subject: [PATCH 104/179] FIXME: implement poisoned_svalue2 --- gcc/analyzer/region-model2.cc | 26 ++++++++++++ gcc/analyzer/region-model2.h | 78 ++++++++++++++++++++++++++--------- 2 files changed, 84 insertions(+), 20 deletions(-) diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc index ecc0d68e434..19856d4288b 100644 --- a/gcc/analyzer/region-model2.cc +++ b/gcc/analyzer/region-model2.cc @@ -663,6 +663,17 @@ poisoned_svalue2::print_details (const region_model2 &model ATTRIBUTE_UNUSED, } #endif +/* FIXME. */ + +void +poisoned_svalue2::dump_to_pp (pretty_printer *pp, bool simple) const +{ + if (simple) + pp_printf (pp, "POISONED(%s)", poison_kind_to_str (m_kind)); + else + pp_printf (pp, "poisoned_svalue2(%s)", poison_kind_to_str (m_kind)); +} + /* class setjmp_svalue2's implementation is in engine.cc, so that it can use the declaration of exploded_node. */ @@ -2758,6 +2769,9 @@ region_model2_manager::~region_model2_manager () for (constants_map_t::iterator iter = m_constants_map.begin (); iter != m_constants_map.end (); ++iter) delete (*iter).second; + for (poisoned_values_map_t::iterator iter = m_poisoned_values_map.begin (); + iter != m_poisoned_values_map.end (); ++iter) + delete (*iter).second; for (initial_values_map_t::iterator iter = m_initial_values_map.begin (); iter != m_initial_values_map.end (); ++iter) delete (*iter).second; @@ -2816,6 +2830,18 @@ region_model2_manager::get_or_create_initial_value (const region2 *reg) return initial_sval; } +const svalue2 * +region_model2_manager::get_or_create_poisoned_svalue2 (enum poison_kind kind, + tree type) +{ + poisoned_svalue2::key_t key (kind, type); + if (poisoned_svalue2 **slot = m_poisoned_values_map.get (key)) + return *slot; + poisoned_svalue2 *poisoned_sval = new poisoned_svalue2 (kind, type); + m_poisoned_values_map.put (key, poisoned_sval); + return poisoned_sval; +} + const svalue2 * region_model2_manager::get_ptr_svalue2 (tree ptr_type, const region2 *pointee) { diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h index ddf8109ec0c..560ffa46d4f 100644 --- a/gcc/analyzer/region-model2.h +++ b/gcc/analyzer/region-model2.h @@ -72,6 +72,26 @@ namespace inchash namespace ana { +/* A hash traits class that uses member functions to implement + the various required ops. */ + +template +struct member_function_hash_traits : public typed_noop_remove +{ + typedef Type value_type; + typedef Type compare_type; + static inline hashval_t hash (value_type v) { return v.hash (); } + static inline bool equal (const value_type &existing, + const value_type &candidate) + { + return existing == candidate; + } + static inline void mark_deleted (Type &t) { t.mark_deleted (); } + static inline void mark_empty (Type &t) { t.mark_empty (); } + static inline bool is_deleted (Type t) { return t.is_deleted (); } + static inline bool is_empty (Type t) { return t.is_empty (); } +}; + /* A region_model2 is effectively a graph of regions and symbolic values. FIXME: we're eliminating IDs in this prototype. We store per-model IDs rather than pointers to make it easier to clone @@ -375,6 +395,32 @@ extern const char *poison_kind_to_str (enum poison_kind); class poisoned_svalue2 : public svalue2 { public: + /* A support class for uniquifying instances of poisoned_svalue2. */ + struct key_t + { + key_t (enum poison_kind kind, tree type) + : m_kind (kind), m_type (type) + {} + + hashval_t hash () const + { + return 42; // FIXME + } + + bool operator== (const key_t &other) const + { + return (m_kind == other.m_kind && m_type == other.m_type); + } + + void mark_deleted () { m_type = reinterpret_cast (1); } + void mark_empty () { m_type = NULL_TREE; } + bool is_deleted () const { return m_type == reinterpret_cast (1); } + bool is_empty () const { return m_type == NULL_TREE; } + + enum poison_kind m_kind; + tree m_type; + }; + poisoned_svalue2 (enum poison_kind kind, tree type) : svalue2 (type), m_kind (kind) {} @@ -415,6 +461,12 @@ is_a_helper ::test (const svalue2 *sval) return sval->get_kind () == svalue2::SK_POISONED; } +template <> struct default_hash_traits +: public member_function_hash_traits +{ + static const bool empty_zero_p = true; +}; + namespace ana { #if 0 @@ -540,26 +592,6 @@ is_a_helper ::test (const svalue2 *sval) namespace ana { -/* A hash traits class that uses member functions to implement - the various required ops. */ - -template -struct member_function_hash_traits : public typed_noop_remove -{ - typedef Type value_type; - typedef Type compare_type; - static inline hashval_t hash (value_type v) { return v.hash (); } - static inline bool equal (const value_type &existing, - const value_type &candidate) - { - return existing == candidate; - } - static inline void mark_deleted (Type &t) { t.mark_deleted (); } - static inline void mark_empty (Type &t) { t.mark_empty (); } - static inline bool is_deleted (Type t) { return t.is_deleted (); } - static inline bool is_empty (Type t) { return t.is_empty (); } -}; - /* Concrete subclass of svalue2 representing a unary operation on another svalue2s (e.g. a cast). */ @@ -1584,6 +1616,8 @@ public: /* svalue2 consolidation. */ const svalue2 *get_or_create_constant_svalue2 (tree cst_expr); + const svalue2 *get_or_create_poisoned_svalue2 (enum poison_kind kind, + tree type); const svalue2 *get_or_create_initial_value (const region2 *reg); const svalue2 *get_ptr_svalue2 (tree ptr_type, const region2 *pointee); const svalue2 *get_or_create_unaryop (tree type, enum tree_code op, @@ -1644,6 +1678,10 @@ private: typedef hash_map constants_map_t; constants_map_t m_constants_map; + typedef hash_map poisoned_values_map_t; + poisoned_values_map_t m_poisoned_values_map; + typedef hash_map initial_values_map_t; initial_values_map_t m_initial_values_map; -- 2.21.0