gdb: fix shellcheck warnings SC2154 (referenced but not assigned) in gdbarch.sh
[deliverable/binutils-gdb.git] / gdb / gdbtypes.c
index f23def1ff71cca58e41326de7fa7e10c408c90e5..73984357338db7e16a55336ae599b718182e082b 100644 (file)
@@ -39,6 +39,7 @@
 #include "dwarf2/loc.h"
 #include "gdbcore.h"
 #include "floatformat.h"
+#include <algorithm>
 
 /* Initialize BADNESS constants.  */
 
@@ -236,7 +237,7 @@ get_type_arch (const struct type *type)
   struct gdbarch *arch;
 
   if (TYPE_OBJFILE_OWNED (type))
-    arch = get_objfile_arch (TYPE_OWNER (type).objfile);
+    arch = TYPE_OWNER (type).objfile->arch ();
   else
     arch = TYPE_OWNER (type).gdbarch;
 
@@ -886,6 +887,10 @@ operator== (const dynamic_prop &l, const dynamic_prop &r)
     case PROP_LOCEXPR:
     case PROP_LOCLIST:
       return l.data.baton == r.data.baton;
+    case PROP_VARIANT_PARTS:
+      return l.data.variant_parts == r.data.variant_parts;
+    case PROP_TYPE:
+      return l.data.original_type == r.data.original_type;
     }
 
   gdb_assert_not_reached ("unhandled dynamic_prop kind");
@@ -1966,6 +1971,13 @@ is_dynamic_type_internal (struct type *type, int top_level)
   if (TYPE_ALLOCATED_PROP (type))
     return 1;
 
+  struct dynamic_prop *prop = get_dyn_prop (DYN_PROP_VARIANT_PARTS, type);
+  if (prop != nullptr && prop->kind != PROP_TYPE)
+    return 1;
+
+  if (TYPE_HAS_DYNAMIC_LENGTH (type))
+    return 1;
+
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_RANGE:
@@ -2003,10 +2015,27 @@ is_dynamic_type_internal (struct type *type, int top_level)
       {
        int i;
 
+       bool is_cplus = HAVE_CPLUS_STRUCT (type);
+
        for (i = 0; i < TYPE_NFIELDS (type); ++i)
-         if (!field_is_static (&TYPE_FIELD (type, i))
-             && is_dynamic_type_internal (TYPE_FIELD_TYPE (type, i), 0))
+         {
+           /* Static fields can be ignored here.  */
+           if (field_is_static (&TYPE_FIELD (type, i)))
+             continue;
+           /* If the field has dynamic type, then so does TYPE.  */
+           if (is_dynamic_type_internal (TYPE_FIELD_TYPE (type, i), 0))
+             return 1;
+           /* If the field is at a fixed offset, then it is not
+              dynamic.  */
+           if (TYPE_FIELD_LOC_KIND (type, i) != FIELD_LOC_KIND_DWARF_BLOCK)
+             continue;
+           /* Do not consider C++ virtual base types to be dynamic
+              due to the field's offset being dynamic; these are
+              handled via other means.  */
+           if (is_cplus && BASETYPE_VIA_VIRTUAL (type, i))
+             continue;
            return 1;
+         }
       }
       break;
     }
@@ -2215,6 +2244,162 @@ resolve_dynamic_union (struct type *type,
   return resolved_type;
 }
 
