analyzer: fix ICE on initializers for unsized array fields [PR96777]
authorDavid Malcolm <dmalcolm@redhat.com>
Tue, 25 Aug 2020 13:26:05 +0000 (09:26 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Wed, 26 Aug 2020 01:39:32 +0000 (21:39 -0400)
gcc/analyzer/ChangeLog:
PR analyzer/96777
* region-model.h (class compound_svalue): Document that all keys
must be concrete.
(compound_svalue::compound_svalue): Move definition to svalue.cc.
* store.cc (binding_map::apply_ctor_to_region): Handle
initializers for trailing arrays with incomplete size.
* svalue.cc (compound_svalue::compound_svalue): Move definition
here from region-model.h.  Add assertion that all keys are
concrete.

gcc/testsuite/ChangeLog:
PR analyzer/96777
* gcc.dg/analyzer/pr96777.c: New test.

gcc/analyzer/region-model.h
gcc/analyzer/store.cc
gcc/analyzer/svalue.cc
gcc/testsuite/gcc.dg/analyzer/pr96777.c [new file with mode: 0644]

index 79d739e3a7b66ec801d175b666015ec0faee7a8c..f325a8b83810a7cef9416f3697fcd45c9bc8545d 100644 (file)
@@ -1109,6 +1109,9 @@ namespace ana {
    mapping, but are required to use an svalue, such as when handling
    compound assignments and compound return values.
 
+   All keys within the underlying binding_map are required to be concrete,
+   not symbolic.
+
    Instances of this class shouldn't be bound as-is into the store;
    instead they should be unpacked.  Similarly, they should not be
    nested.  */
@@ -1150,11 +1153,7 @@ public:
     const binding_map *m_map_ptr;
   };
 
-  compound_svalue (tree type, const binding_map &map)
-  : svalue (calc_complexity (map), type),
-    m_map (map)
-  {
-  }
+  compound_svalue (tree type, const binding_map &map);
 
   enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_COMPOUND; }
   const compound_svalue *dyn_cast_compound_svalue () const { return this; }
index 298088f6ef9a8ea0c285bbb883189144bd00f575..8439366f0b51e584b47029be8cfab8ec9bef4b2f 100644 (file)
@@ -429,6 +429,31 @@ binding_map::apply_ctor_to_region (const region *parent_reg, tree ctor,
          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);
        }
     }
index eabb13affcba25db1da11cf6b0f480598f27caba..99b5507a43c4959104e3f7a7c9282472358c4d35 100644 (file)
@@ -910,6 +910,20 @@ unmergeable_svalue::implicitly_live_p (const svalue_set &live_svalues,
 
 /* class compound_svalue : public svalue.  */
 
+compound_svalue::compound_svalue (tree type, const binding_map &map)
+: svalue (calc_complexity (map), type), m_map (map)
+{
+  /* All keys within the underlying binding_map are required to be concrete,
+     not symbolic.  */
+#if CHECKING_P
+  for (iterator_t iter = begin (); iter != end (); ++iter)
+    {
+      const binding_key *key = (*iter).first;
+      gcc_assert (key->concrete_p ());
+    }
+#endif
+}
+
 /* Implementation of svalue::dump_to_pp vfunc for compound_svalue.  */
 
 void
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96777.c b/gcc/testsuite/gcc.dg/analyzer/pr96777.c
new file mode 100644 (file)
index 0000000..2bb2a4e
--- /dev/null
@@ -0,0 +1,12 @@
+struct ge {
+  char au;
+  char pz[];
+};
+
+struct ge tr = { 'X', 'X', };
+
+int
+main (void)
+{
+  return tr.pz[0] == 'X';
+}