From: David Malcolm Date: Tue, 13 Oct 2020 22:49:11 +0000 (-0400) Subject: analyzer: fix ICE on globals with unknown size [PR93388] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=61a43de58cb6de7212a622060500ad0a0fd94fae;p=gcc.git analyzer: fix ICE on globals with unknown size [PR93388] This patch fixes an ICE seen when attempting to build various existing tests in our testsuite with -fanalyzer, including gcc.c-torture/compile/980816-1.c. gcc/analyzer/ChangeLog: PR analyzer/93388 * region-model.cc (region_model::get_initial_value_for_global): Fall back to returning an initial_svalue if decl_region::get_svalue_for_initializer fails. * region.cc (decl_region::get_svalue_for_initializer): Don't attempt to create a compound_svalue if the region has an unknown size. gcc/testsuite/ChangeLog: PR analyzer/93388 * gcc.dg/analyzer/data-model-21.c: New test. --- diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 922e0361e59..06c0c8668ac 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -1345,26 +1345,27 @@ region_model::get_initial_value_for_global (const region *reg) const if ((called_from_main_p () && !DECL_EXTERNAL (decl)) || TREE_READONLY (decl)) { - /* Get the initializer value for base_reg. */ - const svalue *base_reg_init - = base_reg->get_svalue_for_initializer (m_mgr); - gcc_assert (base_reg_init); - if (reg == base_reg) - return base_reg_init; - else + /* Attempt to get the initializer value for base_reg. */ + if (const svalue *base_reg_init + = base_reg->get_svalue_for_initializer (m_mgr)) { - /* 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, - BK_direct); - const svalue *sval - = c.get_any_binding (m_mgr->get_store_manager (), reg); - if (sval) + if (reg == base_reg) + return base_reg_init; + else { - if (reg->get_type ()) - sval = m_mgr->get_or_create_cast (reg->get_type (), - sval); - return sval; + /* 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, + BK_direct); + 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; + } } } } diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index 0820893a9b4..adf0e2c3ce3 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -927,7 +927,9 @@ decl_region::get_svalue_for_constructor (tree ctor, Get an svalue for the initial value of this region at entry to "main" (either based on DECL_INITIAL, or implicit initialization to - zero. */ + zero. + + Return NULL if there is a problem. */ const svalue * decl_region::get_svalue_for_initializer (region_model_manager *mgr) const @@ -935,12 +937,20 @@ decl_region::get_svalue_for_initializer (region_model_manager *mgr) const tree init = DECL_INITIAL (m_decl); if (!init) { - /* Implicit initialization to zero; use a compound_svalue for it. */ + /* Implicit initialization to zero; use a compound_svalue for it. + Doing so requires that we have a concrete binding for this region, + which can fail if we have a region with unknown size + (e.g. "extern const char arr[];"). */ + const binding_key *binding + = binding_key::make (mgr->get_store_manager (), this, BK_direct); + if (binding->symbolic_p ()) + return NULL; + binding_cluster c (this); c.zero_fill_region (mgr->get_store_manager (), this); return mgr->get_or_create_compound_svalue (TREE_TYPE (m_decl), c.get_map ()); - } + } if (TREE_CODE (init) == CONSTRUCTOR) return get_svalue_for_constructor (init, mgr); diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-21.c b/gcc/testsuite/gcc.dg/analyzer/data-model-21.c new file mode 100644 index 00000000000..b952bcb9748 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/data-model-21.c @@ -0,0 +1,8 @@ +extern const char XtStrings[]; + +void unknown_fn (void *); + +void test (void) +{ + unknown_fn ((char*)&XtStrings[429]); +}