/* Abstraction of GNU v3 abi.
Contributed by Jim Blandy <jimb@redhat.com>
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "valprint.h"
#include "c-lang.h"
#include "typeprint.h"
+#include <algorithm>
static struct cp_abi_ops gnu_v3_abi_ops;
static int
gnuv3_is_operator_name (const char *name)
{
- return startswith (name, "operator");
+ return startswith (name, CP_OPERATOR_STR);
}
/* We assumed in the allocation above that there were four fields. */
gdb_assert (field == (field_list + 4));
- t = arch_type (arch, TYPE_CODE_STRUCT, offset, NULL);
+ t = arch_type (arch, TYPE_CODE_STRUCT, offset * TARGET_CHAR_BIT, NULL);
TYPE_NFIELDS (t) = field - field_list;
TYPE_FIELDS (t) = field_list;
- TYPE_TAG_NAME (t) = "gdb_gnu_v3_abi_vtable";
+ TYPE_NAME (t) = "gdb_gnu_v3_abi_vtable";
INIT_CPLUS_SPECIFIC (t);
return make_type_with_address_space (t, TYPE_INSTANCE_FLAG_CODE_SPACE);
LONGEST offset_to_top;
const char *atsign;
- /* We only have RTTI for class objects. */
- if (TYPE_CODE (values_type) != TYPE_CODE_STRUCT)
+ /* We only have RTTI for dynamic class objects. */
+ if (TYPE_CODE (values_type) != TYPE_CODE_STRUCT
+ || !gnuv3_dynamic_class (values_type))
return NULL;
/* Determine architecture. */
int max_voffset;
};
-typedef struct value_and_voffset *value_and_voffset_p;
-DEF_VEC_P (value_and_voffset_p);
-
/* Hash function for value_and_voffset. */
static hashval_t
== value_address (ovb->value) + value_embedded_offset (ovb->value));
}
-/* qsort comparison function for value_and_voffset. */
+/* Comparison function for value_and_voffset. */
-static int
-compare_value_and_voffset (const void *a, const void *b)
+static bool
+compare_value_and_voffset (const struct value_and_voffset *va,
+ const struct value_and_voffset *vb)
{
- const struct value_and_voffset * const *ova
- = (const struct value_and_voffset * const *) a;
- CORE_ADDR addra = (value_address ((*ova)->value)
- + value_embedded_offset ((*ova)->value));
- const struct value_and_voffset * const *ovb
- = (const struct value_and_voffset * const *) b;
- CORE_ADDR addrb = (value_address ((*ovb)->value)
- + value_embedded_offset ((*ovb)->value));
-
- if (addra < addrb)
- return -1;
- if (addra > addrb)
- return 1;
- return 0;
+ CORE_ADDR addra = (value_address (va->value)
+ + value_embedded_offset (va->value));
+ CORE_ADDR addrb = (value_address (vb->value)
+ + value_embedded_offset (vb->value));
+
+ return addra < addrb;
}
/* A helper function used when printing vtables. This determines the
static void
compute_vtable_size (htab_t offset_hash,
- VEC (value_and_voffset_p) **offset_vec,
+ std::vector<value_and_voffset *> *offset_vec,
struct value *value)
{
int i;
current_vo->value = value;
current_vo->max_voffset = -1;
*slot = current_vo;
- VEC_safe_push (value_and_voffset_p, *offset_vec, current_vo);
+ offset_vec->push_back (current_vo);
}
/* Update the value_and_voffset object with the highest vtable
struct type *type;
struct value *vtable;
struct value_print_options opts;
- htab_t offset_hash;
- struct cleanup *cleanup;
- VEC (value_and_voffset_p) *result_vec = NULL;
- struct value_and_voffset *iter;
- int i, count;
+ int count;
value = coerce_ref (value);
type = check_typedef (value_type (value));
return;
}
- offset_hash = htab_create_alloc (1, hash_value_and_voffset,
- eq_value_and_voffset,
- xfree, xcalloc, xfree);
- cleanup = make_cleanup_htab_delete (offset_hash);
- make_cleanup (VEC_cleanup (value_and_voffset_p), &result_vec);
-
- compute_vtable_size (offset_hash, &result_vec, value);
+ htab_up offset_hash (htab_create_alloc (1, hash_value_and_voffset,
+ eq_value_and_voffset,
+ xfree, xcalloc, xfree));
+ std::vector<value_and_voffset *> result_vec;
- qsort (VEC_address (value_and_voffset_p, result_vec),
- VEC_length (value_and_voffset_p, result_vec),
- sizeof (value_and_voffset_p),
- compare_value_and_voffset);
+ compute_vtable_size (offset_hash.get (), &result_vec, value);
+ std::sort (result_vec.begin (), result_vec.end (),
+ compare_value_and_voffset);
count = 0;
- for (i = 0; VEC_iterate (value_and_voffset_p, result_vec, i, iter); ++i)
+ for (value_and_voffset *iter : result_vec)
{
if (iter->max_voffset >= 0)
{
++count;
}
}
-
- do_cleanups (cleanup);
}
/* Return a GDB type representing `struct std::type_info', laid out
gdb_assert (field == (field_list + 2));
- t = arch_type (arch, TYPE_CODE_STRUCT, offset, NULL);
+ t = arch_type (arch, TYPE_CODE_STRUCT, offset * TARGET_CHAR_BIT, NULL);
TYPE_NFIELDS (t) = field - field_list;
TYPE_FIELDS (t) = field_list;
- TYPE_TAG_NAME (t) = "gdb_gnu_v3_type_info";
+ TYPE_NAME (t) = "gdb_gnu_v3_type_info";
INIT_CPLUS_SPECIFIC (t);
return t;
struct type *typeinfo_type;
struct type *type;
struct gdbarch *gdbarch;
- struct cleanup *cleanup;
struct value *result;
- char *type_name, *canonical;
+ std::string type_name, canonical;
/* We have to handle values a bit trickily here, to allow this code
to work properly with non_lvalue values that are really just
gdbarch = get_type_arch (type);
type_name = type_to_string (type);
- if (type_name == NULL)
+ if (type_name.empty ())
error (_("cannot find typeinfo for unnamed type"));
- cleanup = make_cleanup (xfree, type_name);
/* We need to canonicalize the type name here, because we do lookups
using the demangled name, and so we must match the format it
uses. E.g., GDB tends to use "const char *" as a type name, but
the demangler uses "char const *". */
- canonical = cp_canonicalize_string (type_name);
- if (canonical != NULL)
- {
- make_cleanup (xfree, canonical);
- type_name = canonical;
- }
+ canonical = cp_canonicalize_string (type_name.c_str ());
+ if (!canonical.empty ())
+ type_name = canonical;
typeinfo_type = gnuv3_get_typeid_type (gdbarch);
vtable = gnuv3_get_vtable (gdbarch, type, address);
if (vtable == NULL)
- error (_("cannot find typeinfo for object of type '%s'"), type_name);
+ error (_("cannot find typeinfo for object of type '%s'"),
+ type_name.c_str ());
typeinfo_value = value_field (vtable, vtable_field_type_info);
result = value_ind (value_cast (make_pointer_type (typeinfo_type, NULL),
typeinfo_value));
}
else
{
- char *sym_name;
- struct bound_minimal_symbol minsym;
-
- sym_name = concat ("typeinfo for ", type_name, (char *) NULL);
- make_cleanup (xfree, sym_name);
- minsym = lookup_minimal_symbol (sym_name, NULL, NULL);
+ std::string sym_name = std::string ("typeinfo for ") + type_name;
+ bound_minimal_symbol minsym
+ = lookup_minimal_symbol (sym_name.c_str (), NULL, NULL);
if (minsym.minsym == NULL)
- error (_("could not find typeinfo symbol for '%s'"), type_name);
+ error (_("could not find typeinfo symbol for '%s'"), type_name.c_str ());
result = value_at_lazy (typeinfo_type, BMSYMBOL_VALUE_ADDRESS (minsym));
}
- do_cleanups (cleanup);
return result;
}
/* Implement the 'get_typename_from_type_info' method. */
-static char *
+static std::string
gnuv3_get_typename_from_type_info (struct value *type_info_ptr)
{
struct gdbarch *gdbarch = get_type_arch (value_type (type_info_ptr));
/* Strip off @plt and version suffixes. */
atsign = strchr (class_name, '@');
if (atsign != NULL)
- return savestring (class_name, atsign - class_name);
- return xstrdup (class_name);
+ return std::string (class_name, atsign - class_name);
+ return class_name;
}
/* Implement the 'get_type_from_type_info' method. */
static struct type *
gnuv3_get_type_from_type_info (struct value *type_info_ptr)
{
- char *type_name;
- struct cleanup *cleanup;
- struct value *type_val;
- struct type *result;
-
- type_name = gnuv3_get_typename_from_type_info (type_info_ptr);
- cleanup = make_cleanup (xfree, type_name);
-
/* We have to parse the type name, since in general there is not a
symbol for a type. This is somewhat bogus since there may be a
mis-parse. Another approach might be to re-use the demangler's
internal form to reconstruct the type somehow. */
-
- expression_up expr = parse_expression (type_name);
-
- type_val = evaluate_type (expr.get ());
- result = value_type (type_val);
-
- do_cleanups (cleanup);
- return result;
+ std::string type_name = gnuv3_get_typename_from_type_info (type_info_ptr);
+ expression_up expr (parse_expression (type_name.c_str ()));
+ struct value *type_val = evaluate_type (expr.get ());
+ return value_type (type_val);
}
/* Determine if we are currently in a C++ thunk. If so, get the address
of the real function from the function descriptor before passing on
the address to other layers of GDB. */
func_addr = gdbarch_convert_from_func_ptr_addr (gdbarch, method_stop_pc,
- ¤t_target);
+ current_top_target ());
if (func_addr != 0)
method_stop_pc = func_addr;
gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference;
}
-extern initialize_file_ftype _initialize_gnu_v3_abi; /* -Wmissing-prototypes */
-
void
_initialize_gnu_v3_abi (void)
{