gdb: fix vfork with multiple threads
[deliverable/binutils-gdb.git] / gdb / gnu-v3-abi.c
index e2b9198b08282a839d7e838bcf433167aebe8df5..45e57c210cbfafea723a27e7fe3b46db6733f460 100644 (file)
@@ -1,7 +1,7 @@
 /* Abstraction of GNU v3 abi.
    Contributed by Jim Blandy <jimb@redhat.com>
 
-   Copyright (C) 2001-2018 Free Software Foundation, Inc.
+   Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "cp-abi.h"
 #include "cp-support.h"
 #include "demangle.h"
+#include "dwarf2.h"
 #include "objfiles.h"
 #include "valprint.h"
 #include "c-lang.h"
 #include "typeprint.h"
 #include <algorithm>
+#include "cli/cli-style.h"
+#include "dwarf2/loc.h"
+#include "inferior.h"
 
 static struct cp_abi_ops gnu_v3_abi_ops;
 
@@ -57,25 +61,25 @@ gnuv3_is_operator_name (const char *name)
    struct gdb_gnu_v3_abi_vtable {
 
      / * An array of virtual call and virtual base offsets.  The real
-         length of this array depends on the class hierarchy; we use
-         negative subscripts to access the elements.  Yucky, but
-         better than the alternatives.  * /
+        length of this array depends on the class hierarchy; we use
+        negative subscripts to access the elements.  Yucky, but
+        better than the alternatives.  * /
      ptrdiff_t vcall_and_vbase_offsets[0];
 
      / * The offset from a virtual pointer referring to this table
-         to the top of the complete object.  * /
+        to the top of the complete object.  * /
      ptrdiff_t offset_to_top;
 
      / * The type_info pointer for this class.  This is really a
-         std::type_info *, but GDB doesn't really look at the
-         type_info object itself, so we don't bother to get the type
-         exactly right.  * /
+        std::type_info *, but GDB doesn't really look at the
+        type_info object itself, so we don't bother to get the type
+        exactly right.  * /
      void *type_info;
 
      / * Virtual table pointers in objects point here.  * /
 
      / * Virtual function pointers.  Like the vcall/vbase array, the
-         real length of this table depends on the class hierarchy.  * /
+        real length of this table depends on the class hierarchy.  * /
      void (*virtual_functions[0]) ();
 
    };
@@ -132,39 +136,39 @@ build_gdb_vtable_type (struct gdbarch *arch)
 
   /* ptrdiff_t vcall_and_vbase_offsets[0]; */
   FIELD_NAME (*field) = "vcall_and_vbase_offsets";
-  FIELD_TYPE (*field) = lookup_array_range_type (ptrdiff_type, 0, -1);
+  field->set_type (lookup_array_range_type (ptrdiff_type, 0, -1));
   SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT);
-  offset += TYPE_LENGTH (FIELD_TYPE (*field));
+  offset += TYPE_LENGTH (field->type ());
   field++;
 
   /* ptrdiff_t offset_to_top; */
   FIELD_NAME (*field) = "offset_to_top";
-  FIELD_TYPE (*field) = ptrdiff_type;
+  field->set_type (ptrdiff_type);
   SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT);
-  offset += TYPE_LENGTH (FIELD_TYPE (*field));
+  offset += TYPE_LENGTH (field->type ());
   field++;
 
   /* void *type_info; */
   FIELD_NAME (*field) = "type_info";
-  FIELD_TYPE (*field) = void_ptr_type;
+  field->set_type (void_ptr_type);
   SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT);
-  offset += TYPE_LENGTH (FIELD_TYPE (*field));
+  offset += TYPE_LENGTH (field->type ());
   field++;
 
   /* void (*virtual_functions[0]) (); */
   FIELD_NAME (*field) = "virtual_functions";
-  FIELD_TYPE (*field) = lookup_array_range_type (ptr_to_void_fn_type, 0, -1);
+  field->set_type (lookup_array_range_type (ptr_to_void_fn_type, 0, -1));
   SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT);
-  offset += TYPE_LENGTH (FIELD_TYPE (*field));
+  offset += TYPE_LENGTH (field->type ());
   field++;
 
   /* 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 * TARGET_CHAR_BIT, NULL);
-  TYPE_NFIELDS (t) = field - field_list;
-  TYPE_FIELDS (t) = field_list;
-  TYPE_NAME (t) = "gdb_gnu_v3_abi_vtable";
+  t->set_num_fields (field - field_list);
+  t->set_fields (field_list);
+  t->set_name ("gdb_gnu_v3_abi_vtable");
   INIT_CPLUS_SPECIFIC (t);
 
   return make_type_with_address_space (t, TYPE_INSTANCE_FLAG_CODE_SPACE);
@@ -179,7 +183,7 @@ vtable_ptrdiff_type (struct gdbarch *gdbarch)
     = (struct type *) gdbarch_data (gdbarch, vtable_type_gdbarch_data);
 
   /* The "offset_to_top" field has the appropriate (ptrdiff_t) type.  */
