public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Handle pointers and references correctly in DAP
@ 2023-09-05 19:47 Tom Tromey
  2023-09-05 19:47 ` [PATCH 1/5] Pass a type allocator to init_fixed_point_type Tom Tromey
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Tom Tromey @ 2023-09-05 19:47 UTC (permalink / raw)
  To: gdb-patches

This series started off as a simple implementation of a no-op
pretty-printer to handle pointers and references in DAP.

However, this regressed a test, and I realized that the new
is-array-like and is-string-like code should be generalized to work
with any language.

This is done by associating a language with each type, which meant
touching every debug reader, plus a few minor preliminary cleanups.

Regression tested on x86-64 Fedora 36.

---
Tom Tromey (5):
      Pass a type allocator to init_fixed_point_type
      Regularize some DWARF type initialization
      Add is_array_like and to_array to language_defn
      Give a language to a type
      Handle pointers and references correctly in DAP

 gdb/ada-lang.c                   |  13 +++++
 gdb/coffread.c                   |   4 +-
 gdb/ctfread.c                    |  17 ++++---
 gdb/dwarf2/read.c                |  89 +++++++++++++++++----------------
 gdb/gdbtypes.c                   |  31 ++++++------
 gdb/gdbtypes.h                   |  37 ++++++++------
 gdb/language.h                   |  11 +++++
 gdb/mdebugread.c                 |   9 ++--
 gdb/python/lib/gdb/printing.py   |  16 ++++++
 gdb/python/py-type.c             |  13 ++---
 gdb/rust-lang.h                  |  10 ++++
 gdb/stabsread.c                  |  20 ++++----
 gdb/testsuite/gdb.dap/ptrref.cc  |  34 +++++++++++++
 gdb/testsuite/gdb.dap/ptrref.exp | 103 +++++++++++++++++++++++++++++++++++++++
 gdb/valarith.c                   |   6 +--
 15 files changed, 303 insertions(+), 110 deletions(-)
---
base-commit: a006bc9c37e95b4afaf85715cc54fe57b3300ccd
change-id: 20230905-dap-30821-pointers-6b62c5cb8a9f

Best regards,
-- 
Tom Tromey <tromey@adacore.com>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] Pass a type allocator to init_fixed_point_type
  2023-09-05 19:47 [PATCH 0/5] Handle pointers and references correctly in DAP Tom Tromey
@ 2023-09-05 19:47 ` Tom Tromey
  2023-09-05 19:47 ` [PATCH 2/5] Regularize some DWARF type initialization Tom Tromey
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2023-09-05 19:47 UTC (permalink / raw)
  To: gdb-patches

init_fixed_point_type currently takes an objfile and creates its own
type allocator.  However, for a later patch it is more convenient if
this function accepts a type allocator.  This patch makes this change.
---
 gdb/dwarf2/read.c | 4 ++--
 gdb/gdbtypes.c    | 4 ++--
 gdb/gdbtypes.h    | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 98bedbc5d49..2335bbe0aba 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -15380,11 +15380,11 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
 	}
 	break;
       case DW_ATE_signed_fixed:
-	type = init_fixed_point_type (objfile, bits, 0, name);
+	type = init_fixed_point_type (alloc, bits, 0, name);
 	finish_fixed_point_type (type, gnat_encoding_suffix, die, cu);
 	break;
       case DW_ATE_unsigned_fixed:
-	type = init_fixed_point_type (objfile, bits, 1, name);
+	type = init_fixed_point_type (alloc, bits, 1, name);
 	finish_fixed_point_type (type, gnat_encoding_suffix, die, cu);
 	break;
 
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index c9322108299..667b4e34a24 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -3498,12 +3498,12 @@ init_pointer_type (type_allocator &alloc,
    NAME is the type name.  */
 
 struct type *
-init_fixed_point_type (struct objfile *objfile,
+init_fixed_point_type (type_allocator &alloc,
 		       int bit, int unsigned_p, const char *name)
 {
   struct type *t;
 
-  t = type_allocator (objfile).new_type (TYPE_CODE_FIXED_POINT, bit, name);
+  t = alloc.new_type (TYPE_CODE_FIXED_POINT, bit, name);
   if (unsigned_p)
     t->set_is_unsigned (true);
 
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index f667b10ec7d..df94e952c1f 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -2379,7 +2379,7 @@ extern struct type *init_pointer_type (type_allocator &alloc, int bit,
 				       const char *name,
 				       struct type *target_type);
 
-extern struct type *init_fixed_point_type (struct objfile *, int, int,
+extern struct type *init_fixed_point_type (type_allocator &, int, int,
 					   const char *);
 
 /* Helper functions to construct a struct or record type.  An

-- 
2.40.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/5] Regularize some DWARF type initialization
  2023-09-05 19:47 [PATCH 0/5] Handle pointers and references correctly in DAP Tom Tromey
  2023-09-05 19:47 ` [PATCH 1/5] Pass a type allocator to init_fixed_point_type Tom Tromey
@ 2023-09-05 19:47 ` Tom Tromey
  2023-09-05 19:47 ` [PATCH 3/5] Add is_array_like and to_array to language_defn Tom Tromey
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2023-09-05 19:47 UTC (permalink / raw)
  To: gdb-patches

In one spot, it will be convenient for a subsequent patch if the CU is
passed to a type-creation helper function.  In another spot, remove
the redundant 'objfile' parameter to another such function.
---
 gdb/dwarf2/read.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 2335bbe0aba..63a2a83f0a2 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -15090,9 +15090,10 @@ gnat_encoded_fixed_point_type_info (const char *name)
    it to guess the correct format if necessary.  */
 
 static struct type *
