analyzer: fix region::get_bit_size for bitfields
authorDavid Malcolm <dmalcolm@redhat.com>
Tue, 8 Jun 2021 18:45:07 +0000 (14:45 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Tue, 8 Jun 2021 18:45:07 +0000 (14:45 -0400)
gcc/analyzer/ChangeLog:
* analyzer.h (int_size_in_bits): New decl.
* region.cc (int_size_in_bits): New function.
(region::get_bit_size): Reimplement in terms of the above.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
gcc/analyzer/analyzer.h
gcc/analyzer/region.cc

index fb568e4..525eb06 100644 (file)
@@ -144,6 +144,8 @@ typedef offset_int bit_offset_t;
 typedef offset_int bit_size_t;
 typedef offset_int byte_size_t;
 
+extern bool int_size_in_bits (const_tree type, bit_size_t *out);
+
 /* The location of a region expressesd as an offset relative to a
    base region.  */
 
index 6db1fc9..5f246df 100644 (file)
@@ -208,6 +208,29 @@ region::get_byte_size (byte_size_t *out) const
   return true;
 }
 
+/* If the size of TYPE (in bits) is constant, write it to *OUT
+   and return true.
+   Otherwise return false.  */
+
+bool
+int_size_in_bits (const_tree type, bit_size_t *out)
+{
+  if (INTEGRAL_TYPE_P (type))
+    {
+      *out = TYPE_PRECISION (type);
+      return true;
+    }
+
+  tree sz = TYPE_SIZE (type);
+  if (sz && tree_fits_uhwi_p (sz))
+    {
+      *out = TREE_INT_CST_LOW (sz);
+      return true;
+    }
+  else
+    return false;
+}
+
 /* If the size of this region (in bits) is known statically, write it to *OUT
    and return true.
    Otherwise return false.  */
@@ -215,11 +238,13 @@ region::get_byte_size (byte_size_t *out) const
 bool
 region::get_bit_size (bit_size_t *out) const
 {
-  byte_size_t byte_size;
-  if (!get_byte_size (&byte_size))
+  tree type = get_type ();
+
+  /* Bail out e.g. for heap-allocated regions.  */
+  if (!type)
     return false;
-  *out = byte_size * BITS_PER_UNIT;
-  return true;
+
+  return int_size_in_bits (type, out);
 }
 
 /* Get the field within RECORD_TYPE at BIT_OFFSET.  */