-  return TYPE_FIELD_TYPE (vtable_type, vtable_field_offset_to_top);
+  return vtable_type->field (vtable_field_offset_to_top).type ();
 }
 
 /* Return the offset from the start of the imaginary `struct
@@ -192,7 +196,7 @@ vtable_address_point_offset (struct gdbarch *gdbarch)
     = (struct type *) gdbarch_data (gdbarch, vtable_type_gdbarch_data);
 
   return (TYPE_FIELD_BITPOS (vtable_type, vtable_field_virtual_functions)
-          / TARGET_CHAR_BIT);
+         / TARGET_CHAR_BIT);
 }
 
 
@@ -205,10 +209,10 @@ gnuv3_dynamic_class (struct type *type)
   int fieldnum, fieldelem;
 
   type = check_typedef (type);
-  gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
-             || TYPE_CODE (type) == TYPE_CODE_UNION);
+  gdb_assert (type->code () == TYPE_CODE_STRUCT
+             || type->code () == TYPE_CODE_UNION);
 
-  if (TYPE_CODE (type) == TYPE_CODE_UNION)
+  if (type->code () == TYPE_CODE_UNION)
     return 0;
 
   if (TYPE_CPLUS_DYNAMIC (type))
@@ -218,7 +222,7 @@ gnuv3_dynamic_class (struct type *type)
 
   for (fieldnum = 0; fieldnum < TYPE_N_BASECLASSES (type); fieldnum++)
     if (BASETYPE_VIA_VIRTUAL (type, fieldnum)
-       || gnuv3_dynamic_class (TYPE_FIELD_TYPE (type, fieldnum)))
+       || gnuv3_dynamic_class (type->field (fieldnum).type ()))
       {
        TYPE_CPLUS_DYNAMIC (type) = 1;
        return 1;
@@ -256,7 +260,7 @@ gnuv3_get_vtable (struct gdbarch *gdbarch,
   CORE_ADDR vtable_address;
 
   container_type = check_typedef (container_type);
-  gdb_assert (TYPE_CODE (container_type) == TYPE_CODE_STRUCT);
+  gdb_assert (container_type->code () == TYPE_CODE_STRUCT);
 
   /* If this type does not have a virtual table, don't read the first
      field.  */
