PR analyzer/96860 reports an ICE inside CONSTRUCTOR-handling with
--param analyzer-max-svalue-depth=0 when attempting to build a
binding_map for the CONSTRUCTOR's values.

The issue is that when handling (index, value) pairs for initializing
an array, the index values for the elements exceeds the svalue
complexity limit, and the index is thus treated as unknown, leading to
a symbolic rather than concrete offset for each array element.

This patch updates the CONSTRUCTOR-handling code so that it can
fail, returning an unknown value for the overall value of the
constructor for this case, fixing the ICE.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to master as r11-2955-g18056e45db1c75aa209fa9a756395ddceb867a88.

gcc/analyzer/ChangeLog:
        PR analyzer/96860
        * region.cc (decl_region::get_svalue_for_constructor): Support
        apply_ctor_to_region failing.
        * store.cc (binding_map::apply_ctor_to_region): Add failure
        handling.
        (binding_map::apply_ctor_val_to_range): Likewise.
        (binding_map::apply_ctor_pair_to_child_region): Likewise.  Replace
        assertion that child_base_offset is not symbolic with error
        handling.
        * store.h (binding_map::apply_ctor_to_region): Convert return type
        from void to bool.
        (binding_map::apply_ctor_val_to_range): Likewise.
        (binding_map::apply_ctor_pair_to_child_region): Likewise.

gcc/testsuite/ChangeLog:
        PR analyzer/96860
        * gcc.dg/analyzer/pr96860-1.c: New test.
        * gcc.dg/analyzer/pr96860-2.c: New test.
---
 gcc/analyzer/region.cc                    |  3 ++-
 gcc/analyzer/store.cc                     | 33 ++++++++++++++++-------
 gcc/analyzer/store.h                      |  6 ++---
 gcc/testsuite/gcc.dg/analyzer/pr96860-1.c |  9 +++++++
 gcc/testsuite/gcc.dg/analyzer/pr96860-2.c |  8 ++++++
 5 files changed, 45 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr96860-1.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr96860-2.c

diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc
index 1823901a3ee..53f32dc912c 100644
--- a/gcc/analyzer/region.cc
+++ b/gcc/analyzer/region.cc
@@ -904,7 +904,8 @@ decl_region::get_svalue_for_constructor (tree ctor,
      decl_region as the base region when building child regions
      for offset calculations.  */
   binding_map map;
-  map.apply_ctor_to_region (this, ctor, mgr);
+  if (!map.apply_ctor_to_region (this, ctor, mgr))
+    return mgr->get_or_create_unknown_svalue (get_type ());
 
   /* Return a compound svalue for the map we built.  */
   return mgr->get_or_create_compound_svalue (get_type (), map);
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index 8890a69a6f8..7f15aa92492 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -402,9 +402,11 @@ get_svalue_for_ctor_val (tree val, region_model_manager 
*mgr)
 }
 
 /* Bind values from CONSTRUCTOR to this map, relative to
-   PARENT_REG's relationship to its base region.  */
+   PARENT_REG's relationship to its base region.
+   Return true if successful, false if there was a problem (e.g. due
+   to hitting a complexity limit).  */
 
-void
+bool
 binding_map::apply_ctor_to_region (const region *parent_reg, tree ctor,
                                   region_model_manager *mgr)
 {
@@ -423,18 +425,24 @@ binding_map::apply_ctor_to_region (const region 
*parent_reg, tree ctor,
        {
          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);
+         if (!apply_ctor_val_to_range (parent_reg, mgr,
+                                       min_index, max_index, val))
+           return false;
          continue;
        }
-      apply_ctor_pair_to_child_region (parent_reg, mgr, index, val);
+      if (!apply_ctor_pair_to_child_region (parent_reg, mgr, index, val))
+       return false;
     }
+  return true;
 }
 
 /* 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.  */
+   For use in handling RANGE_EXPR within a CONSTRUCTOR.
+   Return true if successful, false if there was a problem (e.g. due
+   to hitting a complexity limit).  */
 
-void
+bool
 binding_map::apply_ctor_val_to_range (const region *parent_reg,
                                      region_model_manager *mgr,
                                      tree min_index, tree max_index,
@@ -469,12 +477,15 @@ binding_map::apply_ctor_val_to_range (const region 
*parent_reg,
 
   /* Bind the value to the range.  */
   put (range_key, sval);
+  return true;
 }
 
 /* Bind the value VAL into INDEX within PARENT_REF.
-   For use in handling a pair of entries within a CONSTRUCTOR.  */
+   For use in handling a pair of entries within a CONSTRUCTOR.
+   Return true if successful, false if there was a problem (e.g. due
+   to hitting a complexity limit).  */
 
-void
+bool
 binding_map::apply_ctor_pair_to_child_region (const region *parent_reg,
                                              region_model_manager *mgr,
                                              tree index, tree val)
@@ -482,7 +493,7 @@ binding_map::apply_ctor_pair_to_child_region (const region 
*parent_reg,
   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);
+    return apply_ctor_to_region (child_reg, val, mgr);
   else
     {
       const svalue *sval = get_svalue_for_ctor_val (val, mgr);
@@ -502,7 +513,8 @@ binding_map::apply_ctor_pair_to_child_region (const region 
*parent_reg,
          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 ());
+         if (child_base_offset.symbolic_p ())
+           return false;
          /* 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 ());
@@ -515,6 +527,7 @@ binding_map::apply_ctor_pair_to_child_region (const region 
*parent_reg,
        }
       gcc_assert (k->concrete_p ());
       put (k, sval);
+      return true;
     }
 }
 
diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h
index 0ac93179dc6..83a43107b21 100644
--- a/gcc/analyzer/store.h
+++ b/gcc/analyzer/store.h
@@ -340,15 +340,15 @@ public:
   void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const;
   void dump (bool simple) const;
 
-  void apply_ctor_to_region (const region *parent_reg, tree ctor,
+  bool apply_ctor_to_region (const region *parent_reg, tree ctor,
                             region_model_manager *mgr);
 
 private:
-  void apply_ctor_val_to_range (const region *parent_reg,
+  bool 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,
+  bool apply_ctor_pair_to_child_region (const region *parent_reg,
                                        region_model_manager *mgr,
                                        tree index, tree val);
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c 
b/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c
new file mode 100644
index 00000000000..8f298ec04e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c
@@ -0,0 +1,9 @@
+/* { dg-require-effective-target int128 } */
+/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */
+
+void x7 (void)
+{
+  __int128 z5[] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1,
+  };
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c 
b/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c
new file mode 100644
index 00000000000..90a818cb283
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c
@@ -0,0 +1,8 @@
+/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */
+
+void x7 (void)
+{
+  long z5[] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1,
+  };
+}
-- 
2.26.2

Reply via email to