aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2020-08-24 09:33:42 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2020-08-31 16:07:46 -0400
commit0d1b4edc5fff834e8f924b20dd021ded7a21d2d2 (patch)
tree65926af7487d5485acfedf8ed468b9b52073f5fe /gcc
parentecdb93224c56189a129e97c556fe6b78e1b15a63 (diff)
downloadgcc-0d1b4edc5fff834e8f924b20dd021ded7a21d2d2.zip
gcc-0d1b4edc5fff834e8f924b20dd021ded7a21d2d2.tar.gz
gcc-0d1b4edc5fff834e8f924b20dd021ded7a21d2d2.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/analyzer/store.cc129
-rw-r--r--gcc/analyzer/store.h8
-rw-r--r--gcc/testsuite/g++.dg/analyzer/pr96763.C13
3 files changed, 115 insertions, 35 deletions
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index 14f7c00..8890a69 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -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);
}
}
diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h
index 636a9547..0ac9317 100644
--- a/gcc/analyzer/store.h
+++ b/gcc/analyzer/store.h
@@ -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;
};
diff --git a/gcc/testsuite/g++.dg/analyzer/pr96763.C b/gcc/testsuite/g++.dg/analyzer/pr96763.C
new file mode 100644
index 0000000..1b29e30
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/pr96763.C
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++11 } }
+
+struct c0;
+
+struct md {
+ int c0::*jj[2];
+};
+
+void
+n0 ()
+{
+ md{};
+}