@@ -287,7 +291,7 @@ gnuv3_get_vtable (struct gdbarch *gdbarch,
 
 static struct type *
 gnuv3_rtti_type (struct value *value,
-                 int *full_p, LONGEST *top_p, int *using_enc_p)
+                int *full_p, LONGEST *top_p, int *using_enc_p)
 {
   struct gdbarch *gdbarch;
   struct type *values_type = check_typedef (value_type (value));
@@ -300,12 +304,12 @@ gnuv3_rtti_type (struct value *value,
   const char *atsign;
 
   /* We only have RTTI for dynamic class objects.  */
-  if (TYPE_CODE (values_type) != TYPE_CODE_STRUCT
+  if (values_type->code () != TYPE_CODE_STRUCT
       || !gnuv3_dynamic_class (values_type))
     return NULL;
 
   /* Determine architecture.  */
-  gdbarch = get_type_arch (values_type);
+  gdbarch = values_type->arch ();
 
   if (using_enc_p)
     *using_enc_p = 0;
@@ -318,7 +322,7 @@ gnuv3_rtti_type (struct value *value,
   /* Find the linker symbol for this vtable.  */
   vtable_symbol
     = lookup_minimal_symbol_by_pc (value_address (vtable)
-                                   + value_embedded_offset (vtable)).minsym;
+                                  + value_embedded_offset (vtable)).minsym;
   if (! vtable_symbol)
     return NULL;
   
@@ -327,7 +331,7 @@ gnuv3_rtti_type (struct value *value,
      If we didn't like this approach, we could instead look in the
      type_info object itself to get the class name.  But this way
      should work just as well, and doesn't read target memory.  */
-  vtable_symbol_name = MSYMBOL_DEMANGLED_NAME (vtable_symbol);
+  vtable_symbol_name = vtable_symbol->demangled_name ();
   if (vtable_symbol_name == NULL
       || !startswith (vtable_symbol_name, "vtable for "))
     {
@@ -364,8 +368,8 @@ gnuv3_rtti_type (struct value *value,
 
   if (full_p)
     *full_p = (- offset_to_top == value_embedded_offset (value)
-               && (TYPE_LENGTH (value_enclosing_type (value))
-                   >= TYPE_LENGTH (run_time_type)));
+              && (TYPE_LENGTH (value_enclosing_type (value))
+                  >= TYPE_LENGTH (run_time_type)));
   if (top_p)
     *top_p = - offset_to_top;
   return run_time_type;
@@ -387,12 +391,12 @@ gnuv3_get_virtual_fn (struct gdbarch *gdbarch, struct value *container,
 
   /* Fetch the appropriate function pointer from the vtable.  */
   vfn = value_subscript (value_field (vtable, vtable_field_virtual_functions),
-                         vtable_index);
+                        vtable_index);
 
   /* If this architecture uses function descriptors directly in the vtable,
      then the address of the vtable entry is actually a "function pointer"
      (i.e. points to the descriptor).  We don't need to scale the index
-     by the size of a function descriptor; GCC does that before outputing
+     by the size of a function descriptor; GCC does that before outputting
      debug information.  */
   if (gdbarch_vtable_function_descriptors (gdbarch))
     vfn = value_addr (vfn);
@@ -408,18 +412,18 @@ gnuv3_get_virtual_fn (struct gdbarch *gdbarch, struct value *container,
 
 static struct value *
 gnuv3_virtual_fn_field (struct value **value_p,
-                        struct fn_field *f, int j,
+                       struct fn_field *f, int j,
                        struct type *vfn_base, int offset)
 {
   struct type *values_type = check_typedef (value_type (*value_p));
   struct gdbarch *gdbarch;
 
   /* Some simple sanity checks.  */
-  if (TYPE_CODE (values_type) != TYPE_CODE_STRUCT)
+  if (values_type->code () != TYPE_CODE_STRUCT)
     error (_("Only classes can have virtual functions."));
 
   /* Determine architecture.  */
-  gdbarch = get_type_arch (values_type);
+  gdbarch = values_type->arch ();
 
   /* Cast our value to the base class which defines this virtual
      function.  This takes care of any necessary `this'
@@ -451,7 +455,7 @@ gnuv3_baseclass_offset (struct type *type, int index,
   long int cur_base_offset, base_offset;
 
   /* Determine architecture.  */
-  gdbarch = get_type_arch (type);
+  gdbarch = type->arch ();
   ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
 
   /* If it isn't a virtual base, this is easy.  The offset is in the
@@ -459,6 +463,30 @@ gnuv3_baseclass_offset (struct type *type, int index,
   if (!BASETYPE_VIA_VIRTUAL (type, index))
     return TYPE_BASECLASS_BITPOS (type, index) / 8;
 
+  /* If we have a DWARF expression for the offset, evaluate it.  */
+  if (TYPE_FIELD_LOC_KIND (type, index) == FIELD_LOC_KIND_DWARF_BLOCK)
+    {
+      struct dwarf2_property_baton baton;
+      baton.property_type
+       = lookup_pointer_type (type->field (index).type ());
+      baton.locexpr = *TYPE_FIELD_DWARF_BLOCK (type, index);
+
+      struct dynamic_prop prop;
+      prop.set_locexpr (&baton);
+
+      struct property_addr_info addr_stack;
+      addr_stack.type = type;
+      /* Note that we don't set "valaddr" here.  Doing so causes
+        regressions.  FIXME.  */
+      addr_stack.addr = address + embedded_offset;
+      addr_stack.next = nullptr;
+
+      CORE_ADDR result;
+      if (dwarf2_evaluate_property (&prop, nullptr, &addr_stack, &result,
+                                   true))
+       return (int) (result - addr_stack.addr);
+    }
+
   /* To access a virtual base, we need to use the vbase offset stored in
      our vtable.  Recent GCC versions provide this information.  If it isn't
      available, we could get what we needed from RTTI, or from drawing the
@@ -522,7 +550,7 @@ gnuv3_find_method_in (struct type *domain, CORE_ADDR voffset,
        continue;
 
       pos = TYPE_BASECLASS_BITPOS (domain, i) / 8;
-      basetype = TYPE_FIELD_TYPE (domain, i);
+      basetype = domain->field (i).type ();
       /* Recurse with a modified adjustment.  We don't need to adjust
         voffset.  */
       if (adjustment >= pos && adjustment < pos + TYPE_LENGTH (basetype))
@@ -584,7 +612,7 @@ gnuv3_print_method_ptr (const gdb_byte *contents,
                        struct ui_file *stream)
 {
   struct type *self_type = TYPE_SELF_TYPE (type);
-  struct gdbarch *gdbarch = get_type_arch (self_type);
+  struct gdbarch *gdbarch = self_type->arch ();
   CORE_ADDR ptr_value;
   LONGEST adjustment;
   int vbit;
@@ -664,9 +692,7 @@ gnuv3_print_method_ptr (const gdb_byte *contents,
 static int
 gnuv3_method_ptr_size (struct type *type)
 {
-  struct gdbarch *gdbarch = get_type_arch (type);
-
-  return 2 * TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr);
+  return 2 * TYPE_LENGTH (builtin_type (type->arch ())->builtin_data_ptr);
 }
 
 /* GNU v3 implementation of cplus_make_method_ptr.  */
@@ -675,9 +701,9 @@ static void
 gnuv3_make_method_ptr (struct type *type, gdb_byte *contents,
                       CORE_ADDR value, int is_virtual)
 {
-  struct gdbarch *gdbarch = get_type_arch (type);
+  struct gdbarch *gdbarch = type->arch ();
   int size = TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr);
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum bfd_endian byte_order = type_byte_order (type);
 
   /* FIXME drow/2006-12-24: The adjustment of "this" is currently
      always zero, since the method pointer is of the correct type.
@@ -718,7 +744,7 @@ gnuv3_method_ptr_to_value (struct value **this_p, struct value *method_ptr)
   method_type = TYPE_TARGET_TYPE (check_typedef (value_type (method_ptr)));
 
   /* Extract the pointer to member.  */
-  gdbarch = get_type_arch (self_type);
+  gdbarch = self_type->arch ();
   vbit = gnuv3_decode_method_ptr (gdbarch, contents, &ptr_value, &adjustment);
 
   /* First convert THIS to match the containing type of the pointer to
@@ -821,7 +847,7 @@ compute_vtable_size (htab_t offset_hash,
   void **slot;
   struct value_and_voffset search_vo, *current_vo;
 
-  gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT);
+  gdb_assert (type->code () == TYPE_CODE_STRUCT);
 
   /* If the object is not dynamic, then we are done; as it cannot have
      dynamic base types either.  */
@@ -906,16 +932,16 @@ print_one_vtable (struct gdbarch *gdbarch, struct value *value,
       if (gdbarch_vtable_function_descriptors (gdbarch))
        vfn = value_addr (vfn);
 
-      TRY
+      try
        {
          addr = value_as_address (vfn);
        }
-      CATCH (ex, RETURN_MASK_ERROR)
+      catch (const gdb_exception_error &ex)
        {
-         printf_filtered (_("<error: %s>"), ex.message);
+         fprintf_styled (gdb_stdout, metadata_style.style (),
+                         _("<error: %s>"), ex.what ());
          got_error = 1;
        }
-      END_CATCH
 
       if (!got_error)
        print_function_pointer_address (opts, gdbarch, addr, gdb_stdout);
@@ -936,7 +962,7 @@ gnuv3_print_vtable (struct value *value)
 
   value = coerce_ref (value);
   type = check_typedef (value_type (value));
-  if (TYPE_CODE (type) == TYPE_CODE_PTR)
+  if (type->code () == TYPE_CODE_PTR)
     {
       value = value_ind (value);
       type = check_typedef (value_type (value));
@@ -951,10 +977,10 @@ gnuv3_print_vtable (struct value *value)
       type = check_typedef (value_type (value));
     }
 
-  gdbarch = get_type_arch (type);
+  gdbarch = type->arch ();
 
   vtable = NULL;
-  if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+  if (type->code () == TYPE_CODE_STRUCT)
     vtable = gnuv3_get_vtable (gdbarch, type,
                               value_as_address (value_addr (value)));
 
@@ -1011,24 +1037,24 @@ build_std_type_info_type (struct gdbarch *arch)
 
   /* The vtable.  */
   FIELD_NAME (*field) = "_vptr.type_info";
-  FIELD_TYPE (*field) = void_ptr_type;
+  field->set_type (void_ptr_type);
   SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT);
-  offset += TYPE_LENGTH (FIELD_TYPE (*field));
+  offset += TYPE_LENGTH (field->type ());
   field++;
 
   /* The name.  */
   FIELD_NAME (*field) = "__name";
-  FIELD_TYPE (*field) = char_ptr_type;
+  field->set_type (char_ptr_type);
   SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT);
-  offset += TYPE_LENGTH (FIELD_TYPE (*field));
+  offset += TYPE_LENGTH (field->type ());
   field++;
 
   gdb_assert (field == (field_list + 2));
 
   t = arch_type (arch, TYPE_CODE_STRUCT, offset * TARGET_CHAR_BIT, NULL);
-  TYPE_NFIELDS (t) = field - field_list;
-  TYPE_FIELDS (t) = field_list;
-  TYPE_NAME (t) = "gdb_gnu_v3_type_info";
+  t->set_num_fields (field - field_list);
+  t->set_fields (field_list);
+  t->set_name ("gdb_gnu_v3_type_info");
   INIT_CPLUS_SPECIFIC (t);
 
   return t;
@@ -1062,7 +1088,8 @@ gnuv3_get_typeid (struct value *value)
   struct type *type;
   struct gdbarch *gdbarch;
   struct value *result;
-  std::string type_name, canonical;
+  std::string type_name;
+  gdb::unique_xmalloc_ptr<char> 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
@@ -1074,12 +1101,12 @@ gnuv3_get_typeid (struct value *value)
 
   /* In the non_lvalue case, a reference might have slipped through
      here.  */
-  if (TYPE_CODE (type) == TYPE_CODE_REF)
+  if (type->code () == TYPE_CODE_REF)
     type = check_typedef (TYPE_TARGET_TYPE (type));
 
   /* Ignore top-level cv-qualifiers.  */
   type = make_cv_type (0, 0, type, NULL);
-  gdbarch = get_type_arch (type);
+  gdbarch = type->arch ();
 
   type_name = type_to_string (type);
   if (type_name.empty ())
@@ -1090,14 +1117,15 @@ gnuv3_get_typeid (struct value *value)
      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.c_str ());
-  if (!canonical.empty ())
-    type_name = canonical;
+  const char *name = (canonical == nullptr
+                     ? type_name.c_str ()
+                     : canonical.get ());
 
   typeinfo_type = gnuv3_get_typeid_type (gdbarch);
 
   /* We check for lval_memory because in the "typeid (type-id)" case,
      the type is passed via a not_lval value object.  */
-  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+  if (type->code () == TYPE_CODE_STRUCT
       && value_lval_const (value) == lval_memory
       && gnuv3_dynamic_class (type))
     {
@@ -1107,19 +1135,19 @@ gnuv3_get_typeid (struct value *value)
       vtable = gnuv3_get_vtable (gdbarch, type, address);
       if (vtable == NULL)
        error (_("cannot find typeinfo for object of type '%s'"),
-              type_name.c_str ());
+              name);
       typeinfo_value = value_field (vtable, vtable_field_type_info);
       result = value_ind (value_cast (make_pointer_type (typeinfo_type, NULL),
                                      typeinfo_value));
     }
   else
     {
-      std::string sym_name = std::string ("typeinfo for ") + type_name;
+      std::string sym_name = std::string ("typeinfo for ") + 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.c_str ());
+       error (_("could not find typeinfo symbol for '%s'"), name);
 
       result = value_at_lazy (typeinfo_type, BMSYMBOL_VALUE_ADDRESS (minsym));
     }
@@ -1132,7 +1160,7 @@ gnuv3_get_typeid (struct value *value)
 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));
+  struct gdbarch *gdbarch = value_type (type_info_ptr)->arch ();
   struct bound_minimal_symbol typeinfo_sym;
   CORE_ADDR addr;
   const char *symname;
@@ -1147,11 +1175,11 @@ gnuv3_get_typename_from_type_info (struct value *type_info_ptr)
 
 #define TYPEINFO_PREFIX "typeinfo for "
 #define TYPEINFO_PREFIX_LEN (sizeof (TYPEINFO_PREFIX) - 1)
-  symname = MSYMBOL_DEMANGLED_NAME (typeinfo_sym.minsym);
+  symname = typeinfo_sym.minsym->demangled_name ();
   if (symname == NULL || strncmp (symname, TYPEINFO_PREFIX,
                                  TYPEINFO_PREFIX_LEN))
     error (_("typeinfo symbol '%s' has unexpected name"),
-          MSYMBOL_LINKAGE_NAME (typeinfo_sym.minsym));
+          typeinfo_sym.minsym->linkage_name ());
   class_name = symname + TYPEINFO_PREFIX_LEN;
 
   /* Strip off @plt and version suffixes.  */
@@ -1201,7 +1229,7 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
   /* The symbol's demangled name should be something like "virtual
      thunk to FUNCTION", where FUNCTION is the name of the function
      being thunked to.  */
-  thunk_name = MSYMBOL_DEMANGLED_NAME (thunk_sym.minsym);
+  thunk_name = thunk_sym.minsym->demangled_name ();
   if (thunk_name == NULL || strstr (thunk_name, " thunk to ") == NULL)
     return 0;
 
@@ -1216,8 +1244,8 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
      (powerpc 64 for example).  Make sure to retrieve 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,
-                                                 current_top_target ());
+  func_addr = gdbarch_convert_from_func_ptr_addr
+    (gdbarch, method_stop_pc, current_inferior ()->top_target ());
   if (func_addr != 0)
     method_stop_pc = func_addr;
 
