the initial value of REG can be taken from the initialization value
of the decl. */
if (called_from_main_p () || TREE_READONLY (decl))
- {
- /* Attempt to get the initializer value for base_reg. */
- if (const svalue *base_reg_init
- = base_reg->get_svalue_for_initializer (m_mgr))
- {
- if (reg == base_reg)
- return base_reg_init;
- else
- {
- /* Get the value for REG within base_reg_init. */
- binding_cluster c (base_reg);
- c.bind (m_mgr->get_store_manager (), base_reg, base_reg_init);
- const svalue *sval
- = c.get_any_binding (m_mgr->get_store_manager (), reg);
- if (sval)
- {
- if (reg->get_type ())
- sval = m_mgr->get_or_create_cast (reg->get_type (),
- sval);
- return sval;
- }
- }
- }
- }
+ return reg->get_initial_value_at_main (m_mgr);
/* Otherwise, return INIT_VAL(REG). */
return m_mgr->get_or_create_initial_value (reg);
}
}
+/* For regions within a global decl, get the svalue for the initial
+ value of this region when the program starts, caching the result. */
+
+const svalue *
+region::get_initial_value_at_main (region_model_manager *mgr) const
+{
+ if (!m_cached_init_sval_at_main)
+ m_cached_init_sval_at_main = calc_initial_value_at_main (mgr);
+ return m_cached_init_sval_at_main;
+}
+
+/* Implementation of region::get_initial_value_at_main. */
+
+const svalue *
+region::calc_initial_value_at_main (region_model_manager *mgr) const
+{
+ const decl_region *base_reg = get_base_region ()->dyn_cast_decl_region ();
+ gcc_assert (base_reg);
+
+ /* Attempt to get the initializer value for base_reg. */
+ if (const svalue *base_reg_init
+ = base_reg->get_svalue_for_initializer (mgr))
+ {
+ if (this == base_reg)
+ return base_reg_init;
+ else
+ {
+ /* Get the value for REG within base_reg_init. */
+ binding_cluster c (base_reg);
+ c.bind (mgr->get_store_manager (), base_reg, base_reg_init);
+ const svalue *sval
+ = c.get_any_binding (mgr->get_store_manager (), this);
+ if (sval)
+ {
+ if (get_type ())
+ sval = mgr->get_or_create_cast (get_type (), sval);
+ return sval;
+ }
+ }
+ }
+
+ /* Otherwise, return INIT_VAL(REG). */
+ return mgr->get_or_create_initial_value (this);
+}
+
/* If this region is a decl_region, return the decl.
Otherwise return NULL. */
region::region (complexity c, unsigned id, const region *parent, tree type)
: m_complexity (c), m_id (id), m_parent (parent), m_type (type),
- m_cached_offset (NULL)
+ m_cached_offset (NULL), m_cached_init_sval_at_main (NULL)
{
gcc_assert (type == NULL_TREE || TYPE_P (type));
}
return NULL;
}
-/* Get an svalue for CTOR, a CONSTRUCTOR for this region's decl. */
+/* Implementation of decl_region::get_svalue_for_constructor
+ for when the cached value hasn't yet been calculated. */
const svalue *
-decl_region::get_svalue_for_constructor (tree ctor,
- region_model_manager *mgr) const
+decl_region::calc_svalue_for_constructor (tree ctor,
+ region_model_manager *mgr) const
{
- gcc_assert (!TREE_CLOBBER_P (ctor));
-
/* Create a binding map, applying ctor to it, using this
decl_region as the base region when building child regions
for offset calculations. */
return mgr->get_or_create_compound_svalue (get_type (), map);
}
+/* Get an svalue for CTOR, a CONSTRUCTOR for this region's decl. */
+
+const svalue *
+decl_region::get_svalue_for_constructor (tree ctor,
+ region_model_manager *mgr) const
+{
+ gcc_assert (!TREE_CLOBBER_P (ctor));
+ gcc_assert (ctor == DECL_INITIAL (m_decl));
+
+ if (!m_ctor_svalue)
+ m_ctor_svalue = calc_svalue_for_constructor (ctor, mgr);
+
+ return m_ctor_svalue;
+}
+
/* For use on decl_regions for global variables.
Get an svalue for the initial value of this region at entry to
const frame_region *maybe_get_frame_region () const;
enum memory_space get_memory_space () const;
bool can_have_initial_svalue_p () const;
+ const svalue *get_initial_value_at_main (region_model_manager *mgr) const;
tree maybe_get_decl () const;
private:
region_offset calc_offset (region_model_manager *mgr) const;
+ const svalue *calc_initial_value_at_main (region_model_manager *mgr) const;
complexity m_complexity;
unsigned m_id; // purely for deterministic sorting at this stage, for dumps
tree m_type;
mutable region_offset *m_cached_offset;
+
+ /* For regions within a global decl, a cache of the svalue for the initial
+ value of this region when the program starts. */
+ mutable const svalue *m_cached_init_sval_at_main;
};
} // namespace ana
public:
decl_region (unsigned id, const region *parent, tree decl)
: region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl),
- m_tracked (calc_tracked_p (decl))
+ m_tracked (calc_tracked_p (decl)),
+ m_ctor_svalue (NULL)
{}
enum region_kind get_kind () const final override { return RK_DECL; }
const svalue *get_svalue_for_initializer (region_model_manager *mgr) const;
private:
+ const svalue *calc_svalue_for_constructor (tree ctor,
+ region_model_manager *mgr) const;
static bool calc_tracked_p (tree decl);
tree m_decl;
store objects).
This can be debugged using -fdump-analyzer-untracked. */
bool m_tracked;
+
+ /* Cached result of get_svalue_for_constructor. */
+ mutable const svalue *m_ctor_svalue;
};
} // namespace ana