analyzer: fix ICE on RANGE_EXPR in CONSTRUCTORs [PR96763]
gcc/analyzer/ChangeLog: PR analyzer/96763 * store.cc (binding_map::apply_ctor_to_region): Handle RANGE_EXPR by calling a new binding_map::apply_ctor_val_to_range subroutine. Split out the existing non-CONSTRUCTOR-handling code to a new apply_ctor_pair_to_child_region subroutine. (binding_map::apply_ctor_val_to_range): New. (binding_map::apply_ctor_pair_to_child_region): New, split out from binding_map::apply_ctor_to_region as noted above. * store.h (binding_map::apply_ctor_val_to_range): New decl. (binding_map::apply_ctor_pair_to_child_region): New decl. gcc/testsuite/ChangeLog: PR analyzer/96763 * g++.dg/analyzer/pr96763.C: New test.
This commit is contained in:
parent
ecdb93224c
commit
0d1b4edc5f
@ -419,43 +419,102 @@ binding_map::apply_ctor_to_region (const region *parent_reg, tree ctor,
|
||||
{
|
||||
if (!index)
|
||||
index = build_int_cst (integer_type_node, ix);
|
||||
const region *child_reg
|
||||
= get_subregion_within_ctor (parent_reg, index, mgr);
|
||||
if (TREE_CODE (val) == CONSTRUCTOR)
|
||||
apply_ctor_to_region (child_reg, val, mgr);
|
||||
else
|
||||
else if (TREE_CODE (index) == RANGE_EXPR)
|
||||
{
|
||||
const svalue *sval = get_svalue_for_ctor_val (val, mgr);
|
||||
const binding_key *k
|
||||
= binding_key::make (mgr->get_store_manager (), child_reg,
|
||||
BK_direct);
|
||||
/* Handle the case where we have an unknown size for child_reg
|
||||
(e.g. due to it being a trailing field with incomplete array
|
||||
type. */
|
||||
if (!k->concrete_p ())
|
||||
{
|
||||
/* Assume that sval has a well-defined size for this case. */
|
||||
tree sval_type = sval->get_type ();
|
||||
gcc_assert (sval_type);
|
||||
HOST_WIDE_INT sval_byte_size = int_size_in_bytes (sval_type);
|
||||
gcc_assert (sval_byte_size != -1);
|
||||
bit_size_t sval_bit_size = sval_byte_size * BITS_PER_UNIT;
|
||||
/* Get offset of child relative to base region. */
|
||||
region_offset child_base_offset = child_reg->get_offset ();
|
||||
gcc_assert (!child_base_offset.symbolic_p ());
|
||||
/* Convert to an offset relative to the parent region. */
|
||||
region_offset parent_base_offset = parent_reg->get_offset ();
|
||||
gcc_assert (!parent_base_offset.symbolic_p ());
|
||||
bit_offset_t child_parent_offset
|
||||
= (child_base_offset.get_bit_offset ()
|
||||
- parent_base_offset.get_bit_offset ());
|
||||
/* Create a concrete key for the child within the parent. */
|
||||
k = mgr->get_store_manager ()->get_concrete_binding
|
||||
(child_parent_offset, sval_bit_size, BK_direct);
|
||||
}
|
||||
gcc_assert (k->concrete_p ());
|
||||
put (k, sval);
|
||||
tree min_index = TREE_OPERAND (index, 0);
|
||||
tree max_index = TREE_OPERAND (index, 1);
|
||||
apply_ctor_val_to_range (parent_reg, mgr, min_index, max_index, val);
|
||||
continue;
|
||||
}
|
||||
apply_ctor_pair_to_child_region (parent_reg, mgr, index, val);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bind the value VAL into the range of elements within PARENT_REF
|
||||
from MIN_INDEX to MAX_INDEX (including endpoints).
|
||||
For use in handling RANGE_EXPR within a CONSTRUCTOR. */
|
||||
|
||||
void
|
||||
binding_map::apply_ctor_val_to_range (const region *parent_reg,
|
||||
region_model_manager *mgr,
|
||||
tree min_index, tree max_index,
|
||||
tree val)
|
||||
{
|
||||
gcc_assert (TREE_CODE (min_index) == INTEGER_CST);
|
||||
gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
|
||||
|
||||
/* Generate a binding key for the range. */
|
||||
const region *min_element
|
||||
= get_subregion_within_ctor (parent_reg, min_index, mgr);
|
||||
const region *max_element
|
||||
= get_subregion_within_ctor (parent_reg, max_index, mgr);
|
||||
region_offset min_offset = min_element->get_offset ();
|
||||
bit_offset_t start_bit_offset = min_offset.get_bit_offset ();
|
||||
store_manager *smgr = mgr->get_store_manager ();
|
||||
const binding_key *max_element_key
|
||||
= binding_key::make (smgr, max_element, BK_direct);
|
||||
gcc_assert (max_element_key->concrete_p ());
|
||||
const concrete_binding *max_element_ckey
|
||||
= max_element_key->dyn_cast_concrete_binding ();
|
||||
bit_size_t range_size_in_bits
|
||||
= max_element_ckey->get_next_bit_offset () - start_bit_offset;
|
||||
const concrete_binding *range_key
|
||||
= smgr->get_concrete_binding (start_bit_offset, range_size_in_bits,
|
||||
BK_direct);
|
||||
gcc_assert (range_key->concrete_p ());
|
||||
|
||||
/* Get the value. */
|
||||
gcc_assert (TREE_CODE (val) != CONSTRUCTOR);
|
||||
const svalue *sval = get_svalue_for_ctor_val (val, mgr);
|
||||
|
||||
/* Bind the value to the range. */
|
||||
put (range_key, sval);
|
||||
}
|
||||
|
||||
/* Bind the value VAL into INDEX within PARENT_REF.
|
||||
For use in handling a pair of entries within a CONSTRUCTOR. */
|
||||
|
||||
void
|
||||
binding_map::apply_ctor_pair_to_child_region (const region *parent_reg,
|
||||
region_model_manager *mgr,
|
||||
tree index, tree val)
|
||||
{
|
||||
const region *child_reg
|
||||
= get_subregion_within_ctor (parent_reg, index, mgr);
|
||||
if (TREE_CODE (val) == CONSTRUCTOR)
|
||||
apply_ctor_to_region (child_reg, val, mgr);
|
||||
else
|
||||
{
|
||||
const svalue *sval = get_svalue_for_ctor_val (val, mgr);
|
||||
const binding_key *k
|
||||
= binding_key::make (mgr->get_store_manager (), child_reg,
|
||||
BK_direct);
|
||||
/* Handle the case where we have an unknown size for child_reg
|
||||
(e.g. due to it being a trailing field with incomplete array
|
||||
type. */
|
||||
if (!k->concrete_p ())
|
||||
{
|
||||
/* Assume that sval has a well-defined size for this case. */
|
||||
tree sval_type = sval->get_type ();
|
||||
gcc_assert (sval_type);
|
||||
HOST_WIDE_INT sval_byte_size = int_size_in_bytes (sval_type);
|
||||
gcc_assert (sval_byte_size != -1);
|
||||
bit_size_t sval_bit_size = sval_byte_size * BITS_PER_UNIT;
|
||||
/* Get offset of child relative to base region. */
|
||||
region_offset child_base_offset = child_reg->get_offset ();
|
||||
gcc_assert (!child_base_offset.symbolic_p ());
|
||||
/* Convert to an offset relative to the parent region. */
|
||||
region_offset parent_base_offset = parent_reg->get_offset ();
|
||||
gcc_assert (!parent_base_offset.symbolic_p ());
|
||||
bit_offset_t child_parent_offset
|
||||
= (child_base_offset.get_bit_offset ()
|
||||
- parent_base_offset.get_bit_offset ());
|
||||
/* Create a concrete key for the child within the parent. */
|
||||
k = mgr->get_store_manager ()->get_concrete_binding
|
||||
(child_parent_offset, sval_bit_size, BK_direct);
|
||||
}
|
||||
gcc_assert (k->concrete_p ());
|
||||
put (k, sval);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,6 +344,14 @@ public:
|
||||
region_model_manager *mgr);
|
||||
|
||||
private:
|
||||
void apply_ctor_val_to_range (const region *parent_reg,
|
||||
region_model_manager *mgr,
|
||||
tree min_index, tree max_index,
|
||||
tree val);
|
||||
void apply_ctor_pair_to_child_region (const region *parent_reg,
|
||||
region_model_manager *mgr,
|
||||
tree index, tree val);
|
||||
|
||||
map_t m_map;
|
||||
};
|
||||
|
||||
|
13
gcc/testsuite/g++.dg/analyzer/pr96763.C
Normal file
13
gcc/testsuite/g++.dg/analyzer/pr96763.C
Normal file
@ -0,0 +1,13 @@
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct c0;
|
||||
|
||||
struct md {
|
||||
int c0::*jj[2];
|
||||
};
|
||||
|
||||
void
|
||||
n0 ()
|
||||
{
|
||||
md{};
|
||||
}
|
Loading…
Reference in New Issue
Block a user