@@ -1229,7 +1257,128 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
   return real_stop_pc;
 }
 
-/* Return nonzero if a type should be passed by reference.
+/* A member function is in one these states.  */
+
+enum definition_style
+{
+  DOES_NOT_EXIST_IN_SOURCE,
+  DEFAULTED_INSIDE,
+  DEFAULTED_OUTSIDE,
+  DELETED,
+  EXPLICIT,
+};
+
+/* Return how the given field is defined.  */
+
+static definition_style
+get_def_style (struct fn_field *fn, int fieldelem)
+{
+  if (TYPE_FN_FIELD_DELETED (fn, fieldelem))
+    return DELETED;
+
+  if (TYPE_FN_FIELD_ARTIFICIAL (fn, fieldelem))
+    return DOES_NOT_EXIST_IN_SOURCE;
+
+  switch (TYPE_FN_FIELD_DEFAULTED (fn, fieldelem))
+    {
+    case DW_DEFAULTED_no:
+      return EXPLICIT;
+    case DW_DEFAULTED_in_class:
+      return DEFAULTED_INSIDE;
+    case DW_DEFAULTED_out_of_class:
+      return DEFAULTED_OUTSIDE;
+    default:
+      break;
+    }
+
+  return EXPLICIT;
+}
+
+/* Helper functions to determine whether the given definition style
+   denotes that the definition is user-provided or implicit.
+   Being defaulted outside the class decl counts as an explicit
+   user-definition, while being defaulted inside is implicit.  */
+
+static bool
+is_user_provided_def (definition_style def)
+{
+  return def == EXPLICIT || def == DEFAULTED_OUTSIDE;
+}
+
+static bool
+is_implicit_def (definition_style def)
+{
+  return def == DOES_NOT_EXIST_IN_SOURCE || def == DEFAULTED_INSIDE;
+}
+
+/* Helper function to decide if METHOD_TYPE is a copy/move
+   constructor type for CLASS_TYPE.  EXPECTED is the expected
+   type code for the "right-hand-side" argument.
+   This function is supposed to be used by the IS_COPY_CONSTRUCTOR_TYPE
+   and IS_MOVE_CONSTRUCTOR_TYPE functions below.  Normally, you should
+   not need to call this directly.  */
+
+static bool
+is_copy_or_move_constructor_type (struct type *class_type,
+                                 struct type *method_type,
+                                 type_code expected)
+{
+  /* The method should take at least two arguments...  */
+  if (method_type->num_fields () < 2)
+    return false;
+
+  /* ...and the second argument should be the same as the class
+     type, with the expected type code...  */
+  struct type *arg_type = method_type->field (1).type ();
+
+  if (arg_type->code () != expected)
+    return false;
+
+  struct type *target = check_typedef (TYPE_TARGET_TYPE (arg_type));
+  if (!(class_types_same_p (target, class_type)))
+    return false;
+
+  /* ...and if any of the remaining arguments don't have a default value
+     then this is not a copy or move constructor, but just a
+     constructor.  */
+  for (int i = 2; i < method_type->num_fields (); i++)
+    {
+      arg_type = method_type->field (i).type ();
+      /* FIXME aktemur/2019-10-31: As of this date, neither
+        clang++-7.0.0 nor g++-8.2.0 produce a DW_AT_default_value
+        attribute.  GDB is also not set to read this attribute, yet.
+        Hence, we immediately return false if there are more than
+        2 parameters.
+        GCC bug link:
+        https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42959
+      */
+      return false;
+    }
+
+  return true;
+}
+
+/* Return true if METHOD_TYPE is a copy ctor type for CLASS_TYPE.  */
+
+static bool
+is_copy_constructor_type (struct type *class_type,
+                         struct type *method_type)
+{
+  return is_copy_or_move_constructor_type (class_type, method_type,
+                                          TYPE_CODE_REF);
+}
+
+/* Return true if METHOD_TYPE is a move ctor type for CLASS_TYPE.  */
+
+static bool
+is_move_constructor_type (struct type *class_type,
+                         struct type *method_type)
+{
+  return is_copy_or_move_constructor_type (class_type, method_type,
+                                          TYPE_CODE_RVALUE_REF);
+}
+
+/* Return pass-by-reference information for the given TYPE.
 
    The rule in the v3 ABI document comes from section 3.1.1.  If the
    type has a non-trivial copy constructor or destructor, then the
@@ -1237,32 +1386,59 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
    is one or perform the copy itself otherwise), pass the address of
    the copy, and then destroy the temporary (if necessary).
 
-   For return values with non-trivial copy constructors or
+   For return values with non-trivial copy/move constructors or
    destructors, space will be allocated in the caller, and a pointer
    will be passed as the first argument (preceding "this").
 
    We don't have a bulletproof mechanism for determining whether a
-   constructor or destructor is trivial.  For GCC and DWARF2 debug
-   information, we can check the artificial flag.
+   constructor or destructor is trivial.  For GCC and DWARF5 debug
+   information, we can check the calling_convention attribute,
+   the 'artificial' flag, the 'defaulted' attribute, and the
+   'deleted' attribute.  */
 
