#include <cmath>
#include <set>
#include <forward_list>
+#include "rust-lang.h"
+#include "common/pathstuff.h"
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
whether the DW_AT_ranges attribute came from the skeleton or DWO. */
ULONGEST ranges_base = 0;
+ /* When reading debug info generated by older versions of rustc, we
+ have to rewrite some union types to be struct types with a
+ variant part. This rewriting must be done after the CU is fully
+ read in, because otherwise at the point of rewriting some struct
+ type might not have been fully processed. So, we keep a list of
+ all such types here and process them after expansion. */
+ std::vector<struct type *> rust_unions;
+
/* Mark used when releasing cached dies. */
unsigned int mark : 1;
this information, but later versions do. */
unsigned int processing_has_namespace_info : 1;
+
+ struct partial_die_info *find_partial_die (sect_offset sect_off);
};
/* Persistent data held for a compilation unit, even when not
/* When we construct a partial symbol table entry we only
need this much information. */
-struct partial_die_info
+struct partial_die_info : public allocate_on_obstack
{
+ partial_die_info (sect_offset sect_off, struct abbrev_info *abbrev);
+
+ /* Disable assign but still keep copy ctor, which is needed
+ load_partial_dies. */
+ partial_die_info& operator=(const partial_die_info& rhs) = delete;
+
+ /* Adjust the partial die before generating a symbol for it. This
+ function may set the is_external flag or change the DIE's
+ name. */
+ void fixup (struct dwarf2_cu *cu);
+
+ /* Read a minimal amount of information into the minimal die
+ structure. */
+ const gdb_byte *read (const struct die_reader_specs *reader,
+ const struct abbrev_info &abbrev,
+ const gdb_byte *info_ptr);
+
/* Offset of this DIE. */
- sect_offset sect_off;
+ const sect_offset sect_off;
/* DWARF-2 tag for this DIE. */
- ENUM_BITFIELD(dwarf_tag) tag : 16;
+ const ENUM_BITFIELD(dwarf_tag) tag : 16;
/* Assorted flags describing the data found in this DIE. */
- unsigned int has_children : 1;
+ const unsigned int has_children : 1;
+
unsigned int is_external : 1;
unsigned int is_declaration : 1;
unsigned int has_type : 1;
/* Flag set if any of the DIE's children are template arguments. */
unsigned int has_template_arguments : 1;
- /* Flag set if fixup_partial_die has been called on this die. */
+ /* Flag set if fixup has been called on this die. */
unsigned int fixup_called : 1;
/* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt. */
/* The name of this DIE. Normally the value of DW_AT_name, but
sometimes a default name for unnamed DIEs. */
- const char *name;
+ const char *name = nullptr;
/* The linkage name, if present. */
- const char *linkage_name;
+ const char *linkage_name = nullptr;
/* The scope to prepend to our children. This is generally
allocated on the comp_unit_obstack, so will disappear
when this compilation unit leaves the cache. */
- const char *scope;
+ const char *scope = nullptr;
/* Some data associated with the partial DIE. The tag determines
which field is live. */
struct dwarf_block *locdesc;
/* The offset of an import, for DW_TAG_imported_unit. */
sect_offset sect_off;
- } d;
+ } d {};
/* If HAS_PC_INFO, the PC range associated with this DIE. */
- CORE_ADDR lowpc;
- CORE_ADDR highpc;
+ CORE_ADDR lowpc = 0;
+ CORE_ADDR highpc = 0;
/* Pointer into the info_buffer (or types_buffer) pointing at the target of
DW_AT_sibling, if any. */
- /* NOTE: This member isn't strictly necessary, read_partial_die could
- return DW_AT_sibling values to its caller load_partial_dies. */
- const gdb_byte *sibling;
+ /* NOTE: This member isn't strictly necessary, partial_die_info::read
+ could return DW_AT_sibling values to its caller load_partial_dies. */
+ const gdb_byte *sibling = nullptr;
/* If HAS_SPECIFICATION, the offset of the DIE referred to by
DW_AT_specification (or DW_AT_abstract_origin or
DW_AT_extension). */
- sect_offset spec_offset;
+ sect_offset spec_offset {};
/* Pointers to this DIE's parent, first child, and next sibling,
if any. */
- struct partial_die_info *die_parent, *die_child, *die_sibling;
+ struct partial_die_info *die_parent = nullptr;
+ struct partial_die_info *die_child = nullptr;
+ struct partial_die_info *die_sibling = nullptr;
+
+ friend struct partial_die_info *
+ dwarf2_cu::find_partial_die (sect_offset sect_off);
+
+ private:
+ /* Only need to do look up in dwarf2_cu::find_partial_die. */
+ partial_die_info (sect_offset sect_off)
+ : partial_die_info (sect_off, DW_TAG_padding, 0)
+ {
+ }
+
+ partial_die_info (sect_offset sect_off_, enum dwarf_tag tag_,
+ int has_children_)
+ : sect_off (sect_off_), tag (tag_), has_children (has_children_)
+ {
+ is_external = 0;
+ is_declaration = 0;
+ has_type = 0;
+ has_specification = 0;
+ has_pc_info = 0;
+ may_be_inlined = 0;
+ main_subprogram = 0;
+ scope_set = 0;
+ has_byte_size = 0;
+ has_const_value = 0;
+ has_template_arguments = 0;
+ fixup_called = 0;
+ is_dwz = 0;
+ spec_is_dwz = 0;
+ }
};
/* This data structure holds the information of an abbrev. */
and friends. */
static int bits_per_byte = 8;
-struct nextfield
-{
- struct nextfield *next;
- int accessibility;
- int virtuality;
- struct field field;
-};
+/* When reading a variant or variant part, we track a bit more
+ information about the field, and store it in an object of this
+ type. */
-struct nextfnfield
+struct variant_field
{
- struct nextfnfield *next;
- struct fn_field fnfield;
+ /* If we see a DW_TAG_variant, then this will be the discriminant
+ value. */
+ ULONGEST discriminant_value;
+ /* If we see a DW_TAG_variant, then this will be set if this is the
+ default branch. */
+ bool default_branch;
+ /* While reading a DW_TAG_variant_part, this will be set if this
+ field is the discriminant. */
+ bool is_discriminant;
};
-struct fnfieldlist
+struct nextfield
{
- const char *name;
- int length;
- struct nextfnfield *head;
+ int accessibility = 0;
+ int virtuality = 0;
+ /* Extra information to describe a variant or variant part. */
+ struct variant_field variant {};
+ struct field field {};
};
-struct decl_field_list
+struct fnfieldlist
{
- struct decl_field field;
- struct decl_field_list *next;
+ const char *name = nullptr;
+ std::vector<struct fn_field> fnfields;
};
/* The routines that read and process dies for a C struct or C++ class
struct field_info
{
/* List of data member and baseclasses fields. */
- struct nextfield *fields, *baseclasses;
+ std::vector<struct nextfield> fields;
+ std::vector<struct nextfield> baseclasses;
/* Number of fields (including baseclasses). */
- int nfields;
-
- /* Number of baseclasses. */
- int nbaseclasses;
+ int nfields = 0;
/* Set if the accesibility of one of the fields is not public. */
- int non_public_fields;
+ int non_public_fields = 0;
/* Member function fieldlist array, contains name of possibly overloaded
member function, number of overloaded member functions and a pointer
to the head of the member function field chain. */
- struct fnfieldlist *fnfieldlists;
-
- /* Number of entries in the fnfieldlists array. */
- int nfnfields;
+ std::vector<struct fnfieldlist> fnfieldlists;
/* typedefs defined inside this class. TYPEDEF_FIELD_LIST contains head of
a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements. */
- struct decl_field_list *typedef_field_list;
- unsigned typedef_field_list_count;
+ std::vector<struct decl_field> typedef_field_list;
/* Nested types defined by this class and the number of elements in this
list. */
- struct decl_field_list *nested_types_list;
- unsigned nested_types_list_count;
+ std::vector<struct decl_field> nested_types_list;
};
/* One item on the queue of compilation units to read in full symbols
static struct partial_die_info *load_partial_dies
(const struct die_reader_specs *, const gdb_byte *, int);
-static const gdb_byte *read_partial_die (const struct die_reader_specs *,
- struct partial_die_info *,
- const struct abbrev_info &,
- unsigned int,
- const gdb_byte *);
-
static struct partial_die_info *find_partial_die (sect_offset, int,
struct dwarf2_cu *);
-static void fixup_partial_die (struct partial_die_info *,
- struct dwarf2_cu *);
-
static const gdb_byte *read_attribute (const struct die_reader_specs *,
struct attribute *, struct attr_abbrev *,
const gdb_byte *);
sect_offset abbrev_offset;
};
-/* Helper routine for build_type_psymtabs_1, passed to qsort. */
+/* Helper routine for build_type_psymtabs_1, passed to std::sort. */
-static int
-sort_tu_by_abbrev_offset (const void *ap, const void *bp)
+static bool
+sort_tu_by_abbrev_offset (const struct tu_abbrev_offset &a,
+ const struct tu_abbrev_offset &b)
{
- const struct tu_abbrev_offset * const *a
- = (const struct tu_abbrev_offset * const*) ap;
- const struct tu_abbrev_offset * const *b
- = (const struct tu_abbrev_offset * const*) bp;
- sect_offset aoff = (*a)->abbrev_offset;
- sect_offset boff = (*b)->abbrev_offset;
-
- return (aoff > boff) - (aoff < boff);
+ return a.abbrev_offset < b.abbrev_offset;
}
/* Efficiently read all the type units.
build_type_psymtabs_1 (struct dwarf2_per_objfile *dwarf2_per_objfile)
{
struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
- struct cleanup *cleanups;
abbrev_table_up abbrev_table;
sect_offset abbrev_offset;
- struct tu_abbrev_offset *sorted_by_abbrev;
int i;
/* It's up to the caller to not call us multiple times. */
/* Sort in a separate table to maintain the order of all_type_units
for .gdb_index: TU indices directly index all_type_units. */
- sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
- dwarf2_per_objfile->n_type_units);
+ std::vector<struct tu_abbrev_offset> sorted_by_abbrev
+ (dwarf2_per_objfile->n_type_units);
for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
{
struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
sig_type->per_cu.section,
sig_type->per_cu.sect_off);
}
- cleanups = make_cleanup (xfree, sorted_by_abbrev);
- qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
- sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
+ std::sort (sorted_by_abbrev.begin (), sorted_by_abbrev.end (),
+ sort_tu_by_abbrev_offset);
abbrev_offset = (sect_offset) ~(unsigned) 0;
init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table.get (),
0, 0, build_type_psymtabs_reader, NULL);
}
-
- do_cleanups (cleanups);
}
/* Print collected type unit statistics. */
while (pdi != NULL)
{
- fixup_partial_die (pdi, cu);
+ pdi->fixup (cu);
/* Anonymous namespaces or modules have no name but have interesting
children, so we need to look at them. Ditto for anonymous
if (parent->scope_set)
return parent->scope;
- fixup_partial_die (parent, cu);
+ parent->fixup (cu);
grandparent_scope = partial_die_parent_scope (parent, cu);
types here will be reused if full symbols are loaded later. */
if (pdi->has_template_arguments)
{
- fixup_partial_die (pdi, cu);
+ pdi->fixup (cu);
if (pdi->name != NULL && strchr (pdi->name, '<') == NULL)
{
pdi = pdi->die_child;
while (pdi != NULL)
{
- fixup_partial_die (pdi, cu);
+ pdi->fixup (cu);
if (pdi->tag == DW_TAG_subprogram
|| pdi->tag == DW_TAG_inlined_subroutine
|| pdi->tag == DW_TAG_lexical_block)
}
}
+/* Allocate a fully-qualified name consisting of the two parts on the
+ obstack. */
+
+static const char *
+rust_fully_qualify (struct obstack *obstack, const char *p1, const char *p2)
+{
+ return obconcat (obstack, p1, "::", p2, (char *) NULL);
+}
+
+/* A helper that allocates a struct discriminant_info to attach to a
+ union type. */
+
+static struct discriminant_info *
+alloc_discriminant_info (struct type *type, int discriminant_index,
+ int default_index)
+{
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
+ gdb_assert (discriminant_index == -1
+ || (discriminant_index >= 0
+ && discriminant_index < TYPE_NFIELDS (type)));
+ gdb_assert (default_index == -1
+ || (default_index >= 0 && default_index < TYPE_NFIELDS (type)));
+
+ TYPE_FLAG_DISCRIMINATED_UNION (type) = 1;
+
+ struct discriminant_info *disc
+ = ((struct discriminant_info *)
+ TYPE_ZALLOC (type,
+ offsetof (struct discriminant_info, discriminants)
+ + TYPE_NFIELDS (type) * sizeof (disc->discriminants[0])));
+ disc->default_index = default_index;
+ disc->discriminant_index = discriminant_index;
+
+ struct dynamic_prop prop;
+ prop.kind = PROP_UNDEFINED;
+ prop.data.baton = disc;
+
+ add_dyn_prop (DYN_PROP_DISCRIMINATED, prop, type);
+
+ return disc;
+}
+
+/* Some versions of rustc emitted enums in an unusual way.
+
+ Ordinary enums were emitted as unions. The first element of each
+ structure in the union was named "RUST$ENUM$DISR". This element
+ held the discriminant.
+
+ These versions of Rust also implemented the "non-zero"
+ optimization. When the enum had two values, and one is empty and
+ the other holds a pointer that cannot be zero, the pointer is used
+ as the discriminant, with a zero value meaning the empty variant.
+ Here, the union's first member is of the form
+ RUST$ENCODED$ENUM$<fieldno>$<fieldno>$...$<variantname>
+ where the fieldnos are the indices of the fields that should be
+ traversed in order to find the field (which may be several fields deep)
+ and the variantname is the name of the variant of the case when the
+ field is zero.
+
+ This function recognizes whether TYPE is of one of these forms,
+ and, if so, smashes it to be a variant type. */
+
+static void
+quirk_rust_enum (struct type *type, struct objfile *objfile)
+{
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
+
+ /* We don't need to deal with empty enums. */
+ if (TYPE_NFIELDS (type) == 0)
+ return;
+
+#define RUST_ENUM_PREFIX "RUST$ENCODED$ENUM$"
+ if (TYPE_NFIELDS (type) == 1
+ && startswith (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX))
+ {
+ const char *name = TYPE_FIELD_NAME (type, 0) + strlen (RUST_ENUM_PREFIX);
+
+ /* Decode the field name to find the offset of the
+ discriminant. */
+ ULONGEST bit_offset = 0;
+ struct type *field_type = TYPE_FIELD_TYPE (type, 0);
+ while (name[0] >= '0' && name[0] <= '9')
+ {
+ char *tail;
+ unsigned long index = strtoul (name, &tail, 10);
+ name = tail;
+ if (*name != '$'
+ || index >= TYPE_NFIELDS (field_type)
+ || (TYPE_FIELD_LOC_KIND (field_type, index)
+ != FIELD_LOC_KIND_BITPOS))
+ {
+ complaint (&symfile_complaints,
+ _("Could not parse Rust enum encoding string \"%s\""
+ "[in module %s]"),
+ TYPE_FIELD_NAME (type, 0),
+ objfile_name (objfile));
+ return;
+ }
+ ++name;
+
+ bit_offset += TYPE_FIELD_BITPOS (field_type, index);
+ field_type = TYPE_FIELD_TYPE (field_type, index);
+ }
+
+ /* Make a union to hold the variants. */
+ struct type *union_type = alloc_type (objfile);
+ TYPE_CODE (union_type) = TYPE_CODE_UNION;
+ TYPE_NFIELDS (union_type) = 3;
+ TYPE_FIELDS (union_type)
+ = (struct field *) TYPE_ZALLOC (type, 3 * sizeof (struct field));
+ TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+
+ /* Put the discriminant must at index 0. */
+ TYPE_FIELD_TYPE (union_type, 0) = field_type;
+ TYPE_FIELD_ARTIFICIAL (union_type, 0) = 1;
+ TYPE_FIELD_NAME (union_type, 0) = "<<discriminant>>";
+ SET_FIELD_BITPOS (TYPE_FIELD (union_type, 0), bit_offset);
+
+ /* The order of fields doesn't really matter, so put the real
+ field at index 1 and the data-less field at index 2. */
+ struct discriminant_info *disc
+ = alloc_discriminant_info (union_type, 0, 1);
+ TYPE_FIELD (union_type, 1) = TYPE_FIELD (type, 0);
+ TYPE_FIELD_NAME (union_type, 1)
+ = rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (union_type, 1)));
+ TYPE_NAME (TYPE_FIELD_TYPE (union_type, 1))
+ = rust_fully_qualify (&objfile->objfile_obstack, TYPE_NAME (type),
+ TYPE_FIELD_NAME (union_type, 1));
+
+ const char *dataless_name
+ = rust_fully_qualify (&objfile->objfile_obstack, TYPE_NAME (type),
+ name);
+ struct type *dataless_type = init_type (objfile, TYPE_CODE_VOID, 0,
+ dataless_name);
+ TYPE_FIELD_TYPE (union_type, 2) = dataless_type;
+ /* NAME points into the original discriminant name, which
+ already has the correct lifetime. */
+ TYPE_FIELD_NAME (union_type, 2) = name;
+ SET_FIELD_BITPOS (TYPE_FIELD (union_type, 2), 0);
+ disc->discriminants[2] = 0;
+
+ /* Smash this type to be a structure type. We have to do this
+ because the type has already been recorded. */
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ TYPE_NFIELDS (type) = 1;
+ TYPE_FIELDS (type)
+ = (struct field *) TYPE_ZALLOC (type, sizeof (struct field));
+
+ /* Install the variant part. */
+ TYPE_FIELD_TYPE (type, 0) = union_type;
+ SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
+ TYPE_FIELD_NAME (type, 0) = "<<variants>>";
+ }
+ else if (TYPE_NFIELDS (type) == 1)
+ {
+ /* We assume that a union with a single field is a univariant
+ enum. */
+ /* Smash this type to be a structure type. We have to do this
+ because the type has already been recorded. */
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+
+ /* Make a union to hold the variants. */
+ struct type *union_type = alloc_type (objfile);
+ TYPE_CODE (union_type) = TYPE_CODE_UNION;
+ TYPE_NFIELDS (union_type) = TYPE_NFIELDS (type);
+ TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+ TYPE_FIELDS (union_type) = TYPE_FIELDS (type);
+
+ struct type *field_type = TYPE_FIELD_TYPE (union_type, 0);
+ const char *variant_name
+ = rust_last_path_segment (TYPE_NAME (field_type));
+ TYPE_FIELD_NAME (union_type, 0) = variant_name;
+ TYPE_NAME (field_type)
+ = rust_fully_qualify (&objfile->objfile_obstack,
+ TYPE_NAME (type), variant_name);
+
+ /* Install the union in the outer struct type. */
+ TYPE_NFIELDS (type) = 1;
+ TYPE_FIELDS (type)
+ = (struct field *) TYPE_ZALLOC (union_type, sizeof (struct field));
+ TYPE_FIELD_TYPE (type, 0) = union_type;
+ TYPE_FIELD_NAME (type, 0) = "<<variants>>";
+ SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
+
+ alloc_discriminant_info (union_type, -1, 0);
+ }
+ else
+ {
+ struct type *disr_type = nullptr;
+ for (int i = 0; i < TYPE_NFIELDS (type); ++i)
+ {
+ disr_type = TYPE_FIELD_TYPE (type, i);
+
+ if (TYPE_NFIELDS (disr_type) == 0)
+ {
+ /* Could be data-less variant, so keep going. */
+ }
+ else if (strcmp (TYPE_FIELD_NAME (disr_type, 0),
+ "RUST$ENUM$DISR") != 0)
+ {
+ /* Not a Rust enum. */
+ return;
+ }
+ else
+ {
+ /* Found one. */
+ break;
+ }
+ }
+
+ /* If we got here without a discriminant, then it's probably
+ just a union. */
+ if (disr_type == nullptr)
+ return;
+
+ /* Smash this type to be a structure type. We have to do this
+ because the type has already been recorded. */
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+
+ /* Make a union to hold the variants. */
+ struct field *disr_field = &TYPE_FIELD (disr_type, 0);
+ struct type *union_type = alloc_type (objfile);
+ TYPE_CODE (union_type) = TYPE_CODE_UNION;
+ TYPE_NFIELDS (union_type) = 1 + TYPE_NFIELDS (type);
+ TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+ TYPE_FIELDS (union_type)
+ = (struct field *) TYPE_ZALLOC (union_type,
+ (TYPE_NFIELDS (union_type)
+ * sizeof (struct field)));
+
+ memcpy (TYPE_FIELDS (union_type) + 1, TYPE_FIELDS (type),
+ TYPE_NFIELDS (type) * sizeof (struct field));
+
+ /* Install the discriminant at index 0 in the union. */
+ TYPE_FIELD (union_type, 0) = *disr_field;
+ TYPE_FIELD_ARTIFICIAL (union_type, 0) = 1;
+ TYPE_FIELD_NAME (union_type, 0) = "<<discriminant>>";
+
+ /* Install the union in the outer struct type. */
+ TYPE_FIELD_TYPE (type, 0) = union_type;
+ TYPE_FIELD_NAME (type, 0) = "<<variants>>";
+ TYPE_NFIELDS (type) = 1;
+
+ /* Set the size and offset of the union type. */
+ SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
+
+ /* We need a way to find the correct discriminant given a
+ variant name. For convenience we build a map here. */
+ struct type *enum_type = FIELD_TYPE (*disr_field);
+ std::unordered_map<std::string, ULONGEST> discriminant_map;
+ for (int i = 0; i < TYPE_NFIELDS (enum_type); ++i)
+ {
+ if (TYPE_FIELD_LOC_KIND (enum_type, i) == FIELD_LOC_KIND_ENUMVAL)
+ {
+ const char *name
+ = rust_last_path_segment (TYPE_FIELD_NAME (enum_type, i));
+ discriminant_map[name] = TYPE_FIELD_ENUMVAL (enum_type, i);
+ }
+ }
+
+ int n_fields = TYPE_NFIELDS (union_type);
+ struct discriminant_info *disc
+ = alloc_discriminant_info (union_type, 0, -1);
+ /* Skip the discriminant here. */
+ for (int i = 1; i < n_fields; ++i)
+ {
+ /* Find the final word in the name of this variant's type.
+ That name can be used to look up the correct
+ discriminant. */
+ const char *variant_name
+ = rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (union_type,
+ i)));
+
+ auto iter = discriminant_map.find (variant_name);
+ if (iter != discriminant_map.end ())
+ disc->discriminants[i] = iter->second;
+
+ /* Remove the discriminant field. */
+ struct type *sub_type = TYPE_FIELD_TYPE (union_type, i);
+ --TYPE_NFIELDS (sub_type);
+ ++TYPE_FIELDS (sub_type);
+ TYPE_FIELD_NAME (union_type, i) = variant_name;
+ TYPE_NAME (sub_type)
+ = rust_fully_qualify (&objfile->objfile_obstack,
+ TYPE_NAME (type), variant_name);
+ }
+ }
+}
+
+/* Rewrite some Rust unions to be structures with variants parts. */
+
+static void
+rust_union_quirks (struct dwarf2_cu *cu)
+{
+ gdb_assert (cu->language == language_rust);
+ for (struct type *type : cu->rust_unions)
+ quirk_rust_enum (type, cu->per_cu->dwarf2_per_objfile->objfile);
+}
+
/* Return the symtab for PER_CU. This works properly regardless of
whether we're using the index or psymtabs. */
physnames. */
compute_delayed_physnames (cu);
+ if (cu->language == language_rust)
+ rust_union_quirks (cu);
+
/* Some compilers don't define a DW_AT_high_pc attribute for the
compilation unit. If the DW_AT_high_pc is missing, synthesize
it, by scanning the DIE's below the compilation unit. */
physnames. */
compute_delayed_physnames (cu);
+ if (cu->language == language_rust)
+ rust_union_quirks (cu);
+
/* TUs share symbol tables.
If this is the first TU to use this symtab, complete the construction
of it with end_expandable_symtab. Otherwise, complete the addition of
return PC_BOUNDS_NOT_PRESENT;
}
- /* read_partial_die has also the strict LOW < HIGH requirement. */
+ /* partial_die_info::read has also the strict LOW < HIGH requirement. */
if (high <= low)
return PC_BOUNDS_INVALID;
struct field *fp;
const char *fieldname = "";
- /* Allocate a new field list entry and link it in. */
- new_field = XNEW (struct nextfield);
- make_cleanup (xfree, new_field);
- memset (new_field, 0, sizeof (struct nextfield));
-
if (die->tag == DW_TAG_inheritance)
{
- new_field->next = fip->baseclasses;
- fip->baseclasses = new_field;
+ fip->baseclasses.emplace_back ();
+ new_field = &fip->baseclasses.back ();
}
else
{
- new_field->next = fip->fields;
- fip->fields = new_field;
+ fip->fields.emplace_back ();
+ new_field = &fip->fields.back ();
}
+
fip->nfields++;
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
FIELD_BITSIZE (*fp) = 0;
FIELD_TYPE (*fp) = die_type (die, cu);
FIELD_NAME (*fp) = type_name_no_tag (fp->type);
- fip->nbaseclasses++;
}
+ else if (die->tag == DW_TAG_variant_part)
+ {
+ /* process_structure_scope will treat this DIE as a union. */
+ process_structure_scope (die, cu);
+
+ /* The variant part is relative to the start of the enclosing
+ structure. */
+ SET_FIELD_BITPOS (*fp, 0);
+ fp->type = get_die_type (die, cu);
+ fp->artificial = 1;
+ fp->name = "<<variant>>";
+ }
+ else
+ gdb_assert_not_reached ("missing case in dwarf2_add_field");
}
/* Can the type given by DIE define another type? */
dwarf2_add_type_defn (struct field_info *fip, struct die_info *die,
struct dwarf2_cu *cu)
{
- struct decl_field_list *new_field;
- struct decl_field *fp;
-
- /* Allocate a new field list entry and link it in. */
- new_field = XCNEW (struct decl_field_list);
- make_cleanup (xfree, new_field);
+ struct decl_field fp;
+ memset (&fp, 0, sizeof (fp));
gdb_assert (type_can_define_types (die));
- fp = &new_field->field;
-
/* Get name of field. NULL is okay here, meaning an anonymous type. */
- fp->name = dwarf2_name (die, cu);
- fp->type = read_type_die (die, cu);
+ fp.name = dwarf2_name (die, cu);
+ fp.type = read_type_die (die, cu);
/* Save accessibility. */
enum dwarf_access_attribute accessibility;
/* The assumed value if neither private nor protected. */
break;
case DW_ACCESS_private:
- fp->is_private = 1;
+ fp.is_private = 1;
break;
case DW_ACCESS_protected:
- fp->is_protected = 1;
+ fp.is_protected = 1;
break;
default:
complaint (&symfile_complaints,
}
if (die->tag == DW_TAG_typedef)
- {
- new_field->next = fip->typedef_field_list;
- fip->typedef_field_list = new_field;
- fip->typedef_field_list_count++;
- }
+ fip->typedef_field_list.push_back (fp);
else
- {
- new_field->next = fip->nested_types_list;
- fip->nested_types_list = new_field;
- fip->nested_types_list_count++;
- }
+ fip->nested_types_list.push_back (fp);
}
/* Create the vector of fields, and attach it to the type. */
and create blank accessibility bitfields if necessary. */
TYPE_NFIELDS (type) = nfields;
TYPE_FIELDS (type) = (struct field *)
- TYPE_ALLOC (type, sizeof (struct field) * nfields);
- memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+ TYPE_ZALLOC (type, sizeof (struct field) * nfields);
if (fip->non_public_fields && cu->language != language_ada)
{
/* If the type has baseclasses, allocate and clear a bit vector for
TYPE_FIELD_VIRTUAL_BITS. */
- if (fip->nbaseclasses && cu->language != language_ada)
+ if (!fip->baseclasses.empty () && cu->language != language_ada)
{
- int num_bytes = B_BYTES (fip->nbaseclasses);
+ int num_bytes = B_BYTES (fip->baseclasses.size ());
unsigned char *pointer;
ALLOCATE_CPLUS_STRUCT_TYPE (type);
pointer = (unsigned char *) TYPE_ALLOC (type, num_bytes);
TYPE_FIELD_VIRTUAL_BITS (type) = pointer;
- B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses);
- TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
+ B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->baseclasses.size ());
+ TYPE_N_BASECLASSES (type) = fip->baseclasses.size ();
}
- /* Copy the saved-up fields into the field vector. Start from the head of
- the list, adding to the tail of the field array, so that they end up in
- the same order in the array in which they were added to the list. */
- while (nfields-- > 0)
+ if (TYPE_FLAG_DISCRIMINATED_UNION (type))
{
- struct nextfield *fieldp;
+ struct discriminant_info *di = alloc_discriminant_info (type, -1, -1);
- if (fip->fields)
- {
- fieldp = fip->fields;
- fip->fields = fieldp->next;
- }
- else
+ for (int index = 0; index < nfields; ++index)
{
- fieldp = fip->baseclasses;
- fip->baseclasses = fieldp->next;
+ struct nextfield &field = fip->fields[index];
+
+ if (field.variant.is_discriminant)
+ di->discriminant_index = index;
+ else if (field.variant.default_branch)
+ di->default_index = index;
+ else
+ di->discriminants[index] = field.variant.discriminant_value;
}
+ }
+
+ /* Copy the saved-up fields into the field vector. */
+ for (int i = 0; i < nfields; ++i)
+ {
+ struct nextfield &field
+ = ((i < fip->baseclasses.size ()) ? fip->baseclasses[i]
+ : fip->fields[i - fip->baseclasses.size ()]);
- TYPE_FIELD (type, nfields) = fieldp->field;
- switch (fieldp->accessibility)
+ TYPE_FIELD (type, i) = field.field;
+ switch (field.accessibility)
{
case DW_ACCESS_private:
if (cu->language != language_ada)
- SET_TYPE_FIELD_PRIVATE (type, nfields);
+ SET_TYPE_FIELD_PRIVATE (type, i);
break;
case DW_ACCESS_protected:
if (cu->language != language_ada)
- SET_TYPE_FIELD_PROTECTED (type, nfields);
+ SET_TYPE_FIELD_PROTECTED (type, i);
break;
case DW_ACCESS_public:
/* Unknown accessibility. Complain and treat it as public. */
{
complaint (&symfile_complaints, _("unsupported accessibility %d"),
- fieldp->accessibility);
+ field.accessibility);
}
break;
}
- if (nfields < fip->nbaseclasses)
+ if (i < fip->baseclasses.size ())
{
- switch (fieldp->virtuality)
+ switch (field.virtuality)
{
case DW_VIRTUALITY_virtual:
case DW_VIRTUALITY_pure_virtual:
if (cu->language == language_ada)
error (_("unexpected virtuality in component of Ada type"));
- SET_TYPE_FIELD_VIRTUAL (type, nfields);
+ SET_TYPE_FIELD_VIRTUAL (type, i);
break;
}
}
{
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
struct attribute *attr;
- struct fnfieldlist *flp;
int i;
+ struct fnfieldlist *flp = nullptr;
struct fn_field *fnp;
const char *fieldname;
- struct nextfnfield *new_fnfield;
struct type *this_type;
enum dwarf_access_attribute accessibility;
return;
/* Look up member function name in fieldlist. */
- for (i = 0; i < fip->nfnfields; i++)
+ for (i = 0; i < fip->fnfieldlists.size (); i++)
{
if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0)
- break;
+ {
+ flp = &fip->fnfieldlists[i];
+ break;
+ }
}
- /* Create new list element if necessary. */
- if (i < fip->nfnfields)
- flp = &fip->fnfieldlists[i];
- else
+ /* Create a new fnfieldlist if necessary. */
+ if (flp == nullptr)
{
- if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
- {
- fip->fnfieldlists = (struct fnfieldlist *)
- xrealloc (fip->fnfieldlists,
- (fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
- * sizeof (struct fnfieldlist));
- if (fip->nfnfields == 0)
- make_cleanup (free_current_contents, &fip->fnfieldlists);
- }
- flp = &fip->fnfieldlists[fip->nfnfields];
+ fip->fnfieldlists.emplace_back ();
+ flp = &fip->fnfieldlists.back ();
flp->name = fieldname;
- flp->length = 0;
- flp->head = NULL;
- i = fip->nfnfields++;
+ i = fip->fnfieldlists.size () - 1;
}
- /* Create a new member function field and chain it to the field list
- entry. */
- new_fnfield = XNEW (struct nextfnfield);
- make_cleanup (xfree, new_fnfield);
- memset (new_fnfield, 0, sizeof (struct nextfnfield));
- new_fnfield->next = flp->head;
- flp->head = new_fnfield;
- flp->length++;
-
- /* Fill in the member function field info. */
- fnp = &new_fnfield->fnfield;
+ /* Create a new member function field and add it to the vector of
+ fnfieldlists. */
+ flp->fnfields.emplace_back ();
+ fnp = &flp->fnfields.back ();
/* Delay processing of the physname until later. */
if (cu->language == language_cplus)
- {
- add_to_method_list (type, i, flp->length - 1, fieldname,
- die, cu);
- }
+ add_to_method_list (type, i, flp->fnfields.size () - 1, fieldname,
+ die, cu);
else
{
const char *physname = dwarf2_physname (fieldname, die, cu);
dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
struct dwarf2_cu *cu)
{
- struct fnfieldlist *flp;
- int i;
-
if (cu->language == language_ada)
error (_("unexpected member functions in Ada type"));
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
- TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
+ TYPE_ALLOC (type,
+ sizeof (struct fn_fieldlist) * fip->fnfieldlists.size ());
- for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
+ for (int i = 0; i < fip->fnfieldlists.size (); i++)
{
- struct nextfnfield *nfp = flp->head;
+ struct fnfieldlist &nf = fip->fnfieldlists[i];
struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
- int k;
- TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
- TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
+ TYPE_FN_FIELDLIST_NAME (type, i) = nf.name;
+ TYPE_FN_FIELDLIST_LENGTH (type, i) = nf.fnfields.size ();
fn_flp->fn_fields = (struct fn_field *)
- TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
- for (k = flp->length; (k--, nfp); nfp = nfp->next)
- fn_flp->fn_fields[k] = nfp->fnfield;
+ TYPE_ALLOC (type, sizeof (struct fn_field) * nf.fnfields.size ());
+
+ for (int k = 0; k < nf.fnfields.size (); ++k)
+ fn_flp->fn_fields[k] = nf.fnfields[k];
}
- TYPE_NFN_FIELDS (type) = fip->nfnfields;
+ TYPE_NFN_FIELDS (type) = fip->fnfieldlists.size ();
}
/* Returns non-zero if NAME is the name of a vtable member in CU's
{
TYPE_CODE (type) = TYPE_CODE_UNION;
}
+ else if (die->tag == DW_TAG_variant_part)
+ {
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ TYPE_FLAG_DISCRIMINATED_UNION (type) = 1;
+ }
else
{
TYPE_CODE (type) = TYPE_CODE_STRUCT;
return type;
}
+/* A helper for process_structure_scope that handles a single member
+ DIE. */
+
+static void
+handle_struct_member_die (struct die_info *child_die, struct type *type,
+ struct field_info *fi,
+ std::vector<struct symbol *> *template_args,
+ struct dwarf2_cu *cu)
+{
+ if (child_die->tag == DW_TAG_member
+ || child_die->tag == DW_TAG_variable
+ || child_die->tag == DW_TAG_variant_part)
+ {
+ /* NOTE: carlton/2002-11-05: A C++ static data member
+ should be a DW_TAG_member that is a declaration, but
+ all versions of G++ as of this writing (so through at
+ least 3.2.1) incorrectly generate DW_TAG_variable
+ tags for them instead. */
+ dwarf2_add_field (fi, child_die, cu);
+ }
+ else if (child_die->tag == DW_TAG_subprogram)
+ {
+ /* Rust doesn't have member functions in the C++ sense.
+ However, it does emit ordinary functions as children
+ of a struct DIE. */
+ if (cu->language == language_rust)
+ read_func_scope (child_die, cu);
+ else
+ {
+ /* C++ member function. */
+ dwarf2_add_member_fn (fi, child_die, type, cu);
+ }
+ }
+ else if (child_die->tag == DW_TAG_inheritance)
+ {
+ /* C++ base class field. */
+ dwarf2_add_field (fi, child_die, cu);
+ }
+ else if (type_can_define_types (child_die))
+ dwarf2_add_type_defn (fi, child_die, cu);
+ else if (child_die->tag == DW_TAG_template_type_param
+ || child_die->tag == DW_TAG_template_value_param)
+ {
+ struct symbol *arg = new_symbol (child_die, NULL, cu);
+
+ if (arg != NULL)
+ template_args->push_back (arg);
+ }
+ else if (child_die->tag == DW_TAG_variant)
+ {
+ /* In a variant we want to get the discriminant and also add a
+ field for our sole member child. */
+ struct attribute *discr = dwarf2_attr (child_die, DW_AT_discr_value, cu);
+
+ for (struct die_info *variant_child = child_die->child;
+ variant_child != NULL;
+ variant_child = sibling_die (variant_child))
+ {
+ if (variant_child->tag == DW_TAG_member)
+ {
+ handle_struct_member_die (variant_child, type, fi,
+ template_args, cu);
+ /* Only handle the one. */
+ break;
+ }
+ }
+
+ /* We don't handle this but we might as well report it if we see
+ it. */
+ if (dwarf2_attr (child_die, DW_AT_discr_list, cu) != nullptr)
+ complaint (&symfile_complaints,
+ _("DW_AT_discr_list is not supported yet"
+ " - DIE at %s [in module %s]"),
+ sect_offset_str (child_die->sect_off),
+ objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+
+ /* The first field was just added, so we can stash the
+ discriminant there. */
+ gdb_assert (!fi->fields.empty ());
+ if (discr == NULL)
+ fi->fields.back ().variant.default_branch = true;
+ else
+ fi->fields.back ().variant.discriminant_value = DW_UNSND (discr);
+ }
+}
+
/* Finish creating a structure or union type, including filling in
its members and creating a symbol for it. */
if (type == NULL)
type = read_structure_type (die, cu);
+ /* When reading a DW_TAG_variant_part, we need to notice when we
+ read the discriminant member, so we can record it later in the
+ discriminant_info. */
+ bool is_variant_part = TYPE_FLAG_DISCRIMINATED_UNION (type);
+ sect_offset discr_offset;
+
+ if (is_variant_part)
+ {
+ struct attribute *discr = dwarf2_attr (die, DW_AT_discr, cu);
+ if (discr == NULL)
+ {
+ /* Maybe it's a univariant form, an extension we support.
+ In this case arrange not to check the offset. */
+ is_variant_part = false;
+ }
+ else if (attr_form_is_ref (discr))
+ {
+ struct dwarf2_cu *target_cu = cu;
+ struct die_info *target_die = follow_die_ref (die, discr, &target_cu);
+
+ discr_offset = target_die->sect_off;
+ }
+ else
+ {
+ complaint (&symfile_complaints,
+ _("DW_AT_discr does not have DIE reference form"
+ " - DIE at %s [in module %s]"),
+ sect_offset_str (die->sect_off),
+ objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+ is_variant_part = false;
+ }
+ }
+
if (die->child != NULL && ! die_is_declaration (die, cu))
{
struct field_info fi;
std::vector<struct symbol *> template_args;
- struct cleanup *back_to = make_cleanup (null_cleanup, 0);
-
- memset (&fi, 0, sizeof (struct field_info));
child_die = die->child;
while (child_die && child_die->tag)
{
- if (child_die->tag == DW_TAG_member
- || child_die->tag == DW_TAG_variable)
- {
- /* NOTE: carlton/2002-11-05: A C++ static data member
- should be a DW_TAG_member that is a declaration, but
- all versions of G++ as of this writing (so through at
- least 3.2.1) incorrectly generate DW_TAG_variable
- tags for them instead. */
- dwarf2_add_field (&fi, child_die, cu);
- }
- else if (child_die->tag == DW_TAG_subprogram)
- {
- /* Rust doesn't have member functions in the C++ sense.
- However, it does emit ordinary functions as children
- of a struct DIE. */
- if (cu->language == language_rust)
- read_func_scope (child_die, cu);
- else
- {
- /* C++ member function. */
- dwarf2_add_member_fn (&fi, child_die, type, cu);
- }
- }
- else if (child_die->tag == DW_TAG_inheritance)
- {
- /* C++ base class field. */
- dwarf2_add_field (&fi, child_die, cu);
- }
- else if (type_can_define_types (child_die))
- dwarf2_add_type_defn (&fi, child_die, cu);
- else if (child_die->tag == DW_TAG_template_type_param
- || child_die->tag == DW_TAG_template_value_param)
- {
- struct symbol *arg = new_symbol (child_die, NULL, cu);
+ handle_struct_member_die (child_die, type, &fi, &template_args, cu);
- if (arg != NULL)
- template_args.push_back (arg);
- }
+ if (is_variant_part && discr_offset == child_die->sect_off)
+ fi.fields.back ().variant.is_discriminant = true;
child_die = sibling_die (child_die);
}
/* Attach fields and member functions to the type. */
if (fi.nfields)
dwarf2_attach_fields_to_type (&fi, type, cu);
- if (fi.nfnfields)
+ if (!fi.fnfieldlists.empty ())
{
dwarf2_attach_fn_fields_to_type (&fi, type, cu);
/* Copy fi.typedef_field_list linked list elements content into the
allocated array TYPE_TYPEDEF_FIELD_ARRAY (type). */
- if (fi.typedef_field_list)
+ if (!fi.typedef_field_list.empty ())
{
- int i = fi.typedef_field_list_count;
+ int count = fi.typedef_field_list.size ();
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_TYPEDEF_FIELD_ARRAY (type)
= ((struct decl_field *)
- TYPE_ALLOC (type, sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * i));
- TYPE_TYPEDEF_FIELD_COUNT (type) = i;
-
- /* Reverse the list order to keep the debug info elements order. */
- while (--i >= 0)
- {
- struct decl_field *dest, *src;
+ TYPE_ALLOC (type,
+ sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * count));
+ TYPE_TYPEDEF_FIELD_COUNT (type) = count;
- dest = &TYPE_TYPEDEF_FIELD (type, i);
- src = &fi.typedef_field_list->field;
- fi.typedef_field_list = fi.typedef_field_list->next;
- *dest = *src;
- }
+ for (int i = 0; i < fi.typedef_field_list.size (); ++i)
+ TYPE_TYPEDEF_FIELD (type, i) = fi.typedef_field_list[i];
}
/* Copy fi.nested_types_list linked list elements content into the
allocated array TYPE_NESTED_TYPES_ARRAY (type). */
- if (fi.nested_types_list != NULL && cu->language != language_ada)
+ if (!fi.nested_types_list.empty () && cu->language != language_ada)
{
- int i = fi.nested_types_list_count;
+ int count = fi.nested_types_list.size ();
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_NESTED_TYPES_ARRAY (type)
= ((struct decl_field *)
- TYPE_ALLOC (type, sizeof (struct decl_field) * i));
- TYPE_NESTED_TYPES_COUNT (type) = i;
+ TYPE_ALLOC (type, sizeof (struct decl_field) * count));
+ TYPE_NESTED_TYPES_COUNT (type) = count;
- /* Reverse the list order to keep the debug info elements order. */
- while (--i >= 0)
- {
- struct decl_field *dest, *src;
-
- dest = &TYPE_NESTED_TYPES_FIELD (type, i);
- src = &fi.nested_types_list->field;
- fi.nested_types_list = fi.nested_types_list->next;
- *dest = *src;
- }
+ for (int i = 0; i < fi.nested_types_list.size (); ++i)
+ TYPE_NESTED_TYPES_FIELD (type, i) = fi.nested_types_list[i];
}
-
- do_cleanups (back_to);
}
quirk_gcc_member_function_pointer (type, objfile);
+ if (cu->language == language_rust && die->tag == DW_TAG_union_type)
+ cu->rust_unions.push_back (type);
/* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its
snapshots) has been known to create a die giving a declaration
continue;
}
- struct partial_die_info pdi;
+ struct partial_die_info pdi ((sect_offset) (info_ptr - reader->buffer),
+ abbrev);
- memset (&pdi, 0, sizeof (pdi));
- info_ptr = read_partial_die (reader, &pdi, *abbrev, bytes_read,
- info_ptr);
+ info_ptr = pdi.read (reader, *abbrev, info_ptr + bytes_read);
/* This two-pass algorithm for processing partial symbols has a
high cost in cache pressure. Thus, handle some simple cases
}
struct partial_die_info *part_die
- = XOBNEW (&cu->comp_unit_obstack, struct partial_die_info);
+ = new (&cu->comp_unit_obstack) partial_die_info (pdi);
- memcpy (part_die, &pdi, sizeof (pdi));
/* We'll save this DIE so link it in. */
part_die->die_parent = parent_die;
part_die->die_sibling = NULL;
}
}
-/* Read a minimal amount of information into the minimal die structure. */
+partial_die_info::partial_die_info (sect_offset sect_off_,
+ struct abbrev_info *abbrev)
+ : partial_die_info (sect_off_, abbrev->tag, abbrev->has_children)
+{
+}
-static const gdb_byte *
-read_partial_die (const struct die_reader_specs *reader,
- struct partial_die_info *part_die,
- const struct abbrev_info &abbrev, unsigned int abbrev_len,
- const gdb_byte *info_ptr)
+/* Read a minimal amount of information into the minimal die structure.
+ INFO_PTR should point just after the initial uleb128 of a DIE. */
+
+const gdb_byte *
+partial_die_info::read (const struct die_reader_specs *reader,
+ const struct abbrev_info &abbrev, const gdb_byte *info_ptr)
{
struct dwarf2_cu *cu = reader->cu;
struct dwarf2_per_objfile *dwarf2_per_objfile
= cu->per_cu->dwarf2_per_objfile;
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- const gdb_byte *buffer = reader->buffer;
unsigned int i;
- struct attribute attr;
int has_low_pc_attr = 0;
int has_high_pc_attr = 0;
int high_pc_relative = 0;
- memset (part_die, 0, sizeof (struct partial_die_info));
-
- part_die->sect_off = (sect_offset) (info_ptr - buffer);
-
- info_ptr += abbrev_len;
-
- part_die->tag = abbrev.tag;
- part_die->has_children = abbrev.has_children;
-
for (i = 0; i < abbrev.num_attrs; ++i)
{
+ struct attribute attr;
+
info_ptr = read_attribute (reader, &attr, &abbrev.attrs[i], info_ptr);
/* Store the data if it is of an attribute we want to keep in a
switch (attr.name)
{
case DW_AT_name:
- switch (part_die->tag)
+ switch (tag)
{
case DW_TAG_compile_unit:
case DW_TAG_partial_unit:
case DW_TAG_enumerator:
/* These tags always have simple identifiers already; no need
to canonicalize them. */
- part_die->name = DW_STRING (&attr);
+ name = DW_STRING (&attr);
break;
default:
- part_die->name
- = dwarf2_canonicalize_name (DW_STRING (&attr), cu,
- &objfile->per_bfd->storage_obstack);
+ {
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+
+ name
+ = dwarf2_canonicalize_name (DW_STRING (&attr), cu,
+ &objfile->per_bfd->storage_obstack);
+ }
break;
}
break;
assume they will be the same, and we only store the last
one we see. */
if (cu->language == language_ada)
- part_die->name = DW_STRING (&attr);
- part_die->linkage_name = DW_STRING (&attr);
+ name = DW_STRING (&attr);
+ linkage_name = DW_STRING (&attr);
break;
case DW_AT_low_pc:
has_low_pc_attr = 1;
- part_die->lowpc = attr_value_as_address (&attr);
+ lowpc = attr_value_as_address (&attr);
break;
case DW_AT_high_pc:
has_high_pc_attr = 1;
- part_die->highpc = attr_value_as_address (&attr);
+ highpc = attr_value_as_address (&attr);
if (cu->header.version >= 4 && attr_form_is_constant (&attr))
high_pc_relative = 1;
break;
/* Support the .debug_loc offsets. */
if (attr_form_is_block (&attr))
{
- part_die->d.locdesc = DW_BLOCK (&attr);
+ d.locdesc = DW_BLOCK (&attr);
}
else if (attr_form_is_section_offset (&attr))
{
}
break;
case DW_AT_external:
- part_die->is_external = DW_UNSND (&attr);
+ is_external = DW_UNSND (&attr);
break;
case DW_AT_declaration:
- part_die->is_declaration = DW_UNSND (&attr);
+ is_declaration = DW_UNSND (&attr);
break;
case DW_AT_type:
- part_die->has_type = 1;
+ has_type = 1;
break;
case DW_AT_abstract_origin:
case DW_AT_specification:
case DW_AT_extension:
- part_die->has_specification = 1;
- part_die->spec_offset = dwarf2_get_ref_die_offset (&attr);
- part_die->spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+ has_specification = 1;
+ spec_offset = dwarf2_get_ref_die_offset (&attr);
+ spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
|| cu->per_cu->is_dwz);
break;
case DW_AT_sibling:
_("ignoring absolute DW_AT_sibling"));
else
{
+ const gdb_byte *buffer = reader->buffer;
sect_offset off = dwarf2_get_ref_die_offset (&attr);
const gdb_byte *sibling_ptr = buffer + to_underlying (off);
else if (sibling_ptr > reader->buffer_end)
dwarf2_section_buffer_overflow_complaint (reader->die_section);
else
- part_die->sibling = sibling_ptr;
+ sibling = sibling_ptr;
}
break;
case DW_AT_byte_size:
- part_die->has_byte_size = 1;
+ has_byte_size = 1;
break;
case DW_AT_const_value:
- part_die->has_const_value = 1;
+ has_const_value = 1;
break;
case DW_AT_calling_convention:
/* DWARF doesn't provide a way to identify a program's source-level
compatibility. */
if (DW_UNSND (&attr) == DW_CC_program
&& cu->language == language_fortran)
- part_die->main_subprogram = 1;
+ main_subprogram = 1;
break;
case DW_AT_inline:
if (DW_UNSND (&attr) == DW_INL_inlined
|| DW_UNSND (&attr) == DW_INL_declared_inlined)
- part_die->may_be_inlined = 1;
+ may_be_inlined = 1;
break;
case DW_AT_import:
- if (part_die->tag == DW_TAG_imported_unit)
+ if (tag == DW_TAG_imported_unit)
{
- part_die->d.sect_off = dwarf2_get_ref_die_offset (&attr);
- part_die->is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+ d.sect_off = dwarf2_get_ref_die_offset (&attr);
+ is_dwz = (attr.form == DW_FORM_GNU_ref_alt
|| cu->per_cu->is_dwz);
}
break;
case DW_AT_main_subprogram:
- part_die->main_subprogram = DW_UNSND (&attr);
+ main_subprogram = DW_UNSND (&attr);
break;
default:
}
if (high_pc_relative)
- part_die->highpc += part_die->lowpc;
+ highpc += lowpc;
if (has_low_pc_attr && has_high_pc_attr)
{
labels are not in the output, so the relocs get a value of 0.
If this is a discarded function, mark the pc bounds as invalid,
so that GDB will ignore it. */
- if (part_die->lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero)
+ if (lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero)
{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
complaint (&symfile_complaints,
_("DW_AT_low_pc %s is zero "
"for DIE at %s [in module %s]"),
- paddress (gdbarch, part_die->lowpc),
- sect_offset_str (part_die->sect_off),
+ paddress (gdbarch, lowpc),
+ sect_offset_str (sect_off),
objfile_name (objfile));
}
/* dwarf2_get_pc_bounds has also the strict low < high requirement. */
- else if (part_die->lowpc >= part_die->highpc)
+ else if (lowpc >= highpc)
{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
complaint (&symfile_complaints,
_("DW_AT_low_pc %s is not < DW_AT_high_pc %s "
"for DIE at %s [in module %s]"),
- paddress (gdbarch, part_die->lowpc),
- paddress (gdbarch, part_die->highpc),
- sect_offset_str (part_die->sect_off),
+ paddress (gdbarch, lowpc),
+ paddress (gdbarch, highpc),
+ sect_offset_str (sect_off),
objfile_name (objfile));
}
else
- part_die->has_pc_info = 1;
+ has_pc_info = 1;
}
return info_ptr;
/* Find a cached partial DIE at OFFSET in CU. */
-static struct partial_die_info *
-find_partial_die_in_comp_unit (sect_offset sect_off, struct dwarf2_cu *cu)
+struct partial_die_info *
+dwarf2_cu::find_partial_die (sect_offset sect_off)
{
struct partial_die_info *lookup_die = NULL;
- struct partial_die_info part_die;
+ struct partial_die_info part_die (sect_off);
- part_die.sect_off = sect_off;
lookup_die = ((struct partial_die_info *)
- htab_find_with_hash (cu->partial_dies, &part_die,
+ htab_find_with_hash (partial_dies, &part_die,
to_underlying (sect_off)));
return lookup_die;
if (offset_in_dwz == cu->per_cu->is_dwz
&& offset_in_cu_p (&cu->header, sect_off))
{
- pd = find_partial_die_in_comp_unit (sect_off, cu);
+ pd = cu->find_partial_die (sect_off);
if (pd != NULL)
return pd;
/* We missed recording what we needed.
load_partial_comp_unit (per_cu);
per_cu->cu->last_used = 0;
- pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu);
+ pd = per_cu->cu->find_partial_die (sect_off);
}
/* If we didn't find it, and not all dies have been loaded,
set. */
load_partial_comp_unit (per_cu);
- pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu);
+ pd = per_cu->cu->find_partial_die (sect_off);
}
if (pd == NULL)
}
}
-/* Adjust PART_DIE before generating a symbol for it. This function
- may set the is_external flag or change the DIE's name. */
-
-static void
-fixup_partial_die (struct partial_die_info *part_die,
- struct dwarf2_cu *cu)
+void
+partial_die_info::fixup (struct dwarf2_cu *cu)
{
/* Once we've fixed up a die, there's no point in doing so again.
This also avoids a memory leak if we were to call
guess_partial_die_structure_name multiple times. */
- if (part_die->fixup_called)
+ if (fixup_called)
return;
/* If we found a reference attribute and the DIE has no name, try
to find a name in the referred to DIE. */
- if (part_die->name == NULL && part_die->has_specification)
+ if (name == NULL && has_specification)
{
struct partial_die_info *spec_die;
- spec_die = find_partial_die (part_die->spec_offset,
- part_die->spec_is_dwz, cu);
+ spec_die = find_partial_die (spec_offset, spec_is_dwz, cu);
- fixup_partial_die (spec_die, cu);
+ spec_die->fixup (cu);
if (spec_die->name)
{
- part_die->name = spec_die->name;
+ name = spec_die->name;
/* Copy DW_AT_external attribute if it is set. */
if (spec_die->is_external)
- part_die->is_external = spec_die->is_external;
+ is_external = spec_die->is_external;
}
}
/* Set default names for some unnamed DIEs. */
- if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
- part_die->name = CP_ANONYMOUS_NAMESPACE_STR;
+ if (name == NULL && tag == DW_TAG_namespace)
+ name = CP_ANONYMOUS_NAMESPACE_STR;
/* If there is no parent die to provide a namespace, and there are
children, see if we can determine the namespace from their linkage
if (cu->language == language_cplus
&& !VEC_empty (dwarf2_section_info_def,
cu->per_cu->dwarf2_per_objfile->types)
- && part_die->die_parent == NULL
- && part_die->has_children
- && (part_die->tag == DW_TAG_class_type
- || part_die->tag == DW_TAG_structure_type
- || part_die->tag == DW_TAG_union_type))
- guess_partial_die_structure_name (part_die, cu);
+ && die_parent == NULL
+ && has_children
+ && (tag == DW_TAG_class_type
+ || tag == DW_TAG_structure_type
+ || tag == DW_TAG_union_type))
+ guess_partial_die_structure_name (this, cu);
/* GCC might emit a nameless struct or union that has a linkage
name. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */
- if (part_die->name == NULL
- && (part_die->tag == DW_TAG_class_type
- || part_die->tag == DW_TAG_interface_type
- || part_die->tag == DW_TAG_structure_type
- || part_die->tag == DW_TAG_union_type)
- && part_die->linkage_name != NULL)
+ if (name == NULL
+ && (tag == DW_TAG_class_type
+ || tag == DW_TAG_interface_type
+ || tag == DW_TAG_structure_type
+ || tag == DW_TAG_union_type)
+ && linkage_name != NULL)
{
char *demangled;
- demangled = gdb_demangle (part_die->linkage_name, DMGL_TYPES);
+ demangled = gdb_demangle (linkage_name, DMGL_TYPES);
if (demangled)
{
const char *base;
base = demangled;
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
- part_die->name
+ name
= ((const char *)
obstack_copy0 (&objfile->per_bfd->storage_obstack,
base, strlen (base)));
}
}
- part_die->fixup_called = 1;
+ fixup_called = 1;
}
/* Read an attribute value described by an attribute form. */