-dwarf2_init_float_type (struct objfile *objfile, int bits, const char *name,
+dwarf2_init_float_type (struct dwarf2_cu *cu, int bits, const char *name,
 			const char *name_hint, enum bfd_endian byte_order)
 {
+  struct objfile *objfile = cu->per_objfile->objfile;
   struct gdbarch *gdbarch = objfile->arch ();
   const struct floatformat **format;
   struct type *type;
@@ -15110,10 +15111,11 @@ dwarf2_init_float_type (struct objfile *objfile, int bits, const char *name,
 /* Allocate an integer type of size BITS and name NAME.  */
 
 static struct type *
-dwarf2_init_integer_type (struct dwarf2_cu *cu, struct objfile *objfile,
-			  int bits, int unsigned_p, const char *name)
+dwarf2_init_integer_type (struct dwarf2_cu *cu, int bits, int unsigned_p,
+			  const char *name)
 {
   struct type *type;
+  struct objfile *objfile = cu->per_objfile->objfile;
 
   /* Versions of Intel's C Compiler generate an integer type called "void"
      instead of using DW_TAG_unspecified_type.  This has been seen on
@@ -15167,10 +15169,10 @@ has_zero_over_zero_small_attribute (struct die_info *die,
    component.  */
 static struct type *
 dwarf2_init_complex_target_type (struct dwarf2_cu *cu,
-				 struct objfile *objfile,
 				 int bits, const char *name_hint,
 				 enum bfd_endian byte_order)
 {
+  struct objfile *objfile = cu->per_objfile->objfile;
   gdbarch *gdbarch = objfile->arch ();
   struct type *tt = nullptr;
 
@@ -15218,7 +15220,7 @@ dwarf2_init_complex_target_type (struct dwarf2_cu *cu,
     tt = nullptr;
 
   const char *name = (tt == nullptr) ? nullptr : tt->name ();
-  return dwarf2_init_float_type (objfile, bits, name, name_hint, byte_order);
+  return dwarf2_init_float_type (cu, bits, name, name_hint, byte_order);
 }
 
 /* Find a representation of a given base type and install
@@ -15321,7 +15323,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
 	type = init_boolean_type (alloc, bits, 1, name);
 	break;
       case DW_ATE_complex_float:
-	type = dwarf2_init_complex_target_type (cu, objfile, bits / 2, name,
+	type = dwarf2_init_complex_target_type (cu, bits / 2, name,
 						byte_order);
 	if (type->code () == TYPE_CODE_ERROR)
 	  {
@@ -15341,10 +15343,10 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
 	type = init_decfloat_type (alloc, bits, name);
 	break;
       case DW_ATE_float:
-	type = dwarf2_init_float_type (objfile, bits, name, name, byte_order);
+	type = dwarf2_init_float_type (cu, bits, name, name, byte_order);
 	break;
       case DW_ATE_signed:
-	type = dwarf2_init_integer_type (cu, objfile, bits, 0, name);
+	type = dwarf2_init_integer_type (cu, bits, 0, name);
 	break;
       case DW_ATE_unsigned:
 	if (cu->lang () == language_fortran
@@ -15352,7 +15354,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
 	    && startswith (name, "character("))
 	  type = init_character_type (alloc, bits, 1, name);
 	else
-	  type = dwarf2_init_integer_type (cu, objfile, bits, 1, name);
+	  type = dwarf2_init_integer_type (cu, bits, 1, name);
 	break;
       case DW_ATE_signed_char:
 	if (cu->lang () == language_ada
@@ -15361,7 +15363,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
 	    || cu->lang () == language_fortran)
 	  type = init_character_type (alloc, bits, 0, name);
 	else
-	  type = dwarf2_init_integer_type (cu, objfile, bits, 0, name);
+	  type = dwarf2_init_integer_type (cu, bits, 0, name);
 	break;
       case DW_ATE_unsigned_char:
 	if (cu->lang () == language_ada
@@ -15371,7 +15373,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
 	    || cu->lang () == language_rust)
 	  type = init_character_type (alloc, bits, 1, name);
 	else
-	  type = dwarf2_init_integer_type (cu, objfile, bits, 1, name);
+	  type = dwarf2_init_integer_type (cu, bits, 1, name);
 	break;
       case DW_ATE_UTF:
 	{

-- 
2.40.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/5] Add is_array_like and to_array to language_defn
  2023-09-05 19:47 [PATCH 0/5] Handle pointers and references correctly in DAP Tom Tromey
  2023-09-05 19:47 ` [PATCH 1/5] Pass a type allocator to init_fixed_point_type Tom Tromey
  2023-09-05 19:47 ` [PATCH 2/5] Regularize some DWARF type initialization Tom Tromey
@ 2023-09-05 19:47 ` Tom Tromey
  2023-09-05 19:47 ` [PATCH 4/5] Give a language to a type Tom Tromey
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2023-09-05 19:47 UTC (permalink / raw)
  To: gdb-patches

This adds new is_array_like and to_array methods to language_defn.
This will be used in a subsequent patch that generalizes the new
Python array- and string-handling code.
---
 gdb/ada-lang.c  | 13 +++++++++++++
 gdb/language.h  | 11 +++++++++++
 gdb/rust-lang.h | 10 ++++++++++
 3 files changed, 34 insertions(+)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index c0cc512bfa3..b03ed53d11c 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13810,6 +13810,19 @@ class ada_language : public language_defn
 
   /* See language.h.  */
 
+  bool is_array_like (struct type *type) const override
+  {
+    return (ada_is_constrained_packed_array_type (type)
+	    || ada_is_array_descriptor_type (type));
+  }
+
+  /* See language.h.  */
+
+  struct value *to_array (struct value *val) const override
+  { return ada_coerce_to_simple_array (val); }
+
+  /* See language.h.  */
+
   const char *struct_too_deep_ellipsis () const override
   { return "(...)"; }
 
diff --git a/gdb/language.h b/gdb/language.h
index 9fd2fb6f387..6ee8f6160e1 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -568,6 +568,17 @@ struct language_defn
   /* Return true if TYPE is a string type.  */
   virtual bool is_string_type_p (struct type *type) const;
 
+  /* Return true if TYPE is array-like.  */
+  virtual bool is_array_like (struct type *type) const
+  { return false; }
+
+  /* Underlying implementation of value_to_array.  Return a value of
+     array type that corresponds to VAL.  The caller must ensure that
+     is_array_like is true for VAL's type.  Return nullptr if the type
+     cannot be handled.  */
+  virtual struct value *to_array (struct value *val) const
+  { return nullptr; }
+
   /* Return a string that is used by the 'set print max-depth' setting.
      When GDB replaces a struct or union (during value printing) that is
      "too deep" this string is displayed instead.  The default value here
diff --git a/gdb/rust-lang.h b/gdb/rust-lang.h
index 2c7ccb93bcf..ce1dff211b6 100644
--- a/gdb/rust-lang.h
+++ b/gdb/rust-lang.h
@@ -196,6 +196,16 @@ class rust_language : public language_defn
 
   /* See language.h.  */
 
+  bool is_array_like (struct type *type) const override
+  { return rust_slice_type_p (type); }
+
+  /* See language.h.  */
+
+  struct value *to_array (struct value *val) const override
+  { return rust_slice_to_array (val); }
+
+  /* See language.h.  */
+
   bool range_checking_on_by_default () const override
   { return true; }
 

-- 
2.40.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 4/5] Give a language to a type
  2023-09-05 19:47 [PATCH 0/5] Handle pointers and references correctly in DAP Tom Tromey
                   ` (2 preceding siblings ...)
  2023-09-05 19:47 ` [PATCH 3/5] Add is_array_like and to_array to language_defn Tom Tromey
@ 2023-09-05 19:47 ` Tom Tromey
  2023-09-05 19:47 ` [PATCH 5/5] Handle pointers and references correctly in DAP Tom Tromey
  2023-09-19 19:30 ` [PATCH 0/5] " Tom Tromey
  5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2023-09-05 19:47 UTC (permalink / raw)
  To: gdb-patches

This changes main_type to hold a language, and updates the debug
readers to set this field.  This is done by adding the language to the
type-allocator object.

Note that the non-DWARF readers are changed on a "best effort" basis.

This patch also reimplements type::is_array_like to use the type's
language, and it adds a new type::is_string_like as well.  This in
turn lets us change the Python implementation of these methods to
simply defer to the type.
---
 gdb/coffread.c       |  4 ++--
 gdb/ctfread.c        | 17 ++++++++-------
 gdb/dwarf2/read.c    | 61 +++++++++++++++++++++++++---------------------------
 gdb/gdbtypes.c       | 27 ++++++++++++-----------
 gdb/gdbtypes.h       | 35 +++++++++++++++++++-----------
 gdb/mdebugread.c     |  9 ++++----
 gdb/python/py-type.c | 13 ++++-------
 gdb/stabsread.c      | 20 +++++++++--------
 gdb/valarith.c       |  6 ++----
 9 files changed, 98 insertions(+), 94 deletions(-)

diff --git a/gdb/coffread.c b/gdb/coffread.c
index e432693600e..fe905e73964 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -354,7 +354,7 @@ coff_alloc_type (int index)
      We will fill it in later if we find out how.  */
   if (type == NULL)
     {
-      type = type_allocator (coffread_objfile).new_type ();
+      type = type_allocator (coffread_objfile, language_c).new_type ();
       *type_addr = type;
     }
   return type;
@@ -1763,7 +1763,7 @@ decode_type (struct coff_symbol *cs, unsigned int c_type,
 
 	  base_type = decode_type (cs, new_c_type, aux, objfile);
 	  index_type = builtin_type (objfile)->builtin_int;
-	  type_allocator alloc (objfile);
+	  type_allocator alloc (objfile, language_c);
 	  range_type
 	    = create_static_range_type (alloc, index_type, 0, n - 1);
 	  type = create_array_type (alloc, base_type, range_type);
diff --git a/gdb/ctfread.c b/gdb/ctfread.c
index c04b043d6d3..c74ec044c18 100644
--- a/gdb/ctfread.c
+++ b/gdb/ctfread.c
@@ -370,7 +370,7 @@ ctf_init_float_type (struct objfile *objfile,
   const struct floatformat **format;
   struct type *type;
 
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, language_c);
   format = gdbarch_floatformat_for_type (gdbarch, name_hint, bits);
   if (format != nullptr)
     type = init_float_type (alloc, bits, name, format);
@@ -553,7 +553,7 @@ read_base_type (struct ctf_context *ccp, ctf_id_t tid)
 		   ctf_errmsg (ctf_errno (fp)));
     }
 
-  type_allocator alloc (of);
+  type_allocator alloc (of, language_c);
   kind = ctf_type_kind (fp, tid);
   if (kind == CTF_K_INTEGER)
     {
@@ -629,7 +629,7 @@ read_structure_type (struct ctf_context *ccp, ctf_id_t tid)
   struct type *type;
   uint32_t kind;
 
-  type = type_allocator (of).new_type ();
+  type = type_allocator (of, language_c).new_type ();
 
   const char *name = ctf_type_name_raw (fp, tid);
   if (name != nullptr && strlen (name) != 0)
@@ -688,7 +688,7 @@ read_func_kind_type (struct ctf_context *ccp, ctf_id_t tid)
   ctf_funcinfo_t cfi;
   uint32_t argc;
 
-  type = type_allocator (of).new_type ();
+  type = type_allocator (of, language_c).new_type ();
 
   type->set_code (TYPE_CODE_FUNC);
   if (ctf_func_type_info (fp, tid, &cfi) < 0)
@@ -739,7 +739,7 @@ read_enum_type (struct ctf_context *ccp, ctf_id_t tid)
   ctf_dict_t *fp = ccp->fp;
   struct type *type;
 
-  type = type_allocator (of).new_type ();
+  type = type_allocator (of, language_c).new_type ();
 
   const char *name = ctf_type_name_raw (fp, tid);
   if (name != nullptr && strlen (name) != 0)
@@ -828,7 +828,7 @@ read_array_type (struct ctf_context *ccp, ctf_id_t tid)
   if (idx_type == nullptr)
     idx_type = builtin_type (objfile)->builtin_int;
 
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, language_c);
   range_type = create_static_range_type (alloc, idx_type, 0, ar.ctr_nelems - 1);
   type = create_array_type (alloc, element_type, range_type);
   if (ar.ctr_nelems <= 1)	/* Check if undefined upper bound.  */
@@ -928,7 +928,8 @@ read_typedef_type (struct ctf_context *ccp, ctf_id_t tid,
   struct type *this_type, *target_type;
 
   char *aname = obstack_strdup (&objfile->objfile_obstack, name);
-  this_type = type_allocator (objfile).new_type (TYPE_CODE_TYPEDEF, 0, aname);
+  this_type = type_allocator (objfile, language_c).new_type (TYPE_CODE_TYPEDEF,
+							     0, aname);
   set_tid_type (objfile, tid, this_type);
   target_type = fetch_tid_type (ccp, btid);
   if (target_type != this_type)
@@ -976,7 +977,7 @@ read_forward_type (struct ctf_context *ccp, ctf_id_t tid)
   struct type *type;
   uint32_t kind;
 
-  type = type_allocator (of).new_type ();
+  type = type_allocator (of, language_c).new_type ();
 
   const char *name = ctf_type_name_raw (fp, tid);
   if (name != nullptr && strlen (name) != 0)
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 63a2a83f0a2..99a31407a0a 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -5890,8 +5890,8 @@ fixup_go_packaging (struct dwarf2_cu *cu)
       struct objfile *objfile = cu->per_objfile->objfile;
       const char *saved_package_name = objfile->intern (package_name.get ());
       struct type *type
-	= type_allocator (objfile).new_type (TYPE_CODE_MODULE, 0,
-					     saved_package_name);
+	= type_allocator (objfile, cu->lang ()).new_type (TYPE_CODE_MODULE, 0,
+							  saved_package_name);
       struct symbol *sym;
 
       sym = new (&objfile->objfile_obstack) symbol;
@@ -6077,8 +6077,8 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
 	= rust_fully_qualify (&objfile->objfile_obstack, type->name (),
 			      name);
       struct type *dataless_type
-	= type_allocator (objfile).new_type (TYPE_CODE_VOID, 0,
-					     dataless_name);
+	= type_allocator (type).new_type (TYPE_CODE_VOID, 0,
+					  dataless_name);
       type->field (2).set_type (dataless_type);
       /* NAME points into the original discriminant name, which
 	 already has the correct lifetime.  */
@@ -12215,7 +12215,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
       fnp->physname = physname ? physname : "";
     }
 
-  fnp->type = type_allocator (objfile).new_type ();
+  fnp->type = type_allocator (objfile, cu->lang ()).new_type ();
   this_type = read_type_die (die, cu);
   if (this_type && this_type->code () == TYPE_CODE_FUNC)
     {
@@ -12446,7 +12446,7 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
     return;
 
   self_type = pfn_type->field (0).type ()->target_type ();
-  new_type = type_allocator (objfile).new_type ();
+  new_type = type_allocator (type).new_type ();
   smash_to_method_type (new_type, self_type, pfn_type->target_type (),
 			pfn_type->fields (), pfn_type->num_fields (),
 			pfn_type->has_varargs ());
@@ -12680,15 +12680,8 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
       return set_die_type (die, type, cu);
     }
 
-  type = type_allocator (objfile).new_type ();
-  if (cu->lang () == language_rust)
-    {
-      /* This is currently only needed for types that might be
-	 slices.  */
-      INIT_RUST_SPECIFIC (type);
-    }
-  else
-    INIT_CPLUS_SPECIFIC (type);
+  type = type_allocator (objfile, cu->lang ()).new_type ();
+  INIT_CPLUS_SPECIFIC (type);
 
   name = dwarf2_name (die, cu);
   if (name != NULL)
@@ -13291,7 +13284,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
       return set_die_type (die, type, cu);
     }
 
-  type = type_allocator (objfile).new_type ();
+  type = type_allocator (objfile, cu->lang ()).new_type ();
 
   type->set_code (TYPE_CODE_ENUM);
   name = dwarf2_full_name (NULL, die, cu);
@@ -13621,7 +13614,7 @@ quirk_ada_thick_pointer (struct die_info *die, struct dwarf2_cu *cu,
       range_fields[i + 1].set_name (objfile->intern (name));
     }
 
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, cu->lang ());
   struct type *bounds = alloc.new_type ();
   bounds->set_code (TYPE_CODE_STRUCT);
 
@@ -13645,7 +13638,7 @@ quirk_ada_thick_pointer (struct die_info *die, struct dwarf2_cu *cu,
       iter = iter->target_type ();
     }
 
-  struct type *result = type_allocator (objfile).new_type ();
+  struct type *result = type_allocator (objfile, cu->lang ()).new_type ();
   result->set_code (TYPE_CODE_STRUCT);
 
   result->alloc_fields (2);
@@ -13722,7 +13715,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   if (die->child == NULL)
     {
       index_type = builtin_type (objfile)->builtin_int;
-      type_allocator alloc (objfile);
+      type_allocator alloc (objfile, cu->lang ());
       range_type = create_static_range_type (alloc, index_type, 0, -1);
       type = create_array_type_with_stride (alloc, element_type, range_type,
 					    byte_stride_prop, bit_stride);
@@ -13761,7 +13754,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
 
   type = element_type;
 
-  type_allocator alloc (cu->per_objfile->objfile);
+  type_allocator alloc (cu->per_objfile->objfile, cu->lang ());
   if (read_array_order (die, cu) == DW_ORD_col_major)
     {
       int i = 0;
@@ -13891,7 +13884,7 @@ read_set_type (struct die_info *die, struct dwarf2_cu *cu)
   if (set_type)
     return set_type;
 
-  type_allocator alloc (cu->per_objfile->objfile);
+  type_allocator alloc (cu->per_objfile->objfile, cu->lang ());
   set_type = create_set_type (alloc, domain_type);
 
   attr = dwarf2_attr (die, DW_AT_byte_size, cu);
@@ -14111,7 +14104,8 @@ read_namespace_type (struct die_info *die, struct dwarf2_cu *cu)
 			    previous_prefix, name, 0, cu);
 
   /* Create the type.  */
-  type = type_allocator (objfile).new_type (TYPE_CODE_NAMESPACE, 0, name);
+  type = type_allocator (objfile, cu->lang ()).new_type (TYPE_CODE_NAMESPACE,
+							 0, name);
 
   return set_die_type (die, type, cu);
 }
@@ -14173,7 +14167,8 @@ read_module_type (struct die_info *die, struct dwarf2_cu *cu)
   struct type *type;
 
   module_name = dwarf2_name (die, cu);
-  type = type_allocator (objfile).new_type (TYPE_CODE_MODULE, 0, module_name);
+  type = type_allocator (objfile, cu->lang ()).new_type (TYPE_CODE_MODULE,
+							 0, module_name);
 
   return set_die_type (die, type, cu);
 }
@@ -14328,7 +14323,7 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
   else if (check_typedef (to_type)->code () == TYPE_CODE_FUNC)
     {
       struct type *new_type
-	= type_allocator (cu->per_objfile->objfile).new_type ();
+	= type_allocator (cu->per_objfile->objfile, cu->lang ()).new_type ();
 
       smash_to_method_type (new_type, domain, to_type->target_type (),
 			    to_type->fields (), to_type->num_fields (),
@@ -14566,7 +14561,7 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
     }
 
   index_type = builtin_type (objfile)->builtin_int;
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, cu->lang ());
   if (length_is_constant)
     range_type = create_static_range_type (alloc, index_type, 1, length);
   else
@@ -14787,7 +14782,8 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
       return this_type;
     }
 
-  this_type = type_allocator (objfile).new_type (TYPE_CODE_TYPEDEF, 0, name);
+  type_allocator alloc (objfile, cu->lang ());
+  this_type = alloc.new_type (TYPE_CODE_TYPEDEF, 0, name);
   this_type->set_target_is_stub (true);
   set_die_type (die, this_type, cu);
   if (target_type != this_type)
@@ -15098,7 +15094,7 @@ dwarf2_init_float_type (struct dwarf2_cu *cu, int bits, const char *name,
   const struct floatformat **format;
   struct type *type;
 
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, cu->lang ());
   format = gdbarch_floatformat_for_type (gdbarch, name_hint, bits);
   if (format)
     type = init_float_type (alloc, bits, name, format, byte_order);
@@ -15125,7 +15121,7 @@ dwarf2_init_integer_type (struct dwarf2_cu *cu, int bits, int unsigned_p,
     type = builtin_type (objfile)->builtin_void;
   else
     {
-      type_allocator alloc (objfile);
+      type_allocator alloc (objfile, cu->lang ());
       type = init_integer_type (alloc, bits, unsigned_p, name);
     }
 
@@ -15311,7 +15307,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
 	}
     }
 
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, cu->lang ());
   switch (encoding)
     {
       case DW_ATE_address:
@@ -15800,7 +15796,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
 	}
     }
 
-  type_allocator alloc (cu->per_objfile->objfile);
+  type_allocator alloc (cu->per_objfile->objfile, cu->lang ());
   if (attr_byte_stride != nullptr
       || attr_bit_stride != nullptr)
     {
@@ -15845,7 +15841,7 @@ read_unspecified_type (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct type *type;
 
-  type = (type_allocator (cu->per_objfile->objfile)
+  type = (type_allocator (cu->per_objfile->objfile, cu->lang ())
 	  .new_type (TYPE_CODE_VOID, 0, nullptr));
   type->set_name (dwarf2_name (die, cu));
 
@@ -19706,7 +19702,8 @@ build_error_marker_type (struct dwarf2_cu *cu, struct die_info *die)
 		     sect_offset_str (die->sect_off));
   saved = obstack_strdup (&objfile->objfile_obstack, message);
 
-  return type_allocator (objfile).new_type (TYPE_CODE_ERROR, 0, saved);
+  return type_allocator (objfile, cu->lang ()).new_type (TYPE_CODE_ERROR,
+							 0, saved);
 }
 
 /* Look up the type of DIE in CU using its type attribute ATTR.
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 667b4e34a24..7011fddd695 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -217,6 +217,7 @@ type_allocator::new_type ()
   /* Alloc the structure and start off with all fields zeroed.  */
   struct type *type = OBSTACK_ZALLOC (obstack, struct type);
   TYPE_MAIN_TYPE (type) = OBSTACK_ZALLOC (obstack, struct main_type);
+  TYPE_MAIN_TYPE (type)->m_lang = m_lang;
 
   if (m_is_objfile)
     {
@@ -5385,10 +5386,6 @@ recursive_dump_type (struct type *type, int spaces)
       print_gnat_stuff (type, spaces);
       break;
 
-    case TYPE_SPECIFIC_RUST_STUFF:
-      gdb_printf ("%*srust\n", spaces, "");
-      break;
-
     case TYPE_SPECIFIC_FLOATFORMAT:
       gdb_printf ("%*sfloatformat ", spaces, "");
       if (TYPE_FLOATFORMAT (type) == NULL
@@ -5629,9 +5626,6 @@ copy_type_recursive (struct type *type, htab_t copied_types)
     case TYPE_SPECIFIC_GNAT_STUFF:
       INIT_GNAT_SPECIFIC (new_type);
       break;
-    case TYPE_SPECIFIC_RUST_STUFF:
-      INIT_RUST_SPECIFIC (new_type);
-      break;
     case TYPE_SPECIFIC_SELF_TYPE:
       set_type_self_type (new_type,
 			  copy_type_recursive (TYPE_SELF_TYPE (type),
@@ -5948,17 +5942,24 @@ type::copy_fields (std::vector<struct field> &src)
   memcpy (this->fields (), src.data (), size);
 }
 
+/* See gdbtypes.h.  */
+
+bool
+type::is_string_like ()
+{
+  const language_defn *defn = language_def (this->language ());
+  return defn->is_string_type_p (this);
+}
+
+/* See gdbtypes.h.  */
+
 bool
 type::is_array_like ()
 {
   if (code () == TYPE_CODE_ARRAY)
     return true;
-  if (HAVE_GNAT_AUX_INFO (this))
-    return (ada_is_constrained_packed_array_type (this)
-	    || ada_is_array_descriptor_type (this));
-  if (HAVE_RUST_SPECIFIC (this))
-    return rust_slice_type_p (this);
-  return false;
+  const language_defn *defn = language_def (this->language ());
+  return defn->is_array_like (this);
 }
 
 \f
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index df94e952c1f..505c8ba12b5 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -501,7 +501,6 @@ enum type_specific_kind
   TYPE_SPECIFIC_NONE,
   TYPE_SPECIFIC_CPLUS_STUFF,
   TYPE_SPECIFIC_GNAT_STUFF,
-  TYPE_SPECIFIC_RUST_STUFF,
   TYPE_SPECIFIC_FLOATFORMAT,
   /* Note: This is used by TYPE_CODE_FUNC and TYPE_CODE_METHOD.  */
   TYPE_SPECIFIC_FUNC,
@@ -857,7 +856,11 @@ struct main_type
   /* * A discriminant telling us which field of the type_specific
      union is being used for this type, if any.  */
 
-  ENUM_BITFIELD(type_specific_kind) type_specific_field : 4;
+  ENUM_BITFIELD(type_specific_kind) type_specific_field : 3;
+
+  /* The language for this type.  */
+
+  ENUM_BITFIELD(language) m_lang : LANGUAGE_BITS;
 
   /* * Number of fields described for this type.  This field appears
      at this location because it packs nicely here.  */
@@ -1430,11 +1433,19 @@ struct type
     return this->code () == TYPE_CODE_PTR || TYPE_IS_REFERENCE (this);
   }
 
+  /* Return true if this type is "string-like", according to its
+     defining language.  */
+  bool is_string_like ();
+
   /* Return true if this type is "array-like".  This includes arrays,
      but also some forms of structure type that are recognized as
      representations of arrays by the type's language.  */
   bool is_array_like ();
 
+  /* Return the language that this type came from.  */
+  enum language language () const
+  { return main_type->m_lang; }
+
   /* * Type that is a pointer to this type.
      NULL if no such pointer-to type is known yet.
      The debugger may add the address of such a type
@@ -1839,14 +1850,6 @@ extern void allocate_gnat_aux_type (struct type *);
     || (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_NONE	\
 	&& (type)->is_fixed_instance ()))
 
-/* Currently there isn't any associated data -- this is just a
-   marker.  */
-#define INIT_RUST_SPECIFIC(type) \
-  TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_RUST_STUFF
-
-#define HAVE_RUST_SPECIFIC(type) \
-  (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_RUST_STUFF)
-
 #define INIT_FUNC_SPECIFIC(type)					       \
   (TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_FUNC,			       \
    TYPE_MAIN_TYPE (type)->type_specific.func_stuff = (struct func_type *)      \
@@ -2242,14 +2245,16 @@ class type_allocator
 public:
 
   /* Create new types on OBJFILE.  */
-  explicit type_allocator (objfile *objfile)
-    : m_is_objfile (true)
+  type_allocator (objfile *objfile, enum language lang)
+    : m_is_objfile (true),
+      m_lang (lang)
   {
     m_data.objfile = objfile;
   }
 
   /* Create new types on GDBARCH.  */
   explicit type_allocator (gdbarch *gdbarch)
+    : m_lang (language_minimal)
   {
     m_data.gdbarch = gdbarch;
   }
@@ -2269,6 +2274,7 @@ class type_allocator
      is passed, overwrite TYPE.  */
   explicit type_allocator (struct type *type,
 			   type_allocator_kind kind = SAME)
+    : m_lang (type->language ())
   {
     if (kind == SAME)
       {
@@ -2289,7 +2295,8 @@ class type_allocator
 
   /* Create new types on the same obstack as TYPE.  */
   explicit type_allocator (const struct type *type)
-    : m_is_objfile (type->is_objfile_owned ())
+    : m_is_objfile (type->is_objfile_owned ()),
+      m_lang (type->language ())
   {
     if (type->is_objfile_owned ())
       m_data.objfile = type->objfile_owner ();
@@ -2326,6 +2333,8 @@ class type_allocator
   /* True if this allocator uses the type field above, indicating that
      the "allocation" should be done in-place.  */
   bool m_smash = false;
+  /* The language for types created by this allocator.  */
+  enum language m_lang;
 };
 
 /* Allocate a TYPE_CODE_INT type structure using ALLOC.  BIT is the
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index ea3e15be53b..47ac5419ec9 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -1381,7 +1381,7 @@ basic_type (int bt, struct objfile *objfile)
   if (map_bt[bt])
     return map_bt[bt];
 
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, get_current_subfile ()->language);
 
   switch (bt)
     {
@@ -1570,7 +1570,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs,
 	}
     }
 
-  type_allocator alloc (mdebugread_objfile);
+  type_allocator alloc (mdebugread_objfile, get_current_subfile ()->language);
 
   /* Move on to next aux.  */
   ax++;
@@ -4290,7 +4290,7 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp,
       rf = rn->rfd;
     }
 
-  type_allocator alloc (mdebugread_objfile);
+  type_allocator alloc (mdebugread_objfile, get_current_subfile ()->language);
 
   /* mips cc uses a rf of -1 for opaque struct definitions.
      Set TYPE_STUB for these types so that check_typedef will
@@ -4753,7 +4753,8 @@ new_type (char *name)
 {
   struct type *t;
 
-  t = type_allocator (mdebugread_objfile).new_type ();
+  t = type_allocator (mdebugread_objfile,
+		      get_current_subfile ()->language).new_type ();
   t->set_name (name);
   INIT_CPLUS_SPECIFIC (t);
   return t;
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 5e5f1750551..bfaa6d24d94 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -448,17 +448,19 @@ static PyObject *
 typy_is_array_like (PyObject *self, void *closure)
 {
   struct type *type = ((type_object *) self)->type;
+  bool result = false;
 
   try
     {
       type = check_typedef (type);
+      result = type->is_array_like ();
     }
   catch (const gdb_exception &except)
     {
       GDB_PY_HANDLE_EXCEPTION (except);
     }
 
-  if (type->is_array_like ())
+  if (result)
     Py_RETURN_TRUE;
   else
     Py_RETURN_FALSE;
@@ -475,14 +477,7 @@ typy_is_string_like (PyObject *self, void *closure)
   try
     {
       type = check_typedef (type);
-
-      const language_defn *lang = nullptr;
-      if (HAVE_GNAT_AUX_INFO (type))
-	lang = language_def (language_ada);
-      else if (HAVE_RUST_SPECIFIC (type))
-	lang = language_def (language_rust);
-      if (lang != nullptr)
-	result = lang->is_string_type_p (type);
+      result = type->is_string_like ();
     }
   catch (const gdb_exception &except)
     {
diff --git a/gdb/stabsread.c b/gdb/stabsread.c
index cc7efda61bf..473c11f3a85 100644
--- a/gdb/stabsread.c
+++ b/gdb/stabsread.c
@@ -346,7 +346,8 @@ dbx_alloc_type (int typenums[2], struct objfile *objfile)
 
   if (typenums[0] == -1)
     {
-      return type_allocator (objfile).new_type ();
+      return type_allocator (objfile,
+			     get_current_subfile ()->language).new_type ();
     }
 
   type_addr = dbx_lookup_type (typenums, objfile);
@@ -356,7 +357,8 @@ dbx_alloc_type (int typenums[2], struct objfile *objfile)
      We will fill it in later if we find out how.  */
   if (*type_addr == 0)
     {
-      *type_addr = type_allocator (objfile).new_type ();
+      *type_addr = type_allocator (objfile,
+				   get_current_subfile ()->language).new_type ();
     }
 
   return (*type_addr);
@@ -372,7 +374,7 @@ dbx_init_float_type (struct objfile *objfile, int bits)
   struct type *type;
 
   format = gdbarch_floatformat_for_type (gdbarch, NULL, bits);
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, get_current_subfile ()->language);
   if (format)
     type = init_float_type (alloc, bits, NULL, format);
   else
@@ -877,7 +879,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
 
 	    /* NULL terminate the string.  */
 	    string_local[ind] = 0;
-	    type_allocator alloc (objfile);
+	    type_allocator alloc (objfile, get_current_subfile ()->language);
 	    range_type
 	      = create_static_range_type (alloc,
 					  builtin_type (objfile)->builtin_int,
@@ -2014,7 +2016,7 @@ read_type (const char **pp, struct objfile *objfile)
     case 'S':			/* Set type */
       {
 	type1 = read_type (pp, objfile);
-	type_allocator alloc (objfile);
+	type_allocator alloc (objfile, get_current_subfile ()->language);
 	type = create_set_type (alloc, type1);
 	if (typenums[0] != -1)
 	  *dbx_lookup_type (typenums, objfile) = type;
@@ -2081,7 +2083,7 @@ rs6000_builtin_type (int typenum, struct objfile *objfile)
      TARGET_CHAR_BIT.  */
 #endif
 
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, get_current_subfile ()->language);
   switch (-typenum)
     {
     case 1:
@@ -3536,7 +3538,7 @@ read_array_type (const char **pp, struct type *type,
       upper = -1;
     }
 
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, get_current_subfile ()->language);
   range_type =
     create_static_range_type (alloc, index_type, lower, upper);
   type_allocator smash_alloc (type, type_allocator::SMASH);
@@ -3734,7 +3736,7 @@ read_sun_builtin_type (const char **pp, int typenums[2], struct objfile *objfile
   if (**pp == ';')
     ++(*pp);
 
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, get_current_subfile ()->language);
   if (type_bits == 0)
     {
       struct type *type = alloc.new_type (TYPE_CODE_VOID,
@@ -4003,7 +4005,7 @@ read_range_type (const char **pp, int typenums[2], int type_size,
   if (n2bits == -1 || n3bits == -1)
     return error_type (pp, objfile);
 
-  type_allocator alloc (objfile);
+  type_allocator alloc (objfile, get_current_subfile ()->language);
 
   if (index_type)
     goto handle_true_range;
diff --git a/gdb/valarith.c b/gdb/valarith.c
index ef376f05936..f3acf98c98b 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -262,10 +262,8 @@ value_to_array (struct value *val)
 
   if (type->is_array_like ())
     {
-      if (HAVE_GNAT_AUX_INFO (type))
-	return ada_coerce_to_simple_array (val);
-      if (HAVE_RUST_SPECIFIC (type))
-	return rust_slice_to_array (val);
+      const language_defn *defn = language_def (type->language ());
+      return defn->to_array (val);
     }
   return nullptr;
 }

-- 
2.40.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 5/5] Handle pointers and references correctly in DAP
  2023-09-05 19:47 [PATCH 0/5] Handle pointers and references correctly in DAP Tom Tromey
                   ` (3 preceding siblings ...)
  2023-09-05 19:47 ` [PATCH 4/5] Give a language to a type Tom Tromey
@ 2023-09-05 19:47 ` Tom Tromey
  2023-09-19 19:30 ` [PATCH 0/5] " Tom Tromey
  5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2023-09-05 19:47 UTC (permalink / raw)
  To: gdb-patches

A user pointed out that the current DAP variable code does not let the
client deference a pointer.  Oops!

Fixing this oversight is simple enough -- adding a new no-op
pretty-printer for pointers and references is quite simple.

However, doing this naive caused a regession in scopes.exp, which
expected there to be no children of a 'const char *' variable.  This
problem was fixed by the preceding patches in the series, which ensure
that a C type of this kind is recognized as a string.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30821
---
 gdb/python/lib/gdb/printing.py   |  16 ++++++
 gdb/testsuite/gdb.dap/ptrref.cc  |  34 +++++++++++++
 gdb/testsuite/gdb.dap/ptrref.exp | 103 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 153 insertions(+)

diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py
index 1a761a6aa57..223a69929d2 100644
--- a/gdb/python/lib/gdb/printing.py
+++ b/gdb/python/lib/gdb/printing.py
@@ -280,6 +280,20 @@ class NoOpScalarPrinter:
         return self.value.format_string(raw=True)
 
 
+class NoOpPointerReferencePrinter:
+    """A no-op pretty printer that wraps a pointer or reference."""
+
+    def __init__(self, value):
+        self.value = value
+        self.num_children = 1
+
+    def to_string(self):
+        return self.value.format_string(deref_refs=False)
+
+    def children(self):
+        yield "value", self.value.referenced_value()
+
+
 class NoOpArrayPrinter:
     """A no-op pretty printer that wraps an array value."""
 
@@ -354,6 +368,8 @@ def make_visualizer(value):
             result = gdb.printing.NoOpArrayPrinter(ty, value)
         elif ty.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION):
             result = gdb.printing.NoOpStructPrinter(ty, value)
+        elif ty.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_REF, gdb.TYPE_CODE_RVALUE_REF):
+            result = NoOpPointerReferencePrinter(value)
         else:
             result = gdb.printing.NoOpScalarPrinter(value)
     return result
diff --git a/gdb/testsuite/gdb.dap/ptrref.cc b/gdb/testsuite/gdb.dap/ptrref.cc
new file mode 100644
index 00000000000..bfb1afe3d17
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/ptrref.cc
@@ -0,0 +1,34 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+void
+func ()
+{
+  int value = 23;
+
+  int *ptr = &value;
+  int &ref = value;
+
+  return;			/* BREAK */
+}
+
+int
+main (int argc, char *argv[])
+{
+  func ();
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.dap/ptrref.exp b/gdb/testsuite/gdb.dap/ptrref.exp
new file mode 100644
index 00000000000..e0cc74529ab
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/ptrref.exp
@@ -0,0 +1,103 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+require allow_dap_tests
+
+load_lib dap-support.exp
+
+standard_testfile .cc
+
+if {[build_executable ${testfile}.exp $testfile $srcfile {debug c++}] == -1} {
+    return
+}
+
+if {[dap_launch $testfile] == ""} {
+    return
+}
+
+set line [gdb_get_line_number "BREAK"]
+set obj [dap_check_request_and_response "set breakpoint by line number" \
+	     setBreakpoints \
+	     [format {o source [o path [%s]] breakpoints [a [o line [i %d]]]} \
+		  [list s $srcfile] $line]]
+set line_bpno [dap_get_breakpoint_number $obj]
+
+dap_check_request_and_response "start inferior" configurationDone
+dap_wait_for_event_and_check "inferior started" thread "body reason" started
+
+dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
+    "body reason" breakpoint \
+    "body hitBreakpointIds" $line_bpno
+
+set bt [lindex [dap_check_request_and_response "backtrace" stackTrace \
+		    {o threadId [i 1]}] \
+	    0]
+set frame_id [dict get [lindex [dict get $bt body stackFrames] 0] id]
+
+set scopes [dap_check_request_and_response "get scopes" scopes \
+		[format {o frameId [i %d]} $frame_id]]
+set scopes [dict get [lindex $scopes 0] body scopes]
+
+gdb_assert {[llength $scopes] == 2} "two scopes"
+
+lassign $scopes scope reg_scope
+gdb_assert {[dict get $scope name] == "Locals"} "scope is locals"
+
+gdb_assert {[dict get $scope namedVariables] == 3} "three vars in scope"
+
+set num [dict get $scope variablesReference]
+set refs [lindex [dap_check_request_and_response "fetch variables" \
+		      "variables" \
+		      [format {o variablesReference [i %d] count [i 3]} \
+			   $num]] \
+	      0]
+
+proc fetch_pointer {name var} {
+    set num [dict get $var variablesReference]
+    set refs [lindex [dap_check_request_and_response "fetch children of $name" \
+			  "variables" \
+			  [format {o variablesReference [i %d] count [i 1]} \
+			       $num]] \
+		  0]
+    set var [lindex [dict get $refs body variables] 0]
+    gdb_assert {[dict get $var value] == 23} \
+	"value of child of $name"
+    gdb_assert {[dict get $var variablesReference] == 0} \
+	"no children for child of $name"
+}
+
+foreach var [dict get $refs body variables] {
+    set name [dict get $var name]
+
+    switch $name {
+	"value" {
+	    gdb_assert {[dict get $var value] == "23"} "check value of value"
+	    gdb_assert {[dict get $var variablesReference] == 0} \
+		"$name does not have child"
+	}
+	"ptr" -
+	"ref" {
+	    gdb_assert {[dict get $var variablesReference] != 0} \
+		"$name has children"
+	    # The implementation somewhat arbitrarily chooses "named"
+	    # children here.
+	    gdb_assert {[dict get $var namedVariables] == 1} \
+		"$name has exactly one child"
+	    fetch_pointer $name $var
+	}
+    }
+}
+
+dap_shutdown

-- 
2.40.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/5] Handle pointers and references correctly in DAP
  2023-09-05 19:47 [PATCH 0/5] Handle pointers and references correctly in DAP Tom Tromey
                   ` (4 preceding siblings ...)
  2023-09-05 19:47 ` [PATCH 5/5] Handle pointers and references correctly in DAP Tom Tromey
@ 2023-09-19 19:30 ` Tom Tromey
  5 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2023-09-19 19:30 UTC (permalink / raw)
  To: Tom Tromey via Gdb-patches; +Cc: Tom Tromey

>>>>> "Tom" == Tom Tromey via Gdb-patches <gdb-patches@sourceware.org> writes:

Tom> This series started off as a simple implementation of a no-op
Tom> pretty-printer to handle pointers and references in DAP.

Tom> However, this regressed a test, and I realized that the new
Tom> is-array-like and is-string-like code should be generalized to work
Tom> with any language.

Tom> This is done by associating a language with each type, which meant
Tom> touching every debug reader, plus a few minor preliminary cleanups.

Tom> Regression tested on x86-64 Fedora 36.

I'm checking this in now.

Tom

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-09-19 19:30 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-05 19:47 [PATCH 0/5] Handle pointers and references correctly in DAP Tom Tromey
2023-09-05 19:47 ` [PATCH 1/5] Pass a type allocator to init_fixed_point_type Tom Tromey
2023-09-05 19:47 ` [PATCH 2/5] Regularize some DWARF type initialization Tom Tromey
2023-09-05 19:47 ` [PATCH 3/5] Add is_array_like and to_array to language_defn Tom Tromey
2023-09-05 19:47 ` [PATCH 4/5] Give a language to a type Tom Tromey
2023-09-05 19:47 ` [PATCH 5/5] Handle pointers and references correctly in DAP Tom Tromey
2023-09-19 19:30 ` [PATCH 0/5] " Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).