+/* See gdbtypes.h.  */
+
+bool
+variant::matches (ULONGEST value, bool is_unsigned) const
+{
+  for (const discriminant_range &range : discriminants)
+    if (range.contains (value, is_unsigned))
+      return true;
+  return false;
+}
+
+static void
+compute_variant_fields_inner (struct type *type,
+                             struct property_addr_info *addr_stack,
+                             const variant_part &part,
+                             std::vector<bool> &flags);
+
+/* A helper function to determine which variant fields will be active.
+   This handles both the variant's direct fields, and any variant
+   parts embedded in this variant.  TYPE is the type we're examining.
+   ADDR_STACK holds information about the concrete object.  VARIANT is
+   the current variant to be handled.  FLAGS is where the results are
+   stored -- this function sets the Nth element in FLAGS if the
+   corresponding field is enabled.  ENABLED is whether this variant is
+   enabled or not.  */
+
+static void
+compute_variant_fields_recurse (struct type *type,
+                               struct property_addr_info *addr_stack,
+                               const variant &variant,
+                               std::vector<bool> &flags,
+                               bool enabled)
+{
+  for (int field = variant.first_field; field < variant.last_field; ++field)
+    flags[field] = enabled;
+
+  for (const variant_part &new_part : variant.parts)
+    {
+      if (enabled)
+       compute_variant_fields_inner (type, addr_stack, new_part, flags);
+      else
+       {
+         for (const auto &sub_variant : new_part.variants)
+           compute_variant_fields_recurse (type, addr_stack, sub_variant,
+                                           flags, enabled);
+       }
+    }
+}
+
+/* A helper function to determine which variant fields will be active.
+   This evaluates the discriminant, decides which variant (if any) is
+   active, and then updates FLAGS to reflect which fields should be
+   available.  TYPE is the type we're examining.  ADDR_STACK holds
+   information about the concrete object.  VARIANT is the current
+   variant to be handled.  FLAGS is where the results are stored --
+   this function sets the Nth element in FLAGS if the corresponding
+   field is enabled.  */
+
+static void
+compute_variant_fields_inner (struct type *type,
+                             struct property_addr_info *addr_stack,
+                             const variant_part &part,
+                             std::vector<bool> &flags)
+{
+  /* Evaluate the discriminant.  */
+  gdb::optional<ULONGEST> discr_value;
+  if (part.discriminant_index != -1)
+    {
+      int idx = part.discriminant_index;
+
+      if (TYPE_FIELD_LOC_KIND (type, idx) != FIELD_LOC_KIND_BITPOS)
+       error (_("Cannot determine struct field location"
+                " (invalid location kind)"));
+
+      if (addr_stack->valaddr.data () != NULL)
+       discr_value = unpack_field_as_long (type, addr_stack->valaddr.data (),
+                                           idx);
+      else
+       {
+         CORE_ADDR addr = (addr_stack->addr
+                           + (TYPE_FIELD_BITPOS (type, idx)
+                              / TARGET_CHAR_BIT));
+
+         LONGEST bitsize = TYPE_FIELD_BITSIZE (type, idx);
+         LONGEST size = bitsize / 8;
+         if (size == 0)
+           size = TYPE_LENGTH (TYPE_FIELD_TYPE (type, idx));
+
+         gdb_byte bits[sizeof (ULONGEST)];
+         read_memory (addr, bits, size);
+
+         LONGEST bitpos = (TYPE_FIELD_BITPOS (type, idx)
+                           % TARGET_CHAR_BIT);
+
+         discr_value = unpack_bits_as_long (TYPE_FIELD_TYPE (type, idx),
+                                            bits, bitpos, bitsize);
+       }
+    }
+
+  /* Go through each variant and see which applies.  */
+  const variant *default_variant = nullptr;
+  const variant *applied_variant = nullptr;
+  for (const auto &variant : part.variants)
+    {
+      if (variant.is_default ())
+       default_variant = &variant;
+      else if (discr_value.has_value ()
+              && variant.matches (*discr_value, part.is_unsigned))
+       {
+         applied_variant = &variant;
+         break;
+       }
+    }
+  if (applied_variant == nullptr)
+    applied_variant = default_variant;
+
+  for (const auto &variant : part.variants)
+    compute_variant_fields_recurse (type, addr_stack, variant,
+                                   flags, applied_variant == &variant);
+}  
+
+/* Determine which variant fields are available in TYPE.  The enabled
+   fields are stored in RESOLVED_TYPE.  ADDR_STACK holds information
+   about the concrete object.  PARTS describes the top-level variant
+   parts for this type.  */
+
+static void
+compute_variant_fields (struct type *type,
+                       struct type *resolved_type,
+                       struct property_addr_info *addr_stack,
+                       const gdb::array_view<variant_part> &parts)
+{
+  /* Assume all fields are included by default.  */
+  std::vector<bool> flags (TYPE_NFIELDS (resolved_type), true);
+
+  /* Now disable fields based on the variants that control them.  */
+  for (const auto &part : parts)
+    compute_variant_fields_inner (type, addr_stack, part, flags);
+
+  TYPE_NFIELDS (resolved_type) = std::count (flags.begin (), flags.end (),
+                                            true);
+  TYPE_FIELDS (resolved_type)
+    = (struct field *) TYPE_ALLOC (resolved_type,
+                                  TYPE_NFIELDS (resolved_type)
+                                  * sizeof (struct field));
+  int out = 0;
+  for (int i = 0; i < TYPE_NFIELDS (type); ++i)
+    {
+      if (!flags[i])
+       continue;
+
+      TYPE_FIELD (resolved_type, out) = TYPE_FIELD (type, i);
+      ++out;
+    }
+}
+
 /* Resolve dynamic bounds of members of the struct TYPE to static
    bounds.  ADDR_STACK is a stack of struct property_addr_info to
    be used if needed during the dynamic resolution.  */
