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.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to master as 61a43de58cb6de7212a622060500ad0a0fd94fae.

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.
---
 gcc/analyzer/region-model.cc                  | 37 ++++++++++---------
 gcc/analyzer/region.cc                        | 16 ++++++--
 gcc/testsuite/gcc.dg/analyzer/data-model-21.c |  8 ++++
 3 files changed, 40 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/data-model-21.c

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]);
+}
-- 
2.26.2

Reply via email to