-   We don't do anything with the constructors or destructors,
-   but we have to get the argument passing right anyway.  */
-static int
+static struct language_pass_by_ref_info
 gnuv3_pass_by_reference (struct type *type)
 {
   int fieldnum, fieldelem;
 
   type = check_typedef (type);
 
+  /* Start with the default values.  */
+  struct language_pass_by_ref_info info;
+
+  bool has_cc_attr = false;
+  bool is_pass_by_value = false;
+  bool is_dynamic = false;
+  definition_style cctor_def = DOES_NOT_EXIST_IN_SOURCE;
+  definition_style dtor_def = DOES_NOT_EXIST_IN_SOURCE;
+  definition_style mctor_def = DOES_NOT_EXIST_IN_SOURCE;
+
   /* We're only interested in things that can have methods.  */
-  if (TYPE_CODE (type) != TYPE_CODE_STRUCT
-      && TYPE_CODE (type) != TYPE_CODE_UNION)
-    return 0;
+  if (type->code () != TYPE_CODE_STRUCT
+      && type->code () != TYPE_CODE_UNION)
+    return info;
+
+  /* The compiler may have emitted the calling convention attribute.
+     Note: GCC does not produce this attribute as of version 9.2.1.
+     Bug link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92418  */
+  if (TYPE_CPLUS_CALLING_CONVENTION (type) == DW_CC_pass_by_value)
+    {
+      has_cc_attr = true;
+      is_pass_by_value = true;
+      /* Do not return immediately.  We have to find out if this type
+        is copy_constructible and destructible.  */
+    }
+
+  if (TYPE_CPLUS_CALLING_CONVENTION (type) == DW_CC_pass_by_reference)
+    {
+      has_cc_attr = true;
+      is_pass_by_value = false;
+    }
 
   /* A dynamic class has a non-trivial copy constructor.
      See c++98 section 12.8 Copying class objects [class.copy].  */
   if (gnuv3_dynamic_class (type))
-    return 1;
+    is_dynamic = true;
 
   for (fieldnum = 0; fieldnum < TYPE_NFN_FIELDS (type); fieldnum++)
     for (fieldelem = 0; fieldelem < TYPE_FN_FIELDLIST_LENGTH (type, fieldnum);
@@ -1272,44 +1448,75 @@ gnuv3_pass_by_reference (struct type *type)
        const char *name = TYPE_FN_FIELDLIST_NAME (type, fieldnum);
        struct type *fieldtype = TYPE_FN_FIELD_TYPE (fn, fieldelem);
 
-       /* If this function is marked as artificial, it is compiler-generated,
-          and we assume it is trivial.  */
-       if (TYPE_FN_FIELD_ARTIFICIAL (fn, fieldelem))
-         continue;
-
-       /* If we've found a destructor, we must pass this by reference.  */
        if (name[0] == '~')
-         return 1;
-
-       /* If the mangled name of this method doesn't indicate that it
-          is a constructor, we're not interested.
-
-          FIXME drow/2007-09-23: We could do this using the name of
-          the method and the name of the class instead of dealing
-          with the mangled name.  We don't have a convenient function
-          to strip off both leading scope qualifiers and trailing
-          template arguments yet.  */
-       if (!is_constructor_name (TYPE_FN_FIELD_PHYSNAME (fn, fieldelem))
-           && !TYPE_FN_FIELD_CONSTRUCTOR (fn, fieldelem))
-         continue;
-
-       /* If this method takes two arguments, and the second argument is
-          a reference to this class, then it is a copy constructor.  */
-       if (TYPE_NFIELDS (fieldtype) == 2)
          {
-           struct type *arg_type = TYPE_FIELD_TYPE (fieldtype, 1);
-
-           if (TYPE_CODE (arg_type) == TYPE_CODE_REF)
+           /* We've found a destructor.
+              There should be at most one dtor definition.  */
+           gdb_assert (dtor_def == DOES_NOT_EXIST_IN_SOURCE);
+           dtor_def = get_def_style (fn, fieldelem);
+         }
+       else if (is_constructor_name (TYPE_FN_FIELD_PHYSNAME (fn, fieldelem))
+                || TYPE_FN_FIELD_CONSTRUCTOR (fn, fieldelem))
+         {
+           /* FIXME drow/2007-09-23: We could do this using the name of
+              the method and the name of the class instead of dealing
+              with the mangled name.  We don't have a convenient function
+              to strip off both leading scope qualifiers and trailing
+              template arguments yet.  */
+           if (is_copy_constructor_type (type, fieldtype))
              {
-               struct type *arg_target_type;
-
-               arg_target_type = check_typedef (TYPE_TARGET_TYPE (arg_type));
-               if (class_types_same_p (arg_target_type, type))
-                 return 1;
+               /* There may be more than one cctors.  E.g.: one that
+                  take a const parameter and another that takes a
+                  non-const parameter.  Such as:
+
+                  class K {
+                    K (const K &k)...
+                    K (K &k)...
+                  };
+
+                  It is sufficient for the type to be non-trivial
+                  even only one of the cctors is explicit.
+                  Therefore, update the cctor_def value in the
+                  implicit -> explicit direction, not backwards.  */
+
+               if (is_implicit_def (cctor_def))
+                 cctor_def = get_def_style (fn, fieldelem);
+             }
+           else if (is_move_constructor_type (type, fieldtype))
+             {
+               /* Again, there may be multiple move ctors.  Update the
+                  mctor_def value if we found an explicit def and the
+                  existing one is not explicit.  Otherwise retain the
+                  existing value.  */
+               if (is_implicit_def (mctor_def))
+                 mctor_def = get_def_style (fn, fieldelem);
              }
          }
       }
 
+  bool cctor_implicitly_deleted
+    = (mctor_def != DOES_NOT_EXIST_IN_SOURCE
+       && cctor_def == DOES_NOT_EXIST_IN_SOURCE);
+
+  bool cctor_explicitly_deleted = (cctor_def == DELETED);
+
+  if (cctor_implicitly_deleted || cctor_explicitly_deleted)
+    info.copy_constructible = false;
+
+  if (dtor_def == DELETED)
+    info.destructible = false;
+
+  info.trivially_destructible = is_implicit_def (dtor_def);
+
+  info.trivially_copy_constructible
+    = (is_implicit_def (cctor_def)
+       && !is_dynamic);
+
+  info.trivially_copyable
+    = (info.trivially_copy_constructible
+       && info.trivially_destructible
+       && !is_user_provided_def (mctor_def));
+
   /* Even if all the constructors and destructors were artificial, one
      of them may have invoked a non-artificial constructor or
      destructor in a base class.  If any base class needs to be passed
@@ -1317,12 +1524,39 @@ gnuv3_pass_by_reference (struct type *type)
      are constructed whenever this class is.  We do not need to worry
      about recursive loops here, since we are only looking at members
      of complete class type.  Also ignore any static members.  */
-  for (fieldnum = 0; fieldnum < TYPE_NFIELDS (type); fieldnum++)
-    if (! field_is_static (&TYPE_FIELD (type, fieldnum))
-        && gnuv3_pass_by_reference (TYPE_FIELD_TYPE (type, fieldnum)))
-      return 1;
+  for (fieldnum = 0; fieldnum < type->num_fields (); fieldnum++)
+    if (!field_is_static (&type->field (fieldnum)))
+      {
+       struct type *field_type = type->field (fieldnum).type ();
+
+       /* For arrays, make the decision based on the element type.  */
+       if (field_type->code () == TYPE_CODE_ARRAY)
+         field_type = check_typedef (TYPE_TARGET_TYPE (field_type));
+
+       struct language_pass_by_ref_info field_info
+         = gnuv3_pass_by_reference (field_type);
+
+       if (!field_info.copy_constructible)
+         info.copy_constructible = false;
+       if (!field_info.destructible)
+         info.destructible = false;
+       if (!field_info.trivially_copyable)
+         info.trivially_copyable = false;
+       if (!field_info.trivially_copy_constructible)
+         info.trivially_copy_constructible = false;
+       if (!field_info.trivially_destructible)
+         info.trivially_destructible = false;
+      }
 
-  return 0;
+  /* Consistency check.  */
+  if (has_cc_attr && info.trivially_copyable != is_pass_by_value)
+    {
+      /* DWARF CC attribute is not the same as the inferred value;
+        use the DWARF attribute.  */
+      info.trivially_copyable = is_pass_by_value;
+    }
+
+  return info;
 }
 
 static void
@@ -1359,8 +1593,9 @@ init_gnuv3_ops (void)
   gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference;
 }
 
+void _initialize_gnu_v3_abi ();
 void
-_initialize_gnu_v3_abi (void)
+_initialize_gnu_v3_abi ()
 {
   init_gnuv3_ops ();
 
This page took 0.035226 seconds and 4 git commands to generate.