@@ -2231,21 +2416,55 @@ resolve_dynamic_struct (struct type *type,
   gdb_assert (TYPE_NFIELDS (type) > 0);
 
   resolved_type = copy_type (type);
-  TYPE_FIELDS (resolved_type)
-    = (struct field *) TYPE_ALLOC (resolved_type,
-                                  TYPE_NFIELDS (resolved_type)
-                                  * sizeof (struct field));
-  memcpy (TYPE_FIELDS (resolved_type),
-         TYPE_FIELDS (type),
-         TYPE_NFIELDS (resolved_type) * sizeof (struct field));
+
+  struct dynamic_prop *variant_prop = get_dyn_prop (DYN_PROP_VARIANT_PARTS,
+                                                   resolved_type);
+  if (variant_prop != nullptr && variant_prop->kind == PROP_VARIANT_PARTS)
+    {
+      compute_variant_fields (type, resolved_type, addr_stack,
+                             *variant_prop->data.variant_parts);
+      /* We want to leave the property attached, so that the Rust code
+        can tell whether the type was originally an enum.  */
+      variant_prop->kind = PROP_TYPE;
+      variant_prop->data.original_type = type;
+    }
+  else
+    {
+      TYPE_FIELDS (resolved_type)
+       = (struct field *) TYPE_ALLOC (resolved_type,
+                                      TYPE_NFIELDS (resolved_type)
+                                      * sizeof (struct field));
+      memcpy (TYPE_FIELDS (resolved_type),
+             TYPE_FIELDS (type),
+             TYPE_NFIELDS (resolved_type) * sizeof (struct field));
+    }
+
   for (i = 0; i < TYPE_NFIELDS (resolved_type); ++i)
     {
       unsigned new_bit_length;
       struct property_addr_info pinfo;
 
-      if (field_is_static (&TYPE_FIELD (type, i)))
+      if (field_is_static (&TYPE_FIELD (resolved_type, i)))
        continue;
 
+      if (TYPE_FIELD_LOC_KIND (resolved_type, i) == FIELD_LOC_KIND_DWARF_BLOCK)
+       {
+         struct dwarf2_property_baton baton;
+         baton.property_type
+           = lookup_pointer_type (TYPE_FIELD_TYPE (resolved_type, i));
+         baton.locexpr = *TYPE_FIELD_DWARF_BLOCK (resolved_type, i);
+
+         struct dynamic_prop prop;
+         prop.kind = PROP_LOCEXPR;
+         prop.data.baton = &baton;
+
+         CORE_ADDR addr;
+         if (dwarf2_evaluate_property (&prop, nullptr, addr_stack, &addr,
+                                       true))
+           SET_FIELD_BITPOS (TYPE_FIELD (resolved_type, i),
+                             TARGET_CHAR_BIT * (addr - addr_stack->addr));
+       }
+
       /* As we know this field is not a static field, the field's
         field_loc_kind should be FIELD_LOC_KIND_BITPOS.  Verify
         this is the case, but only trigger a simple error rather
@@ -2253,11 +2472,11 @@ resolve_dynamic_struct (struct type *type,
         that verification indicates a bug in our code, the error
         is not severe enough to suggest to the user he stops
         his debugging session because of it.  */
-      if (TYPE_FIELD_LOC_KIND (type, i) != FIELD_LOC_KIND_BITPOS)
+      if (TYPE_FIELD_LOC_KIND (resolved_type, i) != FIELD_LOC_KIND_BITPOS)
        error (_("Cannot determine struct field location"
                 " (invalid location kind)"));
 
-      pinfo.type = check_typedef (TYPE_FIELD_TYPE (type, i));
+      pinfo.type = check_typedef (TYPE_FIELD_TYPE (resolved_type, i));
       pinfo.valaddr = addr_stack->valaddr;
       pinfo.addr
        = (addr_stack->addr
@@ -2310,13 +2529,19 @@ resolve_dynamic_type_internal (struct type *type,
                               int top_level)
 {
   struct type *real_type = check_typedef (type);
-  struct type *resolved_type = type;
+  struct type *resolved_type = nullptr;
   struct dynamic_prop *prop;
   CORE_ADDR value;
 
   if (!is_dynamic_type_internal (real_type, top_level))
     return type;
 
+  gdb::optional<CORE_ADDR> type_length;
+  prop = TYPE_DYNAMIC_LENGTH (type);
+  if (prop != NULL
+      && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+    type_length = value;
+
   if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
     {
       resolved_type = copy_type (type);
@@ -2336,9 +2561,10 @@ resolve_dynamic_type_internal (struct type *type,
            struct property_addr_info pinfo;
 
            pinfo.type = check_typedef (TYPE_TARGET_TYPE (type));
-           pinfo.valaddr = NULL;
-           if (addr_stack->valaddr != NULL)
-             pinfo.addr = extract_typed_address (addr_stack->valaddr, type);
+           pinfo.valaddr = {};
+           if (addr_stack->valaddr.data () != NULL)
+             pinfo.addr = extract_typed_address (addr_stack->valaddr.data (),
+                                                 type);
            else
              pinfo.addr = read_memory_typed_address (addr_stack->addr, type);
            pinfo.next = addr_stack;
@@ -2371,6 +2597,15 @@ resolve_dynamic_type_internal (struct type *type,
        }
     }
 
+  if (resolved_type == nullptr)
+    return type;
+
+  if (type_length.has_value ())
+    {
+      TYPE_LENGTH (resolved_type) = *type_length;
+      remove_dyn_prop (DYN_PROP_BYTE_SIZE, resolved_type);
+    }
+
   /* Resolve data_location attribute.  */
   prop = TYPE_DATA_LOCATION (resolved_type);
   if (prop != NULL
@@ -2386,7 +2621,8 @@ resolve_dynamic_type_internal (struct type *type,
 /* See gdbtypes.h  */
 
 struct type *
-resolve_dynamic_type (struct type *type, const gdb_byte *valaddr,
+resolve_dynamic_type (struct type *type,
+                     gdb::array_view<const gdb_byte> valaddr,
                      CORE_ADDR addr)
 {
   struct property_addr_info pinfo
@@ -3000,7 +3236,7 @@ init_float_type (struct objfile *objfile,
 {
   if (byte_order == BFD_ENDIAN_UNKNOWN)
     {
-      struct gdbarch *gdbarch = get_objfile_arch (objfile);
+      struct gdbarch *gdbarch = objfile->arch ();
       byte_order = gdbarch_byte_order (gdbarch);
     }
   const struct floatformat *fmt = floatformats[byte_order];
@@ -5607,7 +5843,7 @@ objfile_type (struct objfile *objfile)
                                 1, struct objfile_type);
 
   /* Use the objfile architecture to determine basic type properties.  */
-  gdbarch = get_objfile_arch (objfile);
+  gdbarch = objfile->arch ();
 
   /* Basic types.  */
   objfile_type->builtin_void
This page took 0.028666 seconds and 4 git commands to generate.