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.
This commit is contained in:
David Malcolm 2020-10-13 18:49:11 -04:00
parent 12b267cc60
commit 61a43de58c
3 changed files with 40 additions and 21 deletions

View File

@ -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;
}
}
}
}

View File

@ -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);

View File

@ -0,0 +1,8 @@
extern const char XtStrings[];
void unknown_fn (void *);
void test (void)
{
unknown_fn ((char*)&XtStrings[429]);
}