public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 22/31] Use ui_file_as_string in gdb/c-exp.y
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (7 preceding siblings ...)
  2016-10-19  1:12 ` [PATCH v2 21/31] Use ui_file_as_string in gdb/compile/ Pedro Alves
@ 2016-10-19  1:12 ` Pedro Alves
  2016-10-19  1:13 ` [PATCH v2 08/31] Use ui_file_as_string in dwarf2_compute_name Pedro Alves
                   ` (21 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:12 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* c-exp.y (OPERATOR NEW): Adjust to use ui_file_as_string and
	std::string.
---
 gdb/c-exp.y | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 29f672f..f65e3a1 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -1555,16 +1555,13 @@ oper:	OPERATOR NEW
 	|	OPERATOR OBJC_LBRAC ']'
 			{ $$ = operator_stoken ("[]"); }
 	|	OPERATOR conversion_type_id
-			{ char *name;
-			  long length;
-			  struct ui_file *buf = mem_fileopen ();
+			{ struct ui_file *buf = mem_fileopen ();
 
 			  c_print_type ($2, NULL, buf, -1, 0,
 					&type_print_raw_options);
-			  name = ui_file_xstrdup (buf, &length);
+			  std::string name = ui_file_as_string (buf);
 			  ui_file_delete (buf);
-			  $$ = operator_stoken (name);
-			  free (name);
+			  $$ = operator_stoken (name.c_str ());
 			}
 	;
 
-- 
2.5.5

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

* [PATCH v2 12/31] Use ui_file_as_string in gdb/utils.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
@ 2016-10-19  1:12 ` Pedro Alves
  2016-10-19  1:12 ` [PATCH v2 19/31] Use ui_file_as_string in gdb/remote.c Pedro Alves
                   ` (29 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:12 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* utils.c (error_stream): Use ui_file_as_string and std::string.
---
 gdb/utils.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/gdb/utils.c b/gdb/utils.c
index 71c0e00..6feeb4d 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -509,10 +509,9 @@ verror (const char *string, va_list args)
 void
 error_stream (struct ui_file *stream)
 {
-  char *message = ui_file_xstrdup (stream, NULL);
+  std::string message = ui_file_as_string (stream);
 
-  make_cleanup (xfree, message);
-  error (("%s"), message);
+  error (("%s"), message.c_str ());
 }
 
 /* Emit a message and abort.  */
-- 
2.5.5

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

* [PATCH v2 07/31] Clean up tracepoint.h/c:collection_list
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (3 preceding siblings ...)
  2016-10-19  1:12 ` [PATCH v2 24/31] Use ui_file_as_string in gdb/ada-lang.c Pedro Alves
@ 2016-10-19  1:12 ` Pedro Alves
  2016-10-19  1:12 ` [PATCH v2 20/31] Use ui_file_as_string in gdb/cli/cli-setshow.c Pedro Alves
                   ` (25 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:12 UTC (permalink / raw)
  To: gdb-patches

Noticed we could do this while working on the expression_up change.

The main goal here was getting rid of the
encode_actions_and_make_cleanup / do_clear_collection_list cleanups.

While at it, uncrustify the code:

 - Make collection_list a C++ class, with data members private (and
   thus renamed m_...).

 - Make related functions be member methods.

 - Use std::vector instead of an open coding a vector implementation.

 - Use std::sort instead of qsort.

 - Rename the "list" member of collection_list, which is an incredibly
   obfuscating name.

 - Rename a couple other things here and there for clarify.

 - Use "bool" more.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* mi/mi-main.c (print_variable_or_computed): Constify 'expression'
	parameter.
	(mi_cmd_trace_frame_collected): Call encode_actions instead of
	encode_actions_and_make_cleanup.  Adjust to use std::vector.
	* tracepoint.c (memrange_cmp): Delete.
	(memrange_comp): New.
	(memrange_sortmerge): Take a memrange vector as parameter instead
	of a collection_list.  Use std::sort instead of qsort.
	(add_register): Now a method of collection_list.  Adjust to m_
	prefix of data fields.
	(add_memrange): Now a method of collection_list.  Adjust to m_
	prefix of data fields.  Adjust to use std::vector.
	(collect_symbol): Now a method of collection_list.  Adjust to m_
	prefix of data fields.
	(do_collect_symbol): Adjust.  Call add_wholly_collected instead of
	accessing the vector directly.
	(collection_list::add_wholly_collected): New.
	(add_local_symbols): Now a method of collection_list.
	(add_static_trace_data): Now a method of collection_list.  Adjust
	to use bool.
	(clear_collection_list, do_clear_collection_list): Delete.
	(init_collection_list): Delete.
	(collection_list::collection_list): New.
	(collection_list::~collection_list): New.
	(stringify_collection_list): Rename to ...
	(collection_list::stringify): ... this and adjust to being a
	method of collection_list.  Adjust to use of std::vector.
	(append_exp): Now a method of collection_list.  Use
	ui_file_as_string.  Adjust to std::vector.
	(collection_list::finish): New.
	(encode_actions_1): Adjust.
	(encode_actions_and_make_cleanup): Rename to ...
	(encode_actions)... this.  No longer returns a cleanup.  No longer
	call init_collection_list nor install do_clear_collection_list
	cleanups.  Call collection_list::finish instead of
	memrange_sortmerge directly.
	(encode_actions_rsp): Adjust to call encode_actions instead of
	encode_actions_and_make_cleanup.  Adjust to method renames.
	(add_aexpr): Now a method of collection_list.
	* tracepoint.h: Include <vector> and <string>.
	(struct memrange): Add constructors.
	(struct collection_list): Now a class.
	(class collection_list) <collection_list, ~collection_list,
	add_wholly_collected, append_exp, add_aexpr, add_register,
	add_memrange, collect_symbol, add_local_symbols,
	add_static_trace_data, finish, stringify, wholly_collected, and
	computed>: New methods.
	<regs_mask>: Rename to ...
	<m_regs_mask>: ... this.
	<listsize, next_memrange, list>: Delete fields.
	<m_memranges>: New field.
	<aexpr_listsize, next_aexpr_elt, aexpr_list>: Delete fields.
	<m_aexprs>: New field.
	<strace_data>: Rename to ...
	<m_strace_data>: ... this.  Now a bool.
	<wholly_collected>: Rename to ...
	<m_wholly_collected>: ... this.  Now a std::vector<std::string>.
	<computed>: Rename to ...
	<m_computed>: ... this.  Now a std::vector<std::string>.
	(encode_actions_and_make_cleanup): Delete declaration.
	(encode_actions): New declaration.
---
 gdb/mi/mi-main.c |  27 ++--
 gdb/tracepoint.c | 398 ++++++++++++++++++++++---------------------------------
 gdb/tracepoint.h |  72 +++++++---
 3 files changed, 236 insertions(+), 261 deletions(-)

diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 25b23d6..f43d10c 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -2742,7 +2742,7 @@ mi_cmd_ada_task_info (char *command, char **argv, int argc)
 /* Print EXPRESSION according to VALUES.  */
 
 static void
-print_variable_or_computed (char *expression, enum print_values values)
+print_variable_or_computed (const char *expression, enum print_values values)
 {
   struct cleanup *old_chain;
   struct value *val;
@@ -2868,8 +2868,7 @@ mi_cmd_trace_frame_collected (char *command, char **argv, int argc)
   old_chain = make_cleanup_restore_current_thread ();
   select_frame (get_current_frame ());
 
-  encode_actions_and_make_cleanup (tloc, &tracepoint_list,
-				   &stepping_list);
+  encode_actions (tloc, &tracepoint_list, &stepping_list);
 
   if (stepping_frame)
     clist = &stepping_list;
@@ -2881,13 +2880,19 @@ mi_cmd_trace_frame_collected (char *command, char **argv, int argc)
   /* Explicitly wholly collected variables.  */
   {
     struct cleanup *list_cleanup;
-    char *p;
     int i;
 
     list_cleanup = make_cleanup_ui_out_list_begin_end (uiout,
 						       "explicit-variables");
-    for (i = 0; VEC_iterate (char_ptr, clist->wholly_collected, i, p); i++)
-      print_variable_or_computed (p, var_print_values);
+
+    const std::vector<std::string> &wholly_collected
+      = clist->wholly_collected ();
+    for (size_t i = 0; i < wholly_collected.size (); i++)
+      {
+	const std::string &str = wholly_collected[i];
+	print_variable_or_computed (str.c_str (), var_print_values);
+      }
+
     do_cleanups (list_cleanup);
   }
 
@@ -2900,8 +2905,14 @@ mi_cmd_trace_frame_collected (char *command, char **argv, int argc)
     list_cleanup
       = make_cleanup_ui_out_list_begin_end (uiout,
 					    "computed-expressions");
-    for (i = 0; VEC_iterate (char_ptr, clist->computed, i, p); i++)
-      print_variable_or_computed (p, comp_print_values);
+
+    const std::vector<std::string> &computed = clist->computed ();
+    for (size_t i = 0; i < computed.size (); i++)
+      {
+	const std::string &str = computed[i];
+	print_variable_or_computed (str.c_str (), comp_print_values);
+      }
+
     do_cleanups (list_cleanup);
   }
 
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index e0ef6e8..7ff41f9 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -181,10 +181,7 @@ static void trace_dump_command (char *, int);
 /* support routines */
 
 struct collection_list;
-static void add_aexpr (struct collection_list *, struct agent_expr *);
 static char *mem2hex (gdb_byte *, char *, int);
-static void add_register (struct collection_list *collection,
-			  unsigned int regno);
 
 static struct command_line *
   all_tracepoint_actions_and_cleanup (struct breakpoint *t);
@@ -852,83 +849,70 @@ enum {
 
 /* MEMRANGE functions: */
 
-static int memrange_cmp (const void *, const void *);
+/* Compare memranges for std::sort.  */
 
-/* Compare memranges for qsort.  */
-static int
-memrange_cmp (const void *va, const void *vb)
+static bool
+memrange_comp (const memrange &a, const memrange &b)
 {
-  const struct memrange *a = (const struct memrange *) va;
-  const struct memrange *b = (const struct memrange *) vb;
-
-  if (a->type < b->type)
-    return -1;
-  if (a->type > b->type)
-    return 1;
-  if (a->type == memrange_absolute)
+  if (a.type == b.type)
     {
-      if ((bfd_vma) a->start < (bfd_vma) b->start)
-	return -1;
-      if ((bfd_vma) a->start > (bfd_vma) b->start)
-	return 1;
-    }
-  else
-    {
-      if (a->start < b->start)
-	return -1;
-      if (a->start > b->start)
-	return 1;
+      if (a.type == memrange_absolute)
+	return (bfd_vma) a.start < (bfd_vma) b.start;
+      else
+	return a.start < b.start;
     }
-  return 0;
+
+  return a.type < b.type;
 }
 
-/* Sort the memrange list using qsort, and merge adjacent memranges.  */
+/* Sort the memrange list using std::sort, and merge adjacent memranges.  */
+
 static void
-memrange_sortmerge (struct collection_list *memranges)
+memrange_sortmerge (std::vector<memrange> &memranges)
 {
-  int a, b;
-
-  qsort (memranges->list, memranges->next_memrange,
-	 sizeof (struct memrange), memrange_cmp);
-  if (memranges->next_memrange > 0)
+  if (!memranges.empty ())
     {
-      for (a = 0, b = 1; b < memranges->next_memrange; b++)
+      int a, b;
+
+      std::sort (memranges.begin (), memranges.end (), memrange_comp);
+
+      for (a = 0, b = 1; b < memranges.size (); b++)
 	{
 	  /* If memrange b overlaps or is adjacent to memrange a,
 	     merge them.  */
-	  if (memranges->list[a].type == memranges->list[b].type
-	      && memranges->list[b].start <= memranges->list[a].end)
+	  if (memranges[a].type == memranges[b].type
+	      && memranges[b].start <= memranges[a].end)
 	    {
-	      if (memranges->list[b].end > memranges->list[a].end)
-		memranges->list[a].end = memranges->list[b].end;
+	      if (memranges[b].end > memranges[a].end)
+		memranges[a].end = memranges[b].end;
 	      continue;		/* next b, same a */
 	    }
 	  a++;			/* next a */
 	  if (a != b)
-	    memcpy (&memranges->list[a], &memranges->list[b],
-		    sizeof (struct memrange));
+	    memranges[a] = memranges[b];
 	}
-      memranges->next_memrange = a + 1;
+      memranges.resize (a + 1);
     }
 }
 
 /* Add a register to a collection list.  */
-static void
-add_register (struct collection_list *collection, unsigned int regno)
+
+void
+collection_list::add_register (unsigned int regno)
 {
   if (info_verbose)
     printf_filtered ("collect register %d\n", regno);
-  if (regno >= (8 * sizeof (collection->regs_mask)))
+  if (regno >= (8 * sizeof (m_regs_mask)))
     error (_("Internal: register number %d too large for tracepoint"),
 	   regno);
-  collection->regs_mask[regno / 8] |= 1 << (regno % 8);
+  m_regs_mask[regno / 8] |= 1 << (regno % 8);
 }
 
 /* Add a memrange to a collection list.  */
-static void
-add_memrange (struct collection_list *memranges, 
-	      int type, bfd_signed_vma base,
-	      unsigned long len)
+
+void
+collection_list::add_memrange (int type, bfd_signed_vma base,
+			       unsigned long len)
 {
   if (info_verbose)
     {
@@ -938,31 +922,22 @@ add_memrange (struct collection_list *memranges,
     }
 
   /* type: memrange_absolute == memory, other n == basereg */
-  memranges->list[memranges->next_memrange].type = type;
   /* base: addr if memory, offset if reg relative.  */
-  memranges->list[memranges->next_memrange].start = base;
   /* len: we actually save end (base + len) for convenience */
-  memranges->list[memranges->next_memrange].end = base + len;
-  memranges->next_memrange++;
-  if (memranges->next_memrange >= memranges->listsize)
-    {
-      memranges->listsize *= 2;
-      memranges->list = (struct memrange *) xrealloc (memranges->list,
-						      memranges->listsize);
-    }
+  m_memranges.push_back (memrange (type, base, base + len));
 
   if (type != memrange_absolute)    /* Better collect the base register!  */
-    add_register (memranges, type);
+    add_register (type);
 }
 
 /* Add a symbol to a collection list.  */
-static void
-collect_symbol (struct collection_list *collect, 
-		struct symbol *sym,
-		struct gdbarch *gdbarch,
-		long frame_regno, long frame_offset,
-		CORE_ADDR scope,
-		int trace_string)
+
+void
+collection_list::collect_symbol (struct symbol *sym,
+				 struct gdbarch *gdbarch,
+				 long frame_regno, long frame_offset,
+				 CORE_ADDR scope,
+				 int trace_string)
 {
   unsigned long len;
   unsigned int reg;
@@ -997,19 +972,19 @@ collect_symbol (struct collection_list *collect,
       if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT)
 	treat_as_expr = 1;
       else
-	add_memrange (collect, memrange_absolute, offset, len);
+	add_memrange (memrange_absolute, offset, len);
       break;
     case LOC_REGISTER:
       reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch);
       if (info_verbose)
 	printf_filtered ("LOC_REG[parm] %s: ", 
 			 SYMBOL_PRINT_NAME (sym));
-      add_register (collect, reg);
+      add_register (reg);
       /* Check for doubles stored in two registers.  */
       /* FIXME: how about larger types stored in 3 or more regs?  */
       if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
 	  len > register_size (gdbarch, reg))
-	add_register (collect, reg + 1);
+	add_register (reg + 1);
       break;
     case LOC_REF_ARG:
       printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
@@ -1026,7 +1001,7 @@ collect_symbol (struct collection_list *collect,
 	  printf_vma (offset);
 	  printf_filtered (" from frame ptr reg %d\n", reg);
 	}
-      add_memrange (collect, reg, offset, len);
+      add_memrange (reg, offset, len);
       break;
     case LOC_REGPARM_ADDR:
       reg = SYMBOL_VALUE (sym);
@@ -1038,7 +1013,7 @@ collect_symbol (struct collection_list *collect,
 	  printf_vma (offset);
 	  printf_filtered (" from reg %d\n", reg);
 	}
-      add_memrange (collect, reg, offset, len);
+      add_memrange (reg, offset, len);
       break;
     case LOC_LOCAL:
       reg = frame_regno;
@@ -1050,7 +1025,7 @@ collect_symbol (struct collection_list *collect,
 	  printf_vma (offset);
 	  printf_filtered (" from frame ptr reg %d\n", reg);
 	}
-      add_memrange (collect, reg, offset, len);
+      add_memrange (reg, offset, len);
       break;
 
     case LOC_UNRESOLVED:
@@ -1092,7 +1067,7 @@ collect_symbol (struct collection_list *collect,
       report_agent_reqs_errors (aexpr);
 
       discard_cleanups (old_chain1);
-      add_aexpr (collect, aexpr);
+      add_aexpr (aexpr);
 
       /* Take care of the registers.  */
       if (aexpr->reg_mask_len > 0)
@@ -1108,7 +1083,7 @@ collect_symbol (struct collection_list *collect,
 		  for (ndx2 = 0; ndx2 < 8; ndx2++)
 		    if (aexpr->reg_mask[ndx1] & (1 << ndx2))
 		      /* It's used -- record it.  */
-		      add_register (collect, ndx1 * 8 + ndx2);
+		      add_register (ndx1 * 8 + ndx2);
 		}
 	    }
 	}
@@ -1138,25 +1113,30 @@ do_collect_symbol (const char *print_name,
 {
   struct add_local_symbols_data *p = (struct add_local_symbols_data *) cb_data;
 
-  collect_symbol (p->collect, sym, p->gdbarch, p->frame_regno,
-		  p->frame_offset, p->pc, p->trace_string);
+  p->collect->collect_symbol (sym, p->gdbarch, p->frame_regno,
+			      p->frame_offset, p->pc, p->trace_string);
   p->count++;
 
-  VEC_safe_push (char_ptr, p->collect->wholly_collected,
-		 xstrdup (print_name));
+  p->collect->add_wholly_collected (print_name);
+}
+
+void
+collection_list::add_wholly_collected (const char *print_name)
+{
+  m_wholly_collected.push_back (print_name);
 }
 
 /* Add all locals (or args) symbols to collection list.  */
-static void
-add_local_symbols (struct collection_list *collect,
-		   struct gdbarch *gdbarch, CORE_ADDR pc,
-		   long frame_regno, long frame_offset, int type,
-		   int trace_string)
+
+void
+collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc,
+				    long frame_regno, long frame_offset, int type,
+				    int trace_string)
 {
   const struct block *block;
   struct add_local_symbols_data cb_data;
 
-  cb_data.collect = collect;
+  cb_data.collect = this;
   cb_data.gdbarch = gdbarch;
   cb_data.pc = pc;
   cb_data.frame_regno = frame_regno;
@@ -1194,64 +1174,32 @@ add_local_symbols (struct collection_list *collect,
     }
 }
 
-static void
-add_static_trace_data (struct collection_list *collection)
+void
+collection_list::add_static_trace_data ()
 {
   if (info_verbose)
     printf_filtered ("collect static trace data\n");
-  collection->strace_data = 1;
+  m_strace_data = true;
 }
 
-/* worker function */
-static void
-clear_collection_list (struct collection_list *list)
+collection_list::collection_list ()
+  : m_regs_mask (),
+    m_strace_data (false)
 {
-  int ndx;
-
-  list->next_memrange = 0;
-  for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
-    {
-      free_agent_expr (list->aexpr_list[ndx]);
-      list->aexpr_list[ndx] = NULL;
-    }
-  list->next_aexpr_elt = 0;
-  memset (list->regs_mask, 0, sizeof (list->regs_mask));
-  list->strace_data = 0;
-
-  xfree (list->aexpr_list);
-  xfree (list->list);
-
-  VEC_free (char_ptr, list->wholly_collected);
-  VEC_free (char_ptr, list->computed);
+  m_memranges.reserve (128);
+  m_aexprs.reserve (128);
 }
 
-/* A cleanup wrapper for function clear_collection_list.  */
-
-static void
-do_clear_collection_list (void *list)
+collection_list::~collection_list ()
 {
-  struct collection_list *l = (struct collection_list *) list;
-
-  clear_collection_list (l);
-}
-
-/* Initialize collection_list CLIST.  */
-
-static void
-init_collection_list (struct collection_list *clist)
-{
-  memset (clist, 0, sizeof *clist);
-
-  clist->listsize = 128;
-  clist->list = XCNEWVEC (struct memrange, clist->listsize);
-
-  clist->aexpr_listsize = 128;
-  clist->aexpr_list = XCNEWVEC (struct agent_expr *, clist->aexpr_listsize);
+  for (int ndx = 0; ndx < m_aexprs.size (); ndx++)
+    free_agent_expr (m_aexprs[ndx]);
 }
 
 /* Reduce a collection list to string form (for gdb protocol).  */
-static char **
-stringify_collection_list (struct collection_list *list)
+
+char **
+collection_list::stringify ()
 {
   char temp_buf[2048];
   char tmp2[40];
@@ -1261,10 +1209,10 @@ stringify_collection_list (struct collection_list *list)
   char *end;
   long i;
 
-  count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1;
+  count = 1 + 1 + m_memranges.size () + m_aexprs.size () + 1;
   str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
 
-  if (list->strace_data)
+  if (m_strace_data)
     {
       if (info_verbose)
 	printf_filtered ("\nCollecting static trace data\n");
@@ -1274,10 +1222,10 @@ stringify_collection_list (struct collection_list *list)
       ndx++;
     }
 
-  for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
-    if (list->regs_mask[i] != 0)    /* Skip leading zeroes in regs_mask.  */
+  for (i = sizeof (m_regs_mask) - 1; i > 0; i--)
+    if (m_regs_mask[i] != 0)    /* Skip leading zeroes in regs_mask.  */
       break;
-  if (list->regs_mask[i] != 0)	/* Prepare to send regs_mask to the stub.  */
+  if (m_regs_mask[i] != 0)	/* Prepare to send regs_mask to the stub.  */
     {
       if (info_verbose)
 	printf_filtered ("\nCollecting registers (mask): 0x");
@@ -1287,8 +1235,8 @@ stringify_collection_list (struct collection_list *list)
 	{
 	  QUIT;			/* Allow user to bail out with ^C.  */
 	  if (info_verbose)
-	    printf_filtered ("%02X", list->regs_mask[i]);
-	  sprintf (end, "%02X", list->regs_mask[i]);
+	    printf_filtered ("%02X", m_regs_mask[i]);
+	  sprintf (end, "%02X", m_regs_mask[i]);
 	  end += 2;
 	}
       (*str_list)[ndx] = xstrdup (temp_buf);
@@ -1296,18 +1244,19 @@ stringify_collection_list (struct collection_list *list)
     }
   if (info_verbose)
     printf_filtered ("\n");
-  if (list->next_memrange > 0 && info_verbose)
+  if (!m_memranges.empty () && info_verbose)
     printf_filtered ("Collecting memranges: \n");
-  for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
+  for (i = 0, count = 0, end = temp_buf; i < m_memranges.size (); i++)
     {
       QUIT;			/* Allow user to bail out with ^C.  */
-      sprintf_vma (tmp2, list->list[i].start);
+      sprintf_vma (tmp2, m_memranges[i].start);
       if (info_verbose)
 	{
 	  printf_filtered ("(%d, %s, %ld)\n", 
-			   list->list[i].type, 
+			   m_memranges[i].type,
 			   tmp2, 
-			   (long) (list->list[i].end - list->list[i].start));
+			   (long) (m_memranges[i].end
+				   - m_memranges[i].start));
 	}
       if (count + 27 > MAX_AGENT_EXPR_LEN)
 	{
@@ -1318,39 +1267,39 @@ stringify_collection_list (struct collection_list *list)
 	}
 
       {
-        bfd_signed_vma length = list->list[i].end - list->list[i].start;
+        bfd_signed_vma length
+	  = m_memranges[i].end - m_memranges[i].start;
 
         /* The "%X" conversion specifier expects an unsigned argument,
            so passing -1 (memrange_absolute) to it directly gives you
            "FFFFFFFF" (or more, depending on sizeof (unsigned)).
            Special-case it.  */
-        if (list->list[i].type == memrange_absolute)
+        if (m_memranges[i].type == memrange_absolute)
           sprintf (end, "M-1,%s,%lX", tmp2, (long) length);
         else
-          sprintf (end, "M%X,%s,%lX", list->list[i].type, tmp2, (long) length);
+          sprintf (end, "M%X,%s,%lX", m_memranges[i].type, tmp2, (long) length);
       }
 
       count += strlen (end);
       end = temp_buf + count;
     }
 
-  for (i = 0; i < list->next_aexpr_elt; i++)
+  for (i = 0; i < m_aexprs.size (); i++)
     {
       QUIT;			/* Allow user to bail out with ^C.  */
-      if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
+      if ((count + 10 + 2 * m_aexprs[i]->len) > MAX_AGENT_EXPR_LEN)
 	{
 	  (*str_list)[ndx] = savestring (temp_buf, count);
 	  ndx++;
 	  count = 0;
 	  end = temp_buf;
 	}
-      sprintf (end, "X%08X,", list->aexpr_list[i]->len);
+      sprintf (end, "X%08X,", m_aexprs[i]->len);
       end += 10;		/* 'X' + 8 hex digits + ',' */
       count += 10;
 
-      end = mem2hex (list->aexpr_list[i]->buf, 
-		     end, list->aexpr_list[i]->len);
-      count += 2 * list->aexpr_list[i]->len;
+      end = mem2hex (m_aexprs[i]->buf, end, m_aexprs[i]->len);
+      count += 2 * m_aexprs[i]->len;
     }
 
   if (count != 0)
@@ -1373,20 +1322,23 @@ stringify_collection_list (struct collection_list *list)
 
 /* Add the printed expression EXP to *LIST.  */
 
-static void
-append_exp (struct expression *exp, VEC(char_ptr) **list)
+void
+collection_list::append_exp (struct expression *exp)
 {
   struct ui_file *tmp_stream = mem_fileopen ();
-  char *text;
 
   print_expression (exp, tmp_stream);
 
-  text = ui_file_xstrdup (tmp_stream, NULL);
-
-  VEC_safe_push (char_ptr, *list, text);
+  m_computed.push_back (ui_file_as_string (tmp_stream));
   ui_file_delete (tmp_stream);
 }
 
+void
+collection_list::finish ()
+{
+  memrange_sortmerge (m_memranges);
+}
+
 static void
 encode_actions_1 (struct command_line *action,
 		  struct bp_location *tloc,
@@ -1426,29 +1378,27 @@ encode_actions_1 (struct command_line *action,
 	      if (0 == strncasecmp ("$reg", action_exp, 4))
 		{
 		  for (i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++)
-		    add_register (collect, i);
+		    collect->add_register (i);
 		  action_exp = strchr (action_exp, ',');	/* more? */
 		}
 	      else if (0 == strncasecmp ("$arg", action_exp, 4))
 		{
-		  add_local_symbols (collect,
-				     target_gdbarch (),
-				     tloc->address,
-				     frame_reg,
-				     frame_offset,
-				     'A',
-				     trace_string);
+		  collect->add_local_symbols (target_gdbarch (),
+					      tloc->address,
+					      frame_reg,
+					      frame_offset,
+					      'A',
+					      trace_string);
 		  action_exp = strchr (action_exp, ',');	/* more? */
 		}
 	      else if (0 == strncasecmp ("$loc", action_exp, 4))
 		{
-		  add_local_symbols (collect,
-				     target_gdbarch (),
-				     tloc->address,
-				     frame_reg,
-				     frame_offset,
-				     'L',
-				     trace_string);
+		  collect->add_local_symbols (target_gdbarch (),
+					      tloc->address,
+					      frame_reg,
+					      frame_offset,
+					      'L',
+					      trace_string);
 		  action_exp = strchr (action_exp, ',');	/* more? */
 		}
 	      else if (0 == strncasecmp ("$_ret", action_exp, 5))
@@ -1465,7 +1415,7 @@ encode_actions_1 (struct command_line *action,
 		  report_agent_reqs_errors (aexpr);
 
 		  discard_cleanups (old_chain1);
-		  add_aexpr (collect, aexpr);
+		  collect->add_aexpr (aexpr);
 
 		  /* take care of the registers */
 		  if (aexpr->reg_mask_len > 0)
@@ -1480,9 +1430,10 @@ encode_actions_1 (struct command_line *action,
 			      /* assume chars have 8 bits */
 			      for (ndx2 = 0; ndx2 < 8; ndx2++)
 				if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-				  /* it's used -- record it */
-				  add_register (collect, 
-						ndx1 * 8 + ndx2);
+				  {
+				    /* It's used -- record it.  */
+				    collect->add_register (ndx1 * 8 + ndx2);
+				  }
 			    }
 			}
 		    }
@@ -1491,7 +1442,7 @@ encode_actions_1 (struct command_line *action,
 		}
 	      else if (0 == strncasecmp ("$_sdata", action_exp, 7))
 		{
-		  add_static_trace_data (collect);
+		  collect->add_static_trace_data ();
 		  action_exp = strchr (action_exp, ',');	/* more? */
 		}
 	      else
@@ -1517,7 +1468,7 @@ encode_actions_1 (struct command_line *action,
 					  name);
 			if (info_verbose)
 			  printf_filtered ("OP_REGISTER: ");
-			add_register (collect, i);
+			collect->add_register (i);
 			break;
 		      }
 
@@ -1527,9 +1478,9 @@ encode_actions_1 (struct command_line *action,
 		      addr = value_address (tempval);
 		      /* Initialize the TYPE_LENGTH if it is a typedef.  */
 		      check_typedef (exp->elts[1].type);
-		      add_memrange (collect, memrange_absolute, addr,
-				    TYPE_LENGTH (exp->elts[1].type));
-		      append_exp (exp.get (), &collect->computed);
+		      collect->add_memrange (memrange_absolute, addr,
+					     TYPE_LENGTH (exp->elts[1].type));
+		      collect->append_exp (exp.get ());
 		      break;
 
 		    case OP_VAR_VALUE:
@@ -1537,16 +1488,13 @@ encode_actions_1 (struct command_line *action,
 			struct symbol *sym = exp->elts[2].symbol;
 			char_ptr name = (char_ptr) SYMBOL_NATURAL_NAME (sym);
 
-			collect_symbol (collect,
-					exp->elts[2].symbol,
-					target_gdbarch (),
-					frame_reg,
-					frame_offset,
-					tloc->address,
-					trace_string);
-			VEC_safe_push (char_ptr,
-				       collect->wholly_collected,
-				       name);
+			collect->collect_symbol (exp->elts[2].symbol,
+						 target_gdbarch (),
+						 frame_reg,
+						 frame_offset,
+						 tloc->address,
+						 trace_string);
+			collect->add_wholly_collected (name);
 		      }
 		      break;
 
@@ -1561,7 +1509,7 @@ encode_actions_1 (struct command_line *action,
 		      report_agent_reqs_errors (aexpr);
 
 		      discard_cleanups (old_chain1);
-		      add_aexpr (collect, aexpr);
+		      collect->add_aexpr (aexpr);
 
 		      /* Take care of the registers.  */
 		      if (aexpr->reg_mask_len > 0)
@@ -1577,14 +1525,15 @@ encode_actions_1 (struct command_line *action,
 				  /* Assume chars have 8 bits.  */
 				  for (ndx2 = 0; ndx2 < 8; ndx2++)
 				    if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-				      /* It's used -- record it.  */
-				      add_register (collect, 
-						    ndx1 * 8 + ndx2);
+				      {
+					/* It's used -- record it.  */
+					collect->add_register (ndx1 * 8 + ndx2);
+				      }
 				}
 			    }
 			}
 
-		      append_exp (exp.get (), &collect->computed);
+		      collect->append_exp (exp.get ());
 		      break;
 		    }		/* switch */
 		}		/* do */
@@ -1614,7 +1563,7 @@ encode_actions_1 (struct command_line *action,
 		  discard_cleanups (old_chain1);
 		  /* Even though we're not officially collecting, add
 		     to the collect list anyway.  */
-		  add_aexpr (collect, aexpr);
+		  collect->add_aexpr (aexpr);
 		}		/* do */
 	    }
 	  while (action_exp && *action_exp++ == ',');
@@ -1635,27 +1584,17 @@ encode_actions_1 (struct command_line *action,
 }
 
 /* Encode actions of tracepoint TLOC->owner and fill TRACEPOINT_LIST
-   and STEPPING_LIST.  Return a cleanup pointer to clean up both
-   TRACEPOINT_LIST and STEPPING_LIST.  */
+   and STEPPING_LIST.  */
 
-struct cleanup *
-encode_actions_and_make_cleanup (struct bp_location *tloc,
-				 struct collection_list *tracepoint_list,
-				 struct collection_list *stepping_list)
+void
+encode_actions (struct bp_location *tloc,
+		struct collection_list *tracepoint_list,
+		struct collection_list *stepping_list)
 {
   struct command_line *actions;
   int frame_reg;
   LONGEST frame_offset;
-  struct cleanup *back_to, *return_chain;
-
-  return_chain = make_cleanup (null_cleanup, NULL);
-  init_collection_list (tracepoint_list);
-  init_collection_list (stepping_list);
 
-  make_cleanup (do_clear_collection_list, tracepoint_list);
-  make_cleanup (do_clear_collection_list, stepping_list);
-
-  back_to = make_cleanup (null_cleanup, NULL);
   gdbarch_virtual_frame_pointer (tloc->gdbarch,
 				 tloc->address, &frame_reg, &frame_offset);
 
@@ -1664,11 +1603,8 @@ encode_actions_and_make_cleanup (struct bp_location *tloc,
   encode_actions_1 (actions, tloc, frame_reg, frame_offset,
 		    tracepoint_list, stepping_list);
 
-  memrange_sortmerge (tracepoint_list);
-  memrange_sortmerge (stepping_list);
-
-  do_cleanups (back_to);
-  return return_chain;
+  tracepoint_list->finish ();
+  stepping_list->finish ();
 }
 
 /* Render all actions into gdb protocol.  */
@@ -1678,32 +1614,20 @@ encode_actions_rsp (struct bp_location *tloc, char ***tdp_actions,
 		    char ***stepping_actions)
 {
   struct collection_list tracepoint_list, stepping_list;
-  struct cleanup *cleanup;
 
   *tdp_actions = NULL;
   *stepping_actions = NULL;
 
-  cleanup = encode_actions_and_make_cleanup (tloc, &tracepoint_list,
-					     &stepping_list);
-
-  *tdp_actions = stringify_collection_list (&tracepoint_list);
-  *stepping_actions = stringify_collection_list (&stepping_list);
+  encode_actions (tloc, &tracepoint_list, &stepping_list);
 
-  do_cleanups (cleanup);
+  *tdp_actions = tracepoint_list.stringify ();
+  *stepping_actions = stepping_list.stringify ();
 }
 
-static void
-add_aexpr (struct collection_list *collect, struct agent_expr *aexpr)
+void
+collection_list::add_aexpr (struct agent_expr *aexpr)
 {
-  if (collect->next_aexpr_elt >= collect->aexpr_listsize)
-    {
-      collect->aexpr_list = XRESIZEVEC (struct agent_expr *,
-					collect->aexpr_list,
-					2 * collect->aexpr_listsize);
-      collect->aexpr_listsize *= 2;
-    }
-  collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
-  collect->next_aexpr_elt++;
+  m_aexprs.push_back (aexpr);
 }
 
 static void
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
index 8985394..d3571b1 100644
--- a/gdb/tracepoint.h
+++ b/gdb/tracepoint.h
@@ -24,6 +24,9 @@
 #include "memrange.h"
 #include "gdb_vecs.h"
 
+#include <vector>
+#include <string>
+
 /* An object describing the contents of a traceframe.  */
 
 struct traceframe_info
@@ -222,6 +225,13 @@ struct static_tracepoint_marker
 
 struct memrange
 {
+  memrange (int type_, bfd_signed_vma start_, bfd_signed_vma end_)
+    : type (type_), start (start_), end (end_)
+  {}
+
+  memrange ()
+  {}
+
   /* memrange_absolute for absolute memory range, else basereg
      number.  */
   int type;
@@ -229,27 +239,58 @@ struct memrange
   bfd_signed_vma end;
 };
 
-struct collection_list
+class collection_list
 {
+public:
+  collection_list ();
+  ~collection_list ();
+
+  void add_wholly_collected (const char *print_name);
+
+  void append_exp (struct expression *exp);
+
+  void add_aexpr (struct agent_expr *aexpr);
+  void add_register (unsigned int regno);
+  void add_memrange (int type, bfd_signed_vma base,
+		     unsigned long len);
+  void collect_symbol (struct symbol *sym,
+		       struct gdbarch *gdbarch,
+		       long frame_regno, long frame_offset,
+		       CORE_ADDR scope,
+		       int trace_string);
+
+  void add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc,
+			  long frame_regno, long frame_offset, int type,
+			  int trace_string);
+  void add_static_trace_data ();
+
+  void finish ();
+
+  char **stringify ();
+
+  const std::vector<std::string> &wholly_collected ()
+  { return m_wholly_collected; }
+
+  const std::vector<std::string> &computed ()
+  { return m_computed; }
+
+private:
   /* room for up to 256 regs */
-  unsigned char regs_mask[32];
-  long listsize;
-  long next_memrange;
-  struct memrange *list;
+  unsigned char m_regs_mask[32];
+
+  std::vector<memrange> m_memranges;
 
-  /* size of array pointed to by expr_list elt.  */
-  long aexpr_listsize;
-  long next_aexpr_elt;
-  struct agent_expr **aexpr_list;
+  /* Vector owns pointers.  */
+  std::vector<agent_expr *> m_aexprs;
 
   /* True is the user requested a collection of "$_sdata", "static
      tracepoint data".  */
-  int strace_data;
+  bool m_strace_data;
 
   /* A set of names of wholly collected objects.  */
-  VEC(char_ptr) *wholly_collected;
+  std::vector<std::string> m_wholly_collected;
   /* A set of computed expressions.  */
-  VEC(char_ptr) *computed;
+  std::vector<std::string> m_computed;
 };
 
 extern void parse_static_tracepoint_marker_definition
@@ -280,10 +321,9 @@ void free_actions (struct breakpoint *);
 
 extern const char *decode_agent_options (const char *exp, int *trace_string);
 
-extern struct cleanup *
-  encode_actions_and_make_cleanup (struct bp_location *tloc,
-				   struct collection_list *tracepoint_list,
-				   struct collection_list *stepping_list);
+extern void encode_actions (struct bp_location *tloc,
+			    struct collection_list *tracepoint_list,
+			    struct collection_list *stepping_list);
 
 extern void encode_actions_rsp (struct bp_location *tloc,
 				char ***tdp_actions, char ***stepping_actions);
-- 
2.5.5

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

* [PATCH v2 20/31] Use ui_file_as_string in gdb/cli/cli-setshow.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (4 preceding siblings ...)
  2016-10-19  1:12 ` [PATCH v2 07/31] Clean up tracepoint.h/c:collection_list Pedro Alves
@ 2016-10-19  1:12 ` Pedro Alves
  2016-10-19  1:12 ` [PATCH v2 01/31] Introduce string_printf Pedro Alves
                   ` (24 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:12 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* cli/cli-setshow.c (do_show_command): Adjust to use
	ui_file_as_string and std::string.
---
 gdb/cli/cli-setshow.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
index eb17158..d2ec1df 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -653,13 +653,12 @@ do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
     ui_out_field_stream (uiout, "value", stb);
   else
     {
-      char *value = ui_file_xstrdup (stb, NULL);
+      std::string value = ui_file_as_string (stb);
 
-      make_cleanup (xfree, value);
       if (c->show_value_func != NULL)
-	c->show_value_func (gdb_stdout, from_tty, c, value);
+	c->show_value_func (gdb_stdout, from_tty, c, value.c_str ());
       else
-	deprecated_show_value_hack (gdb_stdout, from_tty, c, value);
+	deprecated_show_value_hack (gdb_stdout, from_tty, c, value.c_str ());
     }
   do_cleanups (old_chain);
 
-- 
2.5.5

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

* [PATCH v2 01/31] Introduce string_printf
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (5 preceding siblings ...)
  2016-10-19  1:12 ` [PATCH v2 20/31] Use ui_file_as_string in gdb/cli/cli-setshow.c Pedro Alves
@ 2016-10-19  1:12 ` Pedro Alves
  2016-10-19 13:43   ` Trevor Saunders
  2016-10-19 17:18   ` Simon Marchi
  2016-10-19  1:12 ` [PATCH v2 21/31] Use ui_file_as_string in gdb/compile/ Pedro Alves
                   ` (23 subsequent siblings)
  30 siblings, 2 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:12 UTC (permalink / raw)
  To: gdb-patches

This introduces the string_printf function.  Like asprintf, but
returns a std::string.

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* common/common-utils.c (string_printf): New function.
	* common/common-utils.h: Include <string>.
	(string_printf): Declare.
---
 gdb/common/common-utils.c | 30 ++++++++++++++++++++++++++++++
 gdb/common/common-utils.h |  6 ++++++
 2 files changed, 36 insertions(+)

diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c
index 5a346ec..05ba3aa 100644
--- a/gdb/common/common-utils.c
+++ b/gdb/common/common-utils.c
@@ -150,6 +150,36 @@ xsnprintf (char *str, size_t size, const char *format, ...)
   return ret;
 }
 
+/* See documentation in common-utils.h.  */
+
+std::string
+string_printf (const char* fmt, ...)
+{
+  std::string str;
+  va_list vp;
+
+  /* Start by assuming some reasonable size will be sufficient.  */
+  str.resize (1024);
+
+  while (1)
+    {
+      size_t size;
+      int result;
+
+      va_start (vp, fmt);
+      size = str.size ();
+      result = vsnprintf (&str[0], size, fmt, vp);
+      va_end (vp);
+
+      str.resize (result);
+
+      if (result < size)
+	break;
+    }
+
+  return str;
+}
+
 char *
 savestring (const char *ptr, size_t len)
 {
diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h
index 47def11..a9053ff 100644
--- a/gdb/common/common-utils.h
+++ b/gdb/common/common-utils.h
@@ -20,6 +20,8 @@
 #ifndef COMMON_UTILS_H
 #define COMMON_UTILS_H
 
+#include <string>
+
 /* If possible, define FUNCTION_NAME, a macro containing the name of
    the function being defined.  Since this macro may not always be
    defined, all uses must be protected by appropriate macro definition
@@ -56,6 +58,10 @@ char *xstrvprintf (const char *format, va_list ap)
 int xsnprintf (char *str, size_t size, const char *format, ...)
      ATTRIBUTE_PRINTF (3, 4);
 
+/* Returns a std::string built from a printf-style format string.  */
+std::string string_printf (const char* fmt, ...)
+  ATTRIBUTE_PRINTF (1, 2);
+
 /* Make a copy of the string at PTR with LEN characters
    (and add a null character at the end in the copy).
    Uses malloc to get the space.  Returns the address of the copy.  */
-- 
2.5.5

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

* [PATCH v2 06/31] Introduce ui_file_as_string
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
  2016-10-19  1:12 ` [PATCH v2 12/31] Use ui_file_as_string in gdb/utils.c Pedro Alves
  2016-10-19  1:12 ` [PATCH v2 19/31] Use ui_file_as_string in gdb/remote.c Pedro Alves
@ 2016-10-19  1:12 ` Pedro Alves
  2016-10-19  1:12 ` [PATCH v2 24/31] Use ui_file_as_string in gdb/ada-lang.c Pedro Alves
                   ` (27 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:12 UTC (permalink / raw)
  To: gdb-patches

ui_file_as_string is a variant of ui_file_xstrdup that returns a
std::string instead of a xmalloc'ed char *.  The idea is using the new
function to eliminate "make_cleanup (xfree, ...)"  cleanups
throughout.

Following patches will make use of this.

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* ui-file.c (do_ui_file_as_string, ui_file_as_string): New
	functions.
	* ui-file.h: Include <string>.
	(ui_file_as_string): New declaration.
---
 gdb/ui-file.c | 22 ++++++++++++++++++++++
 gdb/ui-file.h |  6 ++++++
 2 files changed, 28 insertions(+)

diff --git a/gdb/ui-file.c b/gdb/ui-file.c
index a977f89..31228a3 100644
--- a/gdb/ui-file.c
+++ b/gdb/ui-file.c
@@ -356,6 +356,28 @@ ui_file_xstrdup (struct ui_file *file, long *length)
   return acc.buffer;
 }
 
+/* ui_file utility function for converting a ``struct ui_file'' into a
+   std:string.  */
+
+static void
+do_ui_file_as_string (void *context, const char *buffer, long length)
+{
+  std::string *str = (std::string *) context;
+
+  *str = std::string (buffer, length);
+}
+
+/* See ui-file.h.  */
+
+std::string
+ui_file_as_string (struct ui_file *file)
+{
+  std::string str;
+
+  ui_file_put (file, do_ui_file_as_string, &str);
+  return str;
+}
+
 static void
 do_ui_file_obsavestring (void *context, const char *buffer, long length)
 {
diff --git a/gdb/ui-file.h b/gdb/ui-file.h
index f6df572..2ed11de 100644
--- a/gdb/ui-file.h
+++ b/gdb/ui-file.h
@@ -22,6 +22,8 @@
 struct obstack;
 struct ui_file;
 
+#include <string>
+
 /* Create a generic ui_file object with null methods.  */
 
 extern struct ui_file *ui_file_new (void);
@@ -117,6 +119,10 @@ extern void ui_file_put (struct ui_file *src,
    minus that appended NUL.  */
 extern char *ui_file_xstrdup (struct ui_file *file, long *length);
 
+/* Returns a std::string containing the entire contents of FILE (as
+   determined by ui_file_put()).  */
+extern std::string ui_file_as_string (struct ui_file *file);
+
 /* Similar to ui_file_xstrdup, but return a new string allocated on
    OBSTACK.  */
 extern char *ui_file_obsavestring (struct ui_file *file,
-- 
2.5.5

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

* [PATCH v2 24/31] Use ui_file_as_string in gdb/ada-lang.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (2 preceding siblings ...)
  2016-10-19  1:12 ` [PATCH v2 06/31] Introduce ui_file_as_string Pedro Alves
@ 2016-10-19  1:12 ` Pedro Alves
  2016-10-19  1:12 ` [PATCH v2 07/31] Clean up tracepoint.h/c:collection_list Pedro Alves
                   ` (26 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:12 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* ada-lang.c (type_as_string): Use ui_file_as_string and return
	std::string.
	(type_as_string_and_cleanup): Delete.
	(ada_lookup_struct_elt_type): Use type_as_string.
---
 gdb/ada-lang.c | 31 ++++++-------------------------
 1 file changed, 6 insertions(+), 25 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index d1a39bc..3c04554 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -7608,39 +7608,24 @@ ada_value_struct_elt (struct value *arg, char *name, int no_err)
 	     "a value that is not a record."));
 }
 
-/* Return a string representation of type TYPE.  Caller must free
-   result.  */
+/* Return a string representation of type TYPE.  */
 
-static char *
+static std::string
 type_as_string (struct type *type)
 {
   struct ui_file *tmp_stream = mem_fileopen ();
   struct cleanup *old_chain;
-  char *str;
 
   tmp_stream = mem_fileopen ();
   old_chain = make_cleanup_ui_file_delete (tmp_stream);
 
   type_print (type, "", tmp_stream, -1);
-  str = ui_file_xstrdup (tmp_stream, NULL);
+  std::string str = ui_file_as_string (tmp_stream);
 
   do_cleanups (old_chain);
   return str;
 }
 
-/* Return a string representation of type TYPE, and install a cleanup
-   that releases it.  */
-
-static char *
-type_as_string_and_cleanup (struct type *type)
-{
-  char *str;
-
-  str = type_as_string (type);
-  make_cleanup (xfree, str);
-  return str;
-}
-
 /* Given a type TYPE, look up the type of the component of type named NAME.
    If DISPP is non-null, add its byte displacement from the beginning of a
    structure (pointed to by a value) of type TYPE to *DISPP (does not
@@ -7681,15 +7666,11 @@ ada_lookup_struct_elt_type (struct type *type, char *name, int refok,
       || (TYPE_CODE (type) != TYPE_CODE_STRUCT
           && TYPE_CODE (type) != TYPE_CODE_UNION))
     {
-      const char *type_str;
-
       if (noerr)
         return NULL;
 
-      type_str = (type != NULL
-		  ? type_as_string_and_cleanup (type)
-		  : _("(null)"));
-      error (_("Type %s is not a structure or union type"), type_str);
+      error (_("Type %s is not a structure or union type"),
+	     type != NULL ? type_as_string (type).c_str () : _("(null)"));
     }
 
   type = to_static_fixed_type (type);
@@ -7762,7 +7743,7 @@ BadName:
       const char *name_str = name != NULL ? name : _("<null>");
 
       error (_("Type %s has no component named %s"),
-	     type_as_string_and_cleanup (type), name_str);
+	     type_as_string (type).c_str (), name_str);
     }
 
   return NULL;
-- 
2.5.5

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

* [PATCH v2 19/31] Use ui_file_as_string in gdb/remote.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
  2016-10-19  1:12 ` [PATCH v2 12/31] Use ui_file_as_string in gdb/utils.c Pedro Alves
@ 2016-10-19  1:12 ` Pedro Alves
  2016-10-19  1:12 ` [PATCH v2 06/31] Introduce ui_file_as_string Pedro Alves
                   ` (28 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:12 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* remote.c (escape_buffer): Use ui_file_as_string and return
	std::string.
	(putpkt_binary, read_frame): Adjust to use std::string.
---
 gdb/remote.c | 54 ++++++++++++++++--------------------------------------
 1 file changed, 16 insertions(+), 38 deletions(-)

diff --git a/gdb/remote.c b/gdb/remote.c
index e8cb560..e741a58 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -8220,23 +8220,20 @@ remote_send (char **buf,
     error (_("Remote failure reply: %s"), *buf);
 }
 
-/* Return a pointer to an xmalloc'ed string representing an escaped
-   version of BUF, of len N.  E.g. \n is converted to \\n, \t to \\t,
-   etc.  The caller is responsible for releasing the returned
-   memory.  */
+/* Return a string representing an escaped version of BUF, of len N.
+   E.g. \n is converted to \\n, \t to \\t, etc.  */
 
-static char *
+static std::string
 escape_buffer (const char *buf, int n)
 {
   struct cleanup *old_chain;
   struct ui_file *stb;
-  char *str;
 
   stb = mem_fileopen ();
   old_chain = make_cleanup_ui_file_delete (stb);
 
   fputstrn_unfiltered (buf, n, '\\', stb);
-  str = ui_file_xstrdup (stb, NULL);
+  std::string str = ui_file_as_string (stb);
   do_cleanups (old_chain);
   return str;
 }
@@ -8320,15 +8317,12 @@ putpkt_binary (const char *buf, int cnt)
 
       if (remote_debug)
 	{
-	  struct cleanup *old_chain;
-	  char *str;
-
 	  *p = '\0';
-	  str = escape_buffer (buf2, p - buf2);
-	  old_chain = make_cleanup (xfree, str);
-	  fprintf_unfiltered (gdb_stdlog, "Sending packet: %s...", str);
+
+	  std::string str = escape_buffer (buf2, p - buf2);
+
+	  fprintf_unfiltered (gdb_stdlog, "Sending packet: %s...", str.c_str ());
 	  gdb_flush (gdb_stdlog);
-	  do_cleanups (old_chain);
 	}
       remote_serial_write (buf2, p - buf2);
 
@@ -8406,15 +8400,11 @@ putpkt_binary (const char *buf, int cnt)
 		  {
 		    if (remote_debug)
 		      {
-			struct cleanup *old_chain;
-			char *str;
+			std::string str = escape_buffer (rs->buf, val);
 
-			str = escape_buffer (rs->buf, val);
-			old_chain = make_cleanup (xfree, str);
 			fprintf_unfiltered (gdb_stdlog,
 					    "  Notification received: %s\n",
-					    str);
-			do_cleanups (old_chain);
+					    str.c_str ());
 		      }
 		    handle_notification (rs->notif_state, rs->buf);
 		    /* We're in sync now, rewait for the ack.  */
@@ -8580,16 +8570,12 @@ read_frame (char **buf_p,
 
 	    if (remote_debug)
 	      {
-		struct cleanup *old_chain;
-		char *str;
+		std::string str = escape_buffer (buf, bc);
 
-		str = escape_buffer (buf, bc);
-		old_chain = make_cleanup (xfree, str);
 		fprintf_unfiltered (gdb_stdlog,
 				    "Bad checksum, sentsum=0x%x, "
 				    "csum=0x%x, buf=%s\n",
-				    pktcsum, csum, str);
-		do_cleanups (old_chain);
+				    pktcsum, csum, str.c_str ());
 	      }
 	    /* Number of characters in buffer ignoring trailing
                NULL.  */
@@ -8763,13 +8749,9 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever,
 	{
 	  if (remote_debug)
 	    {
-	     struct cleanup *old_chain;
-	     char *str;
+	      std::string str = escape_buffer (*buf, val);
 
-	     str = escape_buffer (*buf, val);
-	     old_chain = make_cleanup (xfree, str);
-	     fprintf_unfiltered (gdb_stdlog, "Packet received: %s\n", str);
-	     do_cleanups (old_chain);
+	      fprintf_unfiltered (gdb_stdlog, "Packet received: %s\n", str.c_str ());
 	    }
 
 	  /* Skip the ack char if we're in no-ack mode.  */
@@ -8788,15 +8770,11 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever,
 
 	  if (remote_debug)
 	    {
-	      struct cleanup *old_chain;
-	      char *str;
+	      std::string str = escape_buffer (*buf, val);
 
-	      str = escape_buffer (*buf, val);
-	      old_chain = make_cleanup (xfree, str);
 	      fprintf_unfiltered (gdb_stdlog,
 				  "  Notification received: %s\n",
-				  str);
-	      do_cleanups (old_chain);
+				  str.c_str ());
 	    }
 	  if (is_notif != NULL)
 	    *is_notif = 1;
-- 
2.5.5

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

* [PATCH v2 21/31] Use ui_file_as_string in gdb/compile/
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (6 preceding siblings ...)
  2016-10-19  1:12 ` [PATCH v2 01/31] Introduce string_printf Pedro Alves
@ 2016-10-19  1:12 ` Pedro Alves
  2016-10-19 23:08   ` Simon Marchi
  2016-10-19  1:12 ` [PATCH v2 22/31] Use ui_file_as_string in gdb/c-exp.y Pedro Alves
                   ` (22 subsequent siblings)
  30 siblings, 1 reply; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:12 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* c-lang.h (c_compute_program): Now returns std::string.
	* compile/compile-c-support.c (c_compute_program): Now returns a
	std::string.  Use ui_file_as_string.
	* compile/compile.c (get_new_file_names): Change output parameters
	to std::string pointers.  Use string_printf.
	(compile_to_object): Change output parameters to std::string
	pointers.  Use ui_file_as_string.
	(eval_compile_command): Use std::string.
	* language.h (struct language_defn) <la_compute_program>: Now
	returns std::string.
---
 gdb/c-lang.h                    |  7 +++--
 gdb/compile/compile-c-support.c |  6 ++--
 gdb/compile/compile.c           | 70 +++++++++++++++++++----------------------
 gdb/language.h                  | 14 ++++-----
 4 files changed, 46 insertions(+), 51 deletions(-)

diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 12be8bf..fa49791 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -152,13 +152,14 @@ extern int c_textual_element_type (struct type *, char);
 
 extern struct compile_instance *c_get_compile_context (void);
 
-/* This takes the user-supplied text and returns a newly malloc'd bit
-   of code to compile.
+/* This takes the user-supplied text and returns a new bit of code to
+   compile.
 
    This is used as the la_compute_program language method; see that
    for a description of the arguments.  */
 
-extern char *c_compute_program (struct compile_instance *inst,
+extern std::string
+  c_compute_program (struct compile_instance *inst,
 				const char *input,
 				struct gdbarch *gdbarch,
 				const struct block *expr_block,
diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index c42daba..641b0fd 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -326,7 +326,7 @@ generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch,
    to the inferior when the expression was created, and EXPR_PC
    indicates the value of $PC.  */
 
-char *
+std::string
 c_compute_program (struct compile_instance *inst,
 		   const char *input,
 		   struct gdbarch *gdbarch,
@@ -334,7 +334,7 @@ c_compute_program (struct compile_instance *inst,
 		   CORE_ADDR expr_pc)
 {
   struct ui_file *buf, *var_stream = NULL;
-  char *code;
+  std::string code;
   struct cleanup *cleanup;
   struct compile_c_instance *context = (struct compile_c_instance *) inst;
 
@@ -435,7 +435,7 @@ c_compute_program (struct compile_instance *inst,
     fputs_unfiltered ("}\n", buf);
 
   add_code_footer (inst->scope, buf);
-  code = ui_file_xstrdup (buf, NULL);
+  code = ui_file_as_string (buf);
   do_cleanups (cleanup);
   return code;
 }
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 0c4a738..0db95e4 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -259,14 +259,14 @@ get_compile_file_tempdir (void)
    allocated by malloc and should be freed by the caller.  */
 
 static void
-get_new_file_names (char **source_file, char **object_file)
+get_new_file_names (std::string *source_file, std::string *object_file)
 {
   static int seq;
   const char *dir = get_compile_file_tempdir ();
 
   ++seq;
-  *source_file = xstrprintf ("%s%sout%d.c", dir, SLASH_STRING, seq);
-  *object_file = xstrprintf ("%s%sout%d.o", dir, SLASH_STRING, seq);
+  *source_file = string_printf ("%s%sout%d.c", dir, SLASH_STRING, seq);
+  *object_file = string_printf ("%s%sout%d.o", dir, SLASH_STRING, seq);
 }
 
 /* Get the block and PC at which to evaluate an expression.  */
@@ -460,14 +460,13 @@ print_callback (void *ignore, const char *message)
    error condition, error () is called.  The caller is responsible for
    freeing both strings.  */
 
-static char *
+static void
 compile_to_object (struct command_line *cmd, const char *cmd_string,
 		   enum compile_i_scope_types scope,
-		   char **source_filep)
+		   std::string *source_filep,
+		   std::string *object_filep)
 {
-  char *code;
   const char *input;
-  char *source_file, *object_file;
   struct compile_instance *compiler;
   struct cleanup *cleanup, *inner_cleanup;
   const struct block *expr_block;
@@ -503,11 +502,13 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 
   /* From the provided expression, build a scope to pass to the
      compiler.  */
+
+  std::string input_buf;
+
   if (cmd != NULL)
     {
       struct ui_file *stream = mem_fileopen ();
       struct command_line *iter;
-      char *stream_buf;
 
       make_cleanup_ui_file_delete (stream);
       for (iter = cmd->body_list[0]; iter; iter = iter->next)
@@ -516,20 +517,19 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 	  fputs_unfiltered ("\n", stream);
 	}
 
-      stream_buf = ui_file_xstrdup (stream, NULL);
-      make_cleanup (xfree, stream_buf);
-      input = stream_buf;
+      input_buf = ui_file_as_string (stream);
+      input = input_buf.c_str ();
     }
   else if (cmd_string != NULL)
     input = cmd_string;
   else
     error (_("Neither a simple expression, or a multi-line specified."));
 
-  code = current_language->la_compute_program (compiler, input, gdbarch,
-					       expr_block, expr_pc);
-  make_cleanup (xfree, code);
+  std::string code
+    = current_language->la_compute_program (compiler, input, gdbarch,
+					    expr_block, expr_pc);
   if (compile_debug)
-    fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code);
+    fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code.c_str ());
 
   os_rx = osabi_triplet_regexp (gdbarch_osabi (gdbarch));
   arch_rx = gdbarch_gnu_triplet_regexp (gdbarch);
@@ -560,37 +560,34 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 			    argi, argv[argi]);
     }
 
-  get_new_file_names (&source_file, &object_file);
-  inner_cleanup = make_cleanup (xfree, source_file);
-  make_cleanup (xfree, object_file);
+  get_new_file_names (source_filep, object_filep);
 
-  src = gdb_fopen_cloexec (source_file, "w");
+  src = gdb_fopen_cloexec (source_filep->c_str (), "w");
   if (src == NULL)
     perror_with_name (_("Could not open source file for writing"));
-  make_cleanup (cleanup_unlink_file, source_file);
-  if (fputs (code, src) == EOF)
+  inner_cleanup = make_cleanup (cleanup_unlink_file,
+				(void *) source_filep->c_str ());
+  if (fputs (code.c_str (), src) == EOF)
     perror_with_name (_("Could not write to source file"));
   fclose (src);
 
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "source file produced: %s\n\n",
-			source_file);
+			source_filep->c_str ());
 
   /* Call the compiler and start the compilation process.  */
-  compiler->fe->ops->set_source_file (compiler->fe, source_file);
+  compiler->fe->ops->set_source_file (compiler->fe, source_filep->c_str ());
 
-  if (!compiler->fe->ops->compile (compiler->fe, object_file,
+  if (!compiler->fe->ops->compile (compiler->fe, object_filep->c_str (),
 				   compile_debug))
     error (_("Compilation failed."));
 
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "object file produced: %s\n\n",
-			object_file);
+			object_filep->c_str ());
 
   discard_cleanups (inner_cleanup);
   do_cleanups (cleanup);
-  *source_filep = source_file;
-  return object_file;
 }
 
 /* The "compile" prefix command.  */
@@ -609,30 +606,27 @@ void
 eval_compile_command (struct command_line *cmd, const char *cmd_string,
 		      enum compile_i_scope_types scope, void *scope_data)
 {
-  char *object_file, *source_file;
+  std::string source_file, object_file;
 
-  object_file = compile_to_object (cmd, cmd_string, scope, &source_file);
-  if (object_file != NULL)
+  compile_to_object (cmd, cmd_string, scope, &source_file, &object_file);
+  if (!object_file.empty ())
     {
-      struct cleanup *cleanup_xfree, *cleanup_unlink;
+      struct cleanup *cleanup_unlink;
       struct compile_module *compile_module;
 
-      cleanup_xfree = make_cleanup (xfree, object_file);
-      make_cleanup (xfree, source_file);
-      cleanup_unlink = make_cleanup (cleanup_unlink_file, object_file);
-      make_cleanup (cleanup_unlink_file, source_file);
-      compile_module = compile_object_load (object_file, source_file,
+      cleanup_unlink = make_cleanup (cleanup_unlink_file,
+				     (void *) object_file.c_str ());
+      make_cleanup (cleanup_unlink_file, (void *) source_file.c_str ());
+      compile_module = compile_object_load (object_file.c_str (), source_file.c_str (),
 					    scope, scope_data);
       if (compile_module == NULL)
 	{
 	  gdb_assert (scope == COMPILE_I_PRINT_ADDRESS_SCOPE);
-	  do_cleanups (cleanup_xfree);
 	  eval_compile_command (cmd, cmd_string,
 				COMPILE_I_PRINT_VALUE_SCOPE, scope_data);
 	  return;
 	}
       discard_cleanups (cleanup_unlink);
-      do_cleanups (cleanup_xfree);
       compile_object_run (compile_module);
     }
 }
diff --git a/gdb/language.h b/gdb/language.h
index d6f932e..758f265 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -406,8 +406,8 @@ struct language_defn
        If 'la_get_gcc_context' is not defined, then this method is
        ignored.
 
-       This takes the user-supplied text and returns a newly malloc'd
-       bit of code to compile.  The caller owns the result.
+       This takes the user-supplied text and returns a new bit of code
+       to compile.
 
        INST is the compiler instance being used.
        INPUT is the user's input text.
@@ -416,11 +416,11 @@ struct language_defn
        parsed.
        EXPR_PC is the PC at which the expression is being parsed.  */
 
-    char *(*la_compute_program) (struct compile_instance *inst,
-				 const char *input,
-				 struct gdbarch *gdbarch,
-				 const struct block *expr_block,
-				 CORE_ADDR expr_pc);
+    std::string (*la_compute_program) (struct compile_instance *inst,
+				       const char *input,
+				       struct gdbarch *gdbarch,
+				       const struct block *expr_block,
+				       CORE_ADDR expr_pc);
 
     /* Add fields above this point, so the magic number is always last.  */
     /* Magic number for compat checking.  */
-- 
2.5.5

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

* [PATCH v2 03/31] breakpoint.c:commands_command_1 constification and cleanup
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (12 preceding siblings ...)
  2016-10-19  1:13 ` [PATCH v2 15/31] Use ui_file_as_string in execute_command_to_string Pedro Alves
@ 2016-10-19  1:13 ` Pedro Alves
  2016-10-19  1:13 ` [PATCH v2 14/31] Use ui_file_as_string in gdb/guile/ Pedro Alves
                   ` (16 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

This is constification needed for next patch.  Adjust
commands_command_1 to use std::string too because the "arg" parameter
is currently overwritten and then passed to make_cleanup.  The
constification alone would trigger a compile error in the make_cleanup
call otherwise (passing const char * to void * parameter).  Using
std::string gets rid of the cleanup in the first place, resulting in
simpler code.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* breakpoint.c (struct commands_info) <arg>: Constify.
	(commands_command_1): Constify 'arg' parameter.  Use std::string
	and string_printf.
	(commands_from_control_command): Constify 'arg' parameter.
	(map_breakpoint_numbers): Constify 'args' parameter.
	* breakpoint.h (commands_from_control_command): Constify 'arg'
	parameter.
---
 gdb/breakpoint.c | 42 +++++++++++++++++-------------------------
 gdb/breakpoint.h |  2 +-
 2 files changed, 18 insertions(+), 26 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 32d6a95..c9b151f 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -102,8 +102,9 @@ static void disable_command (char *, int);
 
 static void enable_command (char *, int);
 
-static void map_breakpoint_numbers (char *, void (*) (struct breakpoint *,
-						      void *),
+static void map_breakpoint_numbers (const char *,
+				    void (*) (struct breakpoint *,
+					      void *),
 				    void *);
 
 static void ignore_command (char *, int);
@@ -1338,7 +1339,7 @@ struct commands_info
   int from_tty;
 
   /* The breakpoint range spec.  */
-  char *arg;
+  const char *arg;
 
   /* Non-NULL if the body of the commands are being read from this
      already-parsed command.  */
@@ -1399,7 +1400,7 @@ do_map_commands_command (struct breakpoint *b, void *data)
 }
 
 static void
-commands_command_1 (char *arg, int from_tty, 
+commands_command_1 (const char *arg, int from_tty,
 		    struct command_line *control)
 {
   struct cleanup *cleanups;
@@ -1412,32 +1413,22 @@ commands_command_1 (char *arg, int from_tty,
      extra reference to the commands that we must clean up.  */
   cleanups = make_cleanup_decref_counted_command_line (&info.cmd);
 
+  std::string new_arg;
+
   if (arg == NULL || !*arg)
     {
       if (breakpoint_count - prev_breakpoint_count > 1)
-	arg = xstrprintf ("%d-%d", prev_breakpoint_count + 1, 
-			  breakpoint_count);
+	new_arg = string_printf ("%d-%d", prev_breakpoint_count + 1,
+				 breakpoint_count);
       else if (breakpoint_count > 0)
-	arg = xstrprintf ("%d", breakpoint_count);
-      else
-	{
-	  /* So that we don't try to free the incoming non-NULL
-	     argument in the cleanup below.  Mapping breakpoint
-	     numbers will fail in this case.  */
-	  arg = NULL;
-	}
+	new_arg = string_printf ("%d", breakpoint_count);
     }
   else
-    /* The command loop has some static state, so we need to preserve
-       our argument.  */
-    arg = xstrdup (arg);
-
-  if (arg != NULL)
-    make_cleanup (xfree, arg);
+    new_arg = arg;
 
-  info.arg = arg;
+  info.arg = new_arg.c_str ();
 
-  map_breakpoint_numbers (arg, do_map_commands_command, &info);
+  map_breakpoint_numbers (info.arg, do_map_commands_command, &info);
 
   if (info.cmd == NULL)
     error (_("No breakpoints specified."));
@@ -1457,7 +1448,7 @@ commands_command (char *arg, int from_tty)
    This is used by cli-script.c to DTRT with breakpoint commands
    that are part of if and while bodies.  */
 enum command_control_type
-commands_from_control_command (char *arg, struct command_line *cmd)
+commands_from_control_command (const char *arg, struct command_line *cmd)
 {
   commands_command_1 (arg, 0, cmd);
   return simple_control;
@@ -14769,8 +14760,9 @@ ignore_command (char *args, int from_tty)
    whose numbers are given in ARGS.  */
 
 static void
-map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *,
-						      void *),
+map_breakpoint_numbers (const char *args,
+			void (*function) (struct breakpoint *,
+					  void *),
 			void *data)
 {
   int num;
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index aaff3d5..ebaf1e3 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1456,7 +1456,7 @@ extern void enable_breakpoints_after_startup (void);
    after they've already read the commands into a struct
    command_line.  */
 extern enum command_control_type commands_from_control_command
-  (char *arg, struct command_line *cmd);
+  (const char *arg, struct command_line *cmd);
 
 extern void clear_breakpoint_hit_counts (void);
 
-- 
2.5.5

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

* [PATCH v2 29/31] 'struct agent_expr *' -> unique_ptr<agent_expr>
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (15 preceding siblings ...)
  2016-10-19  1:13 ` [PATCH v2 27/31] Use ui_file_as_string in gdb/language.c Pedro Alves
@ 2016-10-19  1:13 ` Pedro Alves
  2016-10-19 23:19   ` Simon Marchi
  2016-10-19  1:13 ` [PATCH v2 23/31] Use ui_file_as_string in gdbarch.sh/gdbarch.c Pedro Alves
                   ` (13 subsequent siblings)
  30 siblings, 1 reply; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

This patch makes the gen_* functions return a unique_ptr instead of
raw pointer:

  typedef gdb::unique_ptr<agent_expr> agent_expr_up;

and then adjusts the codebase throughout to stop using
make_cleanup_free_agent_expr.

The cond_bytecode and cmd_bytecode fields of struct bp_location are
owning pointers, so they're changed to be unique_ptr's instead of raw
pointers.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* ax-gdb.c (is_nontrivial_conversion): Use agent_expr_up.
	(gen_trace_for_var, gen_trace_for_expr, gen_eval_for_expr)
	(gen_trace_for_return_address, gen_printf): Use and return an
	agent_expr_up.  Don't use make_cleanup_free_agent_expr.
	(agent_eval_command_one, maint_agent_printf_command): Use
	agent_expr_up.  Don't use make_cleanup_free_agent_expr.
	* ax-gdb.h (gen_trace_for_expr, gen_trace_for_var)
	(gen_trace_for_return_address, gen_eval_for_expr, gen_printf): Use
	agent_expr_up.
	* ax-general.c (new_agent_expr): Rename to ...
	(agent_expr::agent_expr): ... this, and now a constructor.
	(free_agent_expr): Rename to ...
	(agent_expr::~agent_exp): ... this, and now a destructor.
	(do_free_agent_expr_cleanup, make_cleanup_free_agent_expr):
	Delete.
	* ax.h (struct agent_expr): Add ctor/dtor.
	(agent_expr_up): New typedef.
	(new_agent_expr, free_agent_expr, make_cleanup_free_agent_expr):
	Delete declarations.
	* breakpoint.c (parse_cond_to_aexpr): Use and return an
	agent_expr_up.  Don't use make_cleanup_free_agent_expr.
	(build_target_condition_list): Adjust to use agent_expr_up.
	(parse_cmd_to_aexpr): Use and return an agent_expr_up.  Don't use
	make_cleanup_free_agent_expr.
	(build_target_command_list): Adjust to use agent_expr_up.
	(force_breakpoint_reinsertion): Adjust to use agent_expr_up.
	(bp_location_dtor): Remove unnecessary free_agent_expr and xfree
	calls.
	* breakpoint.h (struct bp_target_info) <cond_bytecode,
	cmd_bytecode>: Now agent_expr_up's.
	* remote.c (remote_download_tracepoint): Adjust to use
	agent_expr_up and remove use of make_cleanup_free_agent_expr.
	* tracepoint.c (validate_actionline, collect_symbol): Adjust to
	use agent_expr_up and remove uses of make_cleanup_free_agent_expr.
	(collection_list::~collection_list): Call delete instead of
	free_agent_expr.
	(encode_actions_1): Adjust to use agent_expr_up and remove uses of
	make_cleanup_free_agent_expr.
	(add_aexpr): Change parameter type to agent_expr_up; Return a raw
	agent_expr pointer.
---
 gdb/ax-gdb.c     | 140 +++++++++++++++++++------------------------------------
 gdb/ax-gdb.h     |  24 +++++-----
 gdb/ax-general.c |  48 ++++++-------------
 gdb/ax.h         |  15 +++---
 gdb/breakpoint.c |  61 ++++++++++--------------
 gdb/breakpoint.h |   4 +-
 gdb/remote.c     |   6 +--
 gdb/tracepoint.c | 107 ++++++++++++++++--------------------------
 gdb/tracepoint.h |   4 +-
 9 files changed, 153 insertions(+), 256 deletions(-)

diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index ccd16f2..1816ba6 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -910,7 +910,7 @@ gen_conversion (struct agent_expr *ax, struct type *from, struct type *to)
 static int
 is_nontrivial_conversion (struct type *from, struct type *to)
 {
-  struct agent_expr *ax = new_agent_expr (NULL, 0);
+  agent_expr_up ax (new agent_expr (NULL, 0));
   int nontrivial;
 
   /* Actually generate the code, and see if anything came out.  At the
@@ -919,9 +919,8 @@ is_nontrivial_conversion (struct type *from, struct type *to)
      floating point and the like, it may not be.  Doing things this
      way allows this function to be independent of the logic in
      gen_conversion.  */
-  gen_conversion (ax, from, to);
+  gen_conversion (ax.get (), from, to);
   nontrivial = ax->len > 0;
-  free_agent_expr (ax);
   return nontrivial;
 }
 
@@ -2391,38 +2390,28 @@ gen_expr_binop_rest (struct expression *exp,
    variable's name, and no parsed expression; for instance, when the
    name comes from a list of local variables of a function.  */
 
-struct agent_expr *
+agent_expr_up
 gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch,
 		   struct symbol *var, int trace_string)
 {
-  struct cleanup *old_chain = 0;
-  struct agent_expr *ax = new_agent_expr (gdbarch, scope);
+  agent_expr_up ax (new agent_expr (gdbarch, scope));
   struct axs_value value;
 
-  old_chain = make_cleanup_free_agent_expr (ax);
-
   ax->tracing = 1;
   ax->trace_string = trace_string;
-  gen_var_ref (gdbarch, ax, &value, var);
+  gen_var_ref (gdbarch, ax.get (), &value, var);
 
   /* If there is no actual variable to trace, flag it by returning
      an empty agent expression.  */
   if (value.optimized_out)
-    {
-      do_cleanups (old_chain);
-      return NULL;
-    }
+    return agent_expr_up ();
 
   /* Make sure we record the final object, and get rid of it.  */
-  gen_traced_pop (gdbarch, ax, &value);
+  gen_traced_pop (gdbarch, ax.get (), &value);
 
   /* Oh, and terminate.  */
-  ax_simple (ax, aop_end);
+  ax_simple (ax.get (), aop_end);
 
-  /* We have successfully built the agent expr, so cancel the cleanup
-     request.  If we add more cleanups that we always want done, this
-     will have to get more complicated.  */
-  discard_cleanups (old_chain);
   return ax;
 }
 
@@ -2433,33 +2422,27 @@ gen_trace_for_var (CORE_ADDR scope, struct gdbarch *gdbarch,
    record the value of all memory touched by the expression.  The
    caller can then use the ax_reqs function to discover which
    registers it relies upon.  */
-struct agent_expr *
+
+agent_expr_up
 gen_trace_for_expr (CORE_ADDR scope, struct expression *expr,
 		    int trace_string)
 {
-  struct cleanup *old_chain = 0;
-  struct agent_expr *ax = new_agent_expr (expr->gdbarch, scope);
+  agent_expr_up ax (new agent_expr (expr->gdbarch, scope));
   union exp_element *pc;
   struct axs_value value;
 
-  old_chain = make_cleanup_free_agent_expr (ax);
-
   pc = expr->elts;
   ax->tracing = 1;
   ax->trace_string = trace_string;
   value.optimized_out = 0;
-  gen_expr (expr, &pc, ax, &value);
+  gen_expr (expr, &pc, ax.get (), &value);
 
   /* Make sure we record the final object, and get rid of it.  */
-  gen_traced_pop (expr->gdbarch, ax, &value);
+  gen_traced_pop (expr->gdbarch, ax.get (), &value);
 
   /* Oh, and terminate.  */
-  ax_simple (ax, aop_end);
+  ax_simple (ax.get (), aop_end);
 
-  /* We have successfully built the agent expr, so cancel the cleanup
-     request.  If we add more cleanups that we always want done, this
-     will have to get more complicated.  */
-  discard_cleanups (old_chain);
   return ax;
 }
 
@@ -2470,58 +2453,44 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr,
    gen_trace_for_expr does.  The generated bytecode sequence leaves
    the result of expression evaluation on the top of the stack.  */
 
-struct agent_expr *
+agent_expr_up
 gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
 {
-  struct cleanup *old_chain = 0;
-  struct agent_expr *ax = new_agent_expr (expr->gdbarch, scope);
+  agent_expr_up ax (new agent_expr (expr->gdbarch, scope));
   union exp_element *pc;
   struct axs_value value;
 
-  old_chain = make_cleanup_free_agent_expr (ax);
-
   pc = expr->elts;
   ax->tracing = 0;
   value.optimized_out = 0;
-  gen_expr (expr, &pc, ax, &value);
+  gen_expr (expr, &pc, ax.get (), &value);
 
-  require_rvalue (ax, &value);
+  require_rvalue (ax.get (), &value);
 
   /* Oh, and terminate.  */
-  ax_simple (ax, aop_end);
+  ax_simple (ax.get (), aop_end);
 
-  /* We have successfully built the agent expr, so cancel the cleanup
-     request.  If we add more cleanups that we always want done, this
-     will have to get more complicated.  */
-  discard_cleanups (old_chain);
   return ax;
 }
 
-struct agent_expr *
+agent_expr_up
 gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch,
 			      int trace_string)
 {
-  struct cleanup *old_chain = 0;
-  struct agent_expr *ax = new_agent_expr (gdbarch, scope);
+  agent_expr_up ax (new agent_expr (gdbarch, scope));
   struct axs_value value;
 
-  old_chain = make_cleanup_free_agent_expr (ax);
-
   ax->tracing = 1;
   ax->trace_string = trace_string;
 
-  gdbarch_gen_return_address (gdbarch, ax, &value, scope);
+  gdbarch_gen_return_address (gdbarch, ax.get (), &value, scope);
 
   /* Make sure we record the final object, and get rid of it.  */
-  gen_traced_pop (gdbarch, ax, &value);
+  gen_traced_pop (gdbarch, ax.get (), &value);
 
   /* Oh, and terminate.  */
-  ax_simple (ax, aop_end);
+  ax_simple (ax.get (), aop_end);
 
-  /* We have successfully built the agent expr, so cancel the cleanup
-     request.  If we add more cleanups that we always want done, this
-     will have to get more complicated.  */
-  discard_cleanups (old_chain);
   return ax;
 }
 
@@ -2529,21 +2498,18 @@ gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch,
    evaluate the arguments and pass everything to a special
    bytecode.  */
 
-struct agent_expr *
+agent_expr_up
 gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch,
 	    CORE_ADDR function, LONGEST channel,
 	    const char *format, int fmtlen,
 	    struct format_piece *frags,
 	    int nargs, struct expression **exprs)
 {
-  struct cleanup *old_chain = 0;
-  struct agent_expr *ax = new_agent_expr (gdbarch, scope);
+  agent_expr_up ax (new agent_expr (gdbarch, scope));
   union exp_element *pc;
   struct axs_value value;
   int tem;
 
-  old_chain = make_cleanup_free_agent_expr (ax);
-
   /* We're computing values, not doing side effects.  */
   ax->tracing = 0;
 
@@ -2553,26 +2519,21 @@ gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch,
     {
       pc = exprs[tem]->elts;
       value.optimized_out = 0;
-      gen_expr (exprs[tem], &pc, ax, &value);
-      require_rvalue (ax, &value);
+      gen_expr (exprs[tem], &pc, ax.get (), &value);
+      require_rvalue (ax.get (), &value);
     }
 
   /* Push function and channel.  */
-  ax_const_l (ax, channel);
-  ax_const_l (ax, function);
+  ax_const_l (ax.get (), channel);
+  ax_const_l (ax.get (), function);
 
   /* Issue the printf bytecode proper.  */
-  ax_simple (ax, aop_printf);
-  ax_raw_byte (ax, nargs);
-  ax_string (ax, format, fmtlen);
+  ax_simple (ax.get (), aop_printf);
+  ax_raw_byte (ax.get (), nargs);
+  ax_string (ax.get (), format, fmtlen);
 
   /* And terminate.  */
-  ax_simple (ax, aop_end);
-
-  /* We have successfully built the agent expr, so cancel the cleanup
-     request.  If we add more cleanups that we always want done, this
-     will have to get more complicated.  */
-  discard_cleanups (old_chain);
+  ax_simple (ax.get (), aop_end);
 
   return ax;
 }
@@ -2580,8 +2541,6 @@ gen_printf (CORE_ADDR scope, struct gdbarch *gdbarch,
 static void
 agent_eval_command_one (const char *exp, int eval, CORE_ADDR pc)
 {
-  struct cleanup *old_chain = 0;
-  struct agent_expr *agent;
   const char *arg;
   int trace_string = 0;
 
@@ -2591,33 +2550,33 @@ agent_eval_command_one (const char *exp, int eval, CORE_ADDR pc)
         exp = decode_agent_options (exp, &trace_string);
     }
 
+  agent_expr_up agent;
+
   arg = exp;
   if (!eval && strcmp (arg, "$_ret") == 0)
     {
-      agent = gen_trace_for_return_address (pc, get_current_arch (),
-					    trace_string);
-      old_chain = make_cleanup_free_agent_expr (agent);
+      agent = gdb::move (gen_trace_for_return_address (pc, get_current_arch (),
+						       trace_string));
     }
   else
     {
       expression_up expr = parse_exp_1 (&arg, pc, block_for_pc (pc), 0);
+
       if (eval)
 	{
 	  gdb_assert (trace_string == 0);
-	  agent = gen_eval_for_expr (pc, expr.get ());
+	  agent = gdb::move (gen_eval_for_expr (pc, expr.get ()));
 	}
       else
-	agent = gen_trace_for_expr (pc, expr.get (), trace_string);
-      old_chain = make_cleanup_free_agent_expr (agent);
+	agent = gdb::move (gen_trace_for_expr (pc, expr.get (), trace_string));
     }
 
-  ax_reqs (agent);
-  ax_print (gdb_stdout, agent);
+  ax_reqs (agent.get ());
+  ax_print (gdb_stdout, agent.get ());
 
   /* It would be nice to call ax_reqs here to gather some general info
      about the expression, and then print out the result.  */
 
-  do_cleanups (old_chain);
   dont_repeat ();
 }
 
@@ -2695,7 +2654,6 @@ maint_agent_printf_command (char *exp, int from_tty)
 {
   struct cleanup *old_chain = 0;
   struct expression *argvec[100];
-  struct agent_expr *agent;
   struct frame_info *fi = get_current_frame ();	/* need current scope */
   const char *cmdrest;
   const char *format_start, *format_end;
@@ -2755,12 +2713,12 @@ maint_agent_printf_command (char *exp, int from_tty)
     }
 
 
-  agent = gen_printf (get_frame_pc (fi), get_current_arch (), 0, 0,
-		      format_start, format_end - format_start,
-		      fpieces, nargs, argvec);
-  make_cleanup_free_agent_expr (agent);
-  ax_reqs (agent);
-  ax_print (gdb_stdout, agent);
+  agent_expr_up agent = gen_printf (get_frame_pc (fi), get_current_arch (),
+				    0, 0,
+				    format_start, format_end - format_start,
+				    fpieces, nargs, argvec);
+  ax_reqs (agent.get ());
+  ax_print (gdb_stdout, agent.get ());
 
   /* It would be nice to call ax_reqs here to gather some general info
      about the expression, and then print out the result.  */
diff --git a/gdb/ax-gdb.h b/gdb/ax-gdb.h
index dacacfc..0d791e9 100644
--- a/gdb/ax-gdb.h
+++ b/gdb/ax-gdb.h
@@ -101,17 +101,17 @@ struct axs_value
    record the value of all memory touched by the expression, and leave
    no values on the stack.  The caller can then use the ax_reqs
    function to discover which registers the expression uses.  */
-extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *,
-					      int);
+extern agent_expr_up gen_trace_for_expr (CORE_ADDR, struct expression *,
+					 int);
 
-extern struct agent_expr *gen_trace_for_var (CORE_ADDR, struct gdbarch *,
-					     struct symbol *, int);
+extern agent_expr_up gen_trace_for_var (CORE_ADDR, struct gdbarch *,
+					struct symbol *, int);
 
-extern struct agent_expr *gen_trace_for_return_address (CORE_ADDR,
-							struct gdbarch *,
-							int);
+extern agent_expr_up gen_trace_for_return_address (CORE_ADDR,
+						   struct gdbarch *,
+						   int);
 
-extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *);
+extern agent_expr_up gen_eval_for_expr (CORE_ADDR, struct expression *);
 
 extern void gen_expr (struct expression *exp, union exp_element **pc,
 		      struct agent_expr *ax, struct axs_value *value);
@@ -119,9 +119,9 @@ extern void gen_expr (struct expression *exp, union exp_element **pc,
 extern void require_rvalue (struct agent_expr *ax, struct axs_value *value);
 
 struct format_piece;
-extern struct agent_expr *gen_printf (CORE_ADDR, struct gdbarch *,
-				      CORE_ADDR, LONGEST, const char *, int,
-				      struct format_piece *,
-				      int, struct expression **);
+extern agent_expr_up gen_printf (CORE_ADDR, struct gdbarch *,
+				 CORE_ADDR, LONGEST, const char *, int,
+				 struct format_piece *,
+				 int, struct expression **);
 
 #endif /* AX_GDB_H */
diff --git a/gdb/ax-general.c b/gdb/ax-general.c
index 7f27a45..35225f6 100644
--- a/gdb/ax-general.c
+++ b/gdb/ax-general.c
@@ -37,52 +37,30 @@ static void generic_ext (struct agent_expr *x, enum agent_op op, int n);
 \f
 /* Functions for building expressions.  */
 
-/* Allocate a new, empty agent expression.  */
-struct agent_expr *
-new_agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
+agent_expr::agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
 {
-  struct agent_expr *x = XNEW (struct agent_expr);
-
-  x->len = 0;
-  x->size = 1;			/* Change this to a larger value once
+  this->len = 0;
+  this->size = 1;		/* Change this to a larger value once
 				   reallocation code is tested.  */
-  x->buf = (unsigned char *) xmalloc (x->size);
+  this->buf = (unsigned char *) xmalloc (this->size);
 
-  x->gdbarch = gdbarch;
-  x->scope = scope;
+  this->gdbarch = gdbarch;
+  this->scope = scope;
 
   /* Bit vector for registers used.  */
-  x->reg_mask_len = 1;
-  x->reg_mask = XCNEWVEC (unsigned char, x->reg_mask_len);
-
-  x->tracing = 0;
-  x->trace_string = 0;
+  this->reg_mask_len = 1;
+  this->reg_mask = XCNEWVEC (unsigned char, this->reg_mask_len);
 
-  return x;
+  this->tracing = 0;
+  this->trace_string = 0;
 }
 
-/* Free a agent expression.  */
-void
-free_agent_expr (struct agent_expr *x)
+agent_expr::~agent_expr ()
 {
-  xfree (x->buf);
-  xfree (x->reg_mask);
-  xfree (x);
+  xfree (this->buf);
+  xfree (this->reg_mask);
 }
 
-static void
-do_free_agent_expr_cleanup (void *x)
-{
-  free_agent_expr ((struct agent_expr *) x);
-}
-
-struct cleanup *
-make_cleanup_free_agent_expr (struct agent_expr *x)
-{
-  return make_cleanup (do_free_agent_expr_cleanup, x);
-}
-
-
 /* Make sure that X has room for at least N more bytes.  This doesn't
    affect the length, just the allocated size.  */
 static void
diff --git a/gdb/ax.h b/gdb/ax.h
index 536efe8..4b90229 100644
--- a/gdb/ax.h
+++ b/gdb/ax.h
@@ -94,6 +94,11 @@ union agent_val
 /* A buffer containing a agent expression.  */
 struct agent_expr
   {
+    /* Construct an empty agent expression.  */
+    explicit agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope);
+
+    ~agent_expr ();
+
     /* The bytes of the expression.  */
     unsigned char *buf;
 
@@ -162,6 +167,9 @@ struct agent_expr
     int trace_string;
   };
 
+/* An agent_expr owning pointer.  */
+typedef gdb::unique_ptr<agent_expr> agent_expr_up;
+
 /* Pointer to an agent_expr structure.  */
 typedef struct agent_expr *agent_expr_p;
 
@@ -183,13 +191,6 @@ enum agent_op
 
 /* Functions for building expressions.  */
 
-/* Allocate a new, empty agent expression.  */
-extern struct agent_expr *new_agent_expr (struct gdbarch *, CORE_ADDR);
-
-/* Free a agent expression.  */
-extern void free_agent_expr (struct agent_expr *);
-extern struct cleanup *make_cleanup_free_agent_expr (struct agent_expr *);
-
 /* Append a raw byte to EXPR.  */
 extern void ax_raw_byte (struct agent_expr *expr, gdb_byte byte);
 
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index b9bb797..77f551b 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -2256,19 +2256,19 @@ unduplicated_should_be_inserted (struct bp_location *bl)
    by the bytecode interpreter.  Return NULL if there was
    any error during parsing.  */
 
-static struct agent_expr *
+static agent_expr_up
 parse_cond_to_aexpr (CORE_ADDR scope, struct expression *cond)
 {
-  struct agent_expr *aexpr = NULL;
-
-  if (!cond)
+  if (cond == NULL)
     return NULL;
 
+  agent_expr_up aexpr;
+
   /* We don't want to stop processing, so catch any errors
      that may show up.  */
   TRY
     {
-      aexpr = gen_eval_for_expr (scope, cond);
+      aexpr = gdb::move (gen_eval_for_expr (scope, cond));
     }
 
   CATCH (ex, RETURN_MASK_ERROR)
@@ -2276,7 +2276,6 @@ parse_cond_to_aexpr (CORE_ADDR scope, struct expression *cond)
       /* If we got here, it means the condition could not be parsed to a valid
 	 bytecode expression and thus can't be evaluated on the target's side.
 	 It's no use iterating through the conditions.  */
-      return NULL;
     }
   END_CATCH
 
@@ -2321,14 +2320,12 @@ build_target_condition_list (struct bp_location *bl)
 	{
 	  if (modified)
 	    {
-	      struct agent_expr *aexpr;
-
 	      /* Re-parse the conditions since something changed.  In that
 		 case we already freed the condition bytecodes (see
 		 force_breakpoint_reinsertion).  We just
 		 need to parse the condition to bytecodes again.  */
-	      aexpr = parse_cond_to_aexpr (bl->address, loc->cond.get ());
-	      loc->cond_bytecode = aexpr;
+	      loc->cond_bytecode = parse_cond_to_aexpr (bl->address,
+							loc->cond.get ());
 	    }
 
 	  /* If we have a NULL bytecode expression, it means something
@@ -2359,8 +2356,7 @@ build_target_condition_list (struct bp_location *bl)
 	      if (!loc->cond_bytecode)
 		return;
 
-	      free_agent_expr (loc->cond_bytecode);
-	      loc->cond_bytecode = NULL;
+	      loc->cond_bytecode.reset ();
 	    }
 	}
     }
@@ -2378,7 +2374,7 @@ build_target_condition_list (struct bp_location *bl)
 	/* Add the condition to the vector.  This will be used later to send the
 	   conditions to the target.  */
 	VEC_safe_push (agent_expr_p, bl->target_info.conditions,
-		       loc->cond_bytecode);
+		       loc->cond_bytecode.get ());
     }
 
   return;
@@ -2388,19 +2384,18 @@ build_target_condition_list (struct bp_location *bl)
    bytecode suitable for evaluation by the bytecode interpreter.
    Return NULL if there was any error during parsing.  */
 
-static struct agent_expr *
+static agent_expr_up
 parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
 {
   struct cleanup *old_cleanups = 0;
   struct expression **argvec;
-  struct agent_expr *aexpr = NULL;
   const char *cmdrest;
   const char *format_start, *format_end;
   struct format_piece *fpieces;
   int nargs;
   struct gdbarch *gdbarch = get_current_arch ();
 
-  if (!cmd)
+  if (cmd == NULL)
     return NULL;
 
   cmdrest = cmd;
@@ -2450,20 +2445,21 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
 	++cmdrest;
     }
 
+  agent_expr_up aexpr;
+
   /* We don't want to stop processing, so catch any errors
      that may show up.  */
   TRY
     {
-      aexpr = gen_printf (scope, gdbarch, 0, 0,
-			  format_start, format_end - format_start,
-			  fpieces, nargs, argvec);
+      aexpr = gdb::move (gen_printf (scope, gdbarch, 0, 0,
+				     format_start, format_end - format_start,
+				     fpieces, nargs, argvec));
     }
   CATCH (ex, RETURN_MASK_ERROR)
     {
       /* If we got here, it means the command could not be parsed to a valid
 	 bytecode expression and thus can't be evaluated on the target's side.
 	 It's no use iterating through the other commands.  */
-      aexpr = NULL;
     }
   END_CATCH
 
@@ -2520,15 +2516,13 @@ build_target_command_list (struct bp_location *bl)
 	{
 	  if (modified)
 	    {
-	      struct agent_expr *aexpr;
-
 	      /* Re-parse the commands since something changed.  In that
 		 case we already freed the command bytecodes (see
 		 force_breakpoint_reinsertion).  We just
 		 need to parse the command to bytecodes again.  */
-	      aexpr = parse_cmd_to_aexpr (bl->address,
-					  loc->owner->extra_string);
-	      loc->cmd_bytecode = aexpr;
+	      loc->cmd_bytecode
+		= parse_cmd_to_aexpr (bl->address,
+				      loc->owner->extra_string);
 	    }
 
 	  /* If we have a NULL bytecode expression, it means something
@@ -2556,8 +2550,7 @@ build_target_command_list (struct bp_location *bl)
 	      if (loc->cmd_bytecode == NULL)
 		return;
 
-	      free_agent_expr (loc->cmd_bytecode);
-	      loc->cmd_bytecode = NULL;
+	      loc->cmd_bytecode.reset ();
 	    }
 	}
     }
@@ -2575,7 +2568,7 @@ build_target_command_list (struct bp_location *bl)
 	/* Add the command to the vector.  This will be used later
 	   to send the commands to the target.  */
 	VEC_safe_push (agent_expr_p, bl->target_info.tcommands,
-		       loc->cmd_bytecode);
+		       loc->cmd_bytecode.get ());
     }
 
   bl->target_info.persist = 0;
@@ -12385,13 +12378,9 @@ force_breakpoint_reinsertion (struct bp_location *bl)
 	 that have already been marked.  */
       loc->condition_changed = condition_updated;
 
-      /* Free the agent expression bytecode as well.  We will compute
-	 it later on.  */
-      if (loc->cond_bytecode)
-	{
-	  free_agent_expr (loc->cond_bytecode);
-	  loc->cond_bytecode = NULL;
-	}
+      /* Release the agent expression bytecode as well.  We will
+	 compute it later on.  */
+      loc->cond_bytecode.reset ();
     }
 }
 /* Called whether new breakpoints are created, or existing breakpoints
@@ -12877,8 +12866,6 @@ say_where (struct breakpoint *b)
 static void
 bp_location_dtor (struct bp_location *self)
 {
-  if (self->cond_bytecode)
-    free_agent_expr (self->cond_bytecode);
   xfree (self->function_name);
 
   VEC_free (agent_expr_p, self->target_info.conditions);
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 9b4c96a..018dddb 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -348,7 +348,7 @@ struct bp_location
   /* Conditional expression in agent expression
      bytecode form.  This is used for stub-side breakpoint
      condition evaluation.  */
-  struct agent_expr *cond_bytecode;
+  agent_expr_up cond_bytecode;
 
   /* Signals that the condition has changed since the last time
      we updated the global location list.  This means the condition
@@ -365,7 +365,7 @@ struct bp_location
 
   enum condition_status condition_changed;
 
-  struct agent_expr *cmd_bytecode;
+  agent_expr_up cmd_bytecode;
 
   /* Signals that breakpoint conditions and/or commands need to be
      re-synched with the target.  This has no use other than
diff --git a/gdb/remote.c b/gdb/remote.c
index e741a58..294d928 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -11842,8 +11842,6 @@ remote_download_tracepoint (struct target_ops *self, struct bp_location *loc)
   char **stepping_actions;
   int ndx;
   struct cleanup *old_chain = NULL;
-  struct agent_expr *aexpr;
-  struct cleanup *aexpr_chain = NULL;
   char *pkt;
   struct breakpoint *b = loc->owner;
   struct tracepoint *t = (struct tracepoint *) b;
@@ -11914,15 +11912,13 @@ remote_download_tracepoint (struct target_ops *self, struct bp_location *loc)
 	 capabilities at definition time.  */
       if (remote_supports_cond_tracepoints ())
 	{
-	  aexpr = gen_eval_for_expr (tpaddr, loc->cond.get ());
-	  aexpr_chain = make_cleanup_free_agent_expr (aexpr);
+	  agent_expr_up aexpr = gen_eval_for_expr (tpaddr, loc->cond.get ());
 	  xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":X%x,",
 		     aexpr->len);
 	  pkt = buf + strlen (buf);
 	  for (ndx = 0; ndx < aexpr->len; ++ndx)
 	    pkt = pack_hex_byte (pkt, aexpr->buf[ndx]);
 	  *pkt = '\0';
-	  do_cleanups (aexpr_chain);
 	}
       else
 	warning (_("Target does not support conditional tracepoints, "
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 7ff41f9..3d28606 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -702,7 +702,6 @@ validate_actionline (const char *line, struct breakpoint *b)
   const char *tmp_p;
   const char *p;
   struct bp_location *loc;
-  struct agent_expr *aexpr;
   struct tracepoint *t = (struct tracepoint *) b;
 
   /* If EOF is typed, *line is NULL.  */
@@ -775,17 +774,16 @@ validate_actionline (const char *line, struct breakpoint *b)
 	      /* We have something to collect, make sure that the expr to
 		 bytecode translator can handle it and that it's not too
 		 long.  */
-	      aexpr = gen_trace_for_expr (loc->address, exp.get (), trace_string);
-	      old_chain = make_cleanup_free_agent_expr (aexpr);
+	      agent_expr_up aexpr = gen_trace_for_expr (loc->address,
+							exp.get (),
+							trace_string);
 
 	      if (aexpr->len > MAX_AGENT_EXPR_LEN)
 		error (_("Expression is too complicated."));
 
-	      ax_reqs (aexpr);
-
-	      report_agent_reqs_errors (aexpr);
+	      ax_reqs (aexpr.get ());
 
-	      do_cleanups (old_chain);
+	      report_agent_reqs_errors (aexpr.get ());
 	    }
 	}
       while (p && *p++ == ',');
@@ -810,16 +808,13 @@ validate_actionline (const char *line, struct breakpoint *b)
 	      /* We have something to evaluate, make sure that the expr to
 		 bytecode translator can handle it and that it's not too
 		 long.  */
-	      aexpr = gen_eval_for_expr (loc->address, exp.get ());
-	      old_chain = make_cleanup_free_agent_expr (aexpr);
+	      agent_expr_up aexpr = gen_eval_for_expr (loc->address, exp.get ());
 
 	      if (aexpr->len > MAX_AGENT_EXPR_LEN)
 		error (_("Expression is too complicated."));
 
-	      ax_reqs (aexpr);
-	      report_agent_reqs_errors (aexpr);
-
-	      do_cleanups (old_chain);
+	      ax_reqs (aexpr.get ());
+	      report_agent_reqs_errors (aexpr.get ());
 	    }
 	}
       while (p && *p++ == ',');
@@ -1045,10 +1040,10 @@ collection_list::collect_symbol (struct symbol *sym,
   /* Expressions are the most general case.  */
   if (treat_as_expr)
     {
-      struct agent_expr *aexpr;
       struct cleanup *old_chain1 = NULL;
 
-      aexpr = gen_trace_for_var (scope, gdbarch, sym, trace_string);
+      agent_expr_up aexpr = gen_trace_for_var (scope, gdbarch,
+					       sym, trace_string);
 
       /* It can happen that the symbol is recorded as a computed
 	 location, but it's been optimized away and doesn't actually
@@ -1060,33 +1055,28 @@ collection_list::collect_symbol (struct symbol *sym,
 	  return;
 	}
 
-      old_chain1 = make_cleanup_free_agent_expr (aexpr);
+      ax_reqs (aexpr.get ());
 
-      ax_reqs (aexpr);
-
-      report_agent_reqs_errors (aexpr);
-
-      discard_cleanups (old_chain1);
-      add_aexpr (aexpr);
+      report_agent_reqs_errors (aexpr.get ());
 
       /* Take care of the registers.  */
       if (aexpr->reg_mask_len > 0)
 	{
-	  int ndx1, ndx2;
-
-	  for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
+	  for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
 	    {
 	      QUIT;	/* Allow user to bail out with ^C.  */
 	      if (aexpr->reg_mask[ndx1] != 0)
 		{
 		  /* Assume chars have 8 bits.  */
-		  for (ndx2 = 0; ndx2 < 8; ndx2++)
+		  for (int ndx2 = 0; ndx2 < 8; ndx2++)
 		    if (aexpr->reg_mask[ndx1] & (1 << ndx2))
 		      /* It's used -- record it.  */
 		      add_register (ndx1 * 8 + ndx2);
 		}
 	    }
 	}
+
+      add_aexpr (gdb::move (aexpr));
     }
 }
 
@@ -1193,7 +1183,7 @@ collection_list::collection_list ()
 collection_list::~collection_list ()
 {
   for (int ndx = 0; ndx < m_aexprs.size (); ndx++)
-    free_agent_expr (m_aexprs[ndx]);
+    delete m_aexprs[ndx];
 }
 
 /* Reduce a collection list to string form (for gdb protocol).  */
@@ -1351,7 +1341,6 @@ encode_actions_1 (struct command_line *action,
   int i;
   struct value *tempval;
   struct cmd_list_element *cmd;
-  struct agent_expr *aexpr;
 
   for (; action; action = action->next)
     {
@@ -1403,32 +1392,24 @@ encode_actions_1 (struct command_line *action,
 		}
 	      else if (0 == strncasecmp ("$_ret", action_exp, 5))
 		{
-		  struct cleanup *old_chain1 = NULL;
-
-		  aexpr = gen_trace_for_return_address (tloc->address,
-							target_gdbarch (),
-							trace_string);
-
-		  old_chain1 = make_cleanup_free_agent_expr (aexpr);
-
-		  ax_reqs (aexpr);
-		  report_agent_reqs_errors (aexpr);
+		  agent_expr_up aexpr
+		    = gen_trace_for_return_address (tloc->address,
+						    target_gdbarch (),
+						    trace_string);
 
-		  discard_cleanups (old_chain1);
-		  collect->add_aexpr (aexpr);
+		  ax_reqs (aexpr.get ());
+		  report_agent_reqs_errors (aexpr.get ());
 
 		  /* take care of the registers */
 		  if (aexpr->reg_mask_len > 0)
 		    {
-		      int ndx1, ndx2;
-
-		      for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
+		      for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
 			{
 			  QUIT;	/* allow user to bail out with ^C */
 			  if (aexpr->reg_mask[ndx1] != 0)
 			    {
 			      /* assume chars have 8 bits */
-			      for (ndx2 = 0; ndx2 < 8; ndx2++)
+			      for (int ndx2 = 0; ndx2 < 8; ndx2++)
 				if (aexpr->reg_mask[ndx1] & (1 << ndx2))
 				  {
 				    /* It's used -- record it.  */
@@ -1438,6 +1419,7 @@ encode_actions_1 (struct command_line *action,
 			}
 		    }
 
+		  collect->add_aexpr (gdb::move (aexpr));
 		  action_exp = strchr (action_exp, ',');	/* more? */
 		}
 	      else if (0 == strncasecmp ("$_sdata", action_exp, 7))
@@ -1499,31 +1481,24 @@ encode_actions_1 (struct command_line *action,
 		      break;
 
 		    default:	/* Full-fledged expression.  */
-		      aexpr = gen_trace_for_expr (tloc->address, exp.get (),
-						  trace_string);
-
-		      old_chain1 = make_cleanup_free_agent_expr (aexpr);
+		      agent_expr_up aexpr = gen_trace_for_expr (tloc->address,
+								exp.get (),
+								trace_string);
 
-		      ax_reqs (aexpr);
+		      ax_reqs (aexpr.get ());
 
-		      report_agent_reqs_errors (aexpr);
-
-		      discard_cleanups (old_chain1);
-		      collect->add_aexpr (aexpr);
+		      report_agent_reqs_errors (aexpr.get ());
 
 		      /* Take care of the registers.  */
 		      if (aexpr->reg_mask_len > 0)
 			{
-			  int ndx1;
-			  int ndx2;
-
-			  for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
+			  for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
 			    {
 			      QUIT;	/* Allow user to bail out with ^C.  */
 			      if (aexpr->reg_mask[ndx1] != 0)
 				{
 				  /* Assume chars have 8 bits.  */
-				  for (ndx2 = 0; ndx2 < 8; ndx2++)
+				  for (int ndx2 = 0; ndx2 < 8; ndx2++)
 				    if (aexpr->reg_mask[ndx1] & (1 << ndx2))
 				      {
 					/* It's used -- record it.  */
@@ -1533,6 +1508,7 @@ encode_actions_1 (struct command_line *action,
 			    }
 			}
 
+		      collect->add_aexpr (gdb::move (aexpr));
 		      collect->append_exp (exp.get ());
 		      break;
 		    }		/* switch */
@@ -1554,16 +1530,15 @@ encode_actions_1 (struct command_line *action,
 						   block_for_pc (tloc->address),
 						   1);
 
-		  aexpr = gen_eval_for_expr (tloc->address, exp.get ());
-		  old_chain1 = make_cleanup_free_agent_expr (aexpr);
+		  agent_expr_up aexpr = gen_eval_for_expr (tloc->address,
+							   exp.get ());
 
-		  ax_reqs (aexpr);
-		  report_agent_reqs_errors (aexpr);
+		  ax_reqs (aexpr.get ());
+		  report_agent_reqs_errors (aexpr.get ());
 
-		  discard_cleanups (old_chain1);
 		  /* Even though we're not officially collecting, add
 		     to the collect list anyway.  */
-		  collect->add_aexpr (aexpr);
+		  collect->add_aexpr (gdb::move (aexpr));
 		}		/* do */
 	    }
 	  while (action_exp && *action_exp++ == ',');
@@ -1625,9 +1600,9 @@ encode_actions_rsp (struct bp_location *tloc, char ***tdp_actions,
 }
 
 void
-collection_list::add_aexpr (struct agent_expr *aexpr)
+collection_list::add_aexpr (agent_expr_up aexpr)
 {
-  m_aexprs.push_back (aexpr);
+  m_aexprs.push_back (aexpr.release ());
 }
 
 static void
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
index d3571b1..7dfd8cc 100644
--- a/gdb/tracepoint.h
+++ b/gdb/tracepoint.h
@@ -249,7 +249,9 @@ public:
 
   void append_exp (struct expression *exp);
 
-  void add_aexpr (struct agent_expr *aexpr);
+  /* Add AEXPR to the list, taking ownership.  */
+  void add_aexpr (agent_expr_up aexpr);
+
   void add_register (unsigned int regno);
   void add_memrange (int type, bfd_signed_vma base,
 		     unsigned long len);
-- 
2.5.5

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

* [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs
@ 2016-10-19  1:13 Pedro Alves
  2016-10-19  1:12 ` [PATCH v2 12/31] Use ui_file_as_string in gdb/utils.c Pedro Alves
                   ` (30 more replies)
  0 siblings, 31 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

This is v2 of the series first sent here:
  https://sourceware.org/ml/gdb-patches/2016-10/msg00223.html

v1's patch #1 is in master now.

v1's patch #2 never made it to the list in v1 for some reason.  This
time, I've split that patch in many smaller pieces.

v1's patch #3 is the struct parse_expression one here.

I've added a few new patches as well:

E.g., one uses unique_ptr to manage agent_expr owning pointers,
similar to the struct expression one.  (My goal here to show the
direction I think we should head.  Help would be much appreciated in
applying the pattern to other random cases.)

The collection_list patch here is much more complete than what was in
v1.

And, so you don't all think C++fication is just pointless churn, the
last patch in the series is new too, and actually implements something
IMO useful.  :-)

*** BLURB HERE ***

Pedro Alves (31):
  Introduce string_printf
  cli/cli-script.c: Remove some dead NULL checks
  breakpoint.c:commands_command_1 constification and cleanup
  cli-script.c: Simplify using std::string, eliminate cleanups
  'struct expression *' -> gdb::unique_xmalloc_ptr<expression>
  Introduce ui_file_as_string
  Clean up tracepoint.h/c:collection_list
  Use ui_file_as_string in dwarf2_compute_name
  Use ui_file_as_string in gdb/xtensa-tdep.c
  Use ui_file_as_string in gdb/ada-valprint.c
  Use ui_file_as_string in gdb/ui-out.c
  Use ui_file_as_string in gdb/utils.c
  Use ui_file_as_string in gdb/arm-tdep.c
  Use ui_file_as_string in gdb/guile/
  Use ui_file_as_string in execute_command_to_string
  Use ui_file_as_string in gdb/top.c
  Use ui_file_as_string in gdb/printcmd.c
  Use ui_file_as_string in gdb/python/
  Use ui_file_as_string in gdb/remote.c
  Use ui_file_as_string in gdb/cli/cli-setshow.c
  Use ui_file_as_string in gdb/compile/
  Use ui_file_as_string in gdb/c-exp.y
  Use ui_file_as_string in gdbarch.sh/gdbarch.c
  Use ui_file_as_string in gdb/ada-lang.c
  Use ui_file_as_string in gdb/infrun.c
  Use ui_file_as_string in gdb/rust-lang.c
  Use ui_file_as_string in gdb/language.c
  Use ui_file_as_string throughout more
  'struct agent_expr *' -> unique_ptr<agent_expr>
  Eliminate agent_expr_p; VEC -> std::vector in struct bp_target_info
  Support an "unlimited" number of user-defined arguments

 gdb/doc/gdb.texinfo             |   6 +-
 gdb/NEWS                        |   3 +
 gdb/ada-lang.c                  |  83 ++-----
 gdb/ada-lang.h                  |   2 +-
 gdb/ada-valprint.c              |  53 ++--
 gdb/ada-varobj.c                | 130 ++++------
 gdb/arm-tdep.c                  |   6 +-
 gdb/ax-gdb.c                    | 149 ++++--------
 gdb/ax-gdb.h                    |  24 +-
 gdb/ax-general.c                |  48 +---
 gdb/ax.h                        |  19 +-
 gdb/break-catch-sig.c           |   2 +-
 gdb/break-catch-syscall.c       |   2 +-
 gdb/break-catch-throw.c         |  26 +-
 gdb/breakpoint.c                | 226 +++++++----------
 gdb/breakpoint.h                |  25 +-
 gdb/c-exp.y                     |   9 +-
 gdb/c-lang.c                    |   9 +-
 gdb/c-lang.h                    |   7 +-
 gdb/c-typeprint.c               |   5 +-
 gdb/c-varobj.c                  | 142 ++++++-----
 gdb/cli/cli-script.c            | 290 ++++++++++------------
 gdb/cli/cli-setshow.c           |   7 +-
 gdb/common/common-utils.c       |  30 +++
 gdb/common/common-utils.h       |  24 ++
 gdb/compile/compile-c-support.c |   6 +-
 gdb/compile/compile.c           |  70 +++---
 gdb/cp-abi.c                    |   2 +-
 gdb/cp-abi.h                    |   7 +-
 gdb/cp-support.c                |  60 ++---
 gdb/cp-support.h                |  10 +-
 gdb/dbxread.c                   |  22 +-
 gdb/dtrace-probe.c              |   6 +-
 gdb/dwarf2read.c                |  25 +-
 gdb/eval.c                      |  43 +---
 gdb/expression.h                |  12 +-
 gdb/gdbarch.c                   |   8 +-
 gdb/gdbarch.sh                  |   8 +-
 gdb/gdbcmd.h                    |   2 +-
 gdb/gdbtypes.c                  |  12 +-
 gdb/gnu-v3-abi.c                |  57 ++---
 gdb/guile/guile.c               |  18 +-
 gdb/guile/scm-breakpoint.c      |   6 +-
 gdb/guile/scm-disasm.c          |   6 +-
 gdb/guile/scm-frame.c           |   6 +-
 gdb/guile/scm-type.c            |  42 ++--
 gdb/guile/scm-value.c           |  18 +-
 gdb/infcmd.c                    |   9 +-
 gdb/infrun.c                    |   6 +-
 gdb/language.c                  |   7 +-
 gdb/language.h                  |  14 +-
 gdb/linespec.c                  |  53 ++--
 gdb/mi/mi-cmd-var.c             |  70 ++----
 gdb/mi/mi-main.c                |  43 ++--
 gdb/minsyms.c                   |  17 +-
 gdb/objc-lang.c                 |   7 +-
 gdb/parse.c                     |  50 ++--
 gdb/printcmd.c                  |  62 ++---
 gdb/python/py-arch.c            |  10 +-
 gdb/python/py-breakpoint.c      |   8 +-
 gdb/python/py-frame.c           |   8 +-
 gdb/python/py-type.c            |  10 +-
 gdb/python/py-unwind.c          |   7 +-
 gdb/python/py-value.c           |   7 +-
 gdb/python/py-varobj.c          |   4 +-
 gdb/python/python.c             |  19 +-
 gdb/remote.c                    |  88 +++----
 gdb/rust-exp.y                  |  11 +-
 gdb/rust-lang.c                 |  57 ++---
 gdb/stabsread.c                 |  21 +-
 gdb/stack.c                     |   6 +-
 gdb/symtab.c                    |  87 +++----
 gdb/symtab.h                    |  39 ++-
 gdb/top.c                       |  14 +-
 gdb/tracepoint.c                | 522 ++++++++++++++++------------------------
 gdb/tracepoint.h                |  74 ++++--
 gdb/typeprint.c                 |  21 +-
 gdb/ui-file.c                   |  22 ++
 gdb/ui-file.h                   |   6 +
 gdb/ui-out.c                    |   9 +-
 gdb/utils.c                     |   5 +-
 gdb/value.c                     |   8 +-
 gdb/value.h                     |   2 +-
 gdb/varobj-iter.h               |   4 +-
 gdb/varobj.c                    | 221 ++++++++---------
 gdb/varobj.h                    |  70 +++---
 gdb/xtensa-tdep.c               |   9 +-
 87 files changed, 1486 insertions(+), 1994 deletions(-)

-- 
2.5.5

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

* [PATCH v2 02/31] cli/cli-script.c: Remove some dead NULL checks
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (10 preceding siblings ...)
  2016-10-19  1:13 ` [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments Pedro Alves
@ 2016-10-19  1:13 ` Pedro Alves
  2016-10-19 17:24   ` Simon Marchi
  2016-10-19  1:13 ` [PATCH v2 15/31] Use ui_file_as_string in execute_command_to_string Pedro Alves
                   ` (18 subsequent siblings)
  30 siblings, 1 reply; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* cli/cli-script.c (execute_control_command): Assume insert_args
	never returns NULL.
	(insert_args): Assume xmalloc never returns NULL.
---
 gdb/cli/cli-script.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 579d0a4..c36cce6 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -459,8 +459,6 @@ execute_control_command (struct command_line *cmd)
     case simple_control:
       /* A simple command, execute it and return.  */
       new_line = insert_args (cmd->line);
-      if (!new_line)
-	break;
       make_cleanup (free_current_contents, &new_line);
       execute_command (new_line, 0);
       ret = cmd->control_type;
@@ -492,8 +490,6 @@ execute_control_command (struct command_line *cmd)
 
 	/* Parse the loop control expression for the while statement.  */
 	new_line = insert_args (cmd->line);
-	if (!new_line)
-	  break;
 	make_cleanup (free_current_contents, &new_line);
 	expr = parse_expression (new_line);
 	make_cleanup (free_current_contents, &expr);
@@ -560,8 +556,6 @@ execute_control_command (struct command_line *cmd)
 	print_command_trace (buffer);
 
 	new_line = insert_args (cmd->line);
-	if (!new_line)
-	  break;
 	make_cleanup (free_current_contents, &new_line);
 	/* Parse the conditional for the if statement.  */
 	expr = parse_expression (new_line);
@@ -605,8 +599,6 @@ execute_control_command (struct command_line *cmd)
 	/* Breakpoint commands list, record the commands in the
 	   breakpoint's command list and return.  */
 	new_line = insert_args (cmd->line);
-	if (!new_line)
-	  break;
 	make_cleanup (free_current_contents, &new_line);
 	ret = commands_from_control_command (new_line, cmd);
 	break;
@@ -853,8 +845,6 @@ insert_args (char *line)
 
   /* Allocate space for the new line and fill it in.  */
   new_line = (char *) xmalloc (len + 1);
-  if (new_line == NULL)
-    return NULL;
 
   /* Restore pointer to beginning of old line.  */
   line = save_line;
-- 
2.5.5

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

* [PATCH v2 15/31] Use ui_file_as_string in execute_command_to_string
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (11 preceding siblings ...)
  2016-10-19  1:13 ` [PATCH v2 02/31] cli/cli-script.c: Remove some dead NULL checks Pedro Alves
@ 2016-10-19  1:13 ` Pedro Alves
  2016-10-19  1:13 ` [PATCH v2 03/31] breakpoint.c:commands_command_1 constification and cleanup Pedro Alves
                   ` (17 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

... and then return std::string and adjust all callers.

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* gdbcmd.h (execute_command_to_string): Now returns std::string.
	(lookup_struct_elt_type): Adjust to use std::string.
	* top.c (execute_command_to_string): Use ui_file_as_string and
	return std::string.
	* guile/guile.c (gdbscm_execute_gdb_command): Adjust to use
	std::string.
	* python/python.c (execute_gdb_command): Adjust to use
	std::string.
---
 gdb/gdbcmd.h        |  2 +-
 gdb/guile/guile.c   | 18 ++++++------------
 gdb/python/python.c | 19 ++++++-------------
 gdb/top.c           |  5 ++---
 4 files changed, 15 insertions(+), 29 deletions(-)

diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h
index 512b72c..6db49e2 100644
--- a/gdb/gdbcmd.h
+++ b/gdb/gdbcmd.h
@@ -128,7 +128,7 @@ extern struct cmd_list_element *showchecklist;
 extern struct cmd_list_element *save_cmdlist;
 
 extern void execute_command (char *, int);
-extern char *execute_command_to_string (char *p, int from_tty);
+extern std::string execute_command_to_string (char *p, int from_tty);
 
 enum command_control_type execute_control_command (struct command_line *);
 
diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c
index 3a19eec..9a126a1 100644
--- a/gdb/guile/guile.c
+++ b/gdb/guile/guile.c
@@ -311,7 +311,6 @@ gdbscm_execute_gdb_command (SCM command_scm, SCM rest)
   int from_tty = 0, to_string = 0;
   const SCM keywords[] = { from_tty_keyword, to_string_keyword, SCM_BOOL_F };
   char *command;
-  char *result = NULL;
   struct cleanup *cleanups;
   struct gdb_exception except = exception_none;
 
@@ -324,6 +323,8 @@ gdbscm_execute_gdb_command (SCM command_scm, SCM rest)
      executed.  */
   cleanups = make_cleanup (xfree, command);
 
+  std::string to_string_res;
+
   TRY
     {
       struct cleanup *inner_cleanups;
@@ -333,12 +334,9 @@ gdbscm_execute_gdb_command (SCM command_scm, SCM rest)
 
       prevent_dont_repeat ();
       if (to_string)
-	result = execute_command_to_string (command, from_tty);
+	to_string_res = execute_command_to_string (command, from_tty);
       else
-	{
-	  execute_command (command, from_tty);
-	  result = NULL;
-	}
+	execute_command (command, from_tty);
 
       /* Do any commands attached to breakpoint we stopped at.  */
       bpstat_do_actions ();
@@ -354,12 +352,8 @@ gdbscm_execute_gdb_command (SCM command_scm, SCM rest)
   do_cleanups (cleanups);
   GDBSCM_HANDLE_GDB_EXCEPTION (except);
 
-  if (result)
-    {
-      SCM r = gdbscm_scm_from_c_string (result);
-      xfree (result);
-      return r;
-    }
+  if (to_string)
+    return gdbscm_scm_from_c_string (to_string_res.c_str ());
   return SCM_UNSPECIFIED;
 }
 
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 7e34d26..0ca7d9a 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -619,7 +619,6 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
   PyObject *from_tty_obj = NULL, *to_string_obj = NULL;
   int from_tty, to_string;
   static char *keywords[] = {"command", "from_tty", "to_string", NULL };
-  char *result = NULL;
 
   if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O!O!", keywords, &arg,
 				     &PyBool_Type, &from_tty_obj,
@@ -644,6 +643,8 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
       to_string = cmp;
     }
 
+  std::string to_string_res;
+
   TRY
     {
       /* Copy the argument text in case the command modifies it.  */
@@ -663,13 +664,9 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
 
       prevent_dont_repeat ();
       if (to_string)
-	result = execute_command_to_string (copy, from_tty);
+	to_string_res = execute_command_to_string (copy, from_tty);
       else
-	{
-	  result = NULL;
-	  execute_command (copy, from_tty);
-	}
-
+	execute_command (copy, from_tty);
       do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
@@ -681,12 +678,8 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
   /* Do any commands attached to breakpoint we stopped at.  */
   bpstat_do_actions ();
 
-  if (result)
-    {
-      PyObject *r = PyString_FromString (result);
-      xfree (result);
-      return r;
-    }
+  if (to_string)
+    return PyString_FromString (to_string_res.c_str ());
   Py_RETURN_NONE;
 }
 
diff --git a/gdb/top.c b/gdb/top.c
index 3cfa113..762a9a8 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -690,12 +690,11 @@ execute_command (char *p, int from_tty)
    returned string, do not display it to the screen.  BATCH_FLAG will be
    temporarily set to true.  */
 
-char *
+std::string
 execute_command_to_string (char *p, int from_tty)
 {
   struct ui_file *str_file;
   struct cleanup *cleanup;
-  char *retval;
 
   /* GDB_STDOUT should be better already restored during these
      restoration callbacks.  */
@@ -726,7 +725,7 @@ execute_command_to_string (char *p, int from_tty)
 
   execute_command (p, from_tty);
 
-  retval = ui_file_xstrdup (str_file, NULL);
+  std::string retval = ui_file_as_string (str_file);
 
   do_cleanups (cleanup);
 
-- 
2.5.5

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

* [PATCH v2 08/31] Use ui_file_as_string in dwarf2_compute_name
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (8 preceding siblings ...)
  2016-10-19  1:12 ` [PATCH v2 22/31] Use ui_file_as_string in gdb/c-exp.y Pedro Alves
@ 2016-10-19  1:13 ` Pedro Alves
  2016-10-19  1:13 ` [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments Pedro Alves
                   ` (20 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* dwarf2read.c (dwarf2_compute_name): Use ui_file_as_string and
	std::string.
---
 gdb/dwarf2read.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index c070cd7..6cc79ea 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -8487,7 +8487,6 @@ dwarf2_compute_name (const char *name,
 	  long length;
 	  const char *prefix;
 	  struct ui_file *buf;
-	  char *intermediate_name;
 	  const char *canonical_name = NULL;
 
 	  prefix = determine_prefix (die, cu);
@@ -8656,26 +8655,24 @@ dwarf2_compute_name (const char *name,
 		}
 	    }
 
-	  intermediate_name = ui_file_xstrdup (buf, &length);
+	  std::string intermediate_name = ui_file_as_string (buf);
 	  ui_file_delete (buf);
 
 	  if (cu->language == language_cplus)
 	    canonical_name
-	      = dwarf2_canonicalize_name (intermediate_name, cu,
+	      = dwarf2_canonicalize_name (intermediate_name.c_str (), cu,
 					  &objfile->per_bfd->storage_obstack);
 
 	  /* If we only computed INTERMEDIATE_NAME, or if
 	     INTERMEDIATE_NAME is already canonical, then we need to
 	     copy it to the appropriate obstack.  */
-	  if (canonical_name == NULL || canonical_name == intermediate_name)
+	  if (canonical_name == NULL || canonical_name == intermediate_name.c_str ())
 	    name = ((const char *)
 		    obstack_copy0 (&objfile->per_bfd->storage_obstack,
-				   intermediate_name,
-				   strlen (intermediate_name)));
+				   intermediate_name.c_str (),
+				   intermediate_name.length ()));
 	  else
 	    name = canonical_name;
-
-	  xfree (intermediate_name);
 	}
     }
 
-- 
2.5.5

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

* [PATCH v2 14/31] Use ui_file_as_string in gdb/guile/
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (13 preceding siblings ...)
  2016-10-19  1:13 ` [PATCH v2 03/31] breakpoint.c:commands_command_1 constification and cleanup Pedro Alves
@ 2016-10-19  1:13 ` Pedro Alves
  2016-10-19  1:13 ` [PATCH v2 27/31] Use ui_file_as_string in gdb/language.c Pedro Alves
                   ` (15 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* guile/scm-breakpoint.c (gdbscm_breakpoint_commands): Use
	ui_file_as_string and adjust to use std::string.
	* guile/scm-disasm.c (gdbscm_arch_disassemble): Likewise.
	* guile/scm-frame.c (frscm_print_frame_smob): Likewise.
	* guile/scm-type.c (tyscm_type_name): Use ui_file_as_string and
	adjust to use std::string.  Throw exception directly instead of
	returning it in EXCP output parameter.
	(tyscm_print_type_smob, gdbscm_type_print_name): Adjust to
	tyscm_type_name interface change.
	* guile/scm-value.c (vlscm_print_value_smob, gdbscm_value_print):
	Use ui_file_as_string and std::string.
---
 gdb/guile/scm-breakpoint.c |  6 ++----
 gdb/guile/scm-disasm.c     |  6 ++----
 gdb/guile/scm-frame.c      |  6 ++----
 gdb/guile/scm-type.c       | 42 ++++++++++++++----------------------------
 gdb/guile/scm-value.c      | 18 ++++++------------
 5 files changed, 26 insertions(+), 52 deletions(-)

diff --git a/gdb/guile/scm-breakpoint.c b/gdb/guile/scm-breakpoint.c
index baecf01..61d16da 100644
--- a/gdb/guile/scm-breakpoint.c
+++ b/gdb/guile/scm-breakpoint.c
@@ -981,7 +981,6 @@ gdbscm_breakpoint_commands (SCM self)
   struct ui_file *string_file;
   struct cleanup *chain;
   SCM result;
-  char *cmdstr;
 
   bp = bp_smob->bp;
 
@@ -1004,9 +1003,8 @@ gdbscm_breakpoint_commands (SCM self)
     }
   END_CATCH
 
-  cmdstr = ui_file_xstrdup (string_file, &length);
-  make_cleanup (xfree, cmdstr);
-  result = gdbscm_scm_from_c_string (cmdstr);
+  std::string cmdstr = ui_file_as_string (string_file);
+  result = gdbscm_scm_from_c_string (cmdstr.c_str ());
 
   do_cleanups (chain);
   return result;
diff --git a/gdb/guile/scm-disasm.c b/gdb/guile/scm-disasm.c
index 78a7b83..a7d6b14 100644
--- a/gdb/guile/scm-disasm.c
+++ b/gdb/guile/scm-disasm.c
@@ -282,7 +282,6 @@ gdbscm_arch_disassemble (SCM self, SCM start_scm, SCM rest)
   for (pc = start, i = 0; pc <= end && i < count; )
     {
       int insn_len = 0;
-      char *as = NULL;
       struct ui_file *memfile = mem_fileopen ();
       struct cleanup *cleanups = make_cleanup_ui_file_delete (memfile);
 
@@ -302,15 +301,14 @@ gdbscm_arch_disassemble (SCM self, SCM start_scm, SCM rest)
 	}
       END_CATCH
 
-      as = ui_file_xstrdup (memfile, NULL);
+      std::string as = ui_file_as_string (memfile);
 
-      result = scm_cons (dascm_make_insn (pc, as, insn_len),
+      result = scm_cons (dascm_make_insn (pc, as.c_str (), insn_len),
 			 result);
 
       pc += insn_len;
       i++;
       do_cleanups (cleanups);
-      xfree (as);
     }
 
   return scm_reverse_x (result, SCM_EOL);
diff --git a/gdb/guile/scm-frame.c b/gdb/guile/scm-frame.c
index 8f920b2..a86ea5f 100644
--- a/gdb/guile/scm-frame.c
+++ b/gdb/guile/scm-frame.c
@@ -157,16 +157,14 @@ frscm_print_frame_smob (SCM self, SCM port, scm_print_state *pstate)
 {
   frame_smob *f_smob = (frame_smob *) SCM_SMOB_DATA (self);
   struct ui_file *strfile;
-  char *s;
 
   gdbscm_printf (port, "#<%s ", frame_smob_name);
 
   strfile = mem_fileopen ();
   fprint_frame_id (strfile, f_smob->frame_id);
-  s = ui_file_xstrdup (strfile, NULL);
-  gdbscm_printf (port, "%s", s);
+  std::string s = ui_file_as_string (strfile);
+  gdbscm_printf (port, "%s", s.c_str ());
   ui_file_delete (strfile);
-  xfree (s);
 
   scm_puts (">", port);
 
diff --git a/gdb/guile/scm-type.c b/gdb/guile/scm-type.c
index 2acdfad..383e58a 100644
--- a/gdb/guile/scm-type.c
+++ b/gdb/guile/scm-type.c
@@ -99,16 +99,12 @@ tyscm_type_smob_type (type_smob *t_smob)
   return t_smob->type;
 }
 
-/* Return the name of TYPE in expanded form.
-   Space for the result is malloc'd, caller must free.
-   If there's an error computing the name, the result is NULL and the
-   exception is stored in *EXCP.  */
+/* Return the name of TYPE in expanded form.  If there's an error
+   computing the name, throws the gdb exception with scm_throw.  */
 
-static char *
-tyscm_type_name (struct type *type, SCM *excp)
+static std::string
+tyscm_type_name (struct type *type)
 {
-  char *name = NULL;
-
   TRY
     {
       struct cleanup *old_chain;
@@ -119,17 +115,19 @@ tyscm_type_name (struct type *type, SCM *excp)
 
       LA_PRINT_TYPE (type, "", stb, -1, 0, &type_print_raw_options);
 
-      name = ui_file_xstrdup (stb, NULL);
+      std::string name = ui_file_as_string (stb);
       do_cleanups (old_chain);
+
+      return name;
     }
   CATCH (except, RETURN_MASK_ALL)
     {
-      *excp = gdbscm_scm_from_gdb_exception (except);
-      return NULL;
+      SCM excp = gdbscm_scm_from_gdb_exception (except);
+      gdbscm_throw (excp);
     }
   END_CATCH
 
-  return name;
+  gdb_assert_not_reached ("no way to get here");
 }
 \f
 /* Administrivia for type smobs.  */
@@ -207,11 +205,7 @@ static int
 tyscm_print_type_smob (SCM self, SCM port, scm_print_state *pstate)
 {
   type_smob *t_smob = (type_smob *) SCM_SMOB_DATA (self);
-  SCM exception;
-  char *name = tyscm_type_name (t_smob->type, &exception);
-
-  if (name == NULL)
-    gdbscm_throw (exception);
+  std::string name = tyscm_type_name (t_smob->type);
 
   /* pstate->writingp = zero if invoked by display/~A, and nonzero if
      invoked by write/~S.  What to do here may need to evolve.
@@ -220,7 +214,7 @@ tyscm_print_type_smob (SCM self, SCM port, scm_print_state *pstate)
   if (pstate->writingp)
     gdbscm_printf (port, "#<%s ", type_smob_name);
 
-  scm_puts (name, port);
+  scm_puts (name.c_str (), port);
 
   if (pstate->writingp)
     scm_puts (">", port);
@@ -608,16 +602,8 @@ gdbscm_type_print_name (SCM self)
   type_smob *t_smob
     = tyscm_get_type_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct type *type = t_smob->type;
-  char *thetype;
-  SCM exception, result;
-
-  thetype = tyscm_type_name (type, &exception);
-
-  if (thetype == NULL)
-    gdbscm_throw (exception);
-
-  result = gdbscm_scm_from_c_string (thetype);
-  xfree (thetype);
+  std::string thetype = tyscm_type_name (type);
+  SCM result = gdbscm_scm_from_c_string (thetype.c_str ());
 
   return result;
 }
diff --git a/gdb/guile/scm-value.c b/gdb/guile/scm-value.c
index 1cdf953..7c1449e 100644
--- a/gdb/guile/scm-value.c
+++ b/gdb/guile/scm-value.c
@@ -141,7 +141,6 @@ static int
 vlscm_print_value_smob (SCM self, SCM port, scm_print_state *pstate)
 {
   value_smob *v_smob = (value_smob *) SCM_SMOB_DATA (self);
-  char *s = NULL;
   struct value_print_options opts;
 
   if (pstate->writingp)
@@ -162,7 +161,9 @@ vlscm_print_value_smob (SCM self, SCM port, scm_print_state *pstate)
       struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
 
       common_val_print (v_smob->value, stb, 0, &opts, current_language);
-      s = ui_file_xstrdup (stb, NULL);
+
+      std::string s = ui_file_as_string (stb);
+      scm_puts (s.c_str (), port);
 
       do_cleanups (old_chain);
     }
@@ -172,12 +173,6 @@ vlscm_print_value_smob (SCM self, SCM port, scm_print_state *pstate)
     }
   END_CATCH
 
-  if (s != NULL)
-    {
-      scm_puts (s, port);
-      xfree (s);
-    }
-
   if (pstate->writingp)
     scm_puts (">", port);
 
@@ -1281,7 +1276,7 @@ gdbscm_value_print (SCM self)
     = vlscm_get_value_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct value *value = v_smob->value;
   struct value_print_options opts;
-  char *s = NULL;
+  std::string s;
   SCM result;
 
   get_user_print_options (&opts);
@@ -1293,7 +1288,7 @@ gdbscm_value_print (SCM self)
       struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
 
       common_val_print (value, stb, 0, &opts, current_language);
-      s = ui_file_xstrdup (stb, NULL);
+      s = ui_file_as_string (stb);
 
       do_cleanups (old_chain);
     }
@@ -1308,9 +1303,8 @@ gdbscm_value_print (SCM self)
      IWBN to use scm_take_locale_string here, but we'd have to temporarily
      override the default port conversion handler because contrary to
      documentation it doesn't necessarily free the input string.  */
-  result = scm_from_stringn (s, strlen (s), host_charset (),
+  result = scm_from_stringn (s.c_str (), s.size (), host_charset (),
 			     SCM_FAILED_CONVERSION_QUESTION_MARK);
-  xfree (s);
 
   return result;
 }
-- 
2.5.5

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

* [PATCH v2 23/31] Use ui_file_as_string in gdbarch.sh/gdbarch.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (16 preceding siblings ...)
  2016-10-19  1:13 ` [PATCH v2 29/31] 'struct agent_expr *' -> unique_ptr<agent_expr> Pedro Alves
@ 2016-10-19  1:13 ` Pedro Alves
  2016-10-19  1:13 ` [PATCH v2 26/31] Use ui_file_as_string in gdb/rust-lang.c Pedro Alves
                   ` (12 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* gdbarch.sh (verify_gdbarch): Use ui_file_as_string and
	std::string.
	* gdbarch.c: Regenerate.
---
 gdb/gdbarch.c  | 8 +++-----
 gdb/gdbarch.sh | 8 +++-----
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 4d8ef18..da4aa25 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -496,7 +496,6 @@ verify_gdbarch (struct gdbarch *gdbarch)
   struct ui_file *log;
   struct cleanup *cleanups;
   long length;
-  char *buf;
 
   log = mem_fileopen ();
   cleanups = make_cleanup_ui_file_delete (log);
@@ -691,12 +690,11 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of gcc_target_options, invalid_p == 0 */
   /* Skip verify of gnu_triplet_regexp, invalid_p == 0 */
   /* Skip verify of addressable_memory_unit_size, invalid_p == 0 */
-  buf = ui_file_xstrdup (log, &length);
-  make_cleanup (xfree, buf);
-  if (length > 0)
+  std::string buf = ui_file_as_string (log);
+  if (!buf.empty ())
     internal_error (__FILE__, __LINE__,
                     _("verify_gdbarch: the following are invalid ...%s"),
-                    buf);
+                    buf.c_str ());
   do_cleanups (cleanups);
 }
 
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 1663156..036786e 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1867,7 +1867,6 @@ verify_gdbarch (struct gdbarch *gdbarch)
   struct ui_file *log;
   struct cleanup *cleanups;
   long length;
-  char *buf;
 
   log = mem_fileopen ();
   cleanups = make_cleanup_ui_file_delete (log);
@@ -1913,12 +1912,11 @@ do
     fi
 done
 cat <<EOF
-  buf = ui_file_xstrdup (log, &length);
-  make_cleanup (xfree, buf);
-  if (length > 0)
+  std::string buf = ui_file_as_string (log);
+  if (!buf.empty ())
     internal_error (__FILE__, __LINE__,
                     _("verify_gdbarch: the following are invalid ...%s"),
-                    buf);
+                    buf.c_str ());
   do_cleanups (cleanups);
 }
 EOF
-- 
2.5.5

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

* [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (9 preceding siblings ...)
  2016-10-19  1:13 ` [PATCH v2 08/31] Use ui_file_as_string in dwarf2_compute_name Pedro Alves
@ 2016-10-19  1:13 ` Pedro Alves
  2016-10-19  6:29   ` Eli Zaretskii
                     ` (2 more replies)
  2016-10-19  1:13 ` [PATCH v2 02/31] cli/cli-script.c: Remove some dead NULL checks Pedro Alves
                   ` (19 subsequent siblings)
  30 siblings, 3 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

I recently wrote a user-defined command that could benefit from
supporting an unlimited number of arguments:

 http://palves.net/list-active-signal-handlers-with-gdb/

E.g., 'info signal-dispositions 1 2 3 4 5 6 7 8 9 10 11'

However, we currently only support up to 10 arguments passed to
user-defined commands ($arg0..$arg9).

I can't find a good reason for that, other than "old code with hard
coded limits".  This patch removes that limit and modernizes the code
along the way:

  - Makes the user_args struct a real C++ class that uses std::vector
    for storage.

  - Removes the "next" pointer from within user_args and uses a
    std::vector to maintain a stack instead.

  - Adds a new RAII-based scoped_user_args_level class to help
    push/pop user args in the stack instead of using a cleanup.

I also needed a way to convert a number to a std::string, so I added a
new utility for that, gdb::to_string.  Yet another thing that can go
away with C++11.

Should probably write a test for this.  Will do if people agree this
is useful.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* NEWS: Mention that user commands now accept an unlimited number
	of arguments.
	* cli/cli-script.c: Include <vector>.
	(struct string_view): New type.
	(MAXUSERARGS): Delete.
	(struct user_args): Now a C++ class.
	(user_args_stack): New.
	(struct scoped_user_args_level): New type.
	(execute_user_command): Use scoped_user_args_level.  Adjust to
	call insert_user_args instead of insert_args.
	(arg_cleanup): Delete.
	(setup_user_args): Deleted, and refactored as ...
	(user_args::user_args): ... this new constructor.  Limit of number
	of arguments removed.
	(insert_args): Delete.
	(insert_user_args) New.
	(user_args::insert_args): New, bits based on old insert_args with
	limit of number of arguments eliminated.
	* common/common-utils.h: Include <sstream>.
	(gdb::to_string): New.

gdb/doc/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* gdb.texinfo (User-defined Commands): Limit on number of
	arguments passed to user-defined commands removed; update.
---
 gdb/doc/gdb.texinfo       |   6 +-
 gdb/NEWS                  |   3 +
 gdb/cli/cli-script.c      | 200 +++++++++++++++++++++++++---------------------
 gdb/common/common-utils.h |  18 +++++
 4 files changed, 135 insertions(+), 92 deletions(-)

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b3eb488..4d48469 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -24057,9 +24057,9 @@ files.
 @cindex arguments, to user-defined commands
 A @dfn{user-defined command} is a sequence of @value{GDBN} commands to
 which you assign a new name as a command.  This is done with the
-@code{define} command.  User commands may accept up to 10 arguments
+@code{define} command.  User commands may accept an unlimited number of arguments
 separated by whitespace.  Arguments are accessed within the user command
-via @code{$arg0@dots{}$arg9}.  A trivial example:
+via @code{$arg0@dots{}$argN}.  A trivial example:
 
 @smallexample
 define adder
@@ -24083,7 +24083,7 @@ functions calls.
 @cindex argument count in user-defined commands
 @cindex how many arguments (user-defined commands)
 In addition, @code{$argc} may be used to find out how many arguments have
-been passed.  This expands to a number in the range 0@dots{}10.
+been passed.
 
 @smallexample
 define adder
diff --git a/gdb/NEWS b/gdb/NEWS
index 4a61438..2317dd8 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -17,6 +17,9 @@
 
 * Support for Java programs compiled with gcj has been removed.
 
+* User commands now accept an unlimited number of arguments.
+  Previously, only up to 10 was accepted.
+
 * New targets
 
 Synopsys ARC			arc*-*-elf32
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 6302f52..eef5a2f 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -33,6 +33,8 @@
 #include "interps.h"
 #include "compile/compile.h"
 
+#include <vector>
+
 /* Prototypes for local functions.  */
 
 static enum command_control_type
@@ -41,9 +43,7 @@ recurse_read_control_structure (char * (*read_next_line_func) (void),
 				void (*validator)(char *, void *),
 				void *closure);
 
-static std::string insert_args (const char *line);
-
-static struct cleanup * setup_user_args (char *p);
+static std::string insert_user_args (const char *line);
 
 static char *read_next_line (void);
 
@@ -56,24 +56,69 @@ static int command_nest_depth = 1;
 /* This is to prevent certain commands being printed twice.  */
 static int suppress_next_print_command_trace = 0;
 
+/* A non-owning slice of a string.  */
+
+struct string_view
+{
+  string_view (const char *str_, size_t len_)
+    : str (str_), len (len_)
+  {}
+
+  const char *str;
+  size_t len;
+};
+
 /* Structure for arguments to user defined functions.  */
-#define MAXUSERARGS 10
-struct user_args
+
+class user_args
+{
+public:
+  /* Save the command line and store the locations of arguments passed
+     to the user defined function.  */
+  explicit user_args (const char *line);
+
+  /* Insert the stored user defined arguments into the $arg arguments
+     found in LINE.  */
+  std::string insert_args (const char *line);
+
+private:
+  /* Disable copy/assignment.  (Since the elements of A point inside
+     COMMAND, copying would need to reconstruct the A vector in the
+     new copy.)  */
+  user_args (const user_args &);
+  user_args &operator= (const user_args &);
+
+  /* It is necessary to store a copy of the command line to ensure
+     that the arguments are not overwritten before they are used.  */
+  std::string m_command_line;
+
+  /* The arguments.  Each element points inside M_COMMAND_LINE.  */
+  std::vector<string_view> m_args;
+};
+
+/* The stack of arguments passed to user defined functions.  We need a
+   stack because user-defined functions can call other user-defined
+   functions.  The vector owns its elements.  */
+static std::vector<user_args *> user_args_stack;
+
+/* An RAII-base class used to push/pop args on the user args
+   stack.  */
+struct scoped_user_args_level
+{
+  /* Parse the command line and push the arguments in the user args
+     stack.  */
+  explicit scoped_user_args_level (const char *line)
   {
-    struct user_args *next;
-    /* It is necessary to store a malloced copy of the command line to
-       ensure that the arguments are not overwritten before they are
-       used.  */
-    char *command;
-    struct
-      {
-	char *arg;
-	int len;
-      }
-    a[MAXUSERARGS];
-    int count;
+    user_args_stack.push_back (new user_args (line));
+  }
+
+  /* Pop the current user arguments from the stack.  */
+  ~scoped_user_args_level ()
+  {
+    delete user_args_stack.back ();
+    user_args_stack.pop_back ();
   }
- *user_args;
+};
 
 \f
 /* Return non-zero if TYPE is a multi-line command (i.e., is terminated
@@ -348,7 +393,6 @@ do_restore_user_call_depth (void * call_depth)
     in_user_command = 0;
 }
 
-
 void
 execute_user_command (struct cmd_list_element *c, char *args)
 {
@@ -364,12 +408,12 @@ execute_user_command (struct cmd_list_element *c, char *args)
     /* Null command */
     return;
 
-  old_chain = setup_user_args (args);
+  scoped_user_args_level push_user_args (args);
 
   if (++user_call_depth > max_user_call_depth)
     error (_("Max user call depth exceeded -- command aborted."));
 
-  make_cleanup (do_restore_user_call_depth, &user_call_depth);
+  old_chain = make_cleanup (do_restore_user_call_depth, &user_call_depth);
 
   /* Set the instream to 0, indicating execution of a
      user-defined function.  */
@@ -456,7 +500,7 @@ execute_control_command (struct command_line *cmd)
     case simple_control:
       {
 	/* A simple command, execute it and return.  */
-	std::string new_line = insert_args (cmd->line);
+	std::string new_line = insert_user_args (cmd->line);
 	execute_command (&new_line[0], 0);
 	ret = cmd->control_type;
 	break;
@@ -487,7 +531,7 @@ execute_control_command (struct command_line *cmd)
 	print_command_trace (buffer);
 
 	/* Parse the loop control expression for the while statement.  */
-	std::string new_line = insert_args (cmd->line);
+	std::string new_line = insert_user_args (cmd->line);
 	expression_up expr = parse_expression (new_line.c_str ());
 
 	ret = simple_control;
@@ -552,7 +596,7 @@ execute_control_command (struct command_line *cmd)
 	print_command_trace (buffer);
 
 	/* Parse the conditional for the if statement.  */
-	std::string new_line = insert_args (cmd->line);
+	std::string new_line = insert_user_args (cmd->line);
 	expression_up expr = parse_expression (new_line.c_str ());
 
 	current = NULL;
@@ -592,7 +636,7 @@ execute_control_command (struct command_line *cmd)
       {
 	/* Breakpoint commands list, record the commands in the
 	   breakpoint's command list and return.  */
-	std::string new_line = insert_args (cmd->line);
+	std::string new_line = insert_user_args (cmd->line);
 	ret = commands_from_control_command (new_line.c_str (), cmd);
 	break;
       }
@@ -678,62 +722,32 @@ if_command (char *arg, int from_tty)
   do_cleanups (old_chain);
 }
 
-/* Cleanup */
-static void
-arg_cleanup (void *ignore)
-{
-  struct user_args *oargs = user_args;
-
-  if (!user_args)
-    internal_error (__FILE__, __LINE__,
-		    _("arg_cleanup called with no user args.\n"));
-
-  user_args = user_args->next;
-  xfree (oargs->command);
-  xfree (oargs);
-}
-
-/* Bind the incomming arguments for a user defined command to
-   $arg0, $arg1 ... $argMAXUSERARGS.  */
+/* Bind the incoming arguments for a user defined command to $arg0,
+   $arg1 ... $argN.  */
 
-static struct cleanup *
-setup_user_args (char *p)
+user_args::user_args (const char *command_line)
 {
-  struct user_args *args;
-  struct cleanup *old_chain;
-  unsigned int arg_count = 0;
-
-  args = XNEW (struct user_args);
-  memset (args, 0, sizeof (struct user_args));
-
-  args->next = user_args;
-  user_args = args;
-
-  old_chain = make_cleanup (arg_cleanup, 0/*ignored*/);
+  const char *p;
 
-  if (p == NULL)
-    return old_chain;
+  if (command_line == NULL)
+    return;
 
-  user_args->command = p = xstrdup (p);
+  m_command_line = command_line;
+  p = m_command_line.c_str ();
 
   while (*p)
     {
-      char *start_arg;
+      const char *start_arg;
       int squote = 0;
       int dquote = 0;
       int bsquote = 0;
 
-      if (arg_count >= MAXUSERARGS)
-	error (_("user defined function may only have %d arguments."),
-	       MAXUSERARGS);
-
       /* Strip whitespace.  */
       while (*p == ' ' || *p == '\t')
 	p++;
 
       /* P now points to an argument.  */
       start_arg = p;
-      user_args->a[arg_count].arg = p;
 
       /* Get to the end of this argument.  */
       while (*p)
@@ -767,11 +781,8 @@ setup_user_args (char *p)
 	    }
 	}
 
-      user_args->a[arg_count].len = p - start_arg;
-      arg_count++;
-      user_args->count++;
+      m_args.push_back (string_view (start_arg, p - start_arg));
     }
-  return old_chain;
 }
 
 /* Given character string P, return a point to the first argument
@@ -790,48 +801,59 @@ locate_arg (const char *p)
   return NULL;
 }
 
-/* Insert the user defined arguments stored in user_arg into the $arg
-   arguments found in line.  */
+/* Insert the user defined arguments stored at top of the user args
+   stack into the $arg arguments found in line.  */
 
 static std::string
-insert_args (const char *line)
+insert_user_args (const char *line)
 {
   /* If we are not in a user-defined function, treat $argc, $arg0, et
      cetera as normal convenience variables.  */
-  if (user_args == NULL)
+  if (user_args_stack.empty ())
     return line;
 
+  user_args *args = user_args_stack.back ();
+  return args->insert_args (line);
+}
+
+/* Insert the user defined arguments stored in user_args into the $arg
+   arguments found in line.  */
+
+std::string
+user_args::insert_args (const char *line)
+{
   std::string new_line;
   const char *p;
 
   while ((p = locate_arg (line)))
     {
-      int i, len;
-
       new_line.append (line, p - line);
 
       if (p[4] == 'c')
 	{
-	  gdb_assert (user_args->count >= 0 && user_args->count <= 10);
-	  if (user_args->count == 10)
-	    {
-	      new_line += '1';
-	      new_line += '0';
-	    }
-	  else
-	    new_line += user_args->count + '0';
+	  new_line += gdb::to_string (m_args.size ());
+	  line = p + 5;
 	}
       else
 	{
-	  i = p[4] - '0';
-	  if (i >= user_args->count)
-	    error (_("Missing argument %d in user function."), i);
+	  char *tmp;
+	  unsigned long i;
 
-	  len = user_args->a[i].len;
-	  if (len > 0)
-	    new_line.append (user_args->a[i].arg, len);
+	  errno = 0;
+	  i = strtoul (p + 4, &tmp, 10);
+	  if ((i == 0 && tmp == p + 4) || errno != 0)
+	    {
+	      line = p + 4;
+	    }
+	  else if (i >= m_args.size ())
+	    error (_("Missing argument %ld in user function."), i);
+	  else
+	    {
+	      new_line.append (m_args[i].str, m_args[i].len);
+
+	      line = tmp;
+	    }
 	}
-      line = p + 5;
     }
   /* Don't forget the tail.  */
   new_line.append (line);
diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h
index a9053ff..436daa9 100644
--- a/gdb/common/common-utils.h
+++ b/gdb/common/common-utils.h
@@ -21,6 +21,7 @@
 #define COMMON_UTILS_H
 
 #include <string>
+#include <sstream>
 
 /* If possible, define FUNCTION_NAME, a macro containing the name of
    the function being defined.  Since this macro may not always be
@@ -62,6 +63,23 @@ int xsnprintf (char *str, size_t size, const char *format, ...)
 std::string string_printf (const char* fmt, ...)
   ATTRIBUTE_PRINTF (1, 2);
 
+/* Returns a string representation of VAL.  Replacement for
+   std::to_string, which is only available in C++11 or later.  */
+
+namespace gdb {
+
+template <class T>
+inline std::string
+to_string (const T &val)
+{
+  std::stringstream ss;
+
+  ss << val;
+  return ss.str ();
+}
+
+}
+
 /* Make a copy of the string at PTR with LEN characters
    (and add a null character at the end in the copy).
    Uses malloc to get the space.  Returns the address of the copy.  */
-- 
2.5.5

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

* [PATCH v2 27/31] Use ui_file_as_string in gdb/language.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (14 preceding siblings ...)
  2016-10-19  1:13 ` [PATCH v2 14/31] Use ui_file_as_string in gdb/guile/ Pedro Alves
@ 2016-10-19  1:13 ` Pedro Alves
  2016-10-19  1:13 ` [PATCH v2 29/31] 'struct agent_expr *' -> unique_ptr<agent_expr> Pedro Alves
                   ` (14 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* language.c (add_language): Use ui_file_as_string and adjust to
	use std::string.
---
 gdb/language.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/gdb/language.c b/gdb/language.c
index 39faecc..2869d75 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -538,7 +538,6 @@ add_language (const struct language_defn *lang)
   /* For the "set language" command.  */
   static const char **language_names = NULL;
   /* For the "help set language" command.  */
-  char *language_set_doc = NULL;
 
   int i;
   struct ui_file *tmp_stream;
@@ -609,19 +608,17 @@ add_language (const struct language_defn *lang)
 			  languages[i]->la_name + 1);
     }
 
-  language_set_doc = ui_file_xstrdup (tmp_stream, NULL);
+  std::string language_set_doc = ui_file_as_string (tmp_stream);
   ui_file_delete (tmp_stream);
 
   add_setshow_enum_cmd ("language", class_support,
 			(const char **) language_names,
 			&language,
-			language_set_doc,
+			language_set_doc.c_str (),
 			_("Show the current source language."),
 			NULL, set_language_command,
 			show_language_command,
 			&setlist, &showlist);
-
-  xfree (language_set_doc);
 }
 
 /* Iterate through all registered languages looking for and calling
-- 
2.5.5

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

* [PATCH v2 26/31] Use ui_file_as_string in gdb/rust-lang.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (17 preceding siblings ...)
  2016-10-19  1:13 ` [PATCH v2 23/31] Use ui_file_as_string in gdbarch.sh/gdbarch.c Pedro Alves
@ 2016-10-19  1:13 ` Pedro Alves
  2016-10-19  1:17 ` [PATCH v2 09/31] Use ui_file_as_string in gdb/xtensa-tdep.c Pedro Alves
                   ` (11 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:13 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>
	    Tom Tromey  <tom@tromey.com>

	* rust-lang.c (struct disr_info) <name>: Now a std::string.
	(rust_get_disr_info): Use ui_file_as_string and adjust to use
	std::string.
	(rust_val_print): Adjust to use std::string.
---
 gdb/rust-lang.c | 57 ++++++++++++++++++++-------------------------------------
 1 file changed, 20 insertions(+), 37 deletions(-)

diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 82cd3f9..54a16cc 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -70,8 +70,8 @@ rust_crate_for_block (const struct block *block)
 
 struct disr_info
 {
-  /* Name of field.  Must be freed by caller.  */
-  char *name;
+  /* Name of field.  */
+  std::string name;
   /* Field number in union.  Negative on error.  For an encoded enum,
      the "hidden" member will always be field 1, and the "real" member
      will always be field 0.  */
@@ -172,14 +172,13 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr,
       if (value == 0)
 	{
 	  ret.field_no = RUST_ENCODED_ENUM_HIDDEN;
-	  ret.name = concat (TYPE_NAME (type), "::", token, (char *) NULL);
+	  ret.name = std::string (TYPE_NAME (type)) + "::" + token;
 	}
       else
 	{
 	  ret.field_no = RUST_ENCODED_ENUM_REAL;
-	  ret.name = concat (TYPE_NAME (type), "::",
-			     rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 0))),
-			     (char *) NULL);
+	  ret.name = (std::string (TYPE_NAME (type)) + "::"
+		      + rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 0))));
 	}
 
       do_cleanups (cleanup);
@@ -208,8 +207,8 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr,
 	       address, temp_file,
 	       0, val, &opts);
 
-  ret.name = ui_file_xstrdup (temp_file, NULL);
-  name_segment = rust_last_path_segment (ret.name);
+  ret.name = ui_file_as_string (temp_file);
+  name_segment = rust_last_path_segment (ret.name.c_str ());
   if (name_segment != NULL)
     {
       for (i = 0; i < TYPE_NFIELDS (type); ++i)
@@ -233,12 +232,11 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr,
 	}
     }
 
-  if (ret.field_no == -1 && ret.name != NULL)
+  if (ret.field_no == -1 && !ret.name.empty ())
     {
       /* Somehow the discriminant wasn't found.  */
-      make_cleanup (xfree, ret.name);
       error (_("Could not find variant of %s with discriminant %s"),
-	     TYPE_TAG_NAME (type), ret.name);
+	     TYPE_TAG_NAME (type), ret.name.c_str ());
     }
 
   do_cleanups (cleanup);
@@ -553,19 +551,17 @@ rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	struct type *variant_type;
 	struct disr_info disr;
 	struct value_print_options opts;
-	struct cleanup *cleanup;
 
 	opts = *options;
 	opts.deref_ref = 0;
 
 	disr = rust_get_disr_info (type, valaddr, embedded_offset, address,
 				   val);
-	cleanup = make_cleanup (xfree, disr.name);
 
 	if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN)
 	  {
-	    fprintf_filtered (stream, "%s", disr.name);
-	    goto cleanup;
+	    fprintf_filtered (stream, "%s", disr.name.c_str ());
+	    break;
 	  }
 
 	first_field = 1;
@@ -581,19 +577,19 @@ rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	  {
 	    /* In case of a non-nullary variant, we output 'Foo(x,y,z)'. */
 	    if (is_tuple)
-	      fprintf_filtered (stream, "%s(", disr.name);
+	      fprintf_filtered (stream, "%s(", disr.name.c_str ());
 	    else
 	      {
 		/* struct variant.  */
-		fprintf_filtered (stream, "%s{", disr.name);
+		fprintf_filtered (stream, "%s{", disr.name.c_str ());
 	      }
 	  }
 	else
 	  {
 	    /* In case of a nullary variant like 'None', just output
 	       the name. */
-	    fprintf_filtered (stream, "%s", disr.name);
-	    goto cleanup;
+	    fprintf_filtered (stream, "%s", disr.name.c_str ());
+	    break;
 	  }
 
 	for (j = start; j < TYPE_NFIELDS (variant_type); j++)
@@ -620,9 +616,6 @@ rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	  fputs_filtered (")", stream);
 	else
 	  fputs_filtered ("}", stream);
-
-      cleanup:
-	do_cleanups (cleanup);
       }
       break;
 
@@ -1628,14 +1621,10 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp,
         type = value_type (lhs);
         if (TYPE_CODE (type) == TYPE_CODE_UNION)
 	  {
-	    struct cleanup *cleanup;
-
 	    disr = rust_get_disr_info (type, value_contents (lhs),
 				       value_embedded_offset (lhs),
 				       value_address (lhs), lhs);
 
-	    cleanup = make_cleanup (xfree, disr.name);
-
 	    if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN)
 	      {
 		variant_type = NULL;
@@ -1654,17 +1643,16 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp,
 	      error(_("Cannot access field %d of variant %s, \
 there are only %d fields"),
 		    disr.is_encoded ? field_number : field_number - 1,
-		    disr.name,
+		    disr.name.c_str (),
 		    disr.is_encoded ? nfields : nfields - 1);
 
 	    if (!(disr.is_encoded
 		  ? rust_tuple_struct_type_p (variant_type)
 		  : rust_tuple_variant_type_p (variant_type)))
-	      error(_("Variant %s is not a tuple variant"), disr.name);
+	      error(_("Variant %s is not a tuple variant"), disr.name.c_str ());
 
 	    result = value_primitive_field (lhs, 0, field_number,
 					    variant_type);
-	    do_cleanups (cleanup);
 	  }
 	else if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
 	  {
@@ -1706,7 +1694,6 @@ tuple structs, and tuple-like enum variants"));
 	  {
 	    int i, start;
 	    struct disr_info disr;
-	    struct cleanup* cleanup;
 	    struct type* variant_type;
 	    char* field_name;
 
@@ -1716,11 +1703,9 @@ tuple structs, and tuple-like enum variants"));
 				       value_embedded_offset (lhs),
 				       value_address (lhs), lhs);
 
-	    cleanup = make_cleanup (xfree, disr.name);
-
 	    if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN)
 	      error(_("Could not find field %s of struct variant %s"),
-		    field_name, disr.name);
+		    field_name, disr.name.c_str ());
 
 	    variant_type = TYPE_FIELD_TYPE (type, disr.field_no);
 
@@ -1728,7 +1713,7 @@ tuple structs, and tuple-like enum variants"));
 		|| rust_tuple_variant_type_p (variant_type))
 	      error(_("Attempting to access named field %s of tuple variant %s, \
 which has only anonymous fields"),
-		    field_name, disr.name);
+		    field_name, disr.name.c_str ());
 
 	    start = disr.is_encoded ? 0 : 1;
 	    for (i = start; i < TYPE_NFIELDS (variant_type); i++)
@@ -1743,9 +1728,7 @@ which has only anonymous fields"),
 	    if (i == TYPE_NFIELDS (variant_type))
 	      /* We didn't find it.  */
 	      error(_("Could not find field %s of struct variant %s"),
-		    field_name, disr.name);
-
-	    do_cleanups (cleanup);
+		    field_name, disr.name.c_str ());
 	  }
 	else
 	  {
-- 
2.5.5

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

* [PATCH v2 25/31] Use ui_file_as_string in gdb/infrun.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (21 preceding siblings ...)
  2016-10-19  1:17 ` [PATCH v2 10/31] Use ui_file_as_string in gdb/ada-valprint.c Pedro Alves
@ 2016-10-19  1:17 ` Pedro Alves
  2016-10-19  1:18 ` [PATCH v2 30/31] Eliminate agent_expr_p; VEC -> std::vector in struct bp_target_info Pedro Alves
                   ` (7 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:17 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* infrun.c (print_target_wait_results): Use ui_file_as_string and
	std::string.
---
 gdb/infrun.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 2636a19..2fa6449 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3433,7 +3433,6 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
 {
   char *status_string = target_waitstatus_to_string (ws);
   struct ui_file *tmp_stream = mem_fileopen ();
-  char *text;
 
   /* The text is split over several lines because it was getting too long.
      Call fprintf_unfiltered (gdb_stdlog) once so that the text is still
@@ -3459,14 +3458,13 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
 		      "infrun:   %s\n",
 		      status_string);
 
-  text = ui_file_xstrdup (tmp_stream, NULL);
+  std::string text = ui_file_as_string (tmp_stream);
 
   /* This uses %s in part to handle %'s in the text, but also to avoid
      a gcc error: the format attribute requires a string literal.  */
-  fprintf_unfiltered (gdb_stdlog, "%s", text);
+  fprintf_unfiltered (gdb_stdlog, "%s", text.c_str ());
 
   xfree (status_string);
-  xfree (text);
   ui_file_delete (tmp_stream);
 }
 
-- 
2.5.5

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

* [PATCH v2 09/31] Use ui_file_as_string in gdb/xtensa-tdep.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (18 preceding siblings ...)
  2016-10-19  1:13 ` [PATCH v2 26/31] Use ui_file_as_string in gdb/rust-lang.c Pedro Alves
@ 2016-10-19  1:17 ` Pedro Alves
  2016-10-19  1:17 ` [PATCH v2 11/31] Use ui_file_as_string in gdb/ui-out.c Pedro Alves
                   ` (10 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:17 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* xtensa-tdep.c (xtensa_verify_config): Use ui_file_as_string and
	std::string.
---
 gdb/xtensa-tdep.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index aafb175..68890ff 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -3065,8 +3065,6 @@ xtensa_verify_config (struct gdbarch *gdbarch)
   struct ui_file *log;
   struct cleanup *cleanups;
   struct gdbarch_tdep *tdep;
-  long length;
-  char *buf;
 
   tdep = gdbarch_tdep (gdbarch);
   log = mem_fileopen ();
@@ -3098,11 +3096,10 @@ xtensa_verify_config (struct gdbarch *gdbarch)
   if (tdep->a0_base == -1)
     fprintf_unfiltered (log, _("\n\ta0_base: No Ax registers"));
 
-  buf = ui_file_xstrdup (log, &length);
-  make_cleanup (xfree, buf);
-  if (length > 0)
+  std::string buf = ui_file_as_string (log);
+  if (!buf.empty ())
     internal_error (__FILE__, __LINE__,
-		    _("the following are invalid: %s"), buf);
+		    _("the following are invalid: %s"), buf.c_str ());
   do_cleanups (cleanups);
 }
 
-- 
2.5.5

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

* [PATCH v2 10/31] Use ui_file_as_string in gdb/ada-valprint.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (20 preceding siblings ...)
  2016-10-19  1:17 ` [PATCH v2 11/31] Use ui_file_as_string in gdb/ui-out.c Pedro Alves
@ 2016-10-19  1:17 ` Pedro Alves
  2016-10-19  1:17 ` [PATCH v2 25/31] Use ui_file_as_string in gdb/infrun.c Pedro Alves
                   ` (8 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:17 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* ada-valprint.c (ada_print_floating): Use ui_file_as_string and
	std::string.
---
 gdb/ada-valprint.c | 53 +++++++++++++++++++++++++++--------------------------
 1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index 6b4b6d4..bae4e4f 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -298,49 +298,50 @@ static void
 ada_print_floating (const gdb_byte *valaddr, struct type *type,
 		    struct ui_file *stream)
 {
-  char *s, *result;
   struct ui_file *tmp_stream = mem_fileopen ();
   struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_stream);
 
   print_floating (valaddr, type, tmp_stream);
-  result = ui_file_xstrdup (tmp_stream, NULL);
-  make_cleanup (xfree, result);
+
+  std::string s = ui_file_as_string (tmp_stream);
+  size_t skip_count = 0;
 
   /* Modify for Ada rules.  */
 
-  s = strstr (result, "inf");
-  if (s == NULL)
-    s = strstr (result, "Inf");
-  if (s == NULL)
-    s = strstr (result, "INF");
-  if (s != NULL)
-    strcpy (s, "Inf");
+  size_t pos = s.find ("inf");
+  if (pos == std::string::npos)
+    pos = s.find ("Inf");
+  if (pos == std::string::npos)
+    pos = s.find ("INF");
+  if (pos != std::string::npos)
+    s.replace (pos, 3, "Inf");
 
-  if (s == NULL)
+  if (pos == std::string::npos)
     {
-      s = strstr (result, "nan");
-      if (s == NULL)
-	s = strstr (result, "NaN");
-      if (s == NULL)
-	s = strstr (result, "Nan");
-      if (s != NULL)
+      pos = s.find ("nan");
+      if (pos == std::string::npos)
+	pos = s.find ("NaN");
+      if (pos == std::string::npos)
+	pos = s.find ("Nan");
+      if (pos != std::string::npos)
 	{
-	  s[0] = s[2] = 'N';
-	  if (result[0] == '-')
-	    result += 1;
+	  s[pos] = s[pos + 2] = 'N';
+	  if (s[0] == '-')
+	    skip_count = 1;
 	}
     }
 
-  if (s == NULL && strchr (result, '.') == NULL)
+  if (pos == std::string::npos
+      && s.find ('.') == std::string::npos)
     {
-      s = strchr (result, 'e');
-      if (s == NULL)
-	fprintf_filtered (stream, "%s.0", result);
+      pos = s.find ('e');
+      if (pos == std::string::npos)
+	fprintf_filtered (stream, "%s.0", s.c_str ());
       else
-	fprintf_filtered (stream, "%.*s.0%s", (int) (s-result), result, s);
+	fprintf_filtered (stream, "%.*s.0%s", (int) pos, s.c_str (), &s[pos]);
     }
   else
-    fprintf_filtered (stream, "%s", result);
+    fprintf_filtered (stream, "%s", &s[skip_count]);
 
   do_cleanups (cleanups);
 }
-- 
2.5.5

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

* [PATCH v2 11/31] Use ui_file_as_string in gdb/ui-out.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (19 preceding siblings ...)
  2016-10-19  1:17 ` [PATCH v2 09/31] Use ui_file_as_string in gdb/xtensa-tdep.c Pedro Alves
@ 2016-10-19  1:17 ` Pedro Alves
  2016-10-19  1:17 ` [PATCH v2 10/31] Use ui_file_as_string in gdb/ada-valprint.c Pedro Alves
                   ` (9 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:17 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* ui-out.c (ui_out_field_stream): Use ui_file_as_string.
---
 gdb/ui-out.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/gdb/ui-out.c b/gdb/ui-out.c
index f6d6050..9b1df3c 100644
--- a/gdb/ui-out.c
+++ b/gdb/ui-out.c
@@ -425,16 +425,13 @@ ui_out_field_stream (struct ui_out *uiout,
 		     const char *fldname,
 		     struct ui_file *stream)
 {
-  long length;
-  char *buffer = ui_file_xstrdup (stream, &length);
-  struct cleanup *old_cleanup = make_cleanup (xfree, buffer);
+  std::string buffer = ui_file_as_string (stream);
 
-  if (length > 0)
-    ui_out_field_string (uiout, fldname, buffer);
+  if (!buffer.empty ())
+    ui_out_field_string (uiout, fldname, buffer.c_str ());
   else
     ui_out_field_skip (uiout, fldname);
   ui_file_rewind (stream);
-  do_cleanups (old_cleanup);
 }
 
 /* Used to omit a field.  */
-- 
2.5.5

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

* [PATCH v2 05/31] 'struct expression *' -> gdb::unique_xmalloc_ptr<expression>
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (23 preceding siblings ...)
  2016-10-19  1:18 ` [PATCH v2 30/31] Eliminate agent_expr_p; VEC -> std::vector in struct bp_target_info Pedro Alves
@ 2016-10-19  1:18 ` Pedro Alves
  2016-10-19 18:45   ` Simon Marchi
  2016-10-19  1:19 ` [PATCH v2 04/31] cli-script.c: Simplify using std::string, eliminate cleanups Pedro Alves
                   ` (5 subsequent siblings)
  30 siblings, 1 reply; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:18 UTC (permalink / raw)
  To: gdb-patches

This patch makes parse_expression and friends return a unique_ptr
instead of raw pointer [1]:

  typedef gdb::unique_malloc_ptr<expression> expression_up;

and then adjusts the codebase throughout to stop using cleanups to
manage lifetime of expression pointers.

Whenever I found a structure owning an expression pointer, I made it
store a unique_ptr instead of a raw pointer, which then requires using
new/delete of the holding structure, instead of XNEW/xfree.

[1] - I'd like to set the rule that types named with an "_up" suffix
      are unique_ptr typedefs.

Note I used gdb::unique_xmalloc_ptr instead of gdb::unique_ptr, simply
because we still use xmalloc instead of new to allocate expression
objects.  Once that's changed, all we need to do is change the
expression_up typedef and the smart pointer will then call delete
instead of xfree.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* ada-lang.c (ada_read_renaming_var_value): Use expression_up.
	(struct ada_catchpoint_location) <excep_cond_expr>: Now an
	expression_up.
	(ada_catchpoint_location_dtor): Reset excep_cond_expr instead of
	using xfree.
	(create_excep_cond_exprs): Use expression_up and gdb::move.
	(allocate_location_exception): Use new instead of XNEW.
	(should_stop_exception): Likewise.  Adjust to use expression_up.
	(create_ada_exception_catchpoint): Use new instead of XNEW.
	* ax-gdb.c (agent_eval_command_one): Use expression_up instead of
	cleanups.
	(maint_agent_printf_command): Use expression_up.
	* break-catch-sig.c (create_signal_catchpoint): Use new instead of
	XNEW.
	* break-catch-syscall.c (create_syscall_event_catchpoint):
	Likewise.
	* break-catch-throw.c (handle_gnu_v3_exceptions): Use new instead
	of XCNEW.  Use gdb::unique_ptr instead of cleanups.
	* breakpoint.c (set_breakpoint_condition, update_watchpoint)
	(parse_cmd_to_aexpr, watchpoint_check)
	(bpstat_check_breakpoint_conditions, watchpoint_locations_match):
	Adjust to use expression_up.
	(init_bp_location): Adjust.
	(free_bp_location): Use delete instead of xfree.
	(set_raw_breakpoint_without_location, set_raw_breakpoint)
	(add_solib_catchpoint, create_fork_vfork_event_catchpoint)
	(new_single_step_breakpoint, create_breakpoint_sal): Use new
	instead of XNEW.
	(find_condition_and_thread): Adjust to use expression_up.
	(create_breakpoint): Use new instead of XNEW.
	(dtor_watchpoint): Don't xfree expression pointers, they're
	unique_ptr's now.
	(insert_watchpoint, remove_watchpoint): Adjust.
	(watch_command_1): Use expression_up.  Use new instead of XCNEW.
	(catch_exec_command_1): Use new instead of XNEW.
	(bp_location_dtor): Don't xfree expression pointers, they're
	unique_ptr's now.
	(base_breakpoint_allocate_location)
	(strace_marker_create_breakpoints_sal): Use new instead of XNEW.
	(delete_breakpoint): Use delete instead of xfree.
	* breakpoint.h (struct bp_location) <cond>: Now an
	unique_ptr<expression> instead of a raw pointer.
	(struct watchpoint) <exp, cond_exp>: Likewise.
	* cli/cli-script.c (execute_control_command): Use expression_up
	instead of cleanups.
	* dtrace-probe.c (dtrace_process_dof_probe): Use expression_up.
	* eval.c (parse_and_eval_address, parse_and_eval_long)
	(parse_and_eval, parse_to_comma_and_eval, parse_and_eval_type):
	Use expression_up instead of cleanups.
	* expression.h (expression_up): New typedef.
	(parse_expression, parse_expression_with_language, parse_exp_1):
	Change return type to expression_up.
	* mi/mi-main.c (mi_cmd_data_evaluate_expression)
	(print_variable_or_computed): Use expression_up.
	* objc-lang.c (print_object_command): Use expression_up instead of
	cleanups.
	* parse.c (parse_exp_1, parse_exp_in_context)
	(parse_exp_in_context_1, parse_expression)
	(parse_expression_with_language): Return an expression_up instead
	of a raw pointer.
	(parse_expression_for_completion): Use expression_up.
	* printcmd.c (struct display) <exp>: Now an expression_up instead
	of a raw pointer.
	(print_command_1, output_command_const, set_command, x_command):
	Use expression_up instead of cleanups.
	(display_command): Likewise.  Use new instead of XNEW.
	(free_display): Use delete instead of xfree.
	(do_one_display): Adjust to use expression_up.
	* remote.c (remote_download_tracepoint): Likewise.
	* stack.c (return_command): Likewise.
	* tracepoint.c (validate_actionline, encode_actions_1): Use
	expression_up instead of cleanups.
	* typeprint.c (whatis_exp, maintenance_print_type): Likewise.
	* value.c (init_if_undefined_command): Likewise.
	* varobj.c (struct varobj_root) <exp>: Now an expression_up
	instead of a raw pointer.
	(varobj_create): Adjust.
	(varobj_set_value): Use an expression_up instead of cleanups.
	(new_root_variable): Use new instead of XNEW.
	(free_variable): Use delete instead of xfree.
	(value_of_root_1): Use std::swap.
---
 gdb/ada-lang.c            | 37 ++++++------------
 gdb/ax-gdb.c              | 15 +++-----
 gdb/break-catch-sig.c     |  2 +-
 gdb/break-catch-syscall.c |  2 +-
 gdb/break-catch-throw.c   |  7 +---
 gdb/breakpoint.c          | 95 ++++++++++++++++++-----------------------------
 gdb/breakpoint.h          |  6 +--
 gdb/cli/cli-script.c      | 14 ++-----
 gdb/dtrace-probe.c        |  6 +--
 gdb/eval.c                | 43 ++++++---------------
 gdb/expression.h          | 12 +++---
 gdb/gnu-v3-abi.c          |  6 +--
 gdb/mi/mi-main.c          | 16 +++-----
 gdb/objc-lang.c           |  7 +---
 gdb/parse.c               | 50 ++++++++++---------------
 gdb/printcmd.c            | 56 +++++++++-------------------
 gdb/remote.c              |  2 +-
 gdb/stack.c               |  6 +--
 gdb/tracepoint.c          | 47 ++++++++++-------------
 gdb/typeprint.c           | 14 ++-----
 gdb/value.c               |  8 +---
 gdb/varobj.c              | 31 ++++++----------
 22 files changed, 173 insertions(+), 309 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index be2f47a..d1a39bc 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -4454,17 +4454,10 @@ ada_read_renaming_var_value (struct symbol *renaming_sym,
 			     const struct block *block)
 {
   const char *sym_name;
-  struct expression *expr;
-  struct value *value;
-  struct cleanup *old_chain = NULL;
 
   sym_name = SYMBOL_LINKAGE_NAME (renaming_sym);
-  expr = parse_exp_1 (&sym_name, 0, block, 0);
-  old_chain = make_cleanup (free_current_contents, &expr);
-  value = evaluate_expression (expr);
-
-  do_cleanups (old_chain);
-  return value;
+  expression_up expr = parse_exp_1 (&sym_name, 0, block, 0);
+  return evaluate_expression (expr.get ());
 }
 \f
 
@@ -12308,7 +12301,7 @@ struct ada_catchpoint_location
   /* The condition that checks whether the exception that was raised
      is the specific exception the user specified on catchpoint
      creation.  */
-  struct expression *excep_cond_expr;
+  expression_up excep_cond_expr;
 };
 
 /* Implement the DTOR method in the bp_location_ops structure for all
@@ -12319,7 +12312,7 @@ ada_catchpoint_location_dtor (struct bp_location *bl)
 {
   struct ada_catchpoint_location *al = (struct ada_catchpoint_location *) bl;
 
-  xfree (al->excep_cond_expr);
+  al->excep_cond_expr.reset ();
 }
 
 /* The vtable to be used in Ada catchpoint locations.  */
@@ -12371,7 +12364,7 @@ create_excep_cond_exprs (struct ada_catchpoint *c)
     {
       struct ada_catchpoint_location *ada_loc
 	= (struct ada_catchpoint_location *) bl;
-      struct expression *exp = NULL;
+      expression_up exp;
 
       if (!bl->shlib_disabled)
 	{
@@ -12380,26 +12373,20 @@ create_excep_cond_exprs (struct ada_catchpoint *c)
 	  s = cond_string;
 	  TRY
 	    {
-	      exp = parse_exp_1 (&s, bl->address,
-				 block_for_pc (bl->address), 0);
+	      exp = gdb::move (parse_exp_1 (&s, bl->address,
+					    block_for_pc (bl->address),
+					    0));
 	    }
 	  CATCH (e, RETURN_MASK_ERROR)
 	    {
 	      warning (_("failed to reevaluate internal exception condition "
 			 "for catchpoint %d: %s"),
 		       c->base.number, e.message);
-	      /* There is a bug in GCC on sparc-solaris when building with
-		 optimization which causes EXP to change unexpectedly
-		 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56982).
-		 The problem should be fixed starting with GCC 4.9.
-		 In the meantime, work around it by forcing EXP back
-		 to NULL.  */
-	      exp = NULL;
 	    }
 	  END_CATCH
 	}
 
-      ada_loc->excep_cond_expr = exp;
+      ada_loc->excep_cond_expr = gdb::move (exp);
     }
 
   do_cleanups (old_chain);
@@ -12427,7 +12414,7 @@ allocate_location_exception (enum ada_exception_catchpoint_kind ex,
 {
   struct ada_catchpoint_location *loc;
 
-  loc = XNEW (struct ada_catchpoint_location);
+  loc = new ada_catchpoint_location ();
   init_bp_location (&loc->base, &ada_catchpoint_location_ops, self);
   loc->excep_cond_expr = NULL;
   return &loc->base;
@@ -12479,7 +12466,7 @@ should_stop_exception (const struct bp_location *bl)
       struct value *mark;
 
       mark = value_mark ();
-      stop = value_true (evaluate_expression (ada_loc->excep_cond_expr));
+      stop = value_true (evaluate_expression (ada_loc->excep_cond_expr.get ()));
       value_free_to_mark (mark);
     }
   CATCH (ex, RETURN_MASK_ALL)
@@ -13143,7 +13130,7 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch,
   struct symtab_and_line sal
     = ada_exception_sal (ex_kind, excep_string, &addr_string, &ops);
 
-  c = XNEW (struct ada_catchpoint);
+  c = new ada_catchpoint ();
   init_ada_exception_breakpoint (&c->base, gdbarch, sal, addr_string,
 				 ops, tempflag, disabled, from_tty);
   c->excep_string = excep_string;
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 7c6cb64..ccd16f2 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -2581,7 +2581,6 @@ static void
 agent_eval_command_one (const char *exp, int eval, CORE_ADDR pc)
 {
   struct cleanup *old_chain = 0;
-  struct expression *expr;
   struct agent_expr *agent;
   const char *arg;
   int trace_string = 0;
@@ -2601,16 +2600,15 @@ agent_eval_command_one (const char *exp, int eval, CORE_ADDR pc)
     }
   else
     {
-      expr = parse_exp_1 (&arg, pc, block_for_pc (pc), 0);
-      old_chain = make_cleanup (free_current_contents, &expr);
+      expression_up expr = parse_exp_1 (&arg, pc, block_for_pc (pc), 0);
       if (eval)
 	{
 	  gdb_assert (trace_string == 0);
-	  agent = gen_eval_for_expr (pc, expr);
+	  agent = gen_eval_for_expr (pc, expr.get ());
 	}
       else
-	agent = gen_trace_for_expr (pc, expr, trace_string);
-      make_cleanup_free_agent_expr (agent);
+	agent = gen_trace_for_expr (pc, expr.get (), trace_string);
+      old_chain = make_cleanup_free_agent_expr (agent);
     }
 
   ax_reqs (agent);
@@ -2696,7 +2694,6 @@ static void
 maint_agent_printf_command (char *exp, int from_tty)
 {
   struct cleanup *old_chain = 0;
-  struct expression *expr;
   struct expression *argvec[100];
   struct agent_expr *agent;
   struct frame_info *fi = get_current_frame ();	/* need current scope */
@@ -2748,8 +2745,8 @@ maint_agent_printf_command (char *exp, int from_tty)
       const char *cmd1;
 
       cmd1 = cmdrest;
-      expr = parse_exp_1 (&cmd1, 0, (struct block *) 0, 1);
-      argvec[nargs] = expr;
+      expression_up expr = parse_exp_1 (&cmd1, 0, (struct block *) 0, 1);
+      argvec[nargs] = expr.release ();
       ++nargs;
       cmdrest = cmd1;
       if (*cmdrest == ',')
diff --git a/gdb/break-catch-sig.c b/gdb/break-catch-sig.c
index 296f900..e869a83 100644
--- a/gdb/break-catch-sig.c
+++ b/gdb/break-catch-sig.c
@@ -371,7 +371,7 @@ create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter,
   struct signal_catchpoint *c;
   struct gdbarch *gdbarch = get_current_arch ();
 
-  c = XNEW (struct signal_catchpoint);
+  c = new signal_catchpoint ();
   init_catchpoint (&c->base, gdbarch, tempflag, NULL, &signal_catchpoint_ops);
   c->signals_to_be_caught = filter;
   c->catch_all = catch_all;
diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
index 63b8cd2..a4df2ce 100644
--- a/gdb/break-catch-syscall.c
+++ b/gdb/break-catch-syscall.c
@@ -433,7 +433,7 @@ create_syscall_event_catchpoint (int tempflag, VEC(int) *filter,
   struct syscall_catchpoint *c;
   struct gdbarch *gdbarch = get_current_arch ();
 
-  c = XNEW (struct syscall_catchpoint);
+  c = new syscall_catchpoint ();
   init_catchpoint (&c->base, gdbarch, tempflag, NULL, ops);
   c->syscalls_to_be_caught = filter;
 
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 153db71..cfec33b 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -393,8 +393,6 @@ static void
 handle_gnu_v3_exceptions (int tempflag, char *except_rx, char *cond_string,
 			  enum exception_event_kind ex_event, int from_tty)
 {
-  struct exception_catchpoint *cp;
-  struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
   regex_t *pattern = NULL;
 
   if (except_rx != NULL)
@@ -406,8 +404,7 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx, char *cond_string,
 			   _("invalid type-matching regexp"));
     }
 
-  cp = XCNEW (struct exception_catchpoint);
-  make_cleanup (xfree, cp);
+  gdb::unique_ptr<exception_catchpoint> cp (new exception_catchpoint ());
 
   init_catchpoint (&cp->base, get_current_arch (), tempflag, cond_string,
 		   &gnu_v3_exception_catchpoint_ops);
@@ -421,7 +418,7 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx, char *cond_string,
   re_set_exception_catchpoint (&cp->base);
 
   install_breakpoint (0, &cp->base, 1);
-  discard_cleanups (cleanup);
+  cp.release ();
 }
 
 /* Look for an "if" token in *STRING.  The "if" token must be preceded
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index c9b151f..2039966 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -981,8 +981,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
     {
       struct watchpoint *w = (struct watchpoint *) b;
 
-      xfree (w->cond_exp);
-      w->cond_exp = NULL;
+      w->cond_exp.reset ();
     }
   else
     {
@@ -990,8 +989,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
 
       for (loc = b->loc; loc; loc = loc->next)
 	{
-	  xfree (loc->cond);
-	  loc->cond = NULL;
+	  loc->cond.reset ();
 
 	  /* No need to free the condition agent expression
 	     bytecode (if we have one).  We will handle this
@@ -1897,11 +1895,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
     {
       const char *s;
 
-      if (b->exp)
-	{
-	  xfree (b->exp);
-	  b->exp = NULL;
-	}
+      b->exp.reset ();
       s = b->exp_string_reparse ? b->exp_string_reparse : b->exp_string;
       b->exp = parse_exp_1 (&s, 0, b->exp_valid_block, 0);
       /* If the meaning of expression itself changed, the old value is
@@ -1917,11 +1911,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
 	 locations (re)created below.  */
       if (b->base.cond_string != NULL)
 	{
-	  if (b->cond_exp != NULL)
-	    {
-	      xfree (b->cond_exp);
-	      b->cond_exp = NULL;
-	    }
+	  b->cond_exp.reset ();
 
 	  s = b->base.cond_string;
 	  b->cond_exp = parse_exp_1 (&s, 0, b->cond_exp_valid_block, 0);
@@ -1953,7 +1943,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
       struct value *val_chain, *v, *result, *next;
       struct program_space *frame_pspace;
 
-      fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain, 0);
+      fetch_subexp_value (b->exp.get (), &pc, &v, &result, &val_chain, 0);
 
       /* Avoid setting b->val if it's already set.  The meaning of
 	 b->val is 'the last value' user saw, and we should update
@@ -2337,7 +2327,7 @@ build_target_condition_list (struct bp_location *bl)
 		 case we already freed the condition bytecodes (see
 		 force_breakpoint_reinsertion).  We just
 		 need to parse the condition to bytecodes again.  */
-	      aexpr = parse_cond_to_aexpr (bl->address, loc->cond);
+	      aexpr = parse_cond_to_aexpr (bl->address, loc->cond.get ());
 	      loc->cond_bytecode = aexpr;
 	    }
 
@@ -2402,7 +2392,7 @@ static struct agent_expr *
 parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
 {
   struct cleanup *old_cleanups = 0;
-  struct expression *expr, **argvec;
+  struct expression **argvec;
   struct agent_expr *aexpr = NULL;
   const char *cmdrest;
   const char *format_start, *format_end;
@@ -2453,8 +2443,8 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
       const char *cmd1;
 
       cmd1 = cmdrest;
-      expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1);
-      argvec[nargs++] = expr;
+      expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1);
+      argvec[nargs++] = expr.release ();
       cmdrest = cmd1;
       if (*cmdrest == ',')
 	++cmdrest;
@@ -5198,7 +5188,7 @@ watchpoint_check (void *p)
 	return WP_VALUE_CHANGED;
 
       mark = value_mark ();
-      fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL, 0);
+      fetch_subexp_value (b->exp.get (), &pc, &new_val, NULL, NULL, 0);
 
       if (b->val_bitsize != 0)
 	new_val = extract_bitfield_from_watchpoint_value (b, new_val);
@@ -5503,10 +5493,10 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
     {
       struct watchpoint *w = (struct watchpoint *) b;
 
-      cond = w->cond_exp;
+      cond = w->cond_exp.get ();
     }
   else
-    cond = bl->cond;
+    cond = bl->cond.get ();
 
   if (cond && b->disposition != disp_del_at_next_stop)
     {
@@ -7129,12 +7119,12 @@ watchpoint_locations_match (struct bp_location *loc1,
        && target_can_accel_watchpoint_condition (loc1->address, 
 						 loc1->length,
 						 loc1->watchpoint_type,
-						 w1->cond_exp))
+						 w1->cond_exp.get ()))
       || (w2->cond_exp
 	  && target_can_accel_watchpoint_condition (loc2->address, 
 						    loc2->length,
 						    loc2->watchpoint_type,
-						    w2->cond_exp)))
+						    w2->cond_exp.get ())))
     return 0;
 
   /* Note that this checks the owner's type, not the location's.  In
@@ -7342,7 +7332,6 @@ init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops,
 
   loc->ops = ops;
   loc->owner = owner;
-  loc->cond = NULL;
   loc->cond_bytecode = NULL;
   loc->shlib_disabled = 0;
   loc->enabled = 1;
@@ -7411,7 +7400,7 @@ static void
 free_bp_location (struct bp_location *loc)
 {
   loc->ops->dtor (loc);
-  xfree (loc);
+  delete loc;
 }
 
 /* Increment reference count.  */
@@ -7494,7 +7483,7 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch,
 				     enum bptype bptype,
 				     const struct breakpoint_ops *ops)
 {
-  struct breakpoint *b = XNEW (struct breakpoint);
+  struct breakpoint *b = new breakpoint ();
 
   init_raw_breakpoint_without_location (b, gdbarch, bptype, ops);
   add_to_breakpoint_chain (b);
@@ -7610,7 +7599,7 @@ set_raw_breakpoint (struct gdbarch *gdbarch,
 		    struct symtab_and_line sal, enum bptype bptype,
 		    const struct breakpoint_ops *ops)
 {
-  struct breakpoint *b = XNEW (struct breakpoint);
+  struct breakpoint *b = new breakpoint ();
 
   init_raw_breakpoint (b, gdbarch, sal, bptype, ops);
   add_to_breakpoint_chain (b);
@@ -8545,7 +8534,7 @@ add_solib_catchpoint (char *arg, int is_load, int is_temp, int enabled)
     arg = "";
   arg = skip_spaces (arg);
 
-  c = XCNEW (struct solib_catchpoint);
+  c = new solib_catchpoint ();
   cleanup = make_cleanup (xfree, c);
 
   if (*arg != '\0')
@@ -8644,7 +8633,7 @@ create_fork_vfork_event_catchpoint (struct gdbarch *gdbarch,
 				    int tempflag, char *cond_string,
                                     const struct breakpoint_ops *ops)
 {
-  struct fork_catchpoint *c = XNEW (struct fork_catchpoint);
+  struct fork_catchpoint *c = new fork_catchpoint ();
 
   init_catchpoint (&c->base, gdbarch, tempflag, cond_string, ops);
 
@@ -8905,7 +8894,7 @@ enable_breakpoints_after_startup (void)
 static struct breakpoint *
 new_single_step_breakpoint (int thread, struct gdbarch *gdbarch)
 {
-  struct breakpoint *b = XNEW (struct breakpoint);
+  struct breakpoint *b = new breakpoint ();
 
   init_raw_breakpoint_without_location (b, gdbarch, bp_single_step,
 					&momentary_breakpoint_ops);
@@ -9413,11 +9402,11 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
     {
       struct tracepoint *t;
 
-      t = XCNEW (struct tracepoint);
+      t = new tracepoint ();
       b = &t->base;
     }
   else
-    b = XNEW (struct breakpoint);
+    b = new breakpoint ();
 
   old_chain = make_cleanup (xfree, b);
 
@@ -9668,11 +9657,8 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
 
       if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
 	{
-	  struct expression *expr;
-
 	  tok = cond_start = end_tok + 1;
-	  expr = parse_exp_1 (&tok, pc, block_for_pc (pc), 0);
-	  xfree (expr);
+	  parse_exp_1 (&tok, pc, block_for_pc (pc), 0);
 	  cond_end = tok;
 	  *cond_string = savestring (cond_start, cond_end - cond_start);
 	}
@@ -9917,11 +9903,11 @@ create_breakpoint (struct gdbarch *gdbarch,
 	{
 	  struct tracepoint *t;
 
-	  t = XCNEW (struct tracepoint);
+	  t = new tracepoint ();
 	  b = &t->base;
 	}
       else
-	b = XNEW (struct breakpoint);
+	b = new breakpoint ();
 
       init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops);
       b->location = copy_event_location (location);
@@ -10642,8 +10628,6 @@ dtor_watchpoint (struct breakpoint *self)
 {
   struct watchpoint *w = (struct watchpoint *) self;
 
-  xfree (w->cond_exp);
-  xfree (w->exp);
   xfree (w->exp_string);
   xfree (w->exp_string_reparse);
   value_free (w->val);
@@ -10695,7 +10679,7 @@ insert_watchpoint (struct bp_location *bl)
   int length = w->exact ? 1 : bl->length;
 
   return target_insert_watchpoint (bl->address, length, bl->watchpoint_type,
-				   w->cond_exp);
+				   w->cond_exp.get ());
 }
 
 /* Implement the "remove" breakpoint_ops method for hardware watchpoints.  */
@@ -10707,7 +10691,7 @@ remove_watchpoint (struct bp_location *bl, enum remove_bp_reason reason)
   int length = w->exact ? 1 : bl->length;
 
   return target_remove_watchpoint (bl->address, length, bl->watchpoint_type,
-				   w->cond_exp);
+				   w->cond_exp.get ());
 }
 
 static int
@@ -11138,7 +11122,6 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
 		 int just_location, int internal)
 {
   struct breakpoint *b, *scope_breakpoint = NULL;
-  struct expression *exp;
   const struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
   struct value *val, *mark, *result;
   int saved_bitpos = 0, saved_bitsize = 0;
@@ -11250,7 +11233,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
   expression = savestring (arg, exp_end - arg);
   back_to = make_cleanup (xfree, expression);
   exp_start = arg = expression;
-  exp = parse_exp_1 (&arg, 0, 0, 0);
+  expression_up exp = parse_exp_1 (&arg, 0, 0, 0);
   exp_end = arg;
   /* Remove trailing whitespace from the expression before saving it.
      This makes the eventual display of the expression string a bit
@@ -11259,7 +11242,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
     --exp_end;
 
   /* Checking if the expression is not constant.  */
-  if (watchpoint_exp_is_const (exp))
+  if (watchpoint_exp_is_const (exp.get ()))
     {
       int len;
 
@@ -11271,7 +11254,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
 
   exp_valid_block = innermost_block;
   mark = value_mark ();
-  fetch_subexp_value (exp, &pc, &val, &result, NULL, just_location);
+  fetch_subexp_value (exp.get (), &pc, &val, &result, NULL, just_location);
 
   if (val != NULL && just_location)
     {
@@ -11307,17 +11290,14 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
   toklen = end_tok - tok;
   if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
     {
-      struct expression *cond;
-
       innermost_block = NULL;
       tok = cond_start = end_tok + 1;
-      cond = parse_exp_1 (&tok, 0, 0, 0);
+      parse_exp_1 (&tok, 0, 0, 0);
 
       /* The watchpoint expression may not be local, but the condition
 	 may still be.  E.g.: `watch global if local > 0'.  */
       cond_exp_valid_block = innermost_block;
 
-      xfree (cond);
       cond_end = tok;
     }
   if (*tok)
@@ -11371,7 +11351,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
   else
     bp_type = bp_hardware_watchpoint;
 
-  w = XCNEW (struct watchpoint);
+  w = new watchpoint ();
   b = &w->base;
   if (use_mask)
     init_raw_breakpoint_without_location (b, NULL, bp_type,
@@ -11382,7 +11362,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
   b->thread = thread;
   b->disposition = disp_donttouch;
   b->pspace = current_program_space;
-  w->exp = exp;
+  w->exp = gdb::move (exp);
   w->exp_valid_block = exp_valid_block;
   w->cond_exp_valid_block = cond_exp_valid_block;
   if (just_location)
@@ -11930,7 +11910,7 @@ catch_exec_command_1 (char *arg, int from_tty,
   if ((*arg != '\0') && !isspace (*arg))
     error (_("Junk at end of arguments."));
 
-  c = XNEW (struct exec_catchpoint);
+  c = new exec_catchpoint ();
   init_catchpoint (&c->base, gdbarch, tempflag, cond_string,
 		   &catch_exec_breakpoint_ops);
   c->exec_pathname = NULL;
@@ -12898,7 +12878,6 @@ say_where (struct breakpoint *b)
 static void
 bp_location_dtor (struct bp_location *self)
 {
-  xfree (self->cond);
   if (self->cond_bytecode)
     free_agent_expr (self->cond_bytecode);
   xfree (self->function_name);
@@ -12931,7 +12910,7 @@ base_breakpoint_allocate_location (struct breakpoint *self)
 {
   struct bp_location *loc;
 
-  loc = XNEW (struct bp_location);
+  loc = new struct bp_location ();
   init_bp_location (loc, &bp_location_ops, self);
   return loc;
 }
@@ -13783,7 +13762,7 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
       location = copy_event_location (canonical->location);
       old_chain = make_cleanup_delete_event_location (location);
 
-      tp = XCNEW (struct tracepoint);
+      tp = new tracepoint ();
       init_breakpoint_sal (&tp->base, gdbarch, expanded,
 			   location, NULL,
 			   cond_string, extra_string,
@@ -13925,7 +13904,7 @@ delete_breakpoint (struct breakpoint *bpt)
   /* On the chance that someone will soon try again to delete this
      same bp, we mark it as deleted before freeing its storage.  */
   bpt->type = bp_none;
-  xfree (bpt);
+  delete bpt;
 }
 
 static void
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index ebaf1e3..9b4c96a 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -343,7 +343,7 @@ struct bp_location
      different for different locations.  Only valid for real
      breakpoints; a watchpoint's conditional expression is stored in
      the owner breakpoint object.  */
-  struct expression *cond;
+  expression_up cond;
 
   /* Conditional expression in agent expression
      bytecode form.  This is used for stub-side breakpoint
@@ -798,12 +798,12 @@ struct watchpoint
   char *exp_string_reparse;
 
   /* The expression we are watching, or NULL if not a watchpoint.  */
-  struct expression *exp;
+  expression_up exp;
   /* The largest block within which it is valid, or NULL if it is
      valid anywhere (e.g. consists just of global symbols).  */
   const struct block *exp_valid_block;
   /* The conditional expression if any.  */
-  struct expression *cond_exp;
+  expression_up cond_exp;
   /* The largest block within which it is valid, or NULL if it is
      valid anywhere (e.g. consists just of global symbols).  */
   const struct block *cond_exp_valid_block;
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 6f1cc8a..6302f52 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -441,9 +441,7 @@ print_command_trace (const char *cmd)
 enum command_control_type
 execute_control_command (struct command_line *cmd)
 {
-  struct expression *expr;
   struct command_line *current;
-  struct cleanup *old_chain = make_cleanup (null_cleanup, 0);
   struct value *val;
   struct value *val_mark;
   int loop;
@@ -490,8 +488,7 @@ execute_control_command (struct command_line *cmd)
 
 	/* Parse the loop control expression for the while statement.  */
 	std::string new_line = insert_args (cmd->line);
-	expr = parse_expression (new_line.c_str ());
-	make_cleanup (free_current_contents, &expr);
+	expression_up expr = parse_expression (new_line.c_str ());
 
 	ret = simple_control;
 	loop = 1;
@@ -505,7 +502,7 @@ execute_control_command (struct command_line *cmd)
 
 	    /* Evaluate the expression.  */
 	    val_mark = value_mark ();
-	    val = evaluate_expression (expr);
+	    val = evaluate_expression (expr.get ());
 	    cond_result = value_true (val);
 	    value_free_to_mark (val_mark);
 
@@ -556,15 +553,14 @@ execute_control_command (struct command_line *cmd)
 
 	/* Parse the conditional for the if statement.  */
 	std::string new_line = insert_args (cmd->line);
-	expr = parse_expression (new_line.c_str ());
-	make_cleanup (free_current_contents, &expr);
+	expression_up expr = parse_expression (new_line.c_str ());
 
 	current = NULL;
 	ret = simple_control;
 
 	/* Evaluate the conditional.  */
 	val_mark = value_mark ();
-	val = evaluate_expression (expr);
+	val = evaluate_expression (expr.get ());
 
 	/* Choose which arm to take commands from based on the value
 	   of the conditional expression.  */
@@ -620,8 +616,6 @@ execute_control_command (struct command_line *cmd)
       break;
     }
 
-  do_cleanups (old_chain);
-
   return ret;
 }
 
diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c
index 242e316..cbeeea8 100644
--- a/gdb/dtrace-probe.c
+++ b/gdb/dtrace-probe.c
@@ -413,7 +413,7 @@ dtrace_process_dof_probe (struct objfile *objfile,
       for (j = 0; j < ret->probe_argc; j++)
 	{
 	  struct dtrace_probe_arg arg;
-	  struct expression *expr = NULL;
+	  expression_up expr;
 
 	  /* Set arg.expr to ensure all fields in expr are initialized and
 	     the compiler will not warn when arg is used.  */
@@ -430,11 +430,11 @@ dtrace_process_dof_probe (struct objfile *objfile,
 
 	  TRY
 	    {
-	      expr = parse_expression_with_language (arg.type_str, language_c);
+	      expr = gdb::move (parse_expression_with_language (arg.type_str,
+								language_c));
 	    }
 	  CATCH (ex, RETURN_MASK_ERROR)
 	    {
-	      expr = NULL;
 	    }
 	  END_CATCH
 
diff --git a/gdb/eval.c b/gdb/eval.c
index 00a107c..f30b8e1 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -95,14 +95,9 @@ evaluate_subexp (struct type *expect_type, struct expression *exp,
 CORE_ADDR
 parse_and_eval_address (const char *exp)
 {
-  struct expression *expr = parse_expression (exp);
-  CORE_ADDR addr;
-  struct cleanup *old_chain =
-    make_cleanup (free_current_contents, &expr);
-
-  addr = value_as_address (evaluate_expression (expr));
-  do_cleanups (old_chain);
-  return addr;
+  expression_up expr = parse_expression (exp);
+
+  return value_as_address (evaluate_expression (expr.get ()));
 }
 
 /* Like parse_and_eval_address, but treats the value of the expression
@@ -110,27 +105,17 @@ parse_and_eval_address (const char *exp)
 LONGEST
 parse_and_eval_long (const char *exp)
 {
-  struct expression *expr = parse_expression (exp);
-  LONGEST retval;
-  struct cleanup *old_chain =
-    make_cleanup (free_current_contents, &expr);
-
-  retval = value_as_long (evaluate_expression (expr));
-  do_cleanups (old_chain);
-  return (retval);
+  expression_up expr = parse_expression (exp);
+
+  return value_as_long (evaluate_expression (expr.get ()));
 }
 
 struct value *
 parse_and_eval (const char *exp)
 {
-  struct expression *expr = parse_expression (exp);
-  struct value *val;
-  struct cleanup *old_chain =
-    make_cleanup (free_current_contents, &expr);
+  expression_up expr = parse_expression (exp);
 
-  val = evaluate_expression (expr);
-  do_cleanups (old_chain);
-  return val;
+  return evaluate_expression (expr.get ());
 }
 
 /* Parse up to a comma (or to a closeparen)
@@ -140,14 +125,9 @@ parse_and_eval (const char *exp)
 struct value *
 parse_to_comma_and_eval (const char **expp)
 {
-  struct expression *expr = parse_exp_1 (expp, 0, (struct block *) 0, 1);
-  struct value *val;
-  struct cleanup *old_chain =
-    make_cleanup (free_current_contents, &expr);
+  expression_up expr = parse_exp_1 (expp, 0, (struct block *) 0, 1);
 
-  val = evaluate_expression (expr);
-  do_cleanups (old_chain);
-  return val;
+  return evaluate_expression (expr.get ());
 }
 \f
 /* Evaluate an expression in internal prefix form
@@ -3104,14 +3084,13 @@ struct type *
 parse_and_eval_type (char *p, int length)
 {
   char *tmp = (char *) alloca (length + 4);
-  struct expression *expr;
 
   tmp[0] = '(';
   memcpy (tmp + 1, p, length);
   tmp[length + 1] = ')';
   tmp[length + 2] = '0';
   tmp[length + 3] = '\0';
-  expr = parse_expression (tmp);
+  expression_up expr = parse_expression (tmp);
   if (expr->elts[0].opcode != UNOP_CAST)
     error (_("Internal error in eval_type."));
   return expr->elts[1].type;
diff --git a/gdb/expression.h b/gdb/expression.h
index 4952d84..d8b8cba 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -85,6 +85,8 @@ struct expression
     union exp_element elts[1];
   };
 
+typedef gdb::unique_xmalloc_ptr<expression> expression_up;
+
 /* Macros for converting between number of expression elements and bytes
    to store that many expression elements.  */
 
@@ -95,16 +97,16 @@ struct expression
 
 /* From parse.c */
 
-extern struct expression *parse_expression (const char *);
+extern expression_up parse_expression (const char *);
 
-extern struct expression *parse_expression_with_language (const char *string,
-							  enum language lang);
+extern expression_up parse_expression_with_language (const char *string,
+						     enum language lang);
 
 extern struct type *parse_expression_for_completion (const char *, char **,
 						     enum type_code *);
 
-extern struct expression *parse_exp_1 (const char **, CORE_ADDR pc,
-				       const struct block *, int);
+extern expression_up parse_exp_1 (const char **, CORE_ADDR pc,
+				  const struct block *, int);
 
 /* For use by parsers; set if we want to parse an expression and
    attempt completion.  */
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index 0e037e6..eda9a11 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -1195,7 +1195,6 @@ gnuv3_get_type_from_type_info (struct value *type_info_ptr)
   char *type_name;
   struct cleanup *cleanup;
   struct value *type_val;
-  struct expression *expr;
   struct type *result;
 
   type_name = gnuv3_get_typename_from_type_info (type_info_ptr);
@@ -1206,10 +1205,9 @@ gnuv3_get_type_from_type_info (struct value *type_info_ptr)
      mis-parse.  Another approach might be to re-use the demangler's
      internal form to reconstruct the type somehow.  */
 
-  expr = parse_expression (type_name);
-  make_cleanup (xfree, expr);
+  expression_up expr = parse_expression (type_name);
 
-  type_val = evaluate_type (expr);
+  type_val = evaluate_type (expr.get ());
   result = value_type (type_val);
 
   do_cleanups (cleanup);
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 81e82ed..25b23d6 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -1363,7 +1363,6 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc)
 void
 mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
 {
-  struct expression *expr;
   struct cleanup *old_chain;
   struct value *val;
   struct ui_file *stb;
@@ -1377,11 +1376,9 @@ mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
     error (_("-data-evaluate-expression: "
 	     "Usage: -data-evaluate-expression expression"));
 
-  expr = parse_expression (argv[0]);
+  expression_up expr = parse_expression (argv[0]);
 
-  make_cleanup (free_current_contents, &expr);
-
-  val = evaluate_expression (expr);
+  val = evaluate_expression (expr.get ());
 
   /* Print the result of the expression evaluation.  */
   get_user_print_options (&opts);
@@ -2747,7 +2744,6 @@ mi_cmd_ada_task_info (char *command, char **argv, int argc)
 static void
 print_variable_or_computed (char *expression, enum print_values values)
 {
-  struct expression *expr;
   struct cleanup *old_chain;
   struct value *val;
   struct ui_file *stb;
@@ -2757,14 +2753,12 @@ print_variable_or_computed (char *expression, enum print_values values)
   stb = mem_fileopen ();
   old_chain = make_cleanup_ui_file_delete (stb);
 
-  expr = parse_expression (expression);
-
-  make_cleanup (free_current_contents, &expr);
+  expression_up expr = parse_expression (expression);
 
   if (values == PRINT_SIMPLE_VALUES)
-    val = evaluate_type (expr);
+    val = evaluate_type (expr.get ());
   else
-    val = evaluate_expression (expr);
+    val = evaluate_expression (expr.get ());
 
   if (values != PRINT_NO_VALUES)
     make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index b2844b9..43d83da 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -1193,14 +1193,11 @@ print_object_command (char *args, int from_tty)
 "The 'print-object' command requires an argument (an Objective-C object)");
 
   {
-    struct expression *expr = parse_expression (args);
-    struct cleanup *old_chain = 
-      make_cleanup (free_current_contents, &expr);
+    expression_up expr = parse_expression (args);
     int pc = 0;
 
     object = evaluate_subexp (builtin_type (expr->gdbarch)->builtin_data_ptr,
-			      expr, &pc, EVAL_NORMAL);
-    do_cleanups (old_chain);
+			      expr.get (), &pc, EVAL_NORMAL);
   }
 
   /* Validate the address for sanity.  */
diff --git a/gdb/parse.c b/gdb/parse.c
index 231eebf..e921438 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -115,12 +115,12 @@ static void free_funcalls (void *ignore);
 static int prefixify_subexp (struct expression *, struct expression *, int,
 			     int);
 
-static struct expression *parse_exp_in_context (const char **, CORE_ADDR,
-						const struct block *, int, 
-						int, int *);
-static struct expression *parse_exp_in_context_1 (const char **, CORE_ADDR,
-						  const struct block *, int,
-						  int, int *);
+static expression_up parse_exp_in_context (const char **, CORE_ADDR,
+					   const struct block *, int,
+					   int, int *);
+static expression_up parse_exp_in_context_1 (const char **, CORE_ADDR,
+					     const struct block *, int,
+					     int, int *);
 
 void _initialize_parse (void);
 
@@ -1108,14 +1108,14 @@ prefixify_subexp (struct expression *inexpr,
 
    If COMMA is nonzero, stop if a comma is reached.  */
 
-struct expression *
+expression_up
 parse_exp_1 (const char **stringptr, CORE_ADDR pc, const struct block *block,
 	     int comma)
 {
   return parse_exp_in_context (stringptr, pc, block, comma, 0, NULL);
 }
 
-static struct expression *
+static expression_up
 parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
 		      const struct block *block,
 		      int comma, int void_context_p, int *out_subexp)
@@ -1131,7 +1131,7 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
    left-hand-side of the struct op.  If not doing such completion, it
    is left untouched.  */
 
-static struct expression *
+static expression_up
 parse_exp_in_context_1 (const char **stringptr, CORE_ADDR pc,
 			const struct block *block,
 			int comma, int void_context_p, int *out_subexp)
@@ -1254,18 +1254,16 @@ parse_exp_in_context_1 (const char **stringptr, CORE_ADDR pc,
   discard_cleanups (old_chain);
 
   *stringptr = lexptr;
-  return ps.expout;
+  return expression_up (ps.expout);
 }
 
 /* Parse STRING as an expression, and complain if this fails
    to use up all of the contents of STRING.  */
 
-struct expression *
+expression_up
 parse_expression (const char *string)
 {
-  struct expression *exp;
-
-  exp = parse_exp_1 (&string, 0, 0, 0);
+  expression_up exp = parse_exp_1 (&string, 0, 0, 0);
   if (*string)
     error (_("Junk after end of expression."));
   return exp;
@@ -1274,11 +1272,10 @@ parse_expression (const char *string)
 /* Same as parse_expression, but using the given language (LANG)
    to parse the expression.  */
 
-struct expression *
+expression_up
 parse_expression_with_language (const char *string, enum language lang)
 {
   struct cleanup *old_chain = NULL;
-  struct expression *expr;
 
   if (current_language->la_language != lang)
     {
@@ -1286,7 +1283,7 @@ parse_expression_with_language (const char *string, enum language lang)
       set_language (lang);
     }
 
-  expr = parse_expression (string);
+  expression_up expr = parse_expression (string);
 
   if (old_chain != NULL)
     do_cleanups (old_chain);
@@ -1305,14 +1302,14 @@ struct type *
 parse_expression_for_completion (const char *string, char **name,
 				 enum type_code *code)
 {
-  struct expression *exp = NULL;
+  expression_up exp;
   struct value *val;
   int subexp;
 
   TRY
     {
       parse_completion = 1;
-      exp = parse_exp_in_context (&string, 0, 0, 0, 0, &subexp);
+      exp = gdb::move (parse_exp_in_context (&string, 0, 0, 0, 0, &subexp));
     }
   CATCH (except, RETURN_MASK_ERROR)
     {
@@ -1333,24 +1330,17 @@ parse_expression_for_completion (const char *string, char **name,
     }
 
   if (expout_last_struct == -1)
-    {
-      xfree (exp);
-      return NULL;
-    }
+    return NULL;
 
-  *name = extract_field_op (exp, &subexp);
+  *name = extract_field_op (exp.get (), &subexp);
   if (!*name)
-    {
-      xfree (exp);
-      return NULL;
-    }
+    return NULL;
 
   /* This might throw an exception.  If so, we want to let it
      propagate.  */
-  val = evaluate_subexpression_type (exp, subexp);
+  val = evaluate_subexpression_type (exp.get (), subexp);
   /* (*NAME) is a part of the EXP memory block freed below.  */
   *name = xstrdup (*name);
-  xfree (exp);
 
   return value_type (val);
 }
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index c7f477b..aa51848 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -119,7 +119,7 @@ struct display
     char *exp_string;
 
     /* Expression to be evaluated and displayed.  */
-    struct expression *exp;
+    expression_up exp;
 
     /* Item number of this auto-display item.  */
     int number;
@@ -1243,8 +1243,6 @@ print_value (struct value *val, const struct format_data *fmtp)
 static void
 print_command_1 (const char *exp, int voidprint)
 {
-  struct expression *expr;
-  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   struct value *val;
   struct format_data fmt;
 
@@ -1252,9 +1250,8 @@ print_command_1 (const char *exp, int voidprint)
 
   if (exp && *exp)
     {
-      expr = parse_expression (exp);
-      make_cleanup (free_current_contents, &expr);
-      val = evaluate_expression (expr);
+      expression_up expr = parse_expression (exp);
+      val = evaluate_expression (expr.get ());
     }
   else
     val = access_value_history (0);
@@ -1262,8 +1259,6 @@ print_command_1 (const char *exp, int voidprint)
   if (voidprint || (val && value_type (val) &&
 		    TYPE_CODE (value_type (val)) != TYPE_CODE_VOID))
     print_value (val, &fmt);
-
-  do_cleanups (old_chain);
 }
 
 static void
@@ -1292,8 +1287,6 @@ output_command (char *exp, int from_tty)
 void
 output_command_const (const char *exp, int from_tty)
 {
-  struct expression *expr;
-  struct cleanup *old_chain;
   char format = 0;
   struct value *val;
   struct format_data fmt;
@@ -1310,10 +1303,9 @@ output_command_const (const char *exp, int from_tty)
       format = fmt.format;
     }
 
-  expr = parse_expression (exp);
-  old_chain = make_cleanup (free_current_contents, &expr);
+  expression_up expr = parse_expression (exp);
 
-  val = evaluate_expression (expr);
+  val = evaluate_expression (expr.get ());
 
   annotate_value_begin (value_type (val));
 
@@ -1325,16 +1317,12 @@ output_command_const (const char *exp, int from_tty)
 
   wrap_here ("");
   gdb_flush (gdb_stdout);
-
-  do_cleanups (old_chain);
 }
 
 static void
 set_command (char *exp, int from_tty)
 {
-  struct expression *expr = parse_expression (exp);
-  struct cleanup *old_chain =
-    make_cleanup (free_current_contents, &expr);
+  expression_up expr = parse_expression (exp);
 
   if (expr->nelts >= 1)
     switch (expr->elts[0].opcode)
@@ -1352,8 +1340,7 @@ set_command (char *exp, int from_tty)
 	  (_("Expression is not an assignment (and might have no effect)"));
       }
 
-  evaluate_expression (expr);
-  do_cleanups (old_chain);
+  evaluate_expression (expr.get ());
 }
 
 static void
@@ -1676,7 +1663,6 @@ address_info (char *exp, int from_tty)
 static void
 x_command (char *exp, int from_tty)
 {
-  struct expression *expr;
   struct format_data fmt;
   struct cleanup *old_chain;
   struct value *val;
@@ -1698,14 +1684,13 @@ x_command (char *exp, int from_tty)
 
   if (exp != 0 && *exp != 0)
     {
-      expr = parse_expression (exp);
+      expression_up expr = parse_expression (exp);
       /* Cause expression not to be there any more if this command is
          repeated with Newline.  But don't clobber a user-defined
          command's definition.  */
       if (from_tty)
 	*exp = 0;
-      old_chain = make_cleanup (free_current_contents, &expr);
-      val = evaluate_expression (expr);
+      val = evaluate_expression (expr.get ());
       if (TYPE_CODE (value_type (val)) == TYPE_CODE_REF)
 	val = coerce_ref (val);
       /* In rvalue contexts, such as this, functions are coerced into
@@ -1718,7 +1703,6 @@ x_command (char *exp, int from_tty)
 	next_address = value_as_address (val);
 
       next_gdbarch = expr->gdbarch;
-      do_cleanups (old_chain);
     }
 
   if (!next_gdbarch)
@@ -1764,7 +1748,6 @@ static void
 display_command (char *arg, int from_tty)
 {
   struct format_data fmt;
-  struct expression *expr;
   struct display *newobj;
   const char *exp = arg;
 
@@ -1792,12 +1775,12 @@ display_command (char *arg, int from_tty)
     }
 
   innermost_block = NULL;
-  expr = parse_expression (exp);
+  expression_up expr = parse_expression (exp);
 
-  newobj = XNEW (struct display);
+  newobj = new display ();
 
   newobj->exp_string = xstrdup (exp);
-  newobj->exp = expr;
+  newobj->exp = gdb::move (expr);
   newobj->block = innermost_block;
   newobj->pspace = current_program_space;
   newobj->number = ++display_number;
@@ -1826,8 +1809,7 @@ static void
 free_display (struct display *d)
 {
   xfree (d->exp_string);
-  xfree (d->exp);
-  xfree (d);
+  delete d;
 }
 
 /* Clear out the display_chain.  Done when new symtabs are loaded,
@@ -1952,8 +1934,7 @@ do_one_display (struct display *d)
      expression if the current architecture has changed.  */
   if (d->exp != NULL && d->exp->gdbarch != get_current_arch ())
     {
-      xfree (d->exp);
-      d->exp = NULL;
+      d->exp.reset ();
       d->block = NULL;
     }
 
@@ -2026,7 +2007,7 @@ do_one_display (struct display *d)
 	  struct value *val;
 	  CORE_ADDR addr;
 
-	  val = evaluate_expression (d->exp);
+	  val = evaluate_expression (d->exp.get ());
 	  addr = value_as_address (val);
 	  if (d->format.format == 'i')
 	    addr = gdbarch_addr_bits_remove (d->exp->gdbarch, addr);
@@ -2063,7 +2044,7 @@ do_one_display (struct display *d)
         {
 	  struct value *val;
 
-	  val = evaluate_expression (d->exp);
+	  val = evaluate_expression (d->exp.get ());
 	  print_formatted (val, d->format.size, &opts, gdb_stdout);
 	}
       CATCH (ex, RETURN_MASK_ERROR)
@@ -2224,10 +2205,9 @@ clear_dangling_display_expressions (struct objfile *objfile)
 	continue;
 
       if (lookup_objfile_from_block (d->block) == objfile
-	  || (d->exp && exp_uses_objfile (d->exp, objfile)))
+	  || (d->exp != NULL && exp_uses_objfile (d->exp.get (), objfile)))
       {
-	xfree (d->exp);
-	d->exp = NULL;
+	d->exp.reset ();
 	d->block = NULL;
       }
     }
diff --git a/gdb/remote.c b/gdb/remote.c
index af7508a..e8cb560 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -11936,7 +11936,7 @@ remote_download_tracepoint (struct target_ops *self, struct bp_location *loc)
 	 capabilities at definition time.  */
       if (remote_supports_cond_tracepoints ())
 	{
-	  aexpr = gen_eval_for_expr (tpaddr, loc->cond);
+	  aexpr = gen_eval_for_expr (tpaddr, loc->cond.get ());
 	  aexpr_chain = make_cleanup_free_agent_expr (aexpr);
 	  xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":X%x,",
 		     aexpr->len);
diff --git a/gdb/stack.c b/gdb/stack.c
index 706dd51..0f8b336 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2439,13 +2439,12 @@ return_command (char *retval_exp, int from_tty)
      message.  */
   if (retval_exp)
     {
-      struct expression *retval_expr = parse_expression (retval_exp);
-      struct cleanup *old_chain = make_cleanup (xfree, retval_expr);
+      expression_up retval_expr = parse_expression (retval_exp);
       struct type *return_type = NULL;
 
       /* Compute the return value.  Should the computation fail, this
          call throws an error.  */
-      return_value = evaluate_expression (retval_expr);
+      return_value = evaluate_expression (retval_expr.get ());
 
       /* Cast return value to the return type of the function.  Should
          the cast fail, this call throws an error.  */
@@ -2460,7 +2459,6 @@ return_command (char *retval_exp, int from_tty)
 		     "Please use an explicit cast of the value to return."));
 	  return_type = value_type (return_value);
 	}
-      do_cleanups (old_chain);
       return_type = check_typedef (return_type);
       return_value = value_cast (return_type, return_value);
 
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index e5c353c..e0ef6e8 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -701,7 +701,6 @@ void
 validate_actionline (const char *line, struct breakpoint *b)
 {
   struct cmd_list_element *c;
-  struct expression *exp = NULL;
   struct cleanup *old_chain = NULL;
   const char *tmp_p;
   const char *p;
@@ -755,9 +754,8 @@ validate_actionline (const char *line, struct breakpoint *b)
 	  for (loc = t->base.loc; loc; loc = loc->next)
 	    {
 	      p = tmp_p;
-	      exp = parse_exp_1 (&p, loc->address,
-				 block_for_pc (loc->address), 1);
-	      old_chain = make_cleanup (free_current_contents, &exp);
+	      expression_up exp = parse_exp_1 (&p, loc->address,
+					       block_for_pc (loc->address), 1);
 
 	      if (exp->elts[0].opcode == OP_VAR_VALUE)
 		{
@@ -780,8 +778,8 @@ validate_actionline (const char *line, struct breakpoint *b)
 	      /* We have something to collect, make sure that the expr to
 		 bytecode translator can handle it and that it's not too
 		 long.  */
-	      aexpr = gen_trace_for_expr (loc->address, exp, trace_string);
-	      make_cleanup_free_agent_expr (aexpr);
+	      aexpr = gen_trace_for_expr (loc->address, exp.get (), trace_string);
+	      old_chain = make_cleanup_free_agent_expr (aexpr);
 
 	      if (aexpr->len > MAX_AGENT_EXPR_LEN)
 		error (_("Expression is too complicated."));
@@ -809,15 +807,14 @@ validate_actionline (const char *line, struct breakpoint *b)
 	      p = tmp_p;
 
 	      /* Only expressions are allowed for this action.  */
-	      exp = parse_exp_1 (&p, loc->address,
-				 block_for_pc (loc->address), 1);
-	      old_chain = make_cleanup (free_current_contents, &exp);
+	      expression_up exp = parse_exp_1 (&p, loc->address,
+					       block_for_pc (loc->address), 1);
 
 	      /* We have something to evaluate, make sure that the expr to
 		 bytecode translator can handle it and that it's not too
 		 long.  */
-	      aexpr = gen_eval_for_expr (loc->address, exp);
-	      make_cleanup_free_agent_expr (aexpr);
+	      aexpr = gen_eval_for_expr (loc->address, exp.get ());
+	      old_chain = make_cleanup_free_agent_expr (aexpr);
 
 	      if (aexpr->len > MAX_AGENT_EXPR_LEN)
 		error (_("Expression is too complicated."));
@@ -1399,7 +1396,6 @@ encode_actions_1 (struct command_line *action,
 		  struct collection_list *stepping_list)
 {
   const char *action_exp;
-  struct expression *exp = NULL;
   int i;
   struct value *tempval;
   struct cmd_list_element *cmd;
@@ -1501,12 +1497,11 @@ encode_actions_1 (struct command_line *action,
 	      else
 		{
 		  unsigned long addr;
-		  struct cleanup *old_chain = NULL;
 		  struct cleanup *old_chain1 = NULL;
 
-		  exp = parse_exp_1 (&action_exp, tloc->address,
-				     block_for_pc (tloc->address), 1);
-		  old_chain = make_cleanup (free_current_contents, &exp);
+		  expression_up exp = parse_exp_1 (&action_exp, tloc->address,
+						   block_for_pc (tloc->address),
+						   1);
 
 		  switch (exp->elts[0].opcode)
 		    {
@@ -1528,13 +1523,13 @@ encode_actions_1 (struct command_line *action,
 
 		    case UNOP_MEMVAL:
 		      /* Safe because we know it's a simple expression.  */
-		      tempval = evaluate_expression (exp);
+		      tempval = evaluate_expression (exp.get ());
 		      addr = value_address (tempval);
 		      /* Initialize the TYPE_LENGTH if it is a typedef.  */
 		      check_typedef (exp->elts[1].type);
 		      add_memrange (collect, memrange_absolute, addr,
 				    TYPE_LENGTH (exp->elts[1].type));
-		      append_exp (exp, &collect->computed);
+		      append_exp (exp.get (), &collect->computed);
 		      break;
 
 		    case OP_VAR_VALUE:
@@ -1556,7 +1551,7 @@ encode_actions_1 (struct command_line *action,
 		      break;
 
 		    default:	/* Full-fledged expression.  */
-		      aexpr = gen_trace_for_expr (tloc->address, exp,
+		      aexpr = gen_trace_for_expr (tloc->address, exp.get (),
 						  trace_string);
 
 		      old_chain1 = make_cleanup_free_agent_expr (aexpr);
@@ -1589,10 +1584,9 @@ encode_actions_1 (struct command_line *action,
 			    }
 			}
 
-		      append_exp (exp, &collect->computed);
+		      append_exp (exp.get (), &collect->computed);
 		      break;
 		    }		/* switch */
-		  do_cleanups (old_chain);
 		}		/* do */
 	    }
 	  while (action_exp && *action_exp++ == ',');
@@ -1605,14 +1599,13 @@ encode_actions_1 (struct command_line *action,
 	      action_exp = skip_spaces_const (action_exp);
 
 		{
-		  struct cleanup *old_chain = NULL;
 		  struct cleanup *old_chain1 = NULL;
 
-		  exp = parse_exp_1 (&action_exp, tloc->address,
-				     block_for_pc (tloc->address), 1);
-		  old_chain = make_cleanup (free_current_contents, &exp);
+		  expression_up exp = parse_exp_1 (&action_exp, tloc->address,
+						   block_for_pc (tloc->address),
+						   1);
 
-		  aexpr = gen_eval_for_expr (tloc->address, exp);
+		  aexpr = gen_eval_for_expr (tloc->address, exp.get ());
 		  old_chain1 = make_cleanup_free_agent_expr (aexpr);
 
 		  ax_reqs (aexpr);
@@ -1622,8 +1615,6 @@ encode_actions_1 (struct command_line *action,
 		  /* Even though we're not officially collecting, add
 		     to the collect list anyway.  */
 		  add_aexpr (collect, aexpr);
-
-		  do_cleanups (old_chain);
 		}		/* do */
 	    }
 	  while (action_exp && *action_exp++ == ',');
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index e77513e..6851a70 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -400,7 +400,6 @@ type_to_string (struct type *type)
 static void
 whatis_exp (char *exp, int show)
 {
-  struct expression *expr;
   struct value *val;
   struct cleanup *old_chain;
   struct type *real_type = NULL;
@@ -451,9 +450,8 @@ whatis_exp (char *exp, int show)
 	  exp = skip_spaces (exp);
 	}
 
-      expr = parse_expression (exp);
-      make_cleanup (free_current_contents, &expr);
-      val = evaluate_type (expr);
+      expression_up expr = parse_expression (exp);
+      val = evaluate_type (expr.get ());
     }
   else
     val = access_value_history (0);
@@ -600,13 +598,10 @@ maintenance_print_type (char *type_name, int from_tty)
 {
   struct value *val;
   struct type *type;
-  struct cleanup *old_chain;
-  struct expression *expr;
 
   if (type_name != NULL)
     {
-      expr = parse_expression (type_name);
-      old_chain = make_cleanup (free_current_contents, &expr);
+      expression_up expr = parse_expression (type_name);
       if (expr->elts[0].opcode == OP_TYPE)
 	{
 	  /* The user expression names a type directly, just use that type.  */
@@ -616,14 +611,13 @@ maintenance_print_type (char *type_name, int from_tty)
 	{
 	  /* The user expression may name a type indirectly by naming an
 	     object of that type.  Find that indirectly named type.  */
-	  val = evaluate_type (expr);
+	  val = evaluate_type (expr.get ());
 	  type = value_type (val);
 	}
       if (type != NULL)
 	{
 	  recursive_dump_type (type, 0);
 	}
-      do_cleanups (old_chain);
     }
 }
 \f
diff --git a/gdb/value.c b/gdb/value.c
index b825aec..62c5e37 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -2113,9 +2113,7 @@ init_if_undefined_command (char* args, int from_tty)
   struct internalvar* intvar;
 
   /* Parse the expression - this is taken from set_command().  */
-  struct expression *expr = parse_expression (args);
-  register struct cleanup *old_chain =
-    make_cleanup (free_current_contents, &expr);
+  expression_up expr = parse_expression (args);
 
   /* Validate the expression.
      Was the expression an assignment?
@@ -2133,9 +2131,7 @@ init_if_undefined_command (char* args, int from_tty)
   /* Only evaluate the expression if the lvalue is void.
      This may still fail if the expresssion is invalid.  */
   if (intvar->kind == INTERNALVAR_VOID)
-    evaluate_expression (expr);
-
-  do_cleanups (old_chain);
+    evaluate_expression (expr.get ());
 }
 
 
diff --git a/gdb/varobj.c b/gdb/varobj.c
index fb1349a..81e897f 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -64,12 +64,12 @@ varobj_enable_pretty_printing (void)
 /* Data structures */
 
 /* Every root variable has one of these structures saved in its
-   varobj.  Members which must be free'd are noted.  */
+   varobj.  */
 struct varobj_root
 {
 
-  /* Alloc'd expression for this parent.  */
-  struct expression *exp;
+  /* The expression for this parent.  */
+  expression_up exp;
 
   /* Block for which this expression is valid.  */
   const struct block *valid_block;
@@ -379,13 +379,13 @@ varobj_create (char *objname,
          But if it fails, we still go on with a call to evaluate_type().  */
       TRY
 	{
-	  value = evaluate_expression (var->root->exp);
+	  value = evaluate_expression (var->root->exp.get ());
 	}
       CATCH (except, RETURN_MASK_ERROR)
 	{
 	  /* Error getting the value.  Try to at least get the
 	     right type.  */
-	  struct value *type_only_value = evaluate_type (var->root->exp);
+	  struct value *type_only_value = evaluate_type (var->root->exp.get ());
 
 	  var->type = value_type (type_only_value);
 	}
@@ -1051,7 +1051,6 @@ varobj_set_value (struct varobj *var, char *expression)
   /* The argument "expression" contains the variable's new value.
      We need to first construct a legal expression for this -- ugh!  */
   /* Does this cover all the bases?  */
-  struct expression *exp;
   struct value *value = NULL; /* Initialize to keep gcc happy.  */
   int saved_input_radix = input_radix;
   const char *s = expression;
@@ -1059,16 +1058,15 @@ varobj_set_value (struct varobj *var, char *expression)
   gdb_assert (varobj_editable_p (var));
 
   input_radix = 10;		/* ALWAYS reset to decimal temporarily.  */
-  exp = parse_exp_1 (&s, 0, 0, 0);
+  expression_up exp = parse_exp_1 (&s, 0, 0, 0);
   TRY
     {
-      value = evaluate_expression (exp);
+      value = evaluate_expression (exp.get ());
     }
 
   CATCH (except, RETURN_MASK_ERROR)
     {
       /* We cannot proceed without a valid expression.  */
-      xfree (exp);
       return 0;
     }
   END_CATCH
@@ -2095,7 +2093,7 @@ new_root_variable (void)
 {
   struct varobj *var = new_variable ();
 
-  var->root = XNEW (struct varobj_root);
+  var->root = new varobj_root ();
   var->root->lang_ops = NULL;
   var->root->exp = NULL;
   var->root->valid_block = NULL;
@@ -2126,12 +2124,8 @@ free_variable (struct varobj *var)
   varobj_clear_saved_item (var->dynamic);
   value_free (var->value);
 
-  /* Free the expression if this is a root variable.  */
   if (is_root_p (var))
-    {
-      xfree (var->root->exp);
-      xfree (var->root);
-    }
+    delete var->root;
 
   xfree (var->name);
   xfree (var->obj_name);
@@ -2296,7 +2290,7 @@ value_of_root_1 (struct varobj **var_handle)
          expression fails we want to just return NULL.  */
       TRY
 	{
-	  new_val = evaluate_expression (var->root->exp);
+	  new_val = evaluate_expression (var->root->exp.get ());
 	}
       CATCH (except, RETURN_MASK_ERROR)
 	{
@@ -2355,10 +2349,7 @@ value_of_root (struct varobj **var_handle, int *type_changed)
 	     button, for example).  Naturally, those locations are not
 	     correct in other frames, so update the expression.  */
 
-         struct expression *tmp_exp = var->root->exp;
-
-         var->root->exp = tmp_var->root->exp;
-         tmp_var->root->exp = tmp_exp;
+	  std::swap (var->root->exp, tmp_var->root->exp);
 
 	  varobj_delete (tmp_var, 0);
 	  *type_changed = 0;
-- 
2.5.5

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

* [PATCH v2 30/31] Eliminate agent_expr_p; VEC -> std::vector in struct bp_target_info
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (22 preceding siblings ...)
  2016-10-19  1:17 ` [PATCH v2 25/31] Use ui_file_as_string in gdb/infrun.c Pedro Alves
@ 2016-10-19  1:18 ` Pedro Alves
  2016-10-19  1:18 ` [PATCH v2 05/31] 'struct expression *' -> gdb::unique_xmalloc_ptr<expression> Pedro Alves
                   ` (6 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:18 UTC (permalink / raw)
  To: gdb-patches

After the previous patch, we end up with these two types with quite
similar, and potentially confusing names:

  typedef gdb::unique_ptr<agent_expr> agent_expr_up;

  /* Pointer to an agent_expr structure.  */
  typedef struct agent_expr *agent_expr_p;

The latter is only necessary to put agent_expr pointers in VECs.  So
just eliminate it and use std::vector instead.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* ax.h (agent_expr_p): Delete.
	(DEF_VEC_P (agent_expr_p)): Delete.
	* breakpoint.c (build_target_condition_list)
	(build_target_command_list): Adjust to use of std::vector.
	(bp_location_dtor): Remove now unnecessary VEC_free calls.
	* breakpoint.h: Include <vector>.
	(struct bp_target_info) <conditions, tcommands>: Now
	std::vector's.
	* remote.c (remote_add_target_side_condition): bp_tgt->conditions
	is now a std::vector; adjust.
	(remote_add_target_side_commands, remote_insert_breakpoint):
	bp_tgt->tcommands is now a std::vector; adjust.
---
 gdb/ax.h         |  6 ------
 gdb/breakpoint.c | 27 +++++++++++++--------------
 gdb/breakpoint.h | 13 +++++++------
 gdb/remote.c     | 28 +++++++++++-----------------
 4 files changed, 31 insertions(+), 43 deletions(-)

diff --git a/gdb/ax.h b/gdb/ax.h
index 4b90229..85d2943 100644
--- a/gdb/ax.h
+++ b/gdb/ax.h
@@ -170,12 +170,6 @@ struct agent_expr
 /* An agent_expr owning pointer.  */
 typedef gdb::unique_ptr<agent_expr> agent_expr_up;
 
-/* Pointer to an agent_expr structure.  */
-typedef struct agent_expr *agent_expr_p;
-
-/* Vector of pointers to agent expressions.  */
-DEF_VEC_P (agent_expr_p);
-
 /* The actual values of the various bytecode operations.  */
 
 enum agent_op
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 77f551b..37c1dbd 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -2298,7 +2298,7 @@ build_target_condition_list (struct bp_location *bl)
   struct bp_location *loc;
 
   /* Release conditions left over from a previous insert.  */
-  VEC_free (agent_expr_p, bl->target_info.conditions);
+  bl->target_info.conditions.clear ();
 
   /* This is only meaningful if the target is
      evaluating conditions and if the user has
@@ -2371,10 +2371,11 @@ build_target_condition_list (struct bp_location *bl)
 	  && loc->pspace->num == bl->pspace->num
 	  && loc->owner->enable_state == bp_enabled
 	  && loc->enabled)
-	/* Add the condition to the vector.  This will be used later to send the
-	   conditions to the target.  */
-	VEC_safe_push (agent_expr_p, bl->target_info.conditions,
-		       loc->cond_bytecode.get ());
+	{
+	  /* Add the condition to the vector.  This will be used later
+	     to send the conditions to the target.  */
+	  bl->target_info.conditions.push_back (loc->cond_bytecode.get ());
+	}
     }
 
   return;
@@ -2481,8 +2482,8 @@ build_target_command_list (struct bp_location *bl)
   int modified = bl->needs_update;
   struct bp_location *loc;
 
-  /* Release commands left over from a previous insert.  */
-  VEC_free (agent_expr_p, bl->target_info.tcommands);
+  /* Clear commands left over from a previous insert.  */
+  bl->target_info.tcommands.clear ();
 
   if (!target_can_run_breakpoint_commands ())
     return;
@@ -2565,10 +2566,11 @@ build_target_command_list (struct bp_location *bl)
 	  && loc->pspace->num == bl->pspace->num
 	  && loc->owner->enable_state == bp_enabled
 	  && loc->enabled)
-	/* Add the command to the vector.  This will be used later
-	   to send the commands to the target.  */
-	VEC_safe_push (agent_expr_p, bl->target_info.tcommands,
-		       loc->cmd_bytecode.get ());
+	{
+	  /* Add the command to the vector.  This will be used later
+	     to send the commands to the target.  */
+	  bl->target_info.tcommands.push_back (loc->cmd_bytecode.get ());
+	}
     }
 
   bl->target_info.persist = 0;
@@ -12867,9 +12869,6 @@ static void
 bp_location_dtor (struct bp_location *self)
 {
   xfree (self->function_name);
-
-  VEC_free (agent_expr_p, self->target_info.conditions);
-  VEC_free (agent_expr_p, self->target_info.tcommands);
 }
 
 static const struct bp_location_ops bp_location_ops =
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 018dddb..bfd6351 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -26,6 +26,7 @@
 #include "command.h"
 #include "break-common.h"
 #include "probe.h"
+#include <vector>
 
 struct value;
 struct block;
@@ -268,13 +269,13 @@ struct bp_target_info
      the size to remove the breakpoint safely.  */
   int placed_size;
 
-  /* Vector of conditions the target should evaluate if it supports target-side
-     breakpoint conditions.  */
-  VEC(agent_expr_p) *conditions;
+  /* Conditions the target should evaluate if it supports target-side
+     breakpoint conditions.  These are non-owning pointers.  */
+  std::vector<agent_expr *> conditions;
 
-  /* Vector of commands the target should evaluate if it supports
-     target-side breakpoint commands.  */
-  VEC(agent_expr_p) *tcommands;
+  /* Commands the target should evaluate if it supports target-side
+     breakpoint commands.  These are non-owning pointers.  */
+  std::vector<agent_expr *> tcommands;
 
   /* Flag that is true if the breakpoint should be left in place even
      when GDB is not connected.  */
diff --git a/gdb/remote.c b/gdb/remote.c
index 294d928..d090dc1 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -9193,10 +9193,7 @@ remote_add_target_side_condition (struct gdbarch *gdbarch,
 				  struct bp_target_info *bp_tgt, char *buf,
 				  char *buf_end)
 {
-  struct agent_expr *aexpr = NULL;
-  int i, ix;
-
-  if (VEC_empty (agent_expr_p, bp_tgt->conditions))
+  if (bp_tgt->conditions.empty ())
     return 0;
 
   buf += strlen (buf);
@@ -9204,13 +9201,13 @@ remote_add_target_side_condition (struct gdbarch *gdbarch,
   buf++;
 
   /* Send conditions to the target and free the vector.  */
-  for (ix = 0;
-       VEC_iterate (agent_expr_p, bp_tgt->conditions, ix, aexpr);
-       ix++)
+  for (int ix = 0; ix < bp_tgt->conditions.size (); ix++)
     {
+      struct agent_expr *aexpr = bp_tgt->conditions[ix];
+
       xsnprintf (buf, buf_end - buf, "X%x,", aexpr->len);
       buf += strlen (buf);
-      for (i = 0; i < aexpr->len; ++i)
+      for (int i = 0; i < aexpr->len; ++i)
 	buf = pack_hex_byte (buf, aexpr->buf[i]);
       *buf = '\0';
     }
@@ -9221,10 +9218,7 @@ static void
 remote_add_target_side_commands (struct gdbarch *gdbarch,
 				 struct bp_target_info *bp_tgt, char *buf)
 {
-  struct agent_expr *aexpr = NULL;
-  int i, ix;
-
-  if (VEC_empty (agent_expr_p, bp_tgt->tcommands))
+  if (bp_tgt->tcommands.empty ())
     return;
 
   buf += strlen (buf);
@@ -9234,13 +9228,13 @@ remote_add_target_side_commands (struct gdbarch *gdbarch,
 
   /* Concatenate all the agent expressions that are commands into the
      cmds parameter.  */
-  for (ix = 0;
-       VEC_iterate (agent_expr_p, bp_tgt->tcommands, ix, aexpr);
-       ix++)
+  for (int ix = 0; ix < bp_tgt->tcommands.size (); ix++)
     {
+      struct agent_expr *aexpr = bp_tgt->tcommands[ix];
+
       sprintf (buf, "X%x,", aexpr->len);
       buf += strlen (buf);
-      for (i = 0; i < aexpr->len; ++i)
+      for (int i = 0; i < aexpr->len; ++i)
 	buf = pack_hex_byte (buf, aexpr->buf[i]);
       *buf = '\0';
     }
@@ -9309,7 +9303,7 @@ remote_insert_breakpoint (struct target_ops *ops,
 
   /* If this breakpoint has target-side commands but this stub doesn't
      support Z0 packets, throw error.  */
-  if (!VEC_empty (agent_expr_p, bp_tgt->tcommands))
+  if (!bp_tgt->tcommands.empty ())
     throw_error (NOT_SUPPORTED_ERROR, _("\
 Target doesn't support breakpoints that have target side commands."));
 
-- 
2.5.5

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

* [PATCH v2 04/31] cli-script.c: Simplify using std::string, eliminate cleanups
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (24 preceding siblings ...)
  2016-10-19  1:18 ` [PATCH v2 05/31] 'struct expression *' -> gdb::unique_xmalloc_ptr<expression> Pedro Alves
@ 2016-10-19  1:19 ` Pedro Alves
  2016-10-19 18:25   ` Simon Marchi
  2016-10-19  1:21 ` [PATCH v2 17/31] Use ui_file_as_string in gdb/printcmd.c Pedro Alves
                   ` (4 subsequent siblings)
  30 siblings, 1 reply; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:19 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* cli/cli-script.c (execute_control_command): Use std::string
	instead of cleanups.
	(locate_arg): Constify return type.
	(insert_args): Constify paremeter.  Simplify using std::string.
	Return a std::string.
---
 gdb/cli/cli-script.c | 110 ++++++++++++++++-----------------------------------
 1 file changed, 33 insertions(+), 77 deletions(-)

diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index c36cce6..6f1cc8a 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -41,7 +41,7 @@ recurse_read_control_structure (char * (*read_next_line_func) (void),
 				void (*validator)(char *, void *),
 				void *closure);
 
-static char *insert_args (char *line);
+static std::string insert_args (const char *line);
 
 static struct cleanup * setup_user_args (char *p);
 
@@ -448,7 +448,6 @@ execute_control_command (struct command_line *cmd)
   struct value *val_mark;
   int loop;
   enum command_control_type ret;
-  char *new_line;
 
   /* Start by assuming failure, if a problem is detected, the code
      below will simply "break" out of the switch.  */
@@ -457,12 +456,13 @@ execute_control_command (struct command_line *cmd)
   switch (cmd->control_type)
     {
     case simple_control:
-      /* A simple command, execute it and return.  */
-      new_line = insert_args (cmd->line);
-      make_cleanup (free_current_contents, &new_line);
-      execute_command (new_line, 0);
-      ret = cmd->control_type;
-      break;
+      {
+	/* A simple command, execute it and return.  */
+	std::string new_line = insert_args (cmd->line);
+	execute_command (&new_line[0], 0);
+	ret = cmd->control_type;
+	break;
+      }
 
     case continue_control:
       print_command_trace ("loop_continue");
@@ -489,9 +489,8 @@ execute_control_command (struct command_line *cmd)
 	print_command_trace (buffer);
 
 	/* Parse the loop control expression for the while statement.  */
-	new_line = insert_args (cmd->line);
-	make_cleanup (free_current_contents, &new_line);
-	expr = parse_expression (new_line);
+	std::string new_line = insert_args (cmd->line);
+	expr = parse_expression (new_line.c_str ());
 	make_cleanup (free_current_contents, &expr);
 
 	ret = simple_control;
@@ -555,10 +554,9 @@ execute_control_command (struct command_line *cmd)
 	xsnprintf (buffer, len, "if %s", cmd->line);
 	print_command_trace (buffer);
 
-	new_line = insert_args (cmd->line);
-	make_cleanup (free_current_contents, &new_line);
 	/* Parse the conditional for the if statement.  */
-	expr = parse_expression (new_line);
+	std::string new_line = insert_args (cmd->line);
+	expr = parse_expression (new_line.c_str ());
 	make_cleanup (free_current_contents, &expr);
 
 	current = NULL;
@@ -598,9 +596,8 @@ execute_control_command (struct command_line *cmd)
       {
 	/* Breakpoint commands list, record the commands in the
 	   breakpoint's command list and return.  */
-	new_line = insert_args (cmd->line);
-	make_cleanup (free_current_contents, &new_line);
-	ret = commands_from_control_command (new_line, cmd);
+	std::string new_line = insert_args (cmd->line);
+	ret = commands_from_control_command (new_line.c_str (), cmd);
 	break;
       }
 
@@ -786,8 +783,8 @@ setup_user_args (char *p)
 /* Given character string P, return a point to the first argument
    ($arg), or NULL if P contains no arguments.  */
 
-static char *
-locate_arg (char *p)
+static const char *
+locate_arg (const char *p)
 {
   while ((p = strchr (p, '$')))
     {
@@ -800,93 +797,52 @@ locate_arg (char *p)
 }
 
 /* Insert the user defined arguments stored in user_arg into the $arg
-   arguments found in line, with the updated copy being placed into
-   nline.  */
+   arguments found in line.  */
 
-static char *
-insert_args (char *line)
+static std::string
+insert_args (const char *line)
 {
-  char *p, *save_line, *new_line;
-  unsigned len, i;
-
   /* If we are not in a user-defined function, treat $argc, $arg0, et
      cetera as normal convenience variables.  */
   if (user_args == NULL)
-    return xstrdup (line);
+    return line;
 
-  /* First we need to know how much memory to allocate for the new
-     line.  */
-  save_line = line;
-  len = 0;
-  while ((p = locate_arg (line)))
-    {
-      len += p - line;
-      i = p[4] - '0';
-
-      if (p[4] == 'c')
-	{
-	  /* $argc.  Number will be <=10.  */
-	  len += user_args->count == 10 ? 2 : 1;
-	}
-      else if (i >= user_args->count)
-	{
-	  error (_("Missing argument %d in user function."), i);
-	  return NULL;
-	}
-      else
-	{
-	  len += user_args->a[i].len;
-	}
-      line = p + 5;
-    }
-
-  /* Don't forget the tail.  */
-  len += strlen (line);
-
-  /* Allocate space for the new line and fill it in.  */
-  new_line = (char *) xmalloc (len + 1);
-
-  /* Restore pointer to beginning of old line.  */
-  line = save_line;
-
-  /* Save pointer to beginning of new line.  */
-  save_line = new_line;
+  std::string new_line;
+  const char *p;
 
   while ((p = locate_arg (line)))
     {
       int i, len;
 
-      memcpy (new_line, line, p - line);
-      new_line += p - line;
+      new_line.append (line, p - line);
 
       if (p[4] == 'c')
 	{
 	  gdb_assert (user_args->count >= 0 && user_args->count <= 10);
 	  if (user_args->count == 10)
 	    {
-	      *(new_line++) = '1';
-	      *(new_line++) = '0';
+	      new_line += '1';
+	      new_line += '0';
 	    }
 	  else
-	    *(new_line++) = user_args->count + '0';
+	    new_line += user_args->count + '0';
 	}
       else
 	{
 	  i = p[4] - '0';
+	  if (i >= user_args->count)
+	    error (_("Missing argument %d in user function."), i);
+
 	  len = user_args->a[i].len;
-	  if (len)
-	    {
-	      memcpy (new_line, user_args->a[i].arg, len);
-	      new_line += len;
-	    }
+	  if (len > 0)
+	    new_line.append (user_args->a[i].arg, len);
 	}
       line = p + 5;
     }
   /* Don't forget the tail.  */
-  strcpy (new_line, line);
+  new_line.append (line);
 
-  /* Return a pointer to the beginning of the new line.  */
-  return save_line;
+  return new_line;
 }
 
 \f
-- 
2.5.5

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

* [PATCH v2 18/31] Use ui_file_as_string in gdb/python/
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (27 preceding siblings ...)
  2016-10-19  1:21 ` [PATCH v2 16/31] Use ui_file_as_string in gdb/top.c Pedro Alves
@ 2016-10-19  1:21 ` Pedro Alves
  2016-10-19  1:21 ` [PATCH v2 13/31] Use ui_file_as_string in gdb/arm-tdep.c Pedro Alves
  2016-10-20 13:08 ` [PATCH v2 28/31] Use ui_file_as_string throughout more Pedro Alves
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:21 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* python/py-arch.c (archpy_disassemble): Use ui_file_as_string and
	std::string.
	* python/py-breakpoint.c (bppy_get_commands): Use
	ui_file_as_string and std::string.
	* python/py-frame.c (frapy_str): Likewise.
	* python/py-type.c (typy_str): Likewise.
	* python/py-unwind.c (unwind_infopy_str): Likewise.
	* python/py-value.c (valpy_str): Likewise.
---
 gdb/python/py-arch.c       | 10 +++++-----
 gdb/python/py-breakpoint.c |  8 +++-----
 gdb/python/py-frame.c      |  8 ++------
 gdb/python/py-type.c       | 10 ++++------
 gdb/python/py-unwind.c     |  7 ++-----
 gdb/python/py-value.c      |  7 +++----
 6 files changed, 19 insertions(+), 31 deletions(-)

diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index 4a2dcbf..60cc5a9 100644
--- a/gdb/python/py-arch.c
+++ b/gdb/python/py-arch.c
@@ -198,7 +198,6 @@ archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw)
        || (end_obj == NULL && count_obj == NULL && pc == start);)
     {
       int insn_len = 0;
-      char *as = NULL;
       struct ui_file *memfile = mem_fileopen ();
       PyObject *insn_dict = PyDict_New ();
 
@@ -232,18 +231,20 @@ archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw)
         }
       END_CATCH
 
-      as = ui_file_xstrdup (memfile, NULL);
+      std::string as = ui_file_as_string (memfile);
+
       if (PyDict_SetItemString (insn_dict, "addr",
                                 gdb_py_long_from_ulongest (pc))
           || PyDict_SetItemString (insn_dict, "asm",
-                                   PyString_FromString (*as ? as : "<unknown>"))
+                                   PyString_FromString (!as.empty ()
+							? as.c_str ()
+							: "<unknown>"))
           || PyDict_SetItemString (insn_dict, "length",
                                    PyInt_FromLong (insn_len)))
         {
           Py_DECREF (result_list);
 
           ui_file_delete (memfile);
-          xfree (as);
 
           return NULL;
         }
@@ -251,7 +252,6 @@ archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw)
       pc += insn_len;
       i++;
       ui_file_delete (memfile);
-      xfree (as);
     }
 
   return result_list;
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 80f5d1f..e61cbcd 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -487,9 +487,8 @@ bppy_get_commands (PyObject *self, void *closure)
   struct breakpoint *bp = self_bp->bp;
   long length;
   struct ui_file *string_file;
-  struct cleanup *chain;
   PyObject *result;
-  char *cmdstr;
+  struct cleanup *chain;
 
   BPPY_REQUIRE_VALID (self_bp);
 
@@ -514,9 +513,8 @@ bppy_get_commands (PyObject *self, void *closure)
   END_CATCH
 
   ui_out_redirect (current_uiout, NULL);
-  cmdstr = ui_file_xstrdup (string_file, &length);
-  make_cleanup (xfree, cmdstr);
-  result = host_string_to_python_string (cmdstr);
+  std::string cmdstr = ui_file_as_string (string_file);
+  result = host_string_to_python_string (cmdstr.c_str ());
   do_cleanups (chain);
   return result;
 }
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 6bdac08..a66f885 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -80,17 +80,13 @@ frame_object_to_frame_info (PyObject *obj)
 static PyObject *
 frapy_str (PyObject *self)
 {
-  char *s;
   PyObject *result;
   struct ui_file *strfile;
 
   strfile = mem_fileopen ();
   fprint_frame_id (strfile, ((frame_object *) self)->frame_id);
-  s = ui_file_xstrdup (strfile, NULL);
-  result = PyString_FromString (s);
-  xfree (s);
-
-  return result;
+  std::string s = ui_file_as_string (strfile);
+  return PyString_FromString (s.c_str ());
 }
 
 /* Implementation of gdb.Frame.is_valid (self) -> Boolean.
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 03cc8d9..da9dadd 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1010,8 +1010,7 @@ typy_template_argument (PyObject *self, PyObject *args)
 static PyObject *
 typy_str (PyObject *self)
 {
-  char *thetype = NULL;
-  long length = 0;
+  std::string thetype;
   PyObject *result;
 
   TRY
@@ -1025,18 +1024,17 @@ typy_str (PyObject *self)
       LA_PRINT_TYPE (type_object_to_type (self), "", stb, -1, 0,
 		     &type_print_raw_options);
 
-      thetype = ui_file_xstrdup (stb, &length);
+      thetype = ui_file_as_string (stb);
       do_cleanups (old_chain);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
-      xfree (thetype);
       GDB_PY_HANDLE_EXCEPTION (except);
     }
   END_CATCH
 
-  result = PyUnicode_Decode (thetype, length, host_charset (), NULL);
-  xfree (thetype);
+  result = PyUnicode_Decode (thetype.c_str (), thetype.length (),
+			     host_charset (), NULL);
 
   return result;
 }
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index cc685ae..3963cd0 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -238,12 +238,9 @@ unwind_infopy_str (PyObject *self)
       }
     fprintf_unfiltered (strfile, ")");
   }
-  {
-    char *s = ui_file_xstrdup (strfile, NULL);
 
-    result = PyString_FromString (s);
-    xfree (s);
-  }
+  std::string s = ui_file_as_string (strfile);
+  result = PyString_FromString (s.c_str ());
   ui_file_delete (strfile);
   return result;
 }
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 46683b8..e326005 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -895,7 +895,7 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
 static PyObject *
 valpy_str (PyObject *self)
 {
-  char *s = NULL;
+  std::string s;
   PyObject *result;
   struct value_print_options opts;
 
@@ -909,7 +909,7 @@ valpy_str (PyObject *self)
 
       common_val_print (((value_object *) self)->value, stb, 0,
 			&opts, python_language);
-      s = ui_file_xstrdup (stb, NULL);
+      s = ui_file_as_string (stb);
 
       do_cleanups (old_chain);
     }
@@ -919,8 +919,7 @@ valpy_str (PyObject *self)
     }
   END_CATCH
 
-  result = PyUnicode_Decode (s, strlen (s), host_charset (), NULL);
-  xfree (s);
+  result = PyUnicode_Decode (s.c_str (), s.length (), host_charset (), NULL);
 
   return result;
 }
-- 
2.5.5

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

* [PATCH v2 13/31] Use ui_file_as_string in gdb/arm-tdep.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (28 preceding siblings ...)
  2016-10-19  1:21 ` [PATCH v2 18/31] Use ui_file_as_string in gdb/python/ Pedro Alves
@ 2016-10-19  1:21 ` Pedro Alves
  2016-10-19 22:54   ` Simon Marchi
  2016-10-20 13:08 ` [PATCH v2 28/31] Use ui_file_as_string throughout more Pedro Alves
  30 siblings, 1 reply; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:21 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* arm-tdep.c (_initialize_arm_tdep): Use ui_file_as_string and
	std::string.
---
 gdb/arm-tdep.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 27a3ebe..31ebdc3 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -9558,7 +9558,7 @@ _initialize_arm_tdep (void)
   const char *setdesc;
   const char *const *regnames;
   int i;
-  static char *helptext;
+  static std::string helptext;
   char regdesc[1024], *rdptr = regdesc;
   size_t rest = sizeof (regdesc);
 
@@ -9629,14 +9629,14 @@ _initialize_arm_tdep (void)
 		      _("The valid values are:\n"),
 		      regdesc,
 		      _("The default is \"std\"."));
-  helptext = ui_file_xstrdup (stb, NULL);
+  helptext = ui_file_as_string (stb);
   ui_file_delete (stb);
 
   add_setshow_enum_cmd("disassembler", no_class,
 		       valid_disassembly_styles, &disassembly_style,
 		       _("Set the disassembly style."),
 		       _("Show the disassembly style."),
-		       helptext,
+		       helptext.c_str (),
 		       set_disassembly_style_sfunc,
 		       NULL, /* FIXME: i18n: The disassembly style is
 				\"%s\".  */
-- 
2.5.5

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

* [PATCH v2 17/31] Use ui_file_as_string in gdb/printcmd.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (25 preceding siblings ...)
  2016-10-19  1:19 ` [PATCH v2 04/31] cli-script.c: Simplify using std::string, eliminate cleanups Pedro Alves
@ 2016-10-19  1:21 ` Pedro Alves
  2016-10-19  1:21 ` [PATCH v2 16/31] Use ui_file_as_string in gdb/top.c Pedro Alves
                   ` (3 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:21 UTC (permalink / raw)
  To: gdb-patches

Yet another cleanup eliminated.

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* printcmd.c (eval_command): Use ui_file_as_string and
	std::string.
---
 gdb/printcmd.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index aa51848..d909823 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -2721,14 +2721,12 @@ eval_command (char *arg, int from_tty)
 {
   struct ui_file *ui_out = mem_fileopen ();
   struct cleanup *cleanups = make_cleanup_ui_file_delete (ui_out);
-  char *expanded;
 
   ui_printf (arg, ui_out);
 
-  expanded = ui_file_xstrdup (ui_out, NULL);
-  make_cleanup (xfree, expanded);
+  std::string expanded = ui_file_as_string (ui_out);
 
-  execute_command (expanded, from_tty);
+  execute_command (&expanded[0], from_tty);
 
   do_cleanups (cleanups);
 }
-- 
2.5.5

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

* [PATCH v2 16/31] Use ui_file_as_string in gdb/top.c
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (26 preceding siblings ...)
  2016-10-19  1:21 ` [PATCH v2 17/31] Use ui_file_as_string in gdb/printcmd.c Pedro Alves
@ 2016-10-19  1:21 ` Pedro Alves
  2016-10-19  1:21 ` [PATCH v2 18/31] Use ui_file_as_string in gdb/python/ Pedro Alves
                   ` (2 subsequent siblings)
  30 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19  1:21 UTC (permalink / raw)
  To: gdb-patches

Yet another cleanup is eliminated.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* top.c (quit_confirm): Use ui_file_as_string and std::string.
---
 gdb/top.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/gdb/top.c b/gdb/top.c
index 762a9a8..4fa9cfb 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1577,8 +1577,6 @@ quit_confirm (void)
 {
   struct ui_file *stb;
   struct cleanup *old_chain;
-  char *str;
-  int qr;
 
   /* Don't even ask if we're only debugging a core file inferior.  */
   if (!have_live_inferiors ())
@@ -1592,12 +1590,11 @@ quit_confirm (void)
   iterate_over_inferiors (print_inferior_quit_action, stb);
   fprintf_filtered (stb, _("\nQuit anyway? "));
 
-  str = ui_file_xstrdup (stb, NULL);
-  make_cleanup (xfree, str);
+  std::string str = ui_file_as_string (stb);
 
-  qr = query ("%s", str);
   do_cleanups (old_chain);
-  return qr;
+
+  return query ("%s", str.c_str ());
 }
 
 /* Prepare to exit GDB cleanly by undoing any changes made to the
-- 
2.5.5

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

* Re: [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments
  2016-10-19  1:13 ` [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments Pedro Alves
@ 2016-10-19  6:29   ` Eli Zaretskii
  2016-10-19 11:33   ` Philipp Rudo
  2016-11-08 15:41   ` Pedro Alves
  2 siblings, 0 replies; 61+ messages in thread
From: Eli Zaretskii @ 2016-10-19  6:29 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> From: Pedro Alves <palves@redhat.com>
> Date: Wed, 19 Oct 2016 02:12:19 +0100
> 
> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Alves  <palves@redhat.com>
> 
> 	* NEWS: Mention that user commands now accept an unlimited number
> 	of arguments.
> 	* cli/cli-script.c: Include <vector>.
> 	(struct string_view): New type.
> 	(MAXUSERARGS): Delete.
> 	(struct user_args): Now a C++ class.
> 	(user_args_stack): New.
> 	(struct scoped_user_args_level): New type.
> 	(execute_user_command): Use scoped_user_args_level.  Adjust to
> 	call insert_user_args instead of insert_args.
> 	(arg_cleanup): Delete.
> 	(setup_user_args): Deleted, and refactored as ...
> 	(user_args::user_args): ... this new constructor.  Limit of number
> 	of arguments removed.
> 	(insert_args): Delete.
> 	(insert_user_args) New.
> 	(user_args::insert_args): New, bits based on old insert_args with
> 	limit of number of arguments eliminated.
> 	* common/common-utils.h: Include <sstream>.
> 	(gdb::to_string): New.
> 
> gdb/doc/ChangeLog:
> yyyy-mm-dd  Pedro Alves  <palves@redhat.com>
> 
> 	* gdb.texinfo (User-defined Commands): Limit on number of
> 	arguments passed to user-defined commands removed; update.

OK for the documentation parts.

Thanks.

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

* Re: [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments
  2016-10-19  1:13 ` [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments Pedro Alves
  2016-10-19  6:29   ` Eli Zaretskii
@ 2016-10-19 11:33   ` Philipp Rudo
  2016-10-19 12:47     ` Pedro Alves
  2016-11-08 15:41   ` Pedro Alves
  2 siblings, 1 reply; 61+ messages in thread
From: Philipp Rudo @ 2016-10-19 11:33 UTC (permalink / raw)
  To: gdb-patches

Hi

On Wed, 19 Oct 2016 02:12:19 +0100
Pedro Alves <palves@redhat.com> wrote:

> I recently wrote a user-defined command that could benefit from
> supporting an unlimited number of arguments:
> 
>  http://palves.net/list-active-signal-handlers-with-gdb/
> 
> E.g., 'info signal-dispositions 1 2 3 4 5 6 7 8 9 10 11'
> 
> However, we currently only support up to 10 arguments passed to
> user-defined commands ($arg0..$arg9).
> 
> I can't find a good reason for that, other than "old code with hard
> coded limits".  This patch removes that limit and modernizes the code
> along the way:
> 
>   - Makes the user_args struct a real C++ class that uses std::vector
>     for storage.
> 
>   - Removes the "next" pointer from within user_args and uses a
>     std::vector to maintain a stack instead.
> 
>   - Adds a new RAII-based scoped_user_args_level class to help
>     push/pop user args in the stack instead of using a cleanup.
> 
> I also needed a way to convert a number to a std::string, so I added a
> new utility for that, gdb::to_string.  Yet another thing that can go
> away with C++11.
[... snip ...]
> +/* Returns a string representation of VAL.  Replacement for
> +   std::to_string, which is only available in C++11 or later.  */
> +
> +namespace gdb {
> +
> +template <class T>
> +inline std::string
> +to_string (const T &val)
> +{
> +  std::stringstream ss;
> +
> +  ss << val;
> +  return ss.str ();
> +}
> +
> +}
> +
>  /* Make a copy of the string at PTR with LEN characters
>     (and add a null character at the end in the copy).
>     Uses malloc to get the space.  Returns the address of the copy.  */

Is this really necessary?
As far as I understood the discussion, we jump directly to C++11. Thus there is no need for an homemade to_string.

Philipp

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

* Re: [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments
  2016-10-19 11:33   ` Philipp Rudo
@ 2016-10-19 12:47     ` Pedro Alves
  2016-10-19 17:40       ` Philipp Rudo
  0 siblings, 1 reply; 61+ messages in thread
From: Pedro Alves @ 2016-10-19 12:47 UTC (permalink / raw)
  To: Philipp Rudo, gdb-patches

On 10/19/2016 12:33 PM, Philipp Rudo wrote:
> Pedro Alves <palves@redhat.com> wrote:

>> I also needed a way to convert a number to a std::string, so I added a
>> new utility for that, gdb::to_string.  Yet another thing that can go
>> away with C++11.
> [... snip ...]
>> +/* Returns a string representation of VAL.  Replacement for
>> +   std::to_string, which is only available in C++11 or later.  */
>> +
>> +namespace gdb {
>> +
>> +template <class T>
>> +inline std::string
>> +to_string (const T &val)
>> +{
>> +  std::stringstream ss;
>> +
>> +  ss << val;
>> +  return ss.str ();
>> +}
>> +
>> +}
>> +
>>  /* Make a copy of the string at PTR with LEN characters
>>     (and add a null character at the end in the copy).
>>     Uses malloc to get the space.  Returns the address of the copy.  */
> 
> Is this really necessary?
> As far as I understood the discussion, we jump directly to C++11. Thus there is no need for an homemade to_string.

We haven't actually officially committed to requiring
C++11, so I didn't want to be blocked by that.  It's
trivial to remove that bit latter if this lands first.

On C++11, I was just giving time for the follow ups to
last week's discussion to settle:

 https://sourceware.org/ml/gdb-patches/2016-10/msg00497.html
 https://sourceware.org/ml/gdb-patches/2016-10/msg00556.html

and give everyone a chance to comment (or re-comment after
consideration).

No one commented on the patches linked to from here either:

 https://sourceware.org/ml/gdb-patches/2016-10/msg00497.html

Up until last week I wasn't even thinking that going C++11
would be possible.  So I don't want to look like I'm rushing
it.  But now it feels like I'm the one delaying .... :-P

Maybe I should just press ahead and be done with it.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 01/31] Introduce string_printf
  2016-10-19  1:12 ` [PATCH v2 01/31] Introduce string_printf Pedro Alves
@ 2016-10-19 13:43   ` Trevor Saunders
  2016-10-19 14:41     ` Pedro Alves
  2016-10-19 17:18   ` Simon Marchi
  1 sibling, 1 reply; 61+ messages in thread
From: Trevor Saunders @ 2016-10-19 13:43 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

> +std::string
> +string_printf (const char* fmt, ...)

std::string is unfortunately kind of large for a return value
its 4 * sizeof (void *), but maybe the simplicity matters more here.

> +{
> +  std::string str;
> +  va_list vp;
> +
> +  /* Start by assuming some reasonable size will be sufficient.  */
> +  str.resize (1024);
> +
> +  while (1)
> +    {
> +      size_t size;
> +      int result;

you could declare these at first use right?

Trev

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

* Re: [PATCH v2 01/31] Introduce string_printf
  2016-10-19 13:43   ` Trevor Saunders
@ 2016-10-19 14:41     ` Pedro Alves
  0 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19 14:41 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: gdb-patches

On 10/19/2016 02:53 PM, Trevor Saunders wrote:
>> +std::string
>> +string_printf (const char* fmt, ...)
> 
> std::string is unfortunately kind of large for a return value
> its 4 * sizeof (void *), but maybe the simplicity matters more here.

That shouldn't matter I think?  Beyond a size, ABIs will return via
the stack instead, and, also, no actual copying (in C++ sense) will
take place, because NRVO should apply here.

> 
>> +{
>> +  std::string str;
>> +  va_list vp;
>> +
>> +  /* Start by assuming some reasonable size will be sufficient.  */
>> +  str.resize (1024);
>> +
>> +  while (1)
>> +    {
>> +      size_t size;
>> +      int result;
> 
> you could declare these at first use right?

Yeah, I considered it, and went back and forth, actually!

It'd look like this instead:

  while (1)
    {
      va_start (vp, fmt);
      size_t size = str.size ();
      int result = vsnprintf (&str[0], size, fmt, vp);
      va_end (vp);

      str.resize (result);

      if (result < size)
	break;
    }

Felt odd to me to see the variables declared in the middle of
va_start/va_end, since those kind of form a scope.  I guess I'm
still not used to declaring PODs i the middle of blocks.  If we
don't that, then when a variable is declared in the middle of a
scope it really stands out that something important might be going
on with the ctor.  But maybe that's just me?  I can certainly
change it. 

Also, while writing this, I was also going back and forth between
doing the initial reserve:

 +  str.resize (1024);

and not doing it, and instead call vsnprintf with a NULL buffer
to pre-compute the necessary size.  The downsize is that
you always have to call vsnprintf twice that way.  The upside
is less wasted memory, considering the case of these strings
ending up stored in some structures.  I saw today that
xstrprintf (via vasprintf) uses the 'pre-compute necessary size'
instead of the 'pre-reserve' approach, so I'm leaning toward
doing that too now.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 01/31] Introduce string_printf
  2016-10-19  1:12 ` [PATCH v2 01/31] Introduce string_printf Pedro Alves
  2016-10-19 13:43   ` Trevor Saunders
@ 2016-10-19 17:18   ` Simon Marchi
  2016-10-19 21:02     ` Pedro Alves
  1 sibling, 1 reply; 61+ messages in thread
From: Simon Marchi @ 2016-10-19 17:18 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 2016-10-18 21:11, Pedro Alves wrote:
> This introduces the string_printf function.  Like asprintf, but
> returns a std::string.
> 
> gdb/ChangeLog:
> yyyy-mm-yy  Pedro Alves  <palves@redhat.com>
> 
> 	* common/common-utils.c (string_printf): New function.
> 	* common/common-utils.h: Include <string>.
> 	(string_printf): Declare.
> ---
>  gdb/common/common-utils.c | 30 ++++++++++++++++++++++++++++++
>  gdb/common/common-utils.h |  6 ++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c
> index 5a346ec..05ba3aa 100644
> --- a/gdb/common/common-utils.c
> +++ b/gdb/common/common-utils.c
> @@ -150,6 +150,36 @@ xsnprintf (char *str, size_t size, const char 
> *format, ...)
>    return ret;
>  }
> 
> +/* See documentation in common-utils.h.  */
> +
> +std::string
> +string_printf (const char* fmt, ...)
> +{
> +  std::string str;
> +  va_list vp;
> +
> +  /* Start by assuming some reasonable size will be sufficient.  */
> +  str.resize (1024);
> +
> +  while (1)
> +    {
> +      size_t size;
> +      int result;
> +
> +      va_start (vp, fmt);
> +      size = str.size ();
> +      result = vsnprintf (&str[0], size, fmt, vp);
> +      va_end (vp);
> +
> +      str.resize (result);

I think you have an off-by-one here, which causes an infinite loop if 
the 1024 bytes buffer is not large enough.  vsnprintf returns the size 
needed without the terminating \0, so the resize here should be of 
"result + 1".  To reproduce/test easily, just change your str.resize 
(1024) to something small.

I thought the use of a while loop for this a bit strange, but I 
understand it's to avoid duplicating the code.

I think you should try writing a unit test for this :).

Simon

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

* Re: [PATCH v2 02/31] cli/cli-script.c: Remove some dead NULL checks
  2016-10-19  1:13 ` [PATCH v2 02/31] cli/cli-script.c: Remove some dead NULL checks Pedro Alves
@ 2016-10-19 17:24   ` Simon Marchi
  2016-10-19 21:18     ` Pedro Alves
  0 siblings, 1 reply; 61+ messages in thread
From: Simon Marchi @ 2016-10-19 17:24 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 2016-10-18 21:11, Pedro Alves wrote:
> @@ -853,8 +845,6 @@ insert_args (char *line)
> 
>    /* Allocate space for the new line and fill it in.  */
>    new_line = (char *) xmalloc (len + 1);
> -  if (new_line == NULL)
> -    return NULL;
> 
>    /* Restore pointer to beginning of old line.  */
>    line = save_line;

A few lines higher in insert_args, there is:

     error (_("Missing argument %d in user function."), i);
     return NULL;

That return NULL is also dead code and could be confusing, leading 
someone to think insert_args can return NULL.  I think you could remove 
it at the same time.

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

* Re: [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments
  2016-10-19 12:47     ` Pedro Alves
@ 2016-10-19 17:40       ` Philipp Rudo
  2016-10-19 17:45         ` Pedro Alves
  0 siblings, 1 reply; 61+ messages in thread
From: Philipp Rudo @ 2016-10-19 17:40 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches

On Wed, 19 Oct 2016 13:47:22 +0100
Pedro Alves <palves@redhat.com> wrote:

> On 10/19/2016 12:33 PM, Philipp Rudo wrote:
> > Pedro Alves <palves@redhat.com> wrote:
> 
> >> I also needed a way to convert a number to a std::string, so I added a
> >> new utility for that, gdb::to_string.  Yet another thing that can go
> >> away with C++11.
> > [... snip ...]
> >> +/* Returns a string representation of VAL.  Replacement for
> >> +   std::to_string, which is only available in C++11 or later.  */
> >> +
> >> +namespace gdb {
> >> +
> >> +template <class T>
> >> +inline std::string
> >> +to_string (const T &val)
> >> +{
> >> +  std::stringstream ss;
> >> +
> >> +  ss << val;
> >> +  return ss.str ();
> >> +}
> >> +
> >> +}
> >> +
> >>  /* Make a copy of the string at PTR with LEN characters
> >>     (and add a null character at the end in the copy).
> >>     Uses malloc to get the space.  Returns the address of the copy.  */
> > 
> > Is this really necessary?
> > As far as I understood the discussion, we jump directly to C++11. Thus there is no need for an homemade to_string.
> 
> We haven't actually officially committed to requiring
> C++11, so I didn't want to be blocked by that.  It's
> trivial to remove that bit latter if this lands first.

True that C++11 is not official yet. But the "trivial to remove" is
exactly the reason I wrote, as those pieces of code tend to stay in the longest.
And in 10+ years nobody knows why there is such a messy mix of different
functions doing the same thing and why it hasn't been done right in the
first place ;)

So my mail should not push you to use std::to_string but be seen as a reminder,
that if we require C++11 your home made function should be deleted better sooner
than later.

Phil

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

* Re: [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments
  2016-10-19 17:40       ` Philipp Rudo
@ 2016-10-19 17:45         ` Pedro Alves
  0 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19 17:45 UTC (permalink / raw)
  To: Philipp Rudo, gdb-patches

On 10/19/2016 06:39 PM, Philipp Rudo wrote:
> Pedro Alves <palves@redhat.com> wrote:

>>>> I also needed a way to convert a number to a std::string, so I added a
>>>> new utility for that, gdb::to_string.  Yet another thing that can go
>>>> away with C++11.
>>> [... snip ...]
>>>> +/* Returns a string representation of VAL.  Replacement for
>>>> +   std::to_string, which is only available in C++11 or later.  */
>>> Is this really necessary?
>>> As far as I understood the discussion, we jump directly to C++11. Thus there is no need for an homemade to_string.
>>
>> We haven't actually officially committed to requiring
>> C++11, so I didn't want to be blocked by that.  It's
>> trivial to remove that bit latter if this lands first.
> 
> True that C++11 is not official yet. But the "trivial to remove" is
> exactly the reason I wrote, as those pieces of code tend to stay in the longest.
> And in 10+ years nobody knows why there is such a messy mix of different
> functions doing the same thing and why it hasn't been done right in the
> first place ;)

Well, in this case the comment leaves no doubt.  :-)

> 
> So my mail should not push you to use std::to_string but be seen as a reminder,
> that if we require C++11 your home made function should be deleted better sooner
> than later.

Agreed.  If this lands first, I'll make sure to remove this piece
after C++11.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 04/31] cli-script.c: Simplify using std::string, eliminate cleanups
  2016-10-19  1:19 ` [PATCH v2 04/31] cli-script.c: Simplify using std::string, eliminate cleanups Pedro Alves
@ 2016-10-19 18:25   ` Simon Marchi
  2016-10-19 21:45     ` Pedro Alves
  0 siblings, 1 reply; 61+ messages in thread
From: Simon Marchi @ 2016-10-19 18:25 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 2016-10-18 21:11, Pedro Alves wrote:
> @@ -457,12 +456,13 @@ execute_control_command (struct command_line 
> *cmd)
>    switch (cmd->control_type)
>      {
>      case simple_control:
> -      /* A simple command, execute it and return.  */
> -      new_line = insert_args (cmd->line);
> -      make_cleanup (free_current_contents, &new_line);
> -      execute_command (new_line, 0);
> -      ret = cmd->control_type;
> -      break;
> +      {
> +	/* A simple command, execute it and return.  */
> +	std::string new_line = insert_args (cmd->line);
> +	execute_command (&new_line[0], 0);

The need to use &new_line[0] instead of .c_str() here looks (or smells) 
like a code smell to me.  If execute_command needs to modify the string, 
it should either make its own copy, or at least document in what ways it 
can be modified.  And in general, modifying an std::string's underlying 
array is probably not good (if I understand the standard correctly, it's 
undefined behaviour, though in reality it probably always works).

Do you know of any caller of execute_command that relies on the 
modification that execute_command does to the passed string?  If not, I 
think it would be safer to change the arg to a const char * and 
duplicate the string at function entry.

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

* Re: [PATCH v2 05/31] 'struct expression *' -> gdb::unique_xmalloc_ptr<expression>
  2016-10-19  1:18 ` [PATCH v2 05/31] 'struct expression *' -> gdb::unique_xmalloc_ptr<expression> Pedro Alves
@ 2016-10-19 18:45   ` Simon Marchi
  2016-10-19 21:50     ` Pedro Alves
  0 siblings, 1 reply; 61+ messages in thread
From: Simon Marchi @ 2016-10-19 18:45 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 2016-10-18 21:11, Pedro Alves wrote:
> [1] - I'd like to set the rule that types named with an "_up" suffix
>       are unique_ptr typedefs.

I don't mind.  It sounds funny when saying it out loud though, my goal 
from now on will be to introduce a class named "whats".  It ends up a 
bit cryptic for somebody that doesn't know about that convention 
(newcomers), but then expression_unique_ptr might be a bit long.

I did a quick grep for various converted struct names allocation 
keywords, I see there is still a

     bp_location = XNEWVEC (struct bp_location *, bp_location_count);

Does that need to be converted too?

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

* Re: [PATCH v2 01/31] Introduce string_printf
  2016-10-19 17:18   ` Simon Marchi
@ 2016-10-19 21:02     ` Pedro Alves
  2016-11-08 15:35       ` Pedro Alves
  0 siblings, 1 reply; 61+ messages in thread
From: Pedro Alves @ 2016-10-19 21:02 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

On 10/19/2016 06:17 PM, Simon Marchi wrote:

>> +/* See documentation in common-utils.h.  */
>> +
>> +std::string
>> +string_printf (const char* fmt, ...)
>> +{
>> +  std::string str;
>> +  va_list vp;
>> +
>> +  /* Start by assuming some reasonable size will be sufficient.  */
>> +  str.resize (1024);
>> +
>> +  while (1)
>> +    {
>> +      size_t size;
>> +      int result;
>> +
>> +      va_start (vp, fmt);
>> +      size = str.size ();
>> +      result = vsnprintf (&str[0], size, fmt, vp);
>> +      va_end (vp);
>> +
>> +      str.resize (result);
> 
> I think you have an off-by-one here, which causes an infinite loop if
> the 1024 bytes buffer is not large enough.  vsnprintf returns the size
> needed without the terminating \0, so the resize here should be of
> "result + 1".  To reproduce/test easily, just change your str.resize
> (1024) to something small.

Whoops...  Good catch.  I should have been more careful.  It's the sort
of code that screams for that sort of bug.  :-)  Brown paper bag on me.

resizing to "result + 1" would be incorrect though.  A
std::string's size does not include the terminating \0.
My idea above was to include the size for the \0 in the
initial resize(1024), and then the last resize fixed
it down.  Probably should have added comments.

The version prior to the one I posted had this:

+      /* While only C++11 or later guarantee std::string has contiguous
+        memory, no known C++03 compiler lays memory non-contiguously.
+        This is a _very_ common hack.  */
+      size = str.size () + 1;
+      result = vsnprintf (const_cast<char*> (str.c_str ()), size, fmt, vp);
+      va_end (vp);
+
+      str.resize (result);


And then thinking that people might dislike the hack, I changed
it to consider the \0 as part of the initial string (std::string
can contain embedded NULLs).

But I shouldn't have.  The "hack" is really not a problem:

  https://herbsutter.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/#comment-483

I.e., "everyone" does it like that.

> I thought the use of a while loop for this a bit strange, but I
> understand it's to avoid duplicating the code.

Yeah.

> 
> I think you should try writing a unit test for this :).

That's a good point.  :-)  I did that now.

Here's a new version.  Passes testing along with the
rest of the series, and, switches to "pre-compute buffer size",
as I mentioned in the reply to Trevor.

From 32670757bd2647c04d02d01849e417c5a07a6cf5 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Wed, 19 Oct 2016 20:25:23 +0100
Subject: [PATCH] Introduce string_printf

This introduces the string_printf function.  Like asprintf, but
returns a std::string.

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* Makefile.in (COMMON_OBS): Add utils-selftests.o.
	* common/common-utils.c (string_printf): New function.
	* common/common-utils.h: Include <string>.
	(string_printf): Declare.
	* utils-selftests.c: New file.
---
 gdb/Makefile.in           |  2 +-
 gdb/common/common-utils.c | 25 +++++++++++++++++++++++
 gdb/common/common-utils.h |  6 ++++++
 gdb/utils-selftests.c     | 52 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 84 insertions(+), 1 deletion(-)
 create mode 100644 gdb/utils-selftests.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 2c88434..757fd05 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1064,7 +1064,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
 	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
 	m2-valprint.o \
-	ser-event.o serial.o mdebugread.o top.o utils.o \
+	ser-event.o serial.o mdebugread.o top.o utils.o utils-selftests.o \
 	ui-file.o \
 	user-regs.o \
 	frame.o frame-unwind.o doublest.o \
diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c
index 5a346ec..a6035ad 100644
--- a/gdb/common/common-utils.c
+++ b/gdb/common/common-utils.c
@@ -150,6 +150,31 @@ xsnprintf (char *str, size_t size, const char *format, ...)
   return ret;
 }
 
+/* See documentation in common-utils.h.  */
+
+std::string
+string_printf (const char* fmt, ...)
+{
+  va_list vp;
+  int size;
+
+  va_start (vp, fmt);
+  size = vsnprintf (NULL, 0, fmt, vp);
+  va_end (vp);
+
+  std::string str (size, '\0');
+
+  va_start (vp, fmt);
+  /* While only C++11 or later guarantee std::string uses contiguous
+     memory, including the terminating '\0' and that c_str() returns a
+     pointer to the string's mutable data, in practice that's true
+     with all C++03 compilers.  */
+  vsprintf (const_cast<char *> (str.c_str ()), fmt, vp);
+  va_end (vp);
+
+  return str;
+}
+
 char *
 savestring (const char *ptr, size_t len)
 {
diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h
index 47def11..a9053ff 100644
--- a/gdb/common/common-utils.h
+++ b/gdb/common/common-utils.h
@@ -20,6 +20,8 @@
 #ifndef COMMON_UTILS_H
 #define COMMON_UTILS_H
 
+#include <string>
+
 /* If possible, define FUNCTION_NAME, a macro containing the name of
    the function being defined.  Since this macro may not always be
    defined, all uses must be protected by appropriate macro definition
@@ -56,6 +58,10 @@ char *xstrvprintf (const char *format, va_list ap)
 int xsnprintf (char *str, size_t size, const char *format, ...)
      ATTRIBUTE_PRINTF (3, 4);
 
+/* Returns a std::string built from a printf-style format string.  */
+std::string string_printf (const char* fmt, ...)
+  ATTRIBUTE_PRINTF (1, 2);
+
 /* Make a copy of the string at PTR with LEN characters
    (and add a null character at the end in the copy).
    Uses malloc to get the space.  Returns the address of the copy.  */
diff --git a/gdb/utils-selftests.c b/gdb/utils-selftests.c
new file mode 100644
index 0000000..482b698
--- /dev/null
+++ b/gdb/utils-selftests.c
@@ -0,0 +1,52 @@
+/* Self tests for general utility routines for GDB, the GNU debugger.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+#include "defs.h"
+#include "selftest.h"
+
+/* common-utils self tests.  Defined here instead of in
+   common/common-utils.c because that file is shared with
+   gdbserver.  */
+
+static void
+common_utils_tests (void)
+{
+  SELF_CHECK (string_printf ("%s", "") == "");
+  SELF_CHECK (string_printf ("%d comes before 2", 1) == "1 comes before 2");
+  SELF_CHECK (string_printf ("hello %s", "world") == "hello world");
+
+#define X10 "xxxxxxxxxx"
+#define X100 X10 X10 X10 X10 X10 X10 X10 X10 X10 X10
+#define X1000 X100 X100 X100 X100 X100 X100 X100 X100 X100 X100
+#define X10000 X1000 X1000 X1000 X1000 X1000 X1000 X1000 X1000 X1000 X1000
+#define X100000 X10000 X10000 X10000 X10000 X10000 X10000 X10000 X10000 X10000 X10000
+  SELF_CHECK (string_printf ("%s", X10).size () == 10);
+  SELF_CHECK (string_printf ("%s", X100).size () == 100);
+  SELF_CHECK (string_printf ("%s", X1000).size () == 1000);
+  SELF_CHECK (string_printf ("%s", X10000).size () == 10000);
+  SELF_CHECK (string_printf ("%s", X100000).size () == 100000);
+}
+
+void
+_initialize_utils_selftests (void)
+{
+#if GDB_SELF_TEST
+  register_self_test (common_utils_tests);
+#endif
+}
-- 
2.5.5


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

* Re: [PATCH v2 02/31] cli/cli-script.c: Remove some dead NULL checks
  2016-10-19 17:24   ` Simon Marchi
@ 2016-10-19 21:18     ` Pedro Alves
  0 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19 21:18 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

On 10/19/2016 06:24 PM, Simon Marchi wrote:
> On 2016-10-18 21:11, Pedro Alves wrote:
>> @@ -853,8 +845,6 @@ insert_args (char *line)
>>
>>    /* Allocate space for the new line and fill it in.  */
>>    new_line = (char *) xmalloc (len + 1);
>> -  if (new_line == NULL)
>> -    return NULL;
>>
>>    /* Restore pointer to beginning of old line.  */
>>    line = save_line;
> 
> A few lines higher in insert_args, there is:
> 
>     error (_("Missing argument %d in user function."), i);
>     return NULL;
> 
> That return NULL is also dead code and could be confusing, leading
> someone to think insert_args can return NULL.  I think you could remove
> it at the same time.

Ah.  Guess I missed it because that code disappears with patch
(patch #4).   I wrote patches #2-#4 as a single patch, and
then missed that when I split them to ease review...  :-)

I've changed this locally.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 04/31] cli-script.c: Simplify using std::string, eliminate cleanups
  2016-10-19 18:25   ` Simon Marchi
@ 2016-10-19 21:45     ` Pedro Alves
  0 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19 21:45 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

On 10/19/2016 07:25 PM, Simon Marchi wrote:
> On 2016-10-18 21:11, Pedro Alves wrote:
>> @@ -457,12 +456,13 @@ execute_control_command (struct command_line *cmd)
>>    switch (cmd->control_type)
>>      {
>>      case simple_control:
>> -      /* A simple command, execute it and return.  */
>> -      new_line = insert_args (cmd->line);
>> -      make_cleanup (free_current_contents, &new_line);
>> -      execute_command (new_line, 0);
>> -      ret = cmd->control_type;
>> -      break;
>> +      {
>> +    /* A simple command, execute it and return.  */
>> +    std::string new_line = insert_args (cmd->line);
>> +    execute_command (&new_line[0], 0);
> 
> The need to use &new_line[0] instead of .c_str() here looks (or smells)
> like a code smell to me.  

See my comment to the string_printf patch.  &str[0] is required to
return a pointer to modifiable contents.  What's not technically
defined is assuming that that returns a NULL-terminated buffer.
But in practice it does, everywhere.  See.  The second answer
describes it fully:

  http://stackoverflow.com/questions/347949/how-to-convert-a-stdstring-to-const-char-or-char

Writing a NULL to the middle of the string via the char pointer
won't change the std::string's size(), but that's not a problem
here, because new_line is a temporary and we don't care about
the new_line.size() after the execute_command call.

> If execute_command needs to modify the string,
> it should either make its own copy, or at least document in what ways it
> can be modified.  And in general, modifying an std::string's underlying
> array is probably not good (if I understand the standard correctly, it's
> undefined behaviour, though in reality it probably always works).

See above.

> Do you know of any caller of execute_command that relies on the
> modification that execute_command does to the passed string?  

The main execute_command call coming from the tty.  :-)

Some commands hack the command line to influence what's
actually repeated with <ret>.  Off hand, I remember list_command:

  /* If this command is repeated with RET,
     turn it into the no-arg variant.  */

  if (from_tty)
    *arg = 0;

> If not, I
> think it would be safer to change the arg to a const char * and
> duplicate the string at function entry.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 05/31] 'struct expression *' -> gdb::unique_xmalloc_ptr<expression>
  2016-10-19 18:45   ` Simon Marchi
@ 2016-10-19 21:50     ` Pedro Alves
  2016-10-19 22:25       ` Simon Marchi
  0 siblings, 1 reply; 61+ messages in thread
From: Pedro Alves @ 2016-10-19 21:50 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

On 10/19/2016 07:45 PM, Simon Marchi wrote:
> On 2016-10-18 21:11, Pedro Alves wrote:
>> [1] - I'd like to set the rule that types named with an "_up" suffix
>>       are unique_ptr typedefs.
> 
> I don't mind.  It sounds funny when saying it out loud though, 

I read it as "<type> u. p.".  :-)

> my goal
> from now on will be to introduce a class named "whats".  

:-)

> It ends up a
> bit cryptic for somebody that doesn't know about that convention
> (newcomers), but then expression_unique_ptr might be a bit long.
> 
> I did a quick grep for various converted struct names allocation
> keywords, I see there is still a
> 
>     bp_location = XNEWVEC (struct bp_location *, bp_location_count);
> 
> Does that need to be converted too?

You mean converted to "new"?  No, because that is an array
of pointers, not array of bp_location objects.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 05/31] 'struct expression *' -> gdb::unique_xmalloc_ptr<expression>
  2016-10-19 21:50     ` Pedro Alves
@ 2016-10-19 22:25       ` Simon Marchi
  2016-10-19 22:36         ` Pedro Alves
  0 siblings, 1 reply; 61+ messages in thread
From: Simon Marchi @ 2016-10-19 22:25 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 2016-10-19 17:50, Pedro Alves wrote:
>> I did a quick grep for various converted struct names allocation
>> keywords, I see there is still a
>> 
>>     bp_location = XNEWVEC (struct bp_location *, bp_location_count);
>> 
>> Does that need to be converted too?
> 
> You mean converted to "new"?  No, because that is an array
> of pointers, not array of bp_location objects.

Oh right I missed that, sorry.

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

* Re: [PATCH v2 05/31] 'struct expression *' -> gdb::unique_xmalloc_ptr<expression>
  2016-10-19 22:25       ` Simon Marchi
@ 2016-10-19 22:36         ` Pedro Alves
  0 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19 22:36 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

On 10/19/2016 11:25 PM, Simon Marchi wrote:
> On 2016-10-19 17:50, Pedro Alves wrote:
>>> I did a quick grep for various converted struct names allocation
>>> keywords, I see there is still a
>>>
>>>     bp_location = XNEWVEC (struct bp_location *, bp_location_count);
>>>
>>> Does that need to be converted too?
>>
>> You mean converted to "new"?  No, because that is an array
>> of pointers, not array of bp_location objects.
> 
> Oh right I missed that, sorry.

No worries.  Thanks much for double-checking for missing
conversions like this, and for reviewing the patch in the
first place.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 13/31] Use ui_file_as_string in gdb/arm-tdep.c
  2016-10-19  1:21 ` [PATCH v2 13/31] Use ui_file_as_string in gdb/arm-tdep.c Pedro Alves
@ 2016-10-19 22:54   ` Simon Marchi
  0 siblings, 0 replies; 61+ messages in thread
From: Simon Marchi @ 2016-10-19 22:54 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 2016-10-18 21:12, Pedro Alves wrote:
> gdb/ChangeLog:
> yyyy-mm-yy  Pedro Alves  <palves@redhat.com>
> 
> 	* arm-tdep.c (_initialize_arm_tdep): Use ui_file_as_string and
> 	std::string.
> ---
>  gdb/arm-tdep.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index 27a3ebe..31ebdc3 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -9558,7 +9558,7 @@ _initialize_arm_tdep (void)
>    const char *setdesc;
>    const char *const *regnames;
>    int i;
> -  static char *helptext;
> +  static std::string helptext;
>    char regdesc[1024], *rdptr = regdesc;
>    size_t rest = sizeof (regdesc);
> 
> @@ -9629,14 +9629,14 @@ _initialize_arm_tdep (void)
>  		      _("The valid values are:\n"),
>  		      regdesc,
>  		      _("The default is \"std\"."));
> -  helptext = ui_file_xstrdup (stb, NULL);
> +  helptext = ui_file_as_string (stb);
>    ui_file_delete (stb);
> 
>    add_setshow_enum_cmd("disassembler", no_class,
>  		       valid_disassembly_styles, &disassembly_style,
>  		       _("Set the disassembly style."),
>  		       _("Show the disassembly style."),
> -		       helptext,
> +		       helptext.c_str (),
>  		       set_disassembly_style_sfunc,
>  		       NULL, /* FIXME: i18n: The disassembly style is
>  				\"%s\".  */

I think helptext doesn't need to be static.  Since add_setshow_* makes 
its own copy, it doesn't need to stay alive after the call.

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

* Re: [PATCH v2 21/31] Use ui_file_as_string in gdb/compile/
  2016-10-19  1:12 ` [PATCH v2 21/31] Use ui_file_as_string in gdb/compile/ Pedro Alves
@ 2016-10-19 23:08   ` Simon Marchi
  2016-10-19 23:48     ` Pedro Alves
  0 siblings, 1 reply; 61+ messages in thread
From: Simon Marchi @ 2016-10-19 23:08 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

The doc for get_new_file_names should probably be updated:

/* Compute the names of source and object files to use.  The names are
    allocated by malloc and should be freed by the caller.  */

>  static void
> -get_new_file_names (char **source_file, char **object_file)
> +get_new_file_names (std::string *source_file, std::string 
> *object_file)
>  {


Same for compile_to_object, both for the "freeing" part and the part 
that talks about the return value.

We should use $other_language instead of C++, to be able to do

   source_filep, object_filep = compile_to_object (...)

:)

Btw, would it be good to use references for those strings?

>     error condition, error () is called.  The caller is responsible for
>     freeing both strings.  */
> 
> -static char *
> +static void
>  compile_to_object (struct command_line *cmd, const char *cmd_string,
>  		   enum compile_i_scope_types scope,
> -		   char **source_filep)
> +		   std::string *source_filep,
> +		   std::string *object_filep)
>  {

...

> @@ -609,30 +606,27 @@ void
>  eval_compile_command (struct command_line *cmd, const char 
> *cmd_string,
>  		      enum compile_i_scope_types scope, void *scope_data)
>  {
> -  char *object_file, *source_file;
> +  std::string source_file, object_file;
> 
> -  object_file = compile_to_object (cmd, cmd_string, scope, 
> &source_file);
> -  if (object_file != NULL)
> +  compile_to_object (cmd, cmd_string, scope, &source_file, 
> &object_file);
> +  if (!object_file.empty ())

Can this actually happen?

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

* Re: [PATCH v2 29/31] 'struct agent_expr *' -> unique_ptr<agent_expr>
  2016-10-19  1:13 ` [PATCH v2 29/31] 'struct agent_expr *' -> unique_ptr<agent_expr> Pedro Alves
@ 2016-10-19 23:19   ` Simon Marchi
  2016-10-19 23:58     ` Pedro Alves
  0 siblings, 1 reply; 61+ messages in thread
From: Simon Marchi @ 2016-10-19 23:19 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 2016-10-18 21:12, Pedro Alves wrote:
> diff --git a/gdb/ax-general.c b/gdb/ax-general.c
> index 7f27a45..35225f6 100644
> --- a/gdb/ax-general.c
> +++ b/gdb/ax-general.c
> @@ -37,52 +37,30 @@ static void generic_ext (struct agent_expr *x,
> enum agent_op op, int n);
>  \f
>  /* Functions for building expressions.  */
> 
> -/* Allocate a new, empty agent expression.  */
> -struct agent_expr *
> -new_agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
> +agent_expr::agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
>  {
> -  struct agent_expr *x = XNEW (struct agent_expr);
> -
> -  x->len = 0;
> -  x->size = 1;			/* Change this to a larger value once
> +  this->len = 0;
> +  this->size = 1;		/* Change this to a larger value once
>  				   reallocation code is tested.  */
> -  x->buf = (unsigned char *) xmalloc (x->size);
> +  this->buf = (unsigned char *) xmalloc (this->size);
> 
> -  x->gdbarch = gdbarch;
> -  x->scope = scope;
> +  this->gdbarch = gdbarch;
> +  this->scope = scope;
> 
>    /* Bit vector for registers used.  */
> -  x->reg_mask_len = 1;
> -  x->reg_mask = XCNEWVEC (unsigned char, x->reg_mask_len);
> -
> -  x->tracing = 0;
> -  x->trace_string = 0;
> +  this->reg_mask_len = 1;
> +  this->reg_mask = XCNEWVEC (unsigned char, this->reg_mask_len);
> 
> -  return x;
> +  this->tracing = 0;
> +  this->trace_string = 0;
>  }

In one of Tom's patches, you said to drop the "this->".  Did you leave 
them here for clarity?  Would you remove them if the structure was 
completely converted, with m_ prefixed members (given that the m_ prefix 
makes it clear enough that it's a member)?

> @@ -12385,13 +12378,9 @@ force_breakpoint_reinsertion (struct 
> bp_location *bl)
>  	 that have already been marked.  */
>        loc->condition_changed = condition_updated;
> 
> -      /* Free the agent expression bytecode as well.  We will compute
> -	 it later on.  */
> -      if (loc->cond_bytecode)
> -	{
> -	  free_agent_expr (loc->cond_bytecode);
> -	  loc->cond_bytecode = NULL;
> -	}
> +      /* Release the agent expression bytecode as well.  We will
> +	 compute it later on.  */
> +      loc->cond_bytecode.reset ();

Why did you change Free for Release in the comment?  Since release has a 
different meaning when using unique pointers, it sounds more confusing 
like this I think.

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

* Re: [PATCH v2 21/31] Use ui_file_as_string in gdb/compile/
  2016-10-19 23:08   ` Simon Marchi
@ 2016-10-19 23:48     ` Pedro Alves
  2016-10-20  3:17       ` Simon Marchi
  0 siblings, 1 reply; 61+ messages in thread
From: Pedro Alves @ 2016-10-19 23:48 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

On 10/20/2016 12:08 AM, Simon Marchi wrote:
> The doc for get_new_file_names should probably be updated:
> 
> /* Compute the names of source and object files to use.  The names are
>    allocated by malloc and should be freed by the caller.  */
> 
>>  static void
>> -get_new_file_names (char **source_file, char **object_file)
>> +get_new_file_names (std::string *source_file, std::string *object_file)
>>  {
> 
> 
> Same for compile_to_object, both for the "freeing" part and the part
> that talks about the return value.
> 
> We should use $other_language instead of C++, to be able to do
> 
>   source_filep, object_filep = compile_to_object (...)
> 
> :)

Well, there's std::pair in C++03, and std::tuple in C++11.
And C++17 has structured bindings:

  auto [source_file, object_file] = compile_to_object ();

:-)

But I think returning a real named struct is clearer than all that.
See patch below showing the idea.  WDYT?

> 
> Btw, would it be good to use references for those strings?

Maybe.  I had kept it using pointers to make it clearer at the
call site that these are output parameters.  Maybe that's
old-school C++ mentality?  That moot with this version of the
patch though, so I can dodge discussing that for now.  :-)

> 
>>     error condition, error () is called.  The caller is responsible for
>>     freeing both strings.  */
>>
>> -static char *
>> +static void
>>  compile_to_object (struct command_line *cmd, const char *cmd_string,
>>             enum compile_i_scope_types scope,
>> -           char **source_filep)
>> +           std::string *source_filep,
>> +           std::string *object_filep)
>>  {
> 
> ...
> 
>> @@ -609,30 +606,27 @@ void
>>  eval_compile_command (struct command_line *cmd, const char *cmd_string,
>>                enum compile_i_scope_types scope, void *scope_data)
>>  {
>> -  char *object_file, *source_file;
>> +  std::string source_file, object_file;
>>
>> -  object_file = compile_to_object (cmd, cmd_string, scope,
>> &source_file);
>> -  if (object_file != NULL)
>> +  compile_to_object (cmd, cmd_string, scope, &source_file,
>> &object_file);
>> +  if (!object_file.empty ())
> 
> Can this actually happen?

Hmm, looks like not.

This passes the gdb.compile/ tests.

From 80470a5ac4b3db444f2bc605a639ca6ef795f743 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Thu, 20 Oct 2016 00:28:26 +0100
Subject: [PATCH] Use ui_file_as_string in gdb/compile/

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* c-lang.h (c_compute_program): Now returns std::string.
	* compile/compile-c-support.c (c_compute_program): Now returns a
	std::string.  Use ui_file_as_string.
	* compile/compile.c (get_new_file_names): Change output parameters
	to std::string pointers.  Use string_printf.
	(compile_to_object): Change output parameters to std::string
	pointers.  Use ui_file_as_string.
	(eval_compile_command): Use std::string.
	* language.h (struct language_defn) <la_compute_program>: Now
	returns std::string.
---
 gdb/c-lang.h                    |  14 ++---
 gdb/compile/compile-c-support.c |   6 +-
 gdb/compile/compile.c           | 132 ++++++++++++++++++++++------------------
 gdb/language.h                  |  14 ++---
 4 files changed, 89 insertions(+), 77 deletions(-)

diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 12be8bf..8378d4f 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -152,16 +152,16 @@ extern int c_textual_element_type (struct type *, char);
 
 extern struct compile_instance *c_get_compile_context (void);
 
-/* This takes the user-supplied text and returns a newly malloc'd bit
-   of code to compile.
+/* This takes the user-supplied text and returns a new bit of code to
+   compile.
 
    This is used as the la_compute_program language method; see that
    for a description of the arguments.  */
 
-extern char *c_compute_program (struct compile_instance *inst,
-				const char *input,
-				struct gdbarch *gdbarch,
-				const struct block *expr_block,
-				CORE_ADDR expr_pc);
+extern std::string c_compute_program (struct compile_instance *inst,
+				      const char *input,
+				      struct gdbarch *gdbarch,
+				      const struct block *expr_block,
+				      CORE_ADDR expr_pc);
 
 #endif /* !defined (C_LANG_H) */
diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index c42daba..641b0fd 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -326,7 +326,7 @@ generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch,
    to the inferior when the expression was created, and EXPR_PC
    indicates the value of $PC.  */
 
-char *
+std::string
 c_compute_program (struct compile_instance *inst,
 		   const char *input,
 		   struct gdbarch *gdbarch,
@@ -334,7 +334,7 @@ c_compute_program (struct compile_instance *inst,
 		   CORE_ADDR expr_pc)
 {
   struct ui_file *buf, *var_stream = NULL;
-  char *code;
+  std::string code;
   struct cleanup *cleanup;
   struct compile_c_instance *context = (struct compile_c_instance *) inst;
 
@@ -435,7 +435,7 @@ c_compute_program (struct compile_instance *inst,
     fputs_unfiltered ("}\n", buf);
 
   add_code_footer (inst->scope, buf);
-  code = ui_file_xstrdup (buf, NULL);
+  code = ui_file_as_string (buf);
   do_cleanups (cleanup);
   return code;
 }
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 0c4a738..08dfdc2 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -255,18 +255,40 @@ get_compile_file_tempdir (void)
   return tempdir_name;
 }
 
-/* Compute the names of source and object files to use.  The names are
-   allocated by malloc and should be freed by the caller.  */
-
-static void
-get_new_file_names (char **source_file, char **object_file)
+class compile_file_names
+{
+public:
+  compile_file_names(std::string source_file, std::string object_file)
+    : m_source_file (source_file), m_object_file (object_file)
+  {}
+
+  const char *source_file ()
+  {
+    return m_source_file.c_str ();
+  }
+
+  const char *object_file ()
+  {
+    return m_object_file.c_str ();
+  }
+
+private:
+  std::string m_source_file;
+  std::string m_object_file;
+};
+
+/* Compute the names of source and object files to use.  */
+
+static compile_file_names
+get_new_file_names ()
 {
   static int seq;
   const char *dir = get_compile_file_tempdir ();
 
   ++seq;
-  *source_file = xstrprintf ("%s%sout%d.c", dir, SLASH_STRING, seq);
-  *object_file = xstrprintf ("%s%sout%d.o", dir, SLASH_STRING, seq);
+
+  return compile_file_names (string_printf ("%s%sout%d.c", dir, SLASH_STRING, seq),
+			     string_printf ("%s%sout%d.o", dir, SLASH_STRING, seq));
 }
 
 /* Get the block and PC at which to evaluate an expression.  */
@@ -456,18 +478,13 @@ print_callback (void *ignore, const char *message)
 }
 
 /* Process the compilation request.  On success it returns the object
-   file name and *SOURCE_FILEP is set to source file name.  On an
-   error condition, error () is called.  The caller is responsible for
-   freeing both strings.  */
+   and source file names.  On an error condition, error () is
+   called.  */
 
-static char *
+static compile_file_names
 compile_to_object (struct command_line *cmd, const char *cmd_string,
-		   enum compile_i_scope_types scope,
-		   char **source_filep)
+		   enum compile_i_scope_types scope)
 {
-  char *code;
-  const char *input;
-  char *source_file, *object_file;
   struct compile_instance *compiler;
   struct cleanup *cleanup, *inner_cleanup;
   const struct block *expr_block;
@@ -503,11 +520,14 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 
   /* From the provided expression, build a scope to pass to the
      compiler.  */
+
+  std::string input_buf;
+  const char *input;
+
   if (cmd != NULL)
     {
       struct ui_file *stream = mem_fileopen ();
       struct command_line *iter;
-      char *stream_buf;
 
       make_cleanup_ui_file_delete (stream);
       for (iter = cmd->body_list[0]; iter; iter = iter->next)
@@ -516,20 +536,19 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 	  fputs_unfiltered ("\n", stream);
 	}
 
-      stream_buf = ui_file_xstrdup (stream, NULL);
-      make_cleanup (xfree, stream_buf);
-      input = stream_buf;
+      input_buf = ui_file_as_string (stream);
+      input = input_buf.c_str ();
     }
   else if (cmd_string != NULL)
     input = cmd_string;
   else
     error (_("Neither a simple expression, or a multi-line specified."));
 
-  code = current_language->la_compute_program (compiler, input, gdbarch,
-					       expr_block, expr_pc);
-  make_cleanup (xfree, code);
+  std::string code
+    = current_language->la_compute_program (compiler, input, gdbarch,
+					    expr_block, expr_pc);
   if (compile_debug)
-    fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code);
+    fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code.c_str ());
 
   os_rx = osabi_triplet_regexp (gdbarch_osabi (gdbarch));
   arch_rx = gdbarch_gnu_triplet_regexp (gdbarch);
@@ -560,37 +579,36 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 			    argi, argv[argi]);
     }
 
-  get_new_file_names (&source_file, &object_file);
-  inner_cleanup = make_cleanup (xfree, source_file);
-  make_cleanup (xfree, object_file);
+  compile_file_names fnames = get_new_file_names ();
 
-  src = gdb_fopen_cloexec (source_file, "w");
+  src = gdb_fopen_cloexec (fnames.source_file (), "w");
   if (src == NULL)
     perror_with_name (_("Could not open source file for writing"));
-  make_cleanup (cleanup_unlink_file, source_file);
-  if (fputs (code, src) == EOF)
+  inner_cleanup = make_cleanup (cleanup_unlink_file,
+				(void *) fnames.source_file ());
+  if (fputs (code.c_str (), src) == EOF)
     perror_with_name (_("Could not write to source file"));
   fclose (src);
 
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "source file produced: %s\n\n",
-			source_file);
+			fnames.source_file ());
 
   /* Call the compiler and start the compilation process.  */
-  compiler->fe->ops->set_source_file (compiler->fe, source_file);
+  compiler->fe->ops->set_source_file (compiler->fe, fnames.source_file ());
 
-  if (!compiler->fe->ops->compile (compiler->fe, object_file,
+  if (!compiler->fe->ops->compile (compiler->fe, fnames.object_file (),
 				   compile_debug))
     error (_("Compilation failed."));
 
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "object file produced: %s\n\n",
-			object_file);
+			fnames.object_file ());
 
   discard_cleanups (inner_cleanup);
   do_cleanups (cleanup);
-  *source_filep = source_file;
-  return object_file;
+
+  return fnames;
 }
 
 /* The "compile" prefix command.  */
@@ -609,32 +627,26 @@ void
 eval_compile_command (struct command_line *cmd, const char *cmd_string,
 		      enum compile_i_scope_types scope, void *scope_data)
 {
-  char *object_file, *source_file;
-
-  object_file = compile_to_object (cmd, cmd_string, scope, &source_file);
-  if (object_file != NULL)
+  struct cleanup *cleanup_unlink;
+  struct compile_module *compile_module;
+
+  compile_file_names fnames = compile_to_object (cmd, cmd_string, scope);
+
+  cleanup_unlink = make_cleanup (cleanup_unlink_file,
+				 (void *) fnames.object_file ());
+  make_cleanup (cleanup_unlink_file, (void *) fnames.source_file ());
+  compile_module = compile_object_load (fnames.object_file (),
+					fnames.source_file (),
+					scope, scope_data);
+  if (compile_module == NULL)
     {
-      struct cleanup *cleanup_xfree, *cleanup_unlink;
-      struct compile_module *compile_module;
-
-      cleanup_xfree = make_cleanup (xfree, object_file);
-      make_cleanup (xfree, source_file);
-      cleanup_unlink = make_cleanup (cleanup_unlink_file, object_file);
-      make_cleanup (cleanup_unlink_file, source_file);
-      compile_module = compile_object_load (object_file, source_file,
-					    scope, scope_data);
-      if (compile_module == NULL)
-	{
-	  gdb_assert (scope == COMPILE_I_PRINT_ADDRESS_SCOPE);
-	  do_cleanups (cleanup_xfree);
-	  eval_compile_command (cmd, cmd_string,
-				COMPILE_I_PRINT_VALUE_SCOPE, scope_data);
-	  return;
-	}
-      discard_cleanups (cleanup_unlink);
-      do_cleanups (cleanup_xfree);
-      compile_object_run (compile_module);
+      gdb_assert (scope == COMPILE_I_PRINT_ADDRESS_SCOPE);
+      eval_compile_command (cmd, cmd_string,
+			    COMPILE_I_PRINT_VALUE_SCOPE, scope_data);
+      return;
     }
+  discard_cleanups (cleanup_unlink);
+  compile_object_run (compile_module);
 }
 
 /* See compile/compile-internal.h.  */
diff --git a/gdb/language.h b/gdb/language.h
index d6f932e..758f265 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -406,8 +406,8 @@ struct language_defn
        If 'la_get_gcc_context' is not defined, then this method is
        ignored.
 
-       This takes the user-supplied text and returns a newly malloc'd
-       bit of code to compile.  The caller owns the result.
+       This takes the user-supplied text and returns a new bit of code
+       to compile.
 
        INST is the compiler instance being used.
        INPUT is the user's input text.
@@ -416,11 +416,11 @@ struct language_defn
        parsed.
        EXPR_PC is the PC at which the expression is being parsed.  */
 
-    char *(*la_compute_program) (struct compile_instance *inst,
-				 const char *input,
-				 struct gdbarch *gdbarch,
-				 const struct block *expr_block,
-				 CORE_ADDR expr_pc);
+    std::string (*la_compute_program) (struct compile_instance *inst,
+				       const char *input,
+				       struct gdbarch *gdbarch,
+				       const struct block *expr_block,
+				       CORE_ADDR expr_pc);
 
     /* Add fields above this point, so the magic number is always last.  */
     /* Magic number for compat checking.  */
-- 
2.5.5


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

* Re: [PATCH v2 29/31] 'struct agent_expr *' -> unique_ptr<agent_expr>
  2016-10-19 23:19   ` Simon Marchi
@ 2016-10-19 23:58     ` Pedro Alves
  0 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-19 23:58 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

On 10/20/2016 12:19 AM, Simon Marchi wrote:
> On 2016-10-18 21:12, Pedro Alves wrote:
>> diff --git a/gdb/ax-general.c b/gdb/ax-general.c
>> index 7f27a45..35225f6 100644
>> --- a/gdb/ax-general.c
>> +++ b/gdb/ax-general.c
>> @@ -37,52 +37,30 @@ static void generic_ext (struct agent_expr *x,
>> enum agent_op op, int n);
>>  \f
>>  /* Functions for building expressions.  */
>>
>> -/* Allocate a new, empty agent expression.  */
>> -struct agent_expr *
>> -new_agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
>> +agent_expr::agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
>>  {
>> -  struct agent_expr *x = XNEW (struct agent_expr);
>> -
>> -  x->len = 0;
>> -  x->size = 1;            /* Change this to a larger value once
>> +  this->len = 0;
>> +  this->size = 1;        /* Change this to a larger value once
>>                     reallocation code is tested.  */
>> -  x->buf = (unsigned char *) xmalloc (x->size);
>> +  this->buf = (unsigned char *) xmalloc (this->size);
>>
>> -  x->gdbarch = gdbarch;
>> -  x->scope = scope;
>> +  this->gdbarch = gdbarch;
>> +  this->scope = scope;
>>
>>    /* Bit vector for registers used.  */
>> -  x->reg_mask_len = 1;
>> -  x->reg_mask = XCNEWVEC (unsigned char, x->reg_mask_len);
>> -
>> -  x->tracing = 0;
>> -  x->trace_string = 0;
>> +  this->reg_mask_len = 1;
>> +  this->reg_mask = XCNEWVEC (unsigned char, this->reg_mask_len);
>>
>> -  return x;
>> +  this->tracing = 0;
>> +  this->trace_string = 0;
>>  }
> 
> In one of Tom's patches, you said to drop the "this->".  Did you leave
> them here for clarity?  Would you remove them if the structure was
> completely converted, with m_ prefixed members (given that the m_ prefix
> makes it clear enough that it's a member)?

m_ is supposed to used for private data fields.  In this case,
the fields are still public (and referenced from outside the class
in many places).  I think in such cases using this-> makes the code
much clearer.

> 
>> @@ -12385,13 +12378,9 @@ force_breakpoint_reinsertion (struct
>> bp_location *bl)
>>       that have already been marked.  */
>>        loc->condition_changed = condition_updated;
>>
>> -      /* Free the agent expression bytecode as well.  We will compute
>> -     it later on.  */
>> -      if (loc->cond_bytecode)
>> -    {
>> -      free_agent_expr (loc->cond_bytecode);
>> -      loc->cond_bytecode = NULL;
>> -    }
>> +      /* Release the agent expression bytecode as well.  We will
>> +     compute it later on.  */
>> +      loc->cond_bytecode.reset ();
> 
> Why did you change Free for Release in the comment?  Since release has a
> different meaning when using unique pointers, it sounds more confusing
> like this I think.

Hmm, I saw the "Free" and thought that since we now use "delete", release
would be a generic term that would be clearer.  But you have a good point.
Free -> Delete ?  Or I can just keep it was Free.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 21/31] Use ui_file_as_string in gdb/compile/
  2016-10-19 23:48     ` Pedro Alves
@ 2016-10-20  3:17       ` Simon Marchi
  2016-10-20 12:13         ` Pedro Alves
  0 siblings, 1 reply; 61+ messages in thread
From: Simon Marchi @ 2016-10-20  3:17 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 2016-10-19 19:48, Pedro Alves wrote:
> Well, there's std::pair in C++03, and std::tuple in C++11.
> And C++17 has structured bindings:
> 
>   auto [source_file, object_file] = compile_to_object ();
> 
> :-)
> 
> But I think returning a real named struct is clearer than all that.
> See patch below showing the idea.  WDYT?

Well, your last example looks really nice, since it avoids the overhead 
of writing a class just for one return value, but since we don't have 
access to C++17 quite yet, a class will have to do.

>> 
>> Btw, would it be good to use references for those strings?
> 
> Maybe.  I had kept it using pointers to make it clearer at the
> call site that these are output parameters.  Maybe that's
> old-school C++ mentality?  That moot with this version of the
> patch though, so I can dodge discussing that for now.  :-)

I understand, I don't know which one is best.  What's nice with 
references is that you can't call it with something wrong.

The patch looks good to me... just one missing space...

> -static void
> -get_new_file_names (char **source_file, char **object_file)
> +class compile_file_names
> +{
> +public:
> +  compile_file_names(std::string source_file, std::string object_file)

...here?

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

* Re: [PATCH v2 21/31] Use ui_file_as_string in gdb/compile/
  2016-10-20  3:17       ` Simon Marchi
@ 2016-10-20 12:13         ` Pedro Alves
  0 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-20 12:13 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

On 10/20/2016 04:17 AM, Simon Marchi wrote:
> On 2016-10-19 19:48, Pedro Alves wrote:
>> Well, there's std::pair in C++03, and std::tuple in C++11.
>> And C++17 has structured bindings:
>>
>>   auto [source_file, object_file] = compile_to_object ();
>>
>> :-)
>>
>> But I think returning a real named struct is clearer than all that.
>> See patch below showing the idea.  WDYT?
> 
> Well, your last example looks really nice, since it avoids the overhead
> of writing a class just for one return value, but since we don't have
> access to C++17 quite yet, a class will have to do.

A very simple struct with public fields like this:

struct compile_file_names
{
  std::string source_file;
  std::string objfile_file;
};

would have worked too.  But I wrote it as a full blown class with
a couple accessors that return const char *, because I thought 
that while at it, that would avoid adding several str.c_str() calls
where we're actually using the file names.

Looking a bit deeper, I think that we can make use of the new class
a bit more, and it ends up clarifying the code further.  See
new version below.  Note the point about the ordering.

> 
>>>
>>> Btw, would it be good to use references for those strings?
>>
>> Maybe.  I had kept it using pointers to make it clearer at the
>> call site that these are output parameters.  Maybe that's
>> old-school C++ mentality?  That moot with this version of the
>> patch though, so I can dodge discussing that for now.  :-)
> 
> I understand, I don't know which one is best.  What's nice with
> references is that you can't call it with something wrong.
> 
> The patch looks good to me... just one missing space...
> 
>> -static void
>> -get_new_file_names (char **source_file, char **object_file)
>> +class compile_file_names
>> +{
>> +public:
>> +  compile_file_names(std::string source_file, std::string object_file)
> 
> ...here?

Fixed now.  Also added comments and updated ChangeLog this time.

WDYT?

From 0e7a586e53f91159c49c81f82068dba6c6be6d51 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Thu, 20 Oct 2016 12:50:10 +0100
Subject: [PATCH] Use ui_file_as_string in gdb/compile/

Using ui_file_as_string would imply changing a few prototypes to pass
around source and object file names as std::string.  Instead of that,
wrap those two in a new class.  This ends up eliminating a small
wrinkle: get_new_file_names and compile_object_load have swapped
parameters.  The former takes "source, objfile", while the latter
takes "objfile, source".

gdb/ChangeLog:
yyyy-mm-yy Pedro Alves <palves@redhat.com>

	* c-lang.h (c_compute_program): Now returns std::string.
	* compile/compile-internal.h (class compile_file_names): New
	class.
	* compile/compile-object-load.c (compile_object_load): Replace
	object_file and source_file parameters with a compile_file_names
	parameter.  Adjust.
	* compile-object-load.h: Include "compile-internal.h".
	(compile_object_load): Replace object_file and source_file
	parameters with a compile_file_names parameter.
	* compile/compile-c-support.c (c_compute_program): Now returns a
	std::string.  Use ui_file_as_string.
	* compile/compile.c (get_new_file_names): Remove parameters and
	return a compile_file_names instead.
	(compile_to_object): Now returns a compile_file_names.  Use
	ui_file_as_string.
	(eval_compile_command): Use compile_file_names.
	* language.h (struct language_defn) <la_compute_program>: Now
	returns std::string.
---
 gdb/c-lang.h                      |  14 ++---
 gdb/compile/compile-c-support.c   |   6 +--
 gdb/compile/compile-internal.h    |  25 +++++++++
 gdb/compile/compile-object-load.c |  18 +++----
 gdb/compile/compile-object-load.h |   4 +-
 gdb/compile/compile.c             | 104 +++++++++++++++++---------------------
 gdb/language.h                    |  14 ++---
 7 files changed, 99 insertions(+), 86 deletions(-)

diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 12be8bf..8378d4f 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -152,16 +152,16 @@ extern int c_textual_element_type (struct type *, char);
 
 extern struct compile_instance *c_get_compile_context (void);
 
-/* This takes the user-supplied text and returns a newly malloc'd bit
-   of code to compile.
+/* This takes the user-supplied text and returns a new bit of code to
+   compile.
 
    This is used as the la_compute_program language method; see that
    for a description of the arguments.  */
 
-extern char *c_compute_program (struct compile_instance *inst,
-				const char *input,
-				struct gdbarch *gdbarch,
-				const struct block *expr_block,
-				CORE_ADDR expr_pc);
+extern std::string c_compute_program (struct compile_instance *inst,
+				      const char *input,
+				      struct gdbarch *gdbarch,
+				      const struct block *expr_block,
+				      CORE_ADDR expr_pc);
 
 #endif /* !defined (C_LANG_H) */
diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index c42daba..641b0fd 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -326,7 +326,7 @@ generate_register_struct (struct ui_file *stream, struct gdbarch *gdbarch,
    to the inferior when the expression was created, and EXPR_PC
    indicates the value of $PC.  */
 
-char *
+std::string
 c_compute_program (struct compile_instance *inst,
 		   const char *input,
 		   struct gdbarch *gdbarch,
@@ -334,7 +334,7 @@ c_compute_program (struct compile_instance *inst,
 		   CORE_ADDR expr_pc)
 {
   struct ui_file *buf, *var_stream = NULL;
-  char *code;
+  std::string code;
   struct cleanup *cleanup;
   struct compile_c_instance *context = (struct compile_c_instance *) inst;
 
@@ -435,7 +435,7 @@ c_compute_program (struct compile_instance *inst,
     fputs_unfiltered ("}\n", buf);
 
   add_code_footer (inst->scope, buf);
-  code = ui_file_xstrdup (buf, NULL);
+  code = ui_file_as_string (buf);
   do_cleanups (cleanup);
   return code;
 }
diff --git a/gdb/compile/compile-internal.h b/gdb/compile/compile-internal.h
index 66ea864..5a7bf14 100644
--- a/gdb/compile/compile-internal.h
+++ b/gdb/compile/compile-internal.h
@@ -152,4 +152,29 @@ extern const char *c_get_mode_for_size (int size);
 struct dynamic_prop;
 extern char *c_get_range_decl_name (const struct dynamic_prop *prop);
 
+/* Type used to hold and pass around the source and object file names
+   to use for compilation.  */
+class compile_file_names
+{
+public:
+  compile_file_names (std::string source_file, std::string object_file)
+    : m_source_file (source_file), m_object_file (object_file)
+  {}
+
+  /* Provide read-only views only.  Return 'const char *' instead of
+     std::string to avoid having to use c_str() everywhere in client
+     code.  */
+
+  const char *source_file () const
+  { return m_source_file.c_str (); }
+
+  const char *object_file () const
+  { return m_object_file.c_str (); }
+
+private:
+  /* Storage for the file names.  */
+  std::string m_source_file;
+  std::string m_object_file;
+};
+
 #endif /* GDB_COMPILE_INTERNAL_H */
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
index 9fc6c02..c08aa2b 100644
--- a/gdb/compile/compile-object-load.c
+++ b/gdb/compile/compile-object-load.c
@@ -601,16 +601,14 @@ store_regs (struct type *regs_type, CORE_ADDR regs_base)
     }
 }
 
-/* Load OBJECT_FILE into inferior memory.  Throw an error otherwise.
-   Caller must fully dispose the return value by calling compile_object_run.
-   SOURCE_FILE's copy is stored into the returned object.
-   Caller should free both OBJECT_FILE and SOURCE_FILE immediatelly after this
-   function returns.
-   Function returns NULL only for COMPILE_I_PRINT_ADDRESS_SCOPE when
-   COMPILE_I_PRINT_VALUE_SCOPE should have been used instead.  */
+/* Load the object file specified in FILE_NAMES into inferior memory.
+   Throw an error otherwise.  Caller must fully dispose the return
+   value by calling compile_object_run.  Returns NULL only for
+   COMPILE_I_PRINT_ADDRESS_SCOPE when COMPILE_I_PRINT_VALUE_SCOPE
+   should have been used instead.  */
 
 struct compile_module *
-compile_object_load (const char *object_file, const char *source_file,
+compile_object_load (const compile_file_names &file_names,
 		     enum compile_i_scope_types scope, void *scope_data)
 {
   struct cleanup *cleanups, *cleanups_free_objfile;
@@ -633,7 +631,7 @@ compile_object_load (const char *object_file, const char *source_file,
   struct type *expect_return_type;
   struct munmap_list *munmap_list_head = NULL;
 
-  filename = tilde_expand (object_file);
+  filename = tilde_expand (file_names.object_file ());
   cleanups = make_cleanup (xfree, filename);
 
   abfd = gdb_bfd_open (filename, gnutarget, -1);
@@ -824,7 +822,7 @@ compile_object_load (const char *object_file, const char *source_file,
 
   retval = XNEW (struct compile_module);
   retval->objfile = objfile;
-  retval->source_file = xstrdup (source_file);
+  retval->source_file = xstrdup (file_names.source_file ());
   retval->func_sym = func_sym;
   retval->regs_addr = regs_addr;
   retval->scope = scope;
diff --git a/gdb/compile/compile-object-load.h b/gdb/compile/compile-object-load.h
index 39c1a90..b9cf307 100644
--- a/gdb/compile/compile-object-load.h
+++ b/gdb/compile/compile-object-load.h
@@ -17,6 +17,8 @@
 #ifndef GDB_COMPILE_OBJECT_LOAD_H
 #define GDB_COMPILE_OBJECT_LOAD_H
 
+#include "compile-internal.h"
+
 struct munmap_list;
 
 struct compile_module
@@ -53,7 +55,7 @@ struct compile_module
 };
 
 extern struct compile_module *compile_object_load
-  (const char *object_file, const char *source_file,
+  (const compile_file_names &fnames,
    enum compile_i_scope_types scope, void *scope_data);
 extern void munmap_list_free (struct munmap_list *head);
 
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 0c4a738..dd854d8 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -255,18 +255,18 @@ get_compile_file_tempdir (void)
   return tempdir_name;
 }
 
-/* Compute the names of source and object files to use.  The names are
-   allocated by malloc and should be freed by the caller.  */
+/* Compute the names of source and object files to use.  */
 
-static void
-get_new_file_names (char **source_file, char **object_file)
+static compile_file_names
+get_new_file_names ()
 {
   static int seq;
   const char *dir = get_compile_file_tempdir ();
 
   ++seq;
-  *source_file = xstrprintf ("%s%sout%d.c", dir, SLASH_STRING, seq);
-  *object_file = xstrprintf ("%s%sout%d.o", dir, SLASH_STRING, seq);
+
+  return compile_file_names (string_printf ("%s%sout%d.c", dir, SLASH_STRING, seq),
+			     string_printf ("%s%sout%d.o", dir, SLASH_STRING, seq));
 }
 
 /* Get the block and PC at which to evaluate an expression.  */
@@ -456,18 +456,13 @@ print_callback (void *ignore, const char *message)
 }
 
 /* Process the compilation request.  On success it returns the object
-   file name and *SOURCE_FILEP is set to source file name.  On an
-   error condition, error () is called.  The caller is responsible for
-   freeing both strings.  */
+   and source file names.  On an error condition, error () is
+   called.  */
 
-static char *
+static compile_file_names
 compile_to_object (struct command_line *cmd, const char *cmd_string,
-		   enum compile_i_scope_types scope,
-		   char **source_filep)
+		   enum compile_i_scope_types scope)
 {
-  char *code;
-  const char *input;
-  char *source_file, *object_file;
   struct compile_instance *compiler;
   struct cleanup *cleanup, *inner_cleanup;
   const struct block *expr_block;
@@ -503,11 +498,14 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 
   /* From the provided expression, build a scope to pass to the
      compiler.  */
+
+  std::string input_buf;
+  const char *input;
+
   if (cmd != NULL)
     {
       struct ui_file *stream = mem_fileopen ();
       struct command_line *iter;
-      char *stream_buf;
 
       make_cleanup_ui_file_delete (stream);
       for (iter = cmd->body_list[0]; iter; iter = iter->next)
@@ -516,20 +514,19 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 	  fputs_unfiltered ("\n", stream);
 	}
 
-      stream_buf = ui_file_xstrdup (stream, NULL);
-      make_cleanup (xfree, stream_buf);
-      input = stream_buf;
+      input_buf = ui_file_as_string (stream);
+      input = input_buf.c_str ();
     }
   else if (cmd_string != NULL)
     input = cmd_string;
   else
     error (_("Neither a simple expression, or a multi-line specified."));
 
-  code = current_language->la_compute_program (compiler, input, gdbarch,
-					       expr_block, expr_pc);
-  make_cleanup (xfree, code);
+  std::string code
+    = current_language->la_compute_program (compiler, input, gdbarch,
+					    expr_block, expr_pc);
   if (compile_debug)
-    fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code);
+    fprintf_unfiltered (gdb_stdlog, "debug output:\n\n%s", code.c_str ());
 
   os_rx = osabi_triplet_regexp (gdbarch_osabi (gdbarch));
   arch_rx = gdbarch_gnu_triplet_regexp (gdbarch);
@@ -560,37 +557,36 @@ compile_to_object (struct command_line *cmd, const char *cmd_string,
 			    argi, argv[argi]);
     }
 
-  get_new_file_names (&source_file, &object_file);
-  inner_cleanup = make_cleanup (xfree, source_file);
-  make_cleanup (xfree, object_file);
+  compile_file_names fnames = get_new_file_names ();
 
-  src = gdb_fopen_cloexec (source_file, "w");
+  src = gdb_fopen_cloexec (fnames.source_file (), "w");
   if (src == NULL)
     perror_with_name (_("Could not open source file for writing"));
-  make_cleanup (cleanup_unlink_file, source_file);
-  if (fputs (code, src) == EOF)
+  inner_cleanup = make_cleanup (cleanup_unlink_file,
+				(void *) fnames.source_file ());
+  if (fputs (code.c_str (), src) == EOF)
     perror_with_name (_("Could not write to source file"));
   fclose (src);
 
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "source file produced: %s\n\n",
-			source_file);
+			fnames.source_file ());
 
   /* Call the compiler and start the compilation process.  */
-  compiler->fe->ops->set_source_file (compiler->fe, source_file);
+  compiler->fe->ops->set_source_file (compiler->fe, fnames.source_file ());
 
-  if (!compiler->fe->ops->compile (compiler->fe, object_file,
+  if (!compiler->fe->ops->compile (compiler->fe, fnames.object_file (),
 				   compile_debug))
     error (_("Compilation failed."));
 
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "object file produced: %s\n\n",
-			object_file);
+			fnames.object_file ());
 
   discard_cleanups (inner_cleanup);
   do_cleanups (cleanup);
-  *source_filep = source_file;
-  return object_file;
+
+  return fnames;
 }
 
 /* The "compile" prefix command.  */
@@ -609,32 +605,24 @@ void
 eval_compile_command (struct command_line *cmd, const char *cmd_string,
 		      enum compile_i_scope_types scope, void *scope_data)
 {
-  char *object_file, *source_file;
+  struct cleanup *cleanup_unlink;
+  struct compile_module *compile_module;
+
+  compile_file_names fnames = compile_to_object (cmd, cmd_string, scope);
 
-  object_file = compile_to_object (cmd, cmd_string, scope, &source_file);
-  if (object_file != NULL)
+  cleanup_unlink = make_cleanup (cleanup_unlink_file,
+				 (void *) fnames.object_file ());
+  make_cleanup (cleanup_unlink_file, (void *) fnames.source_file ());
+  compile_module = compile_object_load (fnames, scope, scope_data);
+  if (compile_module == NULL)
     {
-      struct cleanup *cleanup_xfree, *cleanup_unlink;
-      struct compile_module *compile_module;
-
-      cleanup_xfree = make_cleanup (xfree, object_file);
-      make_cleanup (xfree, source_file);
-      cleanup_unlink = make_cleanup (cleanup_unlink_file, object_file);
-      make_cleanup (cleanup_unlink_file, source_file);
-      compile_module = compile_object_load (object_file, source_file,
-					    scope, scope_data);
-      if (compile_module == NULL)
-	{
-	  gdb_assert (scope == COMPILE_I_PRINT_ADDRESS_SCOPE);
-	  do_cleanups (cleanup_xfree);
-	  eval_compile_command (cmd, cmd_string,
-				COMPILE_I_PRINT_VALUE_SCOPE, scope_data);
-	  return;
-	}
-      discard_cleanups (cleanup_unlink);
-      do_cleanups (cleanup_xfree);
-      compile_object_run (compile_module);
+      gdb_assert (scope == COMPILE_I_PRINT_ADDRESS_SCOPE);
+      eval_compile_command (cmd, cmd_string,
+			    COMPILE_I_PRINT_VALUE_SCOPE, scope_data);
+      return;
     }
+  discard_cleanups (cleanup_unlink);
+  compile_object_run (compile_module);
 }
 
 /* See compile/compile-internal.h.  */
diff --git a/gdb/language.h b/gdb/language.h
index d6f932e..758f265 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -406,8 +406,8 @@ struct language_defn
        If 'la_get_gcc_context' is not defined, then this method is
        ignored.
 
-       This takes the user-supplied text and returns a newly malloc'd
-       bit of code to compile.  The caller owns the result.
+       This takes the user-supplied text and returns a new bit of code
+       to compile.
 
        INST is the compiler instance being used.
        INPUT is the user's input text.
@@ -416,11 +416,11 @@ struct language_defn
        parsed.
        EXPR_PC is the PC at which the expression is being parsed.  */
 
-    char *(*la_compute_program) (struct compile_instance *inst,
-				 const char *input,
-				 struct gdbarch *gdbarch,
-				 const struct block *expr_block,
-				 CORE_ADDR expr_pc);
+    std::string (*la_compute_program) (struct compile_instance *inst,
+				       const char *input,
+				       struct gdbarch *gdbarch,
+				       const struct block *expr_block,
+				       CORE_ADDR expr_pc);
 
     /* Add fields above this point, so the magic number is always last.  */
     /* Magic number for compat checking.  */
-- 
2.5.5


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

* [PATCH v2 28/31] Use ui_file_as_string throughout more
  2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
                   ` (29 preceding siblings ...)
  2016-10-19  1:21 ` [PATCH v2 13/31] Use ui_file_as_string in gdb/arm-tdep.c Pedro Alves
@ 2016-10-20 13:08 ` Pedro Alves
  2017-02-23 10:23   ` Yao Qi
  2017-02-23 10:35   ` Yao Qi
  30 siblings, 2 replies; 61+ messages in thread
From: Pedro Alves @ 2016-10-20 13:08 UTC (permalink / raw)
  To: gdb-patches

This replaces most of the remaining ui_file_xstrdup calls with
ui_file_as_string calls.  Whenever a call was replaced, that led to a
cascade of other necessary adjustments throughout, to make the code
use std::string instead of raw pointers.  And then whenever I added a
std::string as member of a struct, I needed to adjust
allocation/destruction of said struct to use new/delete instead of
xmalloc/xfree.

The stopping point was once gdb built again.  These doesn't seem to be
a way to reasonably split this out further.

Maybe-not-obvious changes:

 - demangle_for_lookup returns a cleanup today.  To get rid of that,
   and avoid unnecessary string dupping/copying, this introduces a
   demangle_result_storage type that the caller instantiates and
   passes to demangle_for_lookup.

 - Many methods returned a "char *" to indicate that the caller owns
   the memory and must free it.  Those are switched to return a
   std::string instead.  Methods that return a "view" into some
   internal string return a "const char *" instead.  I.e., we only
   copy/allocate when necessary.

gdb/ChangeLog:
yyyy-mm-yy  Pedro Alves  <palves@redhat.com>

	* ada-lang.c (ada_name_for_lookup, type_as_string): Use and return
	std::string.
	(type_as_string_and_cleanup): Delete.
	(ada_lookup_struct_elt_type): Use type_as_string.
	* ada-lang.h (ada_name_for_lookup): Now returns std::string.
	* ada-varobj.c (ada_varobj_scalar_image): Return a std::string.
	(ada_varobj_describe_child): Make 'child_name' and
	'child_path_expr' parameters std::string pointers.
	(ada_varobj_describe_struct_child, ada_varobj_describe_ptr_child):
	Likewise, and use string_printf.
	(ada_varobj_describe_simple_array_child)
	(ada_varobj_describe_child): Likewise.
	(ada_varobj_get_name_of_child, ada_varobj_get_path_expr_of_child)
	(ada_varobj_get_value_image)
	(ada_varobj_get_value_of_array_variable)
	(ada_varobj_get_value_of_variable, ada_name_of_variable)
	(ada_name_of_child, ada_path_expr_of_child)
	(ada_value_of_variable): Now returns std::string.  Use
	string_printf.
	(ada_value_of_child): Adjust.
	* break-catch-throw.c (check_status_exception_catchpoint): Adjust
	to use std::string.
	* breakpoint.c (watch_command_1): Adjust to use std::string.
	* c-lang.c (c_get_string): Adjust to use std::string.
	* c-typeprint.c (print_name_maybe_canonical): Use std::string.
	* c-varobj.c (varobj_is_anonymous_child): Use ==/!= std::string
	operators.
	(c_name_of_variable): Now returns a std::string.
	(c_describe_child): The 'cname' and 'cfull_expression' output
	parameters are now std::string pointers.  Adjust.
	(c_name_of_child, c_path_expr_of_child, c_value_of_variable)
	(cplus_number_of_children): Adjust to use std::string and
	string_printf.
	(cplus_name_of_variable): Now returns a std::string.
	(cplus_describe_child): The 'cname' and 'cfull_expression' output
	parameters are now std::string pointers.  Adjust.
	(cplus_name_of_child, cplus_path_expr_of_child)
	(cplus_value_of_variable): Now returns a std::string.
	* cp-abi.c (cplus_typename_from_type_info): Return std::string.
	* cp-abi.h (cplus_typename_from_type_info): Return std::string.
	(struct cp_abi_ops) <get_typename_from_type_info>: Return
	std::string.
	* cp-support.c (inspect_type): Use std::string.
	(cp_canonicalize_string_full, cp_canonicalize_string_no_typedefs)
	(cp_canonicalize_string): Return std::string and adjust.
	* cp-support.h (cp_canonicalize_string)
	(cp_canonicalize_string_no_typedefs, cp_canonicalize_string_full):
	Return std::string.
	* dbxread.c (read_dbx_symtab): Use std::string.
	* dwarf2read.c (dwarf2_canonicalize_name): Adjust to use std::string.
	* gdbcmd.h (lookup_struct_elt_type): Adjust to use std::string.
	* gnu-v3-abi.c (gnuv3_get_typeid): Use std::string.
	(gnuv3_get_typename_from_type_info): Return a std::string and
	adjust.
	(gnuv3_get_type_from_type_info): Adjust to use std::string.
	* guile/guile.c (gdbscm_execute_gdb_command): Adjust to use
	std::string.
	* infcmd.c (print_return_value_1): Adjust to use std::string.
	* linespec.c (find_linespec_symbols): Adjust to
	demangle_for_lookup API change.  Use std::string.
	* mi/mi-cmd-var.c (print_varobj, mi_cmd_var_set_format)
	(mi_cmd_var_info_type, mi_cmd_var_info_path_expression)
	(mi_cmd_var_info_expression, mi_cmd_var_evaluate_expression)
	(mi_cmd_var_assign, varobj_update_one): Adjust to use std::string.
	* minsyms.c (lookup_minimal_symbol): Use std::string.
	* python/py-varobj.c (py_varobj_iter_next): Use new instead of
	XNEW.  vitem->name is a std::string now, adjust.
	* rust-exp.y (convert_ast_to_type, convert_name): Adjust to use
	std::string.
	* stabsread.c (define_symbol): Adjust to use std::string.
	* symtab.c (demangle_for_lookup): Now returns 'const char *'.  Add
	a demangle_result_storage parameter.  Use it for storage.
	(lookup_symbol_in_language)
	(lookup_symbol_in_objfile_from_linkage_name): Adjust to new
	demangle_for_lookup API.
	* symtab.h (struct demangle_result_storage): New type.
	(demangle_for_lookup): Now returns 'const char *'.  Add a
	demangle_result_storage parameter.
	* typeprint.c (type_to_string): Return std::string and use
	ui_file_as_string.
	* value.h (type_to_string): Change return type to std::string.
	* varobj-iter.h (struct varobj_item) <name>: Now a std::string.
	(varobj_iter_delete): Use delete instead of xfree.
	* varobj.c (create_child): Return std::string instead of char * in
	output parameter.
	(name_of_variable, name_of_child, my_value_of_variable): Return
	std::string instead of char *.
	(varobj_create, varobj_get_handle): Constify 'objname' parameter.
	Adjust to std::string fields.
	(varobj_get_objname): Return a const char * instead of a char *.
	(varobj_get_expression): Return a std::string.
	(varobj_list_children): Adjust to use std::string.
	(varobj_get_type): Return a std::string.
	(varobj_get_path_expr): Return a const char * instead of a char *.
	Adjust to std::string fields.
	(varobj_get_formatted_value, varobj_get_value): Return a
	std::string.
	(varobj_set_value): Change type of 'expression' parameter to
	std::string.  Use std::string.
	(install_new_value): Use std::string.
	(delete_variable_1): Adjust to use std::string.
	(create_child): Change the 'name' parameter to a std::string
	reference.  Swap it into the new item's name.
	(create_child_with_value): Swap item's name into the new child's
	name.  Use string_printf.
	(new_variable): Use new instead of XNEW.
	(free_variable): Don't xfree fields that are now std::string.
	(name_of_variable, name_of_child): Now returns std::string.
	(value_of_root): Adjust to use std::string.
	(my_value_of_variable, varobj_value_get_print_value): Return
	and use std::string.
	(varobj_value_get_print_value): Adjust to use ui_file_as_string
	and std::string.
	* varobj.h (struct varobj) <name, path_expr, obj_name,
	print_value>: Now std::string's.
	<name_of_variable, name_of_child, path_expr_of_child,
	value_of_variable>: Return std::string.
	(varobj_create, varobj_get_handle): Constify 'objname' parameter.
	(varobj_get_objname): Return a const char * instead of a char *.
	(varobj_get_expression, varobj_get_type): Return a std::string.
	(varobj_get_path_expr): Return a const char * instead of a char *.
	(varobj_get_formatted_value, varobj_get_value): Return a
	std::string.
	(varobj_set_value): Constify 'expression' parameter.
	(varobj_value_get_print_value): Return a std::string.
---
 gdb/ada-lang.c          |  15 +---
 gdb/ada-lang.h          |   2 +-
 gdb/ada-varobj.c        | 130 ++++++++++++++-------------------
 gdb/break-catch-throw.c |  19 ++---
 gdb/breakpoint.c        |   7 +-
 gdb/c-lang.c            |   9 +--
 gdb/c-typeprint.c       |   5 +-
 gdb/c-varobj.c          | 142 +++++++++++++++++-------------------
 gdb/cp-abi.c            |   2 +-
 gdb/cp-abi.h            |   7 +-
 gdb/cp-support.c        |  60 +++++++--------
 gdb/cp-support.h        |  10 +--
 gdb/dbxread.c           |  22 +++---
 gdb/dwarf2read.c        |  12 +--
 gdb/gdbtypes.c          |  12 ++-
 gdb/gnu-v3-abi.c        |  55 +++++---------
 gdb/infcmd.c            |   9 +--
 gdb/linespec.c          |  53 ++++++--------
 gdb/mi/mi-cmd-var.c     |  70 +++++++-----------
 gdb/minsyms.c           |  17 ++---
 gdb/python/py-varobj.c  |   4 +-
 gdb/rust-exp.y          |  11 +--
 gdb/stabsread.c         |  21 +++---
 gdb/symtab.c            |  87 ++++++++--------------
 gdb/symtab.h            |  39 +++++++++-
 gdb/typeprint.c         |   7 +-
 gdb/value.h             |   2 +-
 gdb/varobj-iter.h       |   4 +-
 gdb/varobj.c            | 190 ++++++++++++++++++++++--------------------------
 gdb/varobj.h            |  70 +++++++++---------
 30 files changed, 479 insertions(+), 614 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3c04554..d9b46c6 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -5871,28 +5871,21 @@ ada_iterate_over_symbols (const struct block *block,
 }
 
 /* If NAME is the name of an entity, return a string that should
-   be used to look that entity up in Ada units.  This string should
-   be deallocated after use using xfree.
+   be used to look that entity up in Ada units.
 
    NAME can have any form that the "break" or "print" commands might
    recognize.  In other words, it does not have to be the "natural"
    name, or the "encoded" name.  */
 
-char *
+std::string
 ada_name_for_lookup (const char *name)
 {
-  char *canon;
   int nlen = strlen (name);
 
   if (name[0] == '<' && name[nlen - 1] == '>')
-    {
-      canon = (char *) xmalloc (nlen - 1);
-      memcpy (canon, name + 1, nlen - 2);
-      canon[nlen - 2] = '\0';
-    }
+    return std::string (name + 1, nlen - 2);
   else
-    canon = xstrdup (ada_encode (ada_fold_name (name)));
-  return canon;
+    return ada_encode (ada_fold_name (name));
 }
 
 /* The result is as for ada_lookup_symbol_list with FULL_SEARCH set
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index 7de71eb..189d696 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -370,7 +370,7 @@ extern char *ada_breakpoint_rewrite (char *, int *);
 
 extern char *ada_main_name (void);
 
-extern char *ada_name_for_lookup (const char *name);
+extern std::string ada_name_for_lookup (const char *name);
 
 extern void create_ada_exception_catchpoint
   (struct gdbarch *gdbarch, enum ada_exception_catchpoint_kind ex_kind,
diff --git a/gdb/ada-varobj.c b/gdb/ada-varobj.c
index 1902890..ae46ca2 100644
--- a/gdb/ada-varobj.c
+++ b/gdb/ada-varobj.c
@@ -74,19 +74,16 @@ ada_varobj_decode_var (struct value **value_ptr, struct type **type_ptr)
 /* Return a string containing an image of the given scalar value.
    VAL is the numeric value, while TYPE is the value's type.
    This is useful for plain integers, of course, but even more
-   so for enumerated types.
+   so for enumerated types.  */
 
-   The result should be deallocated by xfree after use.  */
-
-static char *
+static std::string
 ada_varobj_scalar_image (struct type *type, LONGEST val)
 {
   struct ui_file *buf = mem_fileopen ();
   struct cleanup *cleanups = make_cleanup_ui_file_delete (buf);
-  char *result;
 
   ada_print_scalar (type, val, buf);
-  result = ui_file_xstrdup (buf, NULL);
+  std::string result = ui_file_as_string (buf);
   do_cleanups (cleanups);
 
   return result;
@@ -404,10 +401,10 @@ static void ada_varobj_describe_child (struct value *parent_value,
 				       const char *parent_name,
 				       const char *parent_path_expr,
 				       int child_index,
-				       char **child_name,
+				       std::string *child_name,
 				       struct value **child_value,
 				       struct type **child_type,
-				       char **child_path_expr);
+				       std::string *child_path_expr);
 
 /* Same as ada_varobj_describe_child, but limited to struct/union
    objects.  */
@@ -418,10 +415,10 @@ ada_varobj_describe_struct_child (struct value *parent_value,
 				  const char *parent_name,
 				  const char *parent_path_expr,
 				  int child_index,
-				  char **child_name,
+				  std::string *child_name,
 				  struct value **child_value,
 				  struct type **child_type,
-				  char **child_path_expr)
+				  std::string *child_path_expr)
 {
   int fieldno;
   int childno = 0;
@@ -506,7 +503,7 @@ ada_varobj_describe_struct_child (struct value *parent_value,
 	      const char *field_name = TYPE_FIELD_NAME (parent_type, fieldno);
 	      int child_name_len = ada_name_prefix_len (field_name);
 
-	      *child_name = xstrprintf ("%.*s", child_name_len, field_name);
+	      *child_name = string_printf ("%.*s", child_name_len, field_name);
 	    }
 
 	  if (child_value && parent_value)
@@ -527,8 +524,8 @@ ada_varobj_describe_struct_child (struct value *parent_value,
 	      int child_name_len = ada_name_prefix_len (field_name);
 
 	      *child_path_expr =
-		xstrprintf ("(%s).%.*s", parent_path_expr,
-			    child_name_len, field_name);
+		string_printf ("(%s).%.*s", parent_path_expr,
+			       child_name_len, field_name);
 	    }
 
 	  return;
@@ -556,13 +553,13 @@ ada_varobj_describe_ptr_child (struct value *parent_value,
 			       const char *parent_name,
 			       const char *parent_path_expr,
 			       int child_index,
-			       char **child_name,
+			       std::string *child_name,
 			       struct value **child_value,
 			       struct type **child_type,
-			       char **child_path_expr)
+			       std::string *child_path_expr)
 {
   if (child_name)
-    *child_name = xstrprintf ("%s.all", parent_name);
+    *child_name = string_printf ("%s.all", parent_name);
 
   if (child_value && parent_value)
     ada_varobj_ind (parent_value, parent_type, child_value, NULL);
@@ -571,7 +568,7 @@ ada_varobj_describe_ptr_child (struct value *parent_value,
     ada_varobj_ind (parent_value, parent_type, NULL, child_type);
 
   if (child_path_expr)
-    *child_path_expr = xstrprintf ("(%s).all", parent_path_expr);
+    *child_path_expr = string_printf ("(%s).all", parent_path_expr);
 }
 
 /* Same as ada_varobj_describe_child, limited to simple array objects
@@ -586,10 +583,10 @@ ada_varobj_describe_simple_array_child (struct value *parent_value,
 					const char *parent_name,
 					const char *parent_path_expr,
 					int child_index,
-					char **child_name,
+					std::string *child_name,
 					struct value **child_value,
 					struct type **child_type,
-					char **child_path_expr)
+					std::string *child_path_expr)
 {
   struct type *index_type;
   int real_index;
@@ -612,8 +609,7 @@ ada_varobj_describe_simple_array_child (struct value *parent_value,
 
   if (child_path_expr)
     {
-      char *index_img = ada_varobj_scalar_image (index_type, real_index);
-      struct cleanup *cleanups = make_cleanup (xfree, index_img);
+      std::string index_img = ada_varobj_scalar_image (index_type, real_index);
 
       /* Enumeration litterals by themselves are potentially ambiguous.
 	 For instance, consider the following package spec:
@@ -647,13 +643,12 @@ ada_varobj_describe_simple_array_child (struct value *parent_value,
 
       if (index_type_name != NULL)
 	*child_path_expr =
-	  xstrprintf ("(%s)(%.*s'(%s))", parent_path_expr,
-		      ada_name_prefix_len (index_type_name),
-		      index_type_name, index_img);
+	  string_printf ("(%s)(%.*s'(%s))", parent_path_expr,
+			 ada_name_prefix_len (index_type_name),
+			 index_type_name, index_img.c_str ());
       else
 	*child_path_expr =
-	  xstrprintf ("(%s)(%s)", parent_path_expr, index_img);
-      do_cleanups (cleanups);
+	  string_printf ("(%s)(%s)", parent_path_expr, index_img.c_str ());
     }
 }
 
@@ -665,10 +660,10 @@ ada_varobj_describe_child (struct value *parent_value,
 			   const char *parent_name,
 			   const char *parent_path_expr,
 			   int child_index,
-			   char **child_name,
+			   std::string *child_name,
 			   struct value **child_value,
 			   struct type **child_type,
-			   char **child_path_expr)
+			   std::string *child_path_expr)
 {
   /* We cannot compute the child's path expression without
      the parent's path expression.  This is a pre-condition
@@ -680,13 +675,13 @@ ada_varobj_describe_child (struct value *parent_value,
   ada_varobj_adjust_for_child_access (&parent_value, &parent_type);
 
   if (child_name)
-    *child_name = NULL;
+    *child_name = std::string ();
   if (child_value)
     *child_value = NULL;
   if (child_type)
     *child_type = NULL;
   if (child_path_expr)
-    *child_path_expr = NULL;
+    *child_path_expr = std::string ();
 
   if (ada_is_array_descriptor_type (parent_type)
       && TYPE_CODE (parent_type) == TYPE_CODE_TYPEDEF)
@@ -731,20 +726,18 @@ ada_varobj_describe_child (struct value *parent_value,
   /* It should never happen.  But rather than crash, report dummy names
      and return a NULL child_value.  */
   if (child_name)
-    *child_name = xstrdup ("???");
+    *child_name = "???";
 }
 
 /* Return the name of the child number CHILD_INDEX of the (PARENT_VALUE,
-   PARENT_TYPE) pair.  PARENT_NAME is the name of the PARENT.
-
-   The result should be deallocated after use with xfree.  */
+   PARENT_TYPE) pair.  PARENT_NAME is the name of the PARENT.  */
 
-static char *
+static std::string
 ada_varobj_get_name_of_child (struct value *parent_value,
 			      struct type *parent_type,
 			      const char *parent_name, int child_index)
 {
-  char *child_name;
+  std::string child_name;
 
   ada_varobj_describe_child (parent_value, parent_type, parent_name,
 			     NULL, child_index, &child_name, NULL,
@@ -755,18 +748,16 @@ ada_varobj_get_name_of_child (struct value *parent_value,
 /* Return the path expression of the child number CHILD_INDEX of
    the (PARENT_VALUE, PARENT_TYPE) pair.  PARENT_NAME is the name
    of the parent, and PARENT_PATH_EXPR is the parent's path expression.
-   Both must be non-NULL.
+   Both must be non-NULL.  */
 
-   The result must be deallocated after use with xfree.  */
-
-static char *
+static std::string
 ada_varobj_get_path_expr_of_child (struct value *parent_value,
 				   struct type *parent_type,
 				   const char *parent_name,
 				   const char *parent_path_expr,
 				   int child_index)
 {
-  char *child_path_expr;
+  std::string child_path_expr;
 
   ada_varobj_describe_child (parent_value, parent_type, parent_name,
 			     parent_path_expr, child_index, NULL,
@@ -813,11 +804,10 @@ ada_varobj_get_type_of_child (struct value *parent_value,
 
    The resulting string must be deallocated after use with xfree.  */
 
-static char *
+static std::string
 ada_varobj_get_value_image (struct value *value,
 			    struct value_print_options *opts)
 {
-  char *result;
   struct ui_file *buffer;
   struct cleanup *old_chain;
 
@@ -825,7 +815,7 @@ ada_varobj_get_value_image (struct value *value,
   old_chain = make_cleanup_ui_file_delete (buffer);
 
   common_val_print (value, buffer, 0, opts, current_language);
-  result = ui_file_xstrdup (buffer, NULL);
+  std::string result = ui_file_as_string (buffer);
 
   do_cleanups (old_chain);
   return result;
@@ -841,7 +831,7 @@ ada_varobj_get_value_image (struct value *value,
 
    The result should be deallocated after use using xfree.  */
 
-static char *
+static std::string
 ada_varobj_get_value_of_array_variable (struct value *value,
 					struct type *type,
 					struct value_print_options *opts)
@@ -857,50 +847,36 @@ ada_varobj_get_value_of_array_variable (struct value *value,
       && ada_is_string_type (type)
       && (opts->format == 0 || opts->format == 's'))
     {
-      char *str;
-      struct cleanup *old_chain;
-
-      str = ada_varobj_get_value_image (value, opts);
-      old_chain = make_cleanup (xfree, str);
-      result = xstrprintf ("[%d] %s", numchild, str);
-      do_cleanups (old_chain);
+      std::string str = ada_varobj_get_value_image (value, opts);
+      return string_printf ("[%d] %s", numchild, str.c_str ());
     }
   else
-    result = xstrprintf ("[%d]", numchild);
-
-  return result;
+    return string_printf ("[%d]", numchild);
 }
 
 /* Return a string representation of the (VALUE, TYPE) pair, using
    the given print options OPTS as our formatting options.  */
 
-static char *
+static std::string
 ada_varobj_get_value_of_variable (struct value *value,
 				  struct type *type,
 				  struct value_print_options *opts)
 {
-  char *result = NULL;
-
   ada_varobj_decode_var (&value, &type);
 
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
-      result = xstrdup ("{...}");
-      break;
+      return "{...}";
     case TYPE_CODE_ARRAY:
-      result = ada_varobj_get_value_of_array_variable (value, type, opts);
-      break;
+      return ada_varobj_get_value_of_array_variable (value, type, opts);
     default:
       if (!value)
-	result = xstrdup ("");
+	return "";
       else
-	result = ada_varobj_get_value_image (value, opts);
-      break;
+	return ada_varobj_get_value_image (value, opts);
     }
-
-  return result;
 }
 
 /* Ada specific callbacks for VAROBJs.  */
@@ -911,20 +887,20 @@ ada_number_of_children (const struct varobj *var)
   return ada_varobj_get_number_of_children (var->value, var->type);
 }
 
-static char *
+static std::string
 ada_name_of_variable (const struct varobj *parent)
 {
   return c_varobj_ops.name_of_variable (parent);
 }
 
-static char *
+static std::string
 ada_name_of_child (const struct varobj *parent, int index)
 {
   return ada_varobj_get_name_of_child (parent->value, parent->type,
-				       parent->name, index);
+				       parent->name.c_str (), index);
 }
 
-static char*
+static std::string
 ada_path_expr_of_child (const struct varobj *child)
 {
   const struct varobj *parent = child->parent;
@@ -932,7 +908,7 @@ ada_path_expr_of_child (const struct varobj *child)
 
   return ada_varobj_get_path_expr_of_child (parent->value,
 					    parent->type,
-					    parent->name,
+					    parent->name.c_str (),
 					    parent_path_expr,
 					    child->index);
 }
@@ -941,7 +917,7 @@ static struct value *
 ada_value_of_child (const struct varobj *parent, int index)
 {
   return ada_varobj_get_value_of_child (parent->value, parent->type,
-					parent->name, index);
+					parent->name.c_str (), index);
 }
 
 static struct type *
@@ -951,7 +927,7 @@ ada_type_of_child (const struct varobj *parent, int index)
 				       index);
 }
 
-static char *
+static std::string
 ada_value_of_variable (const struct varobj *var,
 		       enum varobj_display_formats format)
 {
@@ -1019,9 +995,9 @@ ada_value_has_mutated (const struct varobj *var, struct value *new_val,
 
   varobj_restrict_range (var->children, &from, &to);
   for (i = from; i < to; i++)
-    if (strcmp (ada_varobj_get_name_of_child (new_val, new_type,
-					      var->name, i),
-		VEC_index (varobj_p, var->children, i)->name) != 0)
+    if (ada_varobj_get_name_of_child (new_val, new_type,
+				      var->name.c_str (), i)
+	!= VEC_index (varobj_p, var->children, i)->name)
       return 1;
 
   return 0;
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index cfec33b..6136a57 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -162,7 +162,7 @@ check_status_exception_catchpoint (struct bpstats *bs)
 {
   struct exception_catchpoint *self
     = (struct exception_catchpoint *) bs->breakpoint_at;
-  char *type_name = NULL;
+  std::string type_name;
 
   bkpt_breakpoint_ops.check_status (bs);
   if (bs->stop == 0)
@@ -174,17 +174,14 @@ check_status_exception_catchpoint (struct bpstats *bs)
   TRY
     {
       struct value *typeinfo_arg;
-      char *canon;
+      std::string canon;
 
       fetch_probe_arguments (NULL, &typeinfo_arg);
       type_name = cplus_typename_from_type_info (typeinfo_arg);
 
-      canon = cp_canonicalize_string (type_name);
-      if (canon != NULL)
-	{
-	  xfree (type_name);
-	  type_name = canon;
-	}
+      canon = cp_canonicalize_string (type_name.c_str ());
+      if (!canon.empty ())
+	std::swap (type_name, canon);
     }
   CATCH (e, RETURN_MASK_ERROR)
     {
@@ -192,12 +189,10 @@ check_status_exception_catchpoint (struct bpstats *bs)
     }
   END_CATCH
 
-  if (type_name != NULL)
+  if (!type_name.empty ())
     {
-      if (regexec (self->pattern, type_name, 0, NULL, 0) != 0)
+      if (regexec (self->pattern, type_name.c_str (), 0, NULL, 0) != 0)
 	bs->stop = 0;
-
-      xfree (type_name);
     }
 }
 
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 2039966..b9bb797 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -11369,14 +11369,13 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
     {
       struct type *t = value_type (val);
       CORE_ADDR addr = value_as_address (val);
-      char *name;
 
       t = check_typedef (TYPE_TARGET_TYPE (check_typedef (t)));
-      name = type_to_string (t);
 
-      w->exp_string_reparse = xstrprintf ("* (%s *) %s", name,
+      std::string name = type_to_string (t);
+
+      w->exp_string_reparse = xstrprintf ("* (%s *) %s", name.c_str (),
 					  core_addr_to_string (addr));
-      xfree (name);
 
       w->exp_string = xstrprintf ("-location %.*s",
 				  (int) (exp_end - exp_start), exp_start);
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index d24b0c8..ecc1e79 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -356,14 +356,11 @@ c_get_string (struct value *value, gdb_byte **buffer,
 
  error:
   {
-    char *type_str;
-
-    type_str = type_to_string (type);
-    if (type_str)
+    std::string type_str = type_to_string (type);
+    if (!type_str.empty ())
       {
-	make_cleanup (xfree, type_str);
 	error (_("Trying to read string with inappropriate type `%s'."),
-	       type_str);
+	       type_str.c_str ());
       }
     else
       error (_("Trying to read string with inappropriate type."));
diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index 8b15b6f..12dda84 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -60,15 +60,14 @@ print_name_maybe_canonical (const char *name,
 			    const struct type_print_options *flags,
 			    struct ui_file *stream)
 {
-  char *s = NULL;
+  std::string s;
 
   if (!flags->raw)
     s = cp_canonicalize_string_full (name,
 				     find_typedef_for_canonicalize,
 				     (void *) flags);
 
-  fputs_filtered (s ? s : name, stream);
-  xfree (s);
+  fputs_filtered (!s.empty () ? s.c_str () : name, stream);
 }
 
 \f
diff --git a/gdb/c-varobj.c b/gdb/c-varobj.c
index b2b239f..16d5077 100644
--- a/gdb/c-varobj.c
+++ b/gdb/c-varobj.c
@@ -37,8 +37,8 @@ static void cplus_class_num_children (struct type *type, int children[3]);
 int
 varobj_is_anonymous_child (const struct varobj *child)
 {
-  return (strcmp (child->name, ANONYMOUS_STRUCT_NAME) == 0
-	  || strcmp (child->name, ANONYMOUS_UNION_NAME) == 0);
+  return (child->name == ANONYMOUS_STRUCT_NAME
+	  || child->name == ANONYMOUS_UNION_NAME);
 }
 
 /* Given the value and the type of a variable object,
@@ -231,10 +231,10 @@ c_number_of_children (const struct varobj *var)
   return children;
 }
 
-static char *
+static std::string
 c_name_of_variable (const struct varobj *parent)
 {
-  return xstrdup (parent->name);
+  return parent->name;
 }
 
 /* Return the value of element TYPE_INDEX of a structure
@@ -279,40 +279,39 @@ value_struct_element_index (struct value *value, int type_index)
 
    If any of CNAME, CVALUE, or CTYPE is not null, but the corresponding
    information cannot be determined, set *CNAME, *CVALUE, or *CTYPE
-   to NULL.  */
+   to empty.  */
 
 static void 
 c_describe_child (const struct varobj *parent, int index,
-		  char **cname, struct value **cvalue, struct type **ctype,
-		  char **cfull_expression)
+		  std::string *cname, struct value **cvalue,
+		  struct type **ctype, std::string *cfull_expression)
 {
   struct value *value = parent->value;
   struct type *type = varobj_get_value_type (parent);
-  char *parent_expression = NULL;
+  std::string parent_expression;
   int was_ptr;
 
   if (cname)
-    *cname = NULL;
+    *cname = std::string ();
   if (cvalue)
     *cvalue = NULL;
   if (ctype)
     *ctype = NULL;
   if (cfull_expression)
     {
-      *cfull_expression = NULL;
+      *cfull_expression = std::string ();
       parent_expression
 	= varobj_get_path_expr (varobj_get_path_expr_parent (parent));
     }
   adjust_value_for_child_access (&value, &type, &was_ptr, 0);
-      
+
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_ARRAY:
       if (cname)
-	*cname
-	  = xstrdup (int_string (index 
-				 + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
-				 10, 1, 0, 0));
+	*cname = int_string (index
+			     + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
+			     10, 1, 0, 0);
 
       if (cvalue && value)
 	{
@@ -333,10 +332,10 @@ c_describe_child (const struct varobj *parent, int index,
 
       if (cfull_expression)
 	*cfull_expression = 
-	  xstrprintf ("(%s)[%s]", parent_expression, 
-		      int_string (index
-				  + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
-				  10, 1, 0, 0));
+	  string_printf ("(%s)[%s]", parent_expression.c_str (),
+			 int_string (index
+				     + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
+				     10, 1, 0, 0));
 
 
       break;
@@ -355,25 +354,26 @@ c_describe_child (const struct varobj *parent, int index,
 	      {
 		if (TYPE_CODE (TYPE_FIELD_TYPE (type, index))
 		    == TYPE_CODE_STRUCT)
-		  *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
+		  *cname = ANONYMOUS_STRUCT_NAME;
 		else
-		  *cname = xstrdup (ANONYMOUS_UNION_NAME);
+		  *cname = ANONYMOUS_UNION_NAME;
 	      }
 
 	    if (cfull_expression)
-	      *cfull_expression = xstrdup ("");
+	      *cfull_expression = "";
 	  }
 	else
 	  {
 	    if (cname)
-	      *cname = xstrdup (field_name);
+	      *cname = field_name;
 
 	    if (cfull_expression)
 	      {
 		const char *join = was_ptr ? "->" : ".";
 
-		*cfull_expression = xstrprintf ("(%s)%s%s", parent_expression,
-						join, field_name);
+		*cfull_expression = string_printf ("(%s)%s%s",
+						   parent_expression.c_str (),
+						   join, field_name);
 	      }
 	  }
 
@@ -390,7 +390,7 @@ c_describe_child (const struct varobj *parent, int index,
 
     case TYPE_CODE_PTR:
       if (cname)
-	*cname = xstrprintf ("*%s", parent->name);
+	*cname = string_printf ("*%s", parent->name.c_str ());
 
       if (cvalue && value)
 	{
@@ -413,33 +413,32 @@ c_describe_child (const struct varobj *parent, int index,
 	*ctype = TYPE_TARGET_TYPE (type);
 
       if (cfull_expression)
-	*cfull_expression = xstrprintf ("*(%s)", parent_expression);
-      
+	*cfull_expression = string_printf ("*(%s)", parent_expression.c_str ());
       break;
 
     default:
       /* This should not happen.  */
       if (cname)
-	*cname = xstrdup ("???");
+	*cname = "???";
       if (cfull_expression)
-	*cfull_expression = xstrdup ("???");
+	*cfull_expression = "???";
       /* Don't set value and type, we don't know then.  */
     }
 }
 
-static char *
+static std::string
 c_name_of_child (const struct varobj *parent, int index)
 {
-  char *name;
+  std::string name;
 
   c_describe_child (parent, index, &name, NULL, NULL, NULL);
   return name;
 }
 
-static char *
+static std::string
 c_path_expr_of_child (const struct varobj *child)
 {
-  char *path_expr;
+  std::string path_expr;
 
   c_describe_child (child->parent, child->index, NULL, NULL, NULL, 
 		    &path_expr);
@@ -479,7 +478,7 @@ get_type (const struct varobj *var)
   return type;
 }
 
-static char *
+static std::string
 c_value_of_variable (const struct varobj *var,
 		     enum varobj_display_formats format)
 {
@@ -496,16 +495,11 @@ c_value_of_variable (const struct varobj *var,
     {
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
-      return xstrdup ("{...}");
+      return "{...}";
       /* break; */
 
     case TYPE_CODE_ARRAY:
-      {
-	char *number;
-
-	number = xstrprintf ("[%d]", var->num_children);
-	return (number);
-      }
+      return string_printf ("[%d]", var->num_children);
       /* break; */
 
     default:
@@ -515,7 +509,7 @@ c_value_of_variable (const struct varobj *var,
 	    /* This can happen if we attempt to get the value of a struct
 	       member when the parent is an invalid pointer.  This is an
 	       error condition, so we should tell the caller.  */
-	    return NULL;
+	    return std::string ();
 	  }
 	else
 	  {
@@ -523,7 +517,7 @@ c_value_of_variable (const struct varobj *var,
 	      /* Frozen variable and no value yet.  We don't
 		 implicitly fetch the value.  MI response will
 		 use empty string for the value, which is OK.  */
-	      return NULL;
+	      return std::string ();
 
 	    gdb_assert (varobj_value_is_changeable_p (var));
 	    gdb_assert (!value_lazy (var->value));
@@ -531,7 +525,7 @@ c_value_of_variable (const struct varobj *var,
 	    /* If the specified format is the current one,
 	       we can reuse print_value.  */
 	    if (format == var->format)
-	      return xstrdup (var->print_value);
+	      return var->print_value;
 	    else
 	      return varobj_value_get_print_value (var->value, format, var);
 	  }
@@ -629,9 +623,9 @@ cplus_number_of_children (const struct varobj *var)
       adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
 
       cplus_class_num_children (type, kids);
-      if (strcmp (var->name, "public") == 0)
+      if (var->name == "public")
 	children = kids[v_public];
-      else if (strcmp (var->name, "private") == 0)
+      else if (var->name == "private")
 	children = kids[v_private];
       else
 	children = kids[v_protected];
@@ -677,7 +671,7 @@ cplus_class_num_children (struct type *type, int children[3])
     }
 }
 
-static char *
+static std::string
 cplus_name_of_variable (const struct varobj *parent)
 {
   return c_name_of_variable (parent);
@@ -704,25 +698,25 @@ match_accessibility (struct type *type, int index, enum accessibility acc)
 
 static void
 cplus_describe_child (const struct varobj *parent, int index,
-		      char **cname, struct value **cvalue, struct type **ctype,
-		      char **cfull_expression)
+		      std::string *cname, struct value **cvalue, struct type **ctype,
+		      std::string *cfull_expression)
 {
   struct value *value;
   struct type *type;
   int was_ptr;
   int lookup_actual_type = 0;
-  char *parent_expression = NULL;
+  const char *parent_expression = NULL;
   const struct varobj *var;
   struct value_print_options opts;
 
   if (cname)
-    *cname = NULL;
+    *cname = std::string ();
   if (cvalue)
     *cvalue = NULL;
   if (ctype)
     *ctype = NULL;
   if (cfull_expression)
-    *cfull_expression = NULL;
+    *cfull_expression = std::string ();
 
   get_user_print_options (&opts);
 
@@ -758,9 +752,9 @@ cplus_describe_child (const struct varobj *parent, int index,
 	  const char *field_name;
 
 	  vptr_fieldno = get_vptr_fieldno (type, &basetype);
-	  if (strcmp (parent->name, "private") == 0)
+	  if (parent->name == "private")
 	    acc = private_field;
-	  else if (strcmp (parent->name, "protected") == 0)
+	  else if (parent->name == "protected")
 	    acc = protected_field;
 
 	  while (index >= 0)
@@ -783,24 +777,24 @@ cplus_describe_child (const struct varobj *parent, int index,
 		{
 		  if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
 		      == TYPE_CODE_STRUCT)
-		    *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
+		    *cname = ANONYMOUS_STRUCT_NAME;
 		  else if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
 			   == TYPE_CODE_UNION)
-		    *cname = xstrdup (ANONYMOUS_UNION_NAME);
+		    *cname = ANONYMOUS_UNION_NAME;
 		}
 
 	      if (cfull_expression)
-		*cfull_expression = xstrdup ("");
+		*cfull_expression = std::string ();
 	    }
 	  else
 	    {
 	      if (cname)
-		*cname = xstrdup (TYPE_FIELD_NAME (type, type_index));
+		*cname = TYPE_FIELD_NAME (type, type_index);
 
 	      if (cfull_expression)
 		*cfull_expression
-		  = xstrprintf ("((%s)%s%s)", parent_expression, join,
-				field_name);
+		  = string_printf ("((%s)%s%s)", parent_expression, join,
+				   field_name);
 	    }
 
 	  if (cvalue && value)
@@ -813,7 +807,7 @@ cplus_describe_child (const struct varobj *parent, int index,
 	{
 	  /* This is a baseclass.  */
 	  if (cname)
-	    *cname = xstrdup (TYPE_FIELD_NAME (type, index));
+	    *cname = TYPE_FIELD_NAME (type, index);
 
 	  if (cvalue && value)
 	    *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value);
@@ -840,11 +834,11 @@ cplus_describe_child (const struct varobj *parent, int index,
 		 as a constructor, if it exists.  Therefore, we must
 		 indicate that the name is a class name by using the
 		 'class' keyword.  See PR mi/11912  */
-	      *cfull_expression = xstrprintf ("(%s(class %s%s) %s)", 
-					      ptr, 
-					      TYPE_FIELD_NAME (type, index),
-					      ptr,
-					      parent_expression);
+	      *cfull_expression = string_printf ("(%s(class %s%s) %s)",
+						 ptr,
+						 TYPE_FIELD_NAME (type, index),
+						 ptr,
+						 parent_expression);
 	    }
 	}
       else
@@ -892,7 +886,7 @@ cplus_describe_child (const struct varobj *parent, int index,
 
 	  gdb_assert (access);
 	  if (cname)
-	    *cname = xstrdup (access);
+	    *cname = access;
 
 	  /* Value and type and full expression are null here.  */
 	}
@@ -903,19 +897,19 @@ cplus_describe_child (const struct varobj *parent, int index,
     }  
 }
 
-static char *
+static std::string
 cplus_name_of_child (const struct varobj *parent, int index)
 {
-  char *name = NULL;
+  std::string name;
 
   cplus_describe_child (parent, index, &name, NULL, NULL, NULL);
   return name;
 }
 
-static char *
+static std::string
 cplus_path_expr_of_child (const struct varobj *child)
 {
-  char *path_expr;
+  std::string path_expr;
 
   cplus_describe_child (child->parent, child->index, NULL, NULL, NULL, 
 			&path_expr);
@@ -940,7 +934,7 @@ cplus_type_of_child (const struct varobj *parent, int index)
   return type;
 }
 
-static char *
+static std::string
 cplus_value_of_variable (const struct varobj *var,
 			 enum varobj_display_formats format)
 {
@@ -948,7 +942,7 @@ cplus_value_of_variable (const struct varobj *var,
   /* If we have one of our special types, don't print out
      any value.  */
   if (CPLUS_FAKE_CHILD (var))
-    return xstrdup ("");
+    return std::string ();
 
   return c_value_of_variable (var, format);
 }
diff --git a/gdb/cp-abi.c b/gdb/cp-abi.c
index afc4d4a..90f0d08 100644
--- a/gdb/cp-abi.c
+++ b/gdb/cp-abi.c
@@ -212,7 +212,7 @@ cplus_type_from_type_info (struct value *value)
 
 /* See cp-abi.h.  */
 
-char *
+std::string
 cplus_typename_from_type_info (struct value *value)
 {
   if (current_cp_abi.get_typename_from_type_info == NULL)
diff --git a/gdb/cp-abi.h b/gdb/cp-abi.h
index 4349a4a..3be9f43 100644
--- a/gdb/cp-abi.h
+++ b/gdb/cp-abi.h
@@ -196,10 +196,9 @@ extern struct type *cplus_type_from_type_info (struct value *value);
 
 /* Given a value which holds a pointer to a std::type_info, return the
    name of the type which that type_info represents.  Throw an
-   exception if the type name cannot be found.  The result is
-   xmalloc'd and must be freed by the caller.  */
+   exception if the type name cannot be found.  */
 
-extern char *cplus_typename_from_type_info (struct value *value);
+extern std::string cplus_typename_from_type_info (struct value *value);
 
 /* Determine if we are currently in a C++ thunk.  If so, get the
    address of the routine we are thunking to and continue to there
@@ -245,7 +244,7 @@ struct cp_abi_ops
   struct value *(*get_typeid) (struct value *value);
   struct type *(*get_typeid_type) (struct gdbarch *gdbarch);
   struct type *(*get_type_from_type_info) (struct value *value);
-  char *(*get_typename_from_type_info) (struct value *value);
+  std::string (*get_typename_from_type_info) (struct value *value);
   CORE_ADDR (*skip_trampoline) (struct frame_info *, CORE_ADDR);
   int (*pass_by_reference) (struct type *type);
 };
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index ea6dcb2..d409b0b 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -288,14 +288,12 @@ inspect_type (struct demangle_parse_info *info,
 
 		 Canonicalize the name again, and store it in the
 		 current node (RET_COMP).  */
-	      char *canon = cp_canonicalize_string_no_typedefs (name);
+	      std::string canon = cp_canonicalize_string_no_typedefs (name);
 
-	      if (canon != NULL)
+	      if (!canon.empty ())
 		{
-		  /* Copy the canonicalization into the obstack and
-		     free CANON.  */
-		  name = copy_string_to_obstack (&info->obstack, canon, &len);
-		  xfree (canon);
+		  /* Copy the canonicalization into the obstack.  */
+		  name = copy_string_to_obstack (&info->obstack, canon.c_str (), &len);
 		}
 
 	      ret_comp->u.s_name.s = name;
@@ -529,22 +527,21 @@ replace_typedefs (struct demangle_parse_info *info,
     }
 }
 
-/* Parse STRING and convert it to canonical form, resolving any typedefs.
-   If parsing fails, or if STRING is already canonical, return NULL.
-   Otherwise return the canonical form.  The return value is allocated via
-   xmalloc.  If FINDER is not NULL, then type components are passed to
-   FINDER to be looked up.  DATA is passed verbatim to FINDER.  */
+/* Parse STRING and convert it to canonical form, resolving any
+   typedefs.  If parsing fails, or if STRING is already canonical,
+   return the empty string.  Otherwise return the canonical form.  If
+   FINDER is not NULL, then type components are passed to FINDER to be
+   looked up.  DATA is passed verbatim to FINDER.  */
 
-char *
+std::string
 cp_canonicalize_string_full (const char *string,
 			     canonicalization_ftype *finder,
 			     void *data)
 {
-  char *ret;
+  std::string ret;
   unsigned int estimated_len;
   struct demangle_parse_info *info;
 
-  ret = NULL;
   estimated_len = strlen (string) * 2;
   info = cp_demangled_name_to_comp (string, NULL);
   if (info != NULL)
@@ -554,18 +551,15 @@ cp_canonicalize_string_full (const char *string,
 
       /* Convert the tree back into a string.  */
       ret = cp_comp_to_string (info->tree, estimated_len);
-      gdb_assert (ret != NULL);
+      gdb_assert (!ret.empty ());
 
       /* Free the parse information.  */
       cp_demangled_name_parse_free (info);
 
       /* Finally, compare the original string with the computed
 	 name, returning NULL if they are the same.  */
-      if (strcmp (string, ret) == 0)
-	{
-	  xfree (ret);
-	  return NULL;
-	}
+      if (ret == string)
+	return std::string ();
     }
 
   return ret;
@@ -574,46 +568,42 @@ cp_canonicalize_string_full (const char *string,
 /* Like cp_canonicalize_string_full, but always passes NULL for
    FINDER.  */
 
-char *
+std::string
 cp_canonicalize_string_no_typedefs (const char *string)
 {
   return cp_canonicalize_string_full (string, NULL, NULL);
 }
 
 /* Parse STRING and convert it to canonical form.  If parsing fails,
-   or if STRING is already canonical, return NULL.  Otherwise return
-   the canonical form.  The return value is allocated via xmalloc.  */
+   or if STRING is already canonical, return the empty string.
+   Otherwise return the canonical form.  */
 
-char *
+std::string
 cp_canonicalize_string (const char *string)
 {
   struct demangle_parse_info *info;
   unsigned int estimated_len;
-  char *ret;
 
   if (cp_already_canonical (string))
-    return NULL;
+    return std::string ();
 
   info = cp_demangled_name_to_comp (string, NULL);
   if (info == NULL)
-    return NULL;
+    return std::string ();
 
   estimated_len = strlen (string) * 2;
-  ret = cp_comp_to_string (info->tree, estimated_len);
+  std::string ret = cp_comp_to_string (info->tree, estimated_len);
   cp_demangled_name_parse_free (info);
 
-  if (ret == NULL)
+  if (ret.empty ())
     {
       warning (_("internal error: string \"%s\" failed to be canonicalized"),
 	       string);
-      return NULL;
+      return std::string ();
     }
 
-  if (strcmp (string, ret) == 0)
-    {
-      xfree (ret);
-      return NULL;
-    }
+  if (ret == string)
+    return std::string ();
 
   return ret;
 }
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 23ffd71..ca7a7d4 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -63,15 +63,15 @@ struct demangle_parse_info
 
 /* Functions from cp-support.c.  */
 
-extern char *cp_canonicalize_string (const char *string);
+extern std::string cp_canonicalize_string (const char *string);
 
-extern char *cp_canonicalize_string_no_typedefs (const char *string);
+extern std::string cp_canonicalize_string_no_typedefs (const char *string);
 
 typedef const char *(canonicalization_ftype) (struct type *, void *);
 
-extern char *cp_canonicalize_string_full (const char *string,
-					  canonicalization_ftype *finder,
-					  void *data);
+extern std::string cp_canonicalize_string_full (const char *string,
+						canonicalization_ftype *finder,
+						void *data);
 
 extern char *cp_class_name_from_physname (const char *physname);
 
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index d5a9587..4a4a5f8 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -1663,20 +1663,16 @@ read_dbx_symtab (struct objfile *objfile)
 	  sym_name = NULL;	/* pacify "gcc -Werror" */
  	  if (psymtab_language == language_cplus)
  	    {
-	      char *new_name, *name = (char *) xmalloc (p - namestring + 1);
- 	      memcpy (name, namestring, p - namestring);
-
- 	      name[p - namestring] = '\0';
- 	      new_name = cp_canonicalize_string (name);
- 	      if (new_name != NULL)
- 		{
- 		  sym_len = strlen (new_name);
+	      std::string name (namestring, p - namestring);
+	      std::string new_name = cp_canonicalize_string (name.c_str ());
+	      if (!new_name.empty ())
+		{
+		  sym_len = new_name.length ();
 		  sym_name = (char *) obstack_copy0 (&objfile->objfile_obstack,
-						     new_name, sym_len);
- 		  xfree (new_name);
- 		}
-              xfree (name);
- 	    }
+						     new_name.c_str (),
+						     sym_len);
+		}
+	    }
 
  	  if (sym_len == 0)
  	    {
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 6cc79ea..1ad6b00 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -19524,14 +19524,14 @@ dwarf2_canonicalize_name (const char *name, struct dwarf2_cu *cu,
 {
   if (name && cu->language == language_cplus)
     {
-      char *canon_name = cp_canonicalize_string (name);
+      std::string canon_name = cp_canonicalize_string (name);
 
-      if (canon_name != NULL)
+      if (!canon_name.empty ())
 	{
-	  if (strcmp (canon_name, name) != 0)
-	    name = (const char *) obstack_copy0 (obstack, canon_name,
-						 strlen (canon_name));
-	  xfree (canon_name);
+	  if (canon_name != name)
+	    name = (const char *) obstack_copy0 (obstack,
+						 canon_name.c_str (),
+						 canon_name.length ());
 	}
     }
 
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index ad890ca..5921aac 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1572,7 +1572,6 @@ struct type *
 lookup_struct_elt_type (struct type *type, const char *name, int noerr)
 {
   int i;
-  char *type_name;
 
   for (;;)
     {
@@ -1586,9 +1585,9 @@ lookup_struct_elt_type (struct type *type, const char *name, int noerr)
   if (TYPE_CODE (type) != TYPE_CODE_STRUCT 
       && TYPE_CODE (type) != TYPE_CODE_UNION)
     {
-      type_name = type_to_string (type);
-      make_cleanup (xfree, type_name);
-      error (_("Type %s is not a structure or union type."), type_name);
+      std::string type_name = type_to_string (type);
+      error (_("Type %s is not a structure or union type."),
+	     type_name.c_str ());
     }
 
 #if 0
@@ -1640,9 +1639,8 @@ lookup_struct_elt_type (struct type *type, const char *name, int noerr)
       return NULL;
     }
 
-  type_name = type_to_string (type);
-  make_cleanup (xfree, type_name);
-  error (_("Type %s has no component named %s."), type_name, name);
+  std::string type_name = type_to_string (type);
+  error (_("Type %s has no component named %s."), type_name.c_str (), name);
 }
 
 /* Store in *MAX the largest number representable by unsigned integer type
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index eda9a11..9be9cd9 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -1081,7 +1081,7 @@ gnuv3_get_typeid (struct value *value)
   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
@@ -1101,20 +1101,16 @@ gnuv3_get_typeid (struct value *value)
   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);
 
@@ -1129,33 +1125,30 @@ 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);
+	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));
@@ -1183,8 +1176,8 @@ gnuv3_get_typename_from_type_info (struct value *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.  */
@@ -1192,26 +1185,14 @@ gnuv3_get_typename_from_type_info (struct value *type_info_ptr)
 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
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 8e34b7e..c603c01 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1688,16 +1688,11 @@ print_return_value_1 (struct ui_out *uiout, struct return_value_info *rv)
     }
   else
     {
-      struct cleanup *oldchain;
-      char *type_name;
-
-      type_name = type_to_string (rv->type);
-      oldchain = make_cleanup (xfree, type_name);
+      std::string type_name = type_to_string (rv->type);
       ui_out_text (uiout, "Value returned has type: ");
-      ui_out_field_string (uiout, "return-type", type_name);
+      ui_out_field_string (uiout, "return-type", type_name.c_str ());
       ui_out_text (uiout, ".");
       ui_out_text (uiout, " Cannot determine contents\n");
-      do_cleanups (oldchain);
     }
 }
 
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 8ceb4ac..1604267 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -3268,27 +3268,28 @@ find_linespec_symbols (struct linespec_state *state,
 		       VEC (symbolp) **symbols,
 		       VEC (bound_minimal_symbol_d) **minsyms)
 {
-  struct cleanup *cleanup;
-  char *canon;
+  demangle_result_storage demangle_storage;
+  std::string ada_lookup_storage;
   const char *lookup_name;
 
-  cleanup = demangle_for_lookup (name, state->language->la_language,
-				 &lookup_name);
   if (state->language->la_language == language_ada)
     {
       /* In Ada, the symbol lookups are performed using the encoded
          name rather than the demangled name.  */
-      lookup_name = ada_name_for_lookup (name);
-      make_cleanup (xfree, (void *) lookup_name);
+      ada_lookup_storage = ada_name_for_lookup (name);
+      lookup_name = ada_lookup_storage.c_str ();
     }
-
-  canon = cp_canonicalize_string_no_typedefs (lookup_name);
-  if (canon != NULL)
+  else
     {
-      lookup_name = canon;
-      make_cleanup (xfree, canon);
+      lookup_name = demangle_for_lookup (name,
+					 state->language->la_language,
+					 demangle_storage);
     }
 
+  std::string canon = cp_canonicalize_string_no_typedefs (lookup_name);
+  if (!canon.empty ())
+    lookup_name = canon.c_str ();
+
   /* It's important to not call expand_symtabs_matching unnecessarily
      as it can really slow things down (by unnecessarily expanding
      potentially 1000s of symtabs, which when debugging some apps can
@@ -3307,7 +3308,7 @@ find_linespec_symbols (struct linespec_state *state,
   if (VEC_empty (symbolp, *symbols)
       && VEC_empty (bound_minimal_symbol_d, *minsyms))
     {
-      char *klass, *method;
+      std::string klass, method;
       const char *last, *p, *scope_op;
       VEC (symbolp) *classes;
 
@@ -3327,35 +3328,29 @@ find_linespec_symbols (struct linespec_state *state,
 	 we already attempted to lookup the entire name as a symbol
 	 and failed.  */
       if (last == NULL)
-	{
-	  do_cleanups (cleanup);
-	  return;
-	}
+	return;
 
       /* LOOKUP_NAME points to the class name.
 	 LAST points to the method name.  */
-      klass = XNEWVEC (char, last - lookup_name + 1);
-      make_cleanup (xfree, klass);
-      strncpy (klass, lookup_name, last - lookup_name);
-      klass[last - lookup_name] = '\0';
+      klass = std::string (lookup_name, last - lookup_name);
 
       /* Skip past the scope operator.  */
       last += strlen (scope_op);
-      method = XNEWVEC (char, strlen (last) + 1);
-      make_cleanup (xfree, method);
-      strcpy (method, last);
+      method = last;
 
       /* Find a list of classes named KLASS.  */
-      classes = lookup_prefix_sym (state, file_symtabs, klass);
-      make_cleanup (VEC_cleanup (symbolp), &classes);
+      classes = lookup_prefix_sym (state, file_symtabs, klass.c_str ());
+      struct cleanup *old_chain
+	= make_cleanup (VEC_cleanup (symbolp), &classes);
 
       if (!VEC_empty (symbolp, classes))
 	{
 	  /* Now locate a list of suitable methods named METHOD.  */
 	  TRY
 	    {
-	      find_method (state, file_symtabs, klass, method, classes,
-			   symbols, minsyms);
+	      find_method (state, file_symtabs,
+			   klass.c_str (), method.c_str (),
+			   classes, symbols, minsyms);
 	    }
 
 	  /* If successful, we're done.  If NOT_FOUND_ERROR
@@ -3367,9 +3362,9 @@ find_linespec_symbols (struct linespec_state *state,
 	    }
 	  END_CATCH
 	}
-    }
 
-  do_cleanups (cleanup);
+      do_cleanups (old_chain);
+    }
 }
 
 /* Return all labels named NAME in FUNCTION_SYMBOLS.  Return the
diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c
index 3bfe4f0..48dc602 100644
--- a/gdb/mi/mi-cmd-var.c
+++ b/gdb/mi/mi-cmd-var.c
@@ -49,34 +49,28 @@ print_varobj (struct varobj *var, enum print_values print_values,
 	      int print_expression)
 {
   struct ui_out *uiout = current_uiout;
-  char *type;
   int thread_id;
   char *display_hint;
 
   ui_out_field_string (uiout, "name", varobj_get_objname (var));
   if (print_expression)
     {
-      char *exp = varobj_get_expression (var);
+      std::string exp = varobj_get_expression (var);
 
-      ui_out_field_string (uiout, "exp", exp);
-      xfree (exp);
+      ui_out_field_string (uiout, "exp", exp.c_str ());
     }
   ui_out_field_int (uiout, "numchild", varobj_get_num_children (var));
   
   if (mi_print_value_p (var, print_values))
     {
-      char *val = varobj_get_value (var);
+      std::string val = varobj_get_value (var);
 
-      ui_out_field_string (uiout, "value", val);
-      xfree (val);
+      ui_out_field_string (uiout, "value", val.c_str ());
     }
 
-  type = varobj_get_type (var);
-  if (type != NULL)
-    {
-      ui_out_field_string (uiout, "type", type);
-      xfree (type);
-    }
+  std::string type = varobj_get_type (var);
+  if (!type.empty ())
+    ui_out_field_string (uiout, "type", type.c_str ());
 
   thread_id = varobj_get_thread_id (var);
   if (thread_id > 0)
@@ -246,7 +240,6 @@ mi_cmd_var_set_format (char *command, char **argv, int argc)
 {
   enum varobj_display_formats format;
   struct varobj *var;
-  char *val;
   struct ui_out *uiout = current_uiout;
 
   if (argc != 2)
@@ -264,9 +257,8 @@ mi_cmd_var_set_format (char *command, char **argv, int argc)
   ui_out_field_string (uiout, "format", varobj_format_string[(int) format]);
  
   /* Report the value in the new format.  */
-  val = varobj_get_value (var);
-  ui_out_field_string (uiout, "value", val);
-  xfree (val);
+  std::string val = varobj_get_value (var);
+  ui_out_field_string (uiout, "value", val.c_str ());
 }
 
 void
@@ -454,18 +446,15 @@ mi_cmd_var_info_type (char *command, char **argv, int argc)
 {
   struct ui_out *uiout = current_uiout;
   struct varobj *var;
-  char *type_name;
 
   if (argc != 1)
     error (_("-var-info-type: Usage: NAME."));
 
   /* Get varobj handle, if a valid var obj name was specified.  */
   var = varobj_get_handle (argv[0]);
-  type_name = varobj_get_type (var);
-
-  ui_out_field_string (uiout, "type", type_name);
 
-  xfree (type_name);
+  std::string type_name = varobj_get_type (var);
+  ui_out_field_string (uiout, "type", type_name.c_str ());
 }
 
 void
@@ -473,7 +462,6 @@ mi_cmd_var_info_path_expression (char *command, char **argv, int argc)
 {
   struct ui_out *uiout = current_uiout;
   struct varobj *var;
-  char *path_expr;
 
   if (argc != 1)
     error (_("Usage: NAME."));
@@ -481,7 +469,7 @@ mi_cmd_var_info_path_expression (char *command, char **argv, int argc)
   /* Get varobj handle, if a valid var obj name was specified.  */
   var = varobj_get_handle (argv[0]);
   
-  path_expr = varobj_get_path_expr (var);
+  const char *path_expr = varobj_get_path_expr (var);
 
   ui_out_field_string (uiout, "path_expr", path_expr);
 }
@@ -492,7 +480,6 @@ mi_cmd_var_info_expression (char *command, char **argv, int argc)
   struct ui_out *uiout = current_uiout;
   const struct language_defn *lang;
   struct varobj *var;
-  char *exp;
 
   if (argc != 1)
     error (_("-var-info-expression: Usage: NAME."));
@@ -504,9 +491,8 @@ mi_cmd_var_info_expression (char *command, char **argv, int argc)
 
   ui_out_field_string (uiout, "lang", lang->la_natural_name);
 
-  exp = varobj_get_expression (var);
-  ui_out_field_string (uiout, "exp", exp);
-  xfree (exp);
+  std::string exp = varobj_get_expression (var);
+  ui_out_field_string (uiout, "exp", exp.c_str ());
 }
 
 void
@@ -588,17 +574,15 @@ mi_cmd_var_evaluate_expression (char *command, char **argv, int argc)
    
   if (formatFound)
     {
-      char *val = varobj_get_formatted_value (var, format);
+      std::string val = varobj_get_formatted_value (var, format);
 
-      ui_out_field_string (uiout, "value", val);
-      xfree (val);
+      ui_out_field_string (uiout, "value", val.c_str ());
     }
   else
     {
-      char *val = varobj_get_value (var);
+      std::string val = varobj_get_value (var);
 
-      ui_out_field_string (uiout, "value", val);
-      xfree (val);
+      ui_out_field_string (uiout, "value", val.c_str ());
     }
 }
 
@@ -607,7 +591,6 @@ mi_cmd_var_assign (char *command, char **argv, int argc)
 {
   struct ui_out *uiout = current_uiout;
   struct varobj *var;
-  char *expression, *val;
   struct cleanup *cleanup;
 
   if (argc != 2)
@@ -619,7 +602,7 @@ mi_cmd_var_assign (char *command, char **argv, int argc)
   if (!varobj_editable_p (var))
     error (_("-var-assign: Variable object is not editable"));
 
-  expression = xstrdup (argv[1]);
+  const char *expression = argv[1];
 
   /* MI command '-var-assign' may write memory, so suppress memory
      changed notification if it does.  */
@@ -631,9 +614,8 @@ mi_cmd_var_assign (char *command, char **argv, int argc)
     error (_("-var-assign: Could not assign "
 	     "expression to variable object"));
 
-  val = varobj_get_value (var);
-  ui_out_field_string (uiout, "value", val);
-  xfree (val);
+  std::string val = varobj_get_value (var);
+  ui_out_field_string (uiout, "value", val.c_str ());
 
   do_cleanups (cleanup);
 }
@@ -756,10 +738,9 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
 	case VAROBJ_IN_SCOPE:
 	  if (mi_print_value_p (r->varobj, print_values))
 	    {
-	      char *val = varobj_get_value (r->varobj);
+	      std::string val = varobj_get_value (r->varobj);
 
-	      ui_out_field_string (uiout, "value", val);
-	      xfree (val);
+	      ui_out_field_string (uiout, "value", val.c_str ());
 	    }
 	  ui_out_field_string (uiout, "in_scope", "true");
 	  break;
@@ -781,10 +762,9 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
 
       if (r->type_changed)
 	{
-	  char *type_name = varobj_get_type (r->varobj);
+	  std::string type_name = varobj_get_type (r->varobj);
 
-	  ui_out_field_string (uiout, "new_type", type_name);
-	  xfree (type_name);
+	  ui_out_field_string (uiout, "new_type", type_name.c_str ());
 	}
 
       if (r->type_changed || r->children_changed)
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index b478402..21255d6 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -171,22 +171,20 @@ lookup_minimal_symbol (const char *name, const char *sfile,
   unsigned int hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
   unsigned int dem_hash = msymbol_hash_iw (name) % MINIMAL_SYMBOL_HASH_SIZE;
 
-  int needtofreename = 0;
-  const char *modified_name;
+  const char *modified_name = name;
 
   if (sfile != NULL)
     sfile = lbasename (sfile);
 
   /* For C++, canonicalize the input name.  */
-  modified_name = name;
+  std::string modified_name_storage;
   if (current_language->la_language == language_cplus)
     {
-      char *cname = cp_canonicalize_string (name);
-
-      if (cname)
+      std::string cname = cp_canonicalize_string (name);
+      if (!cname.empty ())
 	{
-	  modified_name = cname;
-	  needtofreename = 1;
+	  std::swap (modified_name_storage, cname);
+	  modified_name = modified_name_storage.c_str ();
 	}
     }
 
@@ -285,9 +283,6 @@ lookup_minimal_symbol (const char *name, const char *sfile,
 	}
     }
 
-  if (needtofreename)
-    xfree ((void *) modified_name);
-
   /* External symbols are best.  */
   if (found_symbol.minsym != NULL)
     {
diff --git a/gdb/python/py-varobj.c b/gdb/python/py-varobj.c
index 7e74454..a6b1968 100644
--- a/gdb/python/py-varobj.c
+++ b/gdb/python/py-varobj.c
@@ -113,11 +113,11 @@ py_varobj_iter_next (struct varobj_iter *self)
       error (_("Invalid item from the child list"));
     }
 
-  vitem = XNEW (struct varobj_item);
+  vitem = new varobj_item ();
   vitem->value = convert_value_from_python (py_v);
   if (vitem->value == NULL)
     gdbpy_print_stack ();
-  vitem->name = xstrdup (name);
+  vitem->name = name;
 
   self->next_raw_index++;
   do_cleanups (back_to);
diff --git a/gdb/rust-exp.y b/gdb/rust-exp.y
index 6dc4704..da69095 100644
--- a/gdb/rust-exp.y
+++ b/gdb/rust-exp.y
@@ -2052,13 +2052,11 @@ convert_ast_to_type (struct parser_state *state,
 	obstack_1grow (&work_obstack, '(');
 	for (i = 0; VEC_iterate (type_ptr, args, i, type); ++i)
 	  {
-	    char *type_name = type_to_string (type);
+	    std::string type_name = type_to_string (type);
 
 	    if (i > 0)
 	      obstack_1grow (&work_obstack, ',');
-	    obstack_grow_str (&work_obstack, type_name);
-
-	    xfree (type_name);
+	    obstack_grow_str (&work_obstack, type_name.c_str ());
 	  }
 
 	obstack_grow_str0 (&work_obstack, ")");
@@ -2106,13 +2104,12 @@ convert_name (struct parser_state *state, const struct rust_op *operation)
   obstack_1grow (&work_obstack, '<');
   for (i = 0; VEC_iterate (type_ptr, types, i, type); ++i)
     {
-      char *type_name = type_to_string (type);
+      std::string type_name = type_to_string (type);
 
       if (i > 0)
 	obstack_1grow (&work_obstack, ',');
 
-      obstack_grow_str (&work_obstack, type_name);
-      xfree (type_name);
+      obstack_grow_str (&work_obstack, type_name.c_str ());
     }
   obstack_grow_str0 (&work_obstack, ">");
 
diff --git a/gdb/stabsread.c b/gdb/stabsread.c
index e8ebadd..d72db14 100644
--- a/gdb/stabsread.c
+++ b/gdb/stabsread.c
@@ -649,7 +649,6 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type,
   int deftype;
   int synonym = 0;
   int i;
-  char *new_name = NULL;
 
   /* We would like to eliminate nameless symbols, but keep their types.
      E.g. stab entry ":t10=*2" should produce a type 10, which is a pointer
@@ -733,6 +732,8 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type,
   else
     {
     normal:
+      std::string new_name;
+
       if (SYMBOL_LANGUAGE (sym) == language_cplus)
 	{
 	  char *name = (char *) alloca (p - string + 1);
@@ -741,10 +742,11 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type,
 	  name[p - string] = '\0';
 	  new_name = cp_canonicalize_string (name);
 	}
-      if (new_name != NULL)
+      if (!new_name.empty ())
 	{
-	  SYMBOL_SET_NAMES (sym, new_name, strlen (new_name), 1, objfile);
-	  xfree (new_name);
+	  SYMBOL_SET_NAMES (sym,
+			    new_name.c_str (), new_name.length (),
+			    1, objfile);
 	}
       else
 	SYMBOL_SET_NAMES (sym, string, p - string, 1, objfile);
@@ -1642,17 +1644,18 @@ again:
 	  type_name = NULL;
 	  if (current_subfile->language == language_cplus)
 	    {
-	      char *new_name, *name = (char *) alloca (p - *pp + 1);
+	      char *name = (char *) alloca (p - *pp + 1);
 
 	      memcpy (name, *pp, p - *pp);
 	      name[p - *pp] = '\0';
-	      new_name = cp_canonicalize_string (name);
-	      if (new_name != NULL)
+
+	      std::string new_name = cp_canonicalize_string (name);
+	      if (!new_name.empty ())
 		{
 		  type_name
 		    = (char *) obstack_copy0 (&objfile->objfile_obstack,
-					      new_name, strlen (new_name));
-		  xfree (new_name);
+					      new_name.c_str (),
+					      new_name.length ());
 		}
 	    }
 	  if (type_name == NULL)
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 4e03cb7..430bc8d 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -1770,10 +1770,10 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
 }
 
 /* Compute the demangled form of NAME as used by the various symbol
-   lookup functions.  The result is stored in *RESULT_NAME.  Returns a
-   cleanup which can be used to clean up the result.
+   lookup functions.  The result can either be the input NAME
+   directly, or a pointer to a buffer owned by the STORAGE object.
 
-   For Ada, this function just sets *RESULT_NAME to NAME, unmodified.
+   For Ada, this function just returns NAME, unmodified.
    Normally, Ada symbol lookups are performed using the encoded name
    rather than the demangled name, and so it might seem to make sense
    for this function to return an encoded version of NAME.
@@ -1787,59 +1787,38 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
    characters to become lowercase, and thus cause the symbol lookup
    to fail.  */
 
-struct cleanup *
+const char *
 demangle_for_lookup (const char *name, enum language lang,
-		     const char **result_name)
+		     demangle_result_storage &storage)
 {
-  char *demangled_name = NULL;
-  const char *modified_name = NULL;
-  struct cleanup *cleanup = make_cleanup (null_cleanup, 0);
-
-  modified_name = name;
-
   /* If we are using C++, D, or Go, demangle the name before doing a
      lookup, so we can always binary search.  */
   if (lang == language_cplus)
     {
-      demangled_name = gdb_demangle (name, DMGL_ANSI | DMGL_PARAMS);
-      if (demangled_name)
-	{
-	  modified_name = demangled_name;
-	  make_cleanup (xfree, demangled_name);
-	}
-      else
-	{
-	  /* If we were given a non-mangled name, canonicalize it
-	     according to the language (so far only for C++).  */
-	  demangled_name = cp_canonicalize_string (name);
-	  if (demangled_name)
-	    {
-	      modified_name = demangled_name;
-	      make_cleanup (xfree, demangled_name);
-	    }
-	}
+      char *demangled_name = gdb_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+      if (demangled_name != NULL)
+	return storage.set_malloc_ptr (demangled_name);
+
+      /* If we were given a non-mangled name, canonicalize it
+	 according to the language (so far only for C++).  */
+      std::string canon = cp_canonicalize_string (name);
+      if (!canon.empty ())
+	return storage.swap_string (canon);
     }
   else if (lang == language_d)
     {
-      demangled_name = d_demangle (name, 0);
-      if (demangled_name)
-	{
-	  modified_name = demangled_name;
-	  make_cleanup (xfree, demangled_name);
-	}
+      char *demangled_name = d_demangle (name, 0);
+      if (demangled_name != NULL)
+	return storage.set_malloc_ptr (demangled_name);
     }
   else if (lang == language_go)
     {
-      demangled_name = go_demangle (name, 0);
-      if (demangled_name)
-	{
-	  modified_name = demangled_name;
-	  make_cleanup (xfree, demangled_name);
-	}
+      char *demangled_name = go_demangle (name, 0);
+      if (demangled_name != NULL)
+	return storage.set_malloc_ptr (demangled_name);
     }
 
-  *result_name = modified_name;
-  return cleanup;
+  return name;
 }
 
 /* See symtab.h.
@@ -1859,15 +1838,11 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 			   const domain_enum domain, enum language lang,
 			   struct field_of_this_result *is_a_field_of_this)
 {
-  const char *modified_name;
-  struct block_symbol returnval;
-  struct cleanup *cleanup = demangle_for_lookup (name, lang, &modified_name);
+  demangle_result_storage storage;
+  const char *modified_name = demangle_for_lookup (name, lang, storage);
 
-  returnval = lookup_symbol_aux (modified_name, block, domain, lang,
-				 is_a_field_of_this);
-  do_cleanups (cleanup);
-
-  return returnval;
+  return lookup_symbol_aux (modified_name, block, domain, lang,
+			    is_a_field_of_this);
 }
 
 /* See symtab.h.  */
@@ -2278,11 +2253,11 @@ lookup_symbol_in_objfile_from_linkage_name (struct objfile *objfile,
 					    domain_enum domain)
 {
   enum language lang = current_language->la_language;
-  const char *modified_name;
-  struct cleanup *cleanup = demangle_for_lookup (linkage_name, lang,
-						 &modified_name);
   struct objfile *main_objfile, *cur_objfile;
 
+  demangle_result_storage storage;
+  const char *modified_name = demangle_for_lookup (linkage_name, lang, storage);
+
   if (objfile->separate_debug_objfile_backlink)
     main_objfile = objfile->separate_debug_objfile_backlink;
   else
@@ -2300,13 +2275,9 @@ lookup_symbol_in_objfile_from_linkage_name (struct objfile *objfile,
 	result = lookup_symbol_in_objfile_symtabs (cur_objfile, STATIC_BLOCK,
 						   modified_name, domain);
       if (result.symbol != NULL)
-	{
-	  do_cleanups (cleanup);
-	  return result;
-	}
+	return result;
     }
 
-  do_cleanups (cleanup);
   return (struct block_symbol) {NULL, NULL};
 }
 
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 9b1dbb4..a6bf655 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -1637,8 +1637,43 @@ void iterate_over_symbols (const struct block *block, const char *name,
 			   symbol_found_callback_ftype *callback,
 			   void *data);
 
-struct cleanup *demangle_for_lookup (const char *name, enum language lang,
-				     const char **result_name);
+/* Storage type used by demangle_for_lookup.  demangle_for_lookup
+   either returns a const char * pointer that points to either of the
+   fields of this type, or a pointer to the input NAME.  This is done
+   this way because the underlying functions that demangle_for_lookup
+   calls either return a std::string (e.g., cp_canonicalize_string) or
+   a malloc'ed buffer (libiberty's demangled), and we want to avoid
+   unnecessary reallocation/string copying.  */
+class demangle_result_storage
+{
+public:
+
+  /* Swap the std::string storage with STR, and return a pointer to
+     the beginning of the new string.  */
+  const char *swap_string (std::string &str)
+  {
+    std::swap (m_string, str);
+    return m_string.c_str ();
+  }
+
+  /* Set the malloc storage to now point at PTR.  Any previous malloc
+     storage is released.  */
+  const char *set_malloc_ptr (char *ptr)
+  {
+    m_malloc.reset (ptr);
+    return ptr;
+  }
+
+private:
+
+  /* The storage.  */
+  std::string m_string;
+  gdb::unique_xmalloc_ptr<char> m_malloc;
+};
+
+const char *
+  demangle_for_lookup (const char *name, enum language lang,
+		       demangle_result_storage &storage);
 
 struct symbol *allocate_symbol (struct objfile *);
 
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index 6851a70..c1b46be 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -368,10 +368,10 @@ type_print (struct type *type, const char *varstring, struct ui_file *stream,
 /* Print TYPE to a string, returning it.  The caller is responsible for
    freeing the string.  */
 
-char *
+std::string
 type_to_string (struct type *type)
 {
-  char *s = NULL;
+  std::string s;
   struct ui_file *stb;
   struct cleanup *old_chain;
 
@@ -381,11 +381,10 @@ type_to_string (struct type *type)
   TRY
     {
       type_print (type, "", stb, -1);
-      s = ui_file_xstrdup (stb, NULL);
+      s = ui_file_as_string (stb);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
-      s = NULL;
     }
   END_CATCH
 
diff --git a/gdb/value.h b/gdb/value.h
index 3299e87..440bc2d 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -992,7 +992,7 @@ extern void modify_field (struct type *type, gdb_byte *addr,
 extern void type_print (struct type *type, const char *varstring,
 			struct ui_file *stream, int show);
 
-extern char *type_to_string (struct type *type);
+extern std::string type_to_string (struct type *type);
 
 extern gdb_byte *baseclass_addr (struct type *type, int index,
 				 gdb_byte *valaddr,
diff --git a/gdb/varobj-iter.h b/gdb/varobj-iter.h
index bdbf661..1e7889b 100644
--- a/gdb/varobj-iter.h
+++ b/gdb/varobj-iter.h
@@ -19,7 +19,7 @@
 typedef struct varobj_item
 {
   /* Name of this item.  */
-  char *name;
+  std::string name;
 
   /* Value of this item.  */
   struct value *value;
@@ -67,6 +67,6 @@ struct varobj_iter_ops
       if ((ITER) != NULL)		       \
 	{				       \
 	  (ITER)->ops->dtor (ITER);	       \
-	  xfree (ITER);		       \
+	  delete (ITER);		       \
 	}				       \
     } while (0)
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 81e897f..afd82d2 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -156,7 +156,7 @@ static int install_variable (struct varobj *);
 
 static void uninstall_variable (struct varobj *);
 
-static struct varobj *create_child (struct varobj *, int, char *);
+static struct varobj *create_child (struct varobj *, int, std::string &);
 
 static struct varobj *
 create_child_with_value (struct varobj *parent, int index,
@@ -184,16 +184,16 @@ static int install_new_value (struct varobj *var, struct value *value,
 
 static int number_of_children (const struct varobj *);
 
-static char *name_of_variable (const struct varobj *);
+static std::string name_of_variable (const struct varobj *);
 
-static char *name_of_child (struct varobj *, int);
+static std::string name_of_child (struct varobj *, int);
 
 static struct value *value_of_root (struct varobj **var_handle, int *);
 
 static struct value *value_of_child (const struct varobj *parent, int index);
 
-static char *my_value_of_variable (struct varobj *var,
-				   enum varobj_display_formats format);
+static std::string my_value_of_variable (struct varobj *var,
+					 enum varobj_display_formats format);
 
 static int is_root_p (const struct varobj *var);
 
@@ -270,8 +270,8 @@ find_frame_addr_in_frame_chain (CORE_ADDR frame_addr)
 /* Creates a varobj (not its children).  */
 
 struct varobj *
-varobj_create (char *objname,
-	       char *expression, CORE_ADDR frame, enum varobj_type type)
+varobj_create (const char *objname,
+	       const char *expression, CORE_ADDR frame, enum varobj_type type)
 {
   struct varobj *var;
   struct cleanup *old_chain;
@@ -351,9 +351,9 @@ varobj_create (char *objname,
 
       var->format = variable_default_display (var);
       var->root->valid_block = innermost_block;
-      var->name = xstrdup (expression);
+      var->name = expression;
       /* For a root var, the name and the expr are the same.  */
-      var->path_expr = xstrdup (expression);
+      var->path_expr = expression;
 
       /* When the frame is different from the current frame, 
          we must select the appropriate frame before parsing
@@ -418,7 +418,7 @@ varobj_create (char *objname,
 
   if ((var != NULL) && (objname != NULL))
     {
-      var->obj_name = xstrdup (objname);
+      var->obj_name = objname;
 
       /* If a varobj name is duplicated, the install will fail so
          we must cleanup.  */
@@ -452,7 +452,7 @@ varobj_gen_name (void)
    error if OBJNAME cannot be found.  */
 
 struct varobj *
-varobj_get_handle (char *objname)
+varobj_get_handle (const char *objname)
 {
   struct vlist *cv;
   const char *chp;
@@ -465,7 +465,7 @@ varobj_get_handle (char *objname)
     }
 
   cv = *(varobj_table + index);
-  while ((cv != NULL) && (strcmp (cv->var->obj_name, objname) != 0))
+  while (cv != NULL && cv->var->obj_name != objname)
     cv = cv->next;
 
   if (cv == NULL)
@@ -476,16 +476,16 @@ varobj_get_handle (char *objname)
 
 /* Given the handle, return the name of the object.  */
 
-char *
+const char *
 varobj_get_objname (const struct varobj *var)
 {
-  return var->obj_name;
+  return var->obj_name.c_str ();
 }
 
-/* Given the handle, return the expression represented by the object.  The
-   result must be freed by the caller.  */
+/* Given the handle, return the expression represented by the
+   object.  */
 
-char *
+std::string
 varobj_get_expression (const struct varobj *var)
 {
   return name_of_variable (var);
@@ -544,7 +544,6 @@ varobj_set_display_format (struct varobj *var,
   if (varobj_value_is_changeable_p (var) 
       && var->value && !value_lazy (var->value))
     {
-      xfree (var->print_value);
       var->print_value = varobj_value_get_print_value (var->value,
 						       var->format, var);
     }
@@ -867,7 +866,6 @@ varobj_get_num_children (struct varobj *var)
 VEC (varobj_p)*
 varobj_list_children (struct varobj *var, int *from, int *to)
 {
-  char *name;
   int i, children_changed;
 
   var->dynamic->children_requested = 1;
@@ -904,7 +902,7 @@ varobj_list_children (struct varobj *var, int *from, int *to)
 	  /* Either it's the first call to varobj_list_children for
 	     this variable object, and the child was never created,
 	     or it was explicitly deleted by the client.  */
-	  name = name_of_child (var, i);
+	  std::string name = name_of_child (var, i);
 	  existing = create_child (var, i, name);
 	  VEC_replace (varobj_p, var->children, i, existing);
 	}
@@ -929,14 +927,14 @@ varobj_add_child (struct varobj *var, struct varobj_item *item)
    prints on the console.  The caller is responsible for freeing the string.
    */
 
-char *
+std::string
 varobj_get_type (struct varobj *var)
 {
   /* For the "fake" variables, do not return a type.  (Its type is
      NULL, too.)
      Do not return a type for invalid variables as well.  */
   if (CPLUS_FAKE_CHILD (var) || !var->root->is_valid)
-    return NULL;
+    return std::string ();
 
   return type_to_string (var->type);
 }
@@ -984,10 +982,11 @@ varobj_get_path_expr_parent (const struct varobj *var)
 
 /* Return a pointer to the full rooted expression of varobj VAR.
    If it has not been computed yet, compute it.  */
-char *
+
+const char *
 varobj_get_path_expr (const struct varobj *var)
 {
-  if (var->path_expr == NULL)
+  if (var->path_expr.empty ())
     {
       /* For root varobjs, we initialize path_expr
 	 when creating varobj, so here it should be
@@ -998,7 +997,7 @@ varobj_get_path_expr (const struct varobj *var)
       mutable_var->path_expr = (*var->root->lang_ops->path_expr_of_child) (var);
     }
 
-  return var->path_expr;
+  return var->path_expr.c_str ();
 }
 
 const struct language_defn *
@@ -1027,14 +1026,14 @@ varobj_is_dynamic_p (const struct varobj *var)
   return var->dynamic->pretty_printer != NULL;
 }
 
-char *
+std::string
 varobj_get_formatted_value (struct varobj *var,
 			    enum varobj_display_formats format)
 {
   return my_value_of_variable (var, format);
 }
 
-char *
+std::string
 varobj_get_value (struct varobj *var)
 {
   return my_value_of_variable (var, var->format);
@@ -1045,7 +1044,7 @@ varobj_get_value (struct varobj *var)
 /* Note: Invokes functions that can call error().  */
 
 int
-varobj_set_value (struct varobj *var, char *expression)
+varobj_set_value (struct varobj *var, const char *expression)
 {
   struct value *val = NULL; /* Initialize to keep gcc happy.  */
   /* The argument "expression" contains the variable's new value.
@@ -1245,18 +1244,12 @@ update_type_if_necessary (struct varobj *var, struct value *new_value)
       get_user_print_options (&opts);
       if (opts.objectprint)
 	{
-	  struct type *new_type;
-	  char *curr_type_str, *new_type_str;
-	  int type_name_changed;
+	  struct type *new_type = value_actual_type (new_value, 0, 0);
+	  std::string new_type_str = type_to_string (new_type);
+	  std::string curr_type_str = varobj_get_type (var);
 
-	  new_type = value_actual_type (new_value, 0, 0);
-	  new_type_str = type_to_string (new_type);
-	  curr_type_str = varobj_get_type (var);
-	  type_name_changed = strcmp (curr_type_str, new_type_str) != 0;
-	  xfree (curr_type_str);
-	  xfree (new_type_str);
-
-	  if (type_name_changed)
+	  /* Did the type name change?  */
+	  if (curr_type_str != new_type_str)
 	    {
 	      var->type = new_type;
 
@@ -1292,7 +1285,6 @@ install_new_value (struct varobj *var, struct value *value, int initial)
   int need_to_fetch;
   int changed = 0;
   int intentionally_not_fetched = 0;
-  char *print_value = NULL;
 
   /* We need to know the varobj's type to decide if the value should
      be fetched or not.  C++ fake children (public/protected/private)
@@ -1374,6 +1366,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
      values.  Don't get string rendering if the value is
      lazy -- if it is, the code above has decided that the value
      should not be fetched.  */
+  std::string print_value;
   if (value != NULL && !value_lazy (value)
       && var->dynamic->pretty_printer == NULL)
     print_value = varobj_value_get_print_value (value, var->format, var);
@@ -1417,8 +1410,8 @@ install_new_value (struct varobj *var, struct value *value, int initial)
 	      gdb_assert (!value_lazy (var->value));
 	      gdb_assert (!value_lazy (value));
 
-	      gdb_assert (var->print_value != NULL && print_value != NULL);
-	      if (strcmp (var->print_value, print_value) != 0)
+	      gdb_assert (!var->print_value.empty () && !print_value.empty ());
+	      if (var->print_value != print_value)
 		changed = 1;
 	    }
 	}
@@ -1449,17 +1442,14 @@ install_new_value (struct varobj *var, struct value *value, int initial)
      to see if the variable changed.  */
   if (var->dynamic->pretty_printer != NULL)
     {
-      xfree (print_value);
       print_value = varobj_value_get_print_value (var->value, var->format,
 						  var);
-      if ((var->print_value == NULL && print_value != NULL)
-	  || (var->print_value != NULL && print_value == NULL)
-	  || (var->print_value != NULL && print_value != NULL
-	      && strcmp (var->print_value, print_value) != 0))
-	changed = 1;
+      if ((var->print_value.empty () && !print_value.empty ())
+	  || (!var->print_value.empty () && print_value.empty ())
+	  || (!var->print_value.empty () && !print_value.empty ()
+	      && var->print_value != print_value))
+	  changed = 1;
     }
-  if (var->print_value)
-    xfree (var->print_value);
   var->print_value = print_value;
 
   gdb_assert (!var->value || value_type (var->value));
@@ -1854,9 +1844,9 @@ delete_variable_1 (int *delcountp, struct varobj *var, int only_children_p,
     return;
 
   /* Otherwise, add it to the list of deleted ones and proceed to do so.  */
-  /* If the name is null, this is a temporary variable, that has not
+  /* If the name is empty, this is a temporary variable, that has not
      yet been installed, don't report it, it belongs to the caller...  */
-  if (var->obj_name != NULL)
+  if (!var->obj_name.empty ())
     {
       *delcountp = *delcountp + 1;
     }
@@ -1871,7 +1861,7 @@ delete_variable_1 (int *delcountp, struct varobj *var, int only_children_p,
       VEC_replace (varobj_p, var->parent->children, var->index, NULL);
     }
 
-  if (var->obj_name != NULL)
+  if (!var->obj_name.empty ())
     uninstall_variable (var);
 
   /* Free memory associated with this variable.  */
@@ -1888,13 +1878,13 @@ install_variable (struct varobj *var)
   unsigned int index = 0;
   unsigned int i = 1;
 
-  for (chp = var->obj_name; *chp; chp++)
+  for (chp = var->obj_name.c_str (); *chp; chp++)
     {
       index = (index + (i++ * (unsigned int) *chp)) % VAROBJ_TABLE_SIZE;
     }
 
   cv = *(varobj_table + index);
-  while ((cv != NULL) && (strcmp (cv->var->obj_name, var->obj_name) != 0))
+  while (cv != NULL && cv->var->obj_name != var->obj_name)
     cv = cv->next;
 
   if (cv != NULL)
@@ -1933,27 +1923,27 @@ uninstall_variable (struct varobj *var)
   unsigned int i = 1;
 
   /* Remove varobj from hash table.  */
-  for (chp = var->obj_name; *chp; chp++)
+  for (chp = var->obj_name.c_str (); *chp; chp++)
     {
       index = (index + (i++ * (unsigned int) *chp)) % VAROBJ_TABLE_SIZE;
     }
 
   cv = *(varobj_table + index);
   prev = NULL;
-  while ((cv != NULL) && (strcmp (cv->var->obj_name, var->obj_name) != 0))
+  while (cv != NULL && cv->var->obj_name != var->obj_name)
     {
       prev = cv;
       cv = cv->next;
     }
 
   if (varobjdebug)
-    fprintf_unfiltered (gdb_stdlog, "Deleting %s\n", var->obj_name);
+    fprintf_unfiltered (gdb_stdlog, "Deleting %s\n", var->obj_name.c_str ());
 
   if (cv == NULL)
     {
       warning
 	("Assertion failed: Could not find variable object \"%s\" to delete",
-	 var->obj_name);
+	 var->obj_name.c_str ());
       return;
     }
 
@@ -1983,7 +1973,7 @@ uninstall_variable (struct varobj *var)
 	    {
 	      warning (_("Assertion failed: Could not find "
 		         "varobj \"%s\" in root list"),
-		       var->obj_name);
+		       var->obj_name.c_str ());
 	      return;
 	    }
 	  if (prer == NULL)
@@ -2000,11 +1990,11 @@ uninstall_variable (struct varobj *var)
    The created VAROBJ takes ownership of the allocated NAME.  */
 
 static struct varobj *
-create_child (struct varobj *parent, int index, char *name)
+create_child (struct varobj *parent, int index, std::string &name)
 {
   struct varobj_item item;
 
-  item.name = name;
+  std::swap (item.name, name);
   item.value = value_of_child (parent, index);
 
   return create_child_with_value (parent, index, &item);
@@ -2015,21 +2005,22 @@ create_child_with_value (struct varobj *parent, int index,
 			 struct varobj_item *item)
 {
   struct varobj *child;
-  char *childs_name;
 
   child = new_variable ();
 
   /* NAME is allocated by caller.  */
-  child->name = item->name;
+  std::swap (child->name, item->name);
   child->index = index;
   child->parent = parent;
   child->root = parent->root;
 
   if (varobj_is_anonymous_child (child))
-    childs_name = xstrprintf ("%s.%d_anonymous", parent->obj_name, index);
+    child->obj_name = string_printf ("%s.%d_anonymous",
+				     parent->obj_name.c_str (), index);
   else
-    childs_name = xstrprintf ("%s.%s", parent->obj_name, item->name);
-  child->obj_name = childs_name;
+    child->obj_name = string_printf ("%s.%s",
+				     parent->obj_name.c_str (),
+				     child->name.c_str ());
 
   install_variable (child);
 
@@ -2059,10 +2050,7 @@ new_variable (void)
 {
   struct varobj *var;
 
-  var = XNEW (struct varobj);
-  var->name = NULL;
-  var->path_expr = NULL;
-  var->obj_name = NULL;
+  var = new varobj ();
   var->index = -1;
   var->type = NULL;
   var->value = NULL;
@@ -2072,7 +2060,6 @@ new_variable (void)
   var->format = FORMAT_NATURAL;
   var->root = NULL;
   var->updated = 0;
-  var->print_value = NULL;
   var->frozen = 0;
   var->not_fetched = 0;
   var->dynamic = XNEW (struct varobj_dynamic);
@@ -2127,12 +2114,8 @@ free_variable (struct varobj *var)
   if (is_root_p (var))
     delete var->root;
 
-  xfree (var->name);
-  xfree (var->obj_name);
-  xfree (var->print_value);
-  xfree (var->path_expr);
   xfree (var->dynamic);
-  xfree (var);
+  delete var;
 }
 
 static void
@@ -2203,17 +2186,17 @@ number_of_children (const struct varobj *var)
   return (*var->root->lang_ops->number_of_children) (var);
 }
 
-/* What is the expression for the root varobj VAR? Returns a malloc'd
-   string.  */
-static char *
+/* What is the expression for the root varobj VAR? */
+
+static std::string
 name_of_variable (const struct varobj *var)
 {
   return (*var->root->lang_ops->name_of_variable) (var);
 }
 
-/* What is the name of the INDEX'th child of VAR? Returns a malloc'd
-   string.  */
-static char *
+/* What is the name of the INDEX'th child of VAR?  */
+
+static std::string
 name_of_child (struct varobj *var, int index)
 {
   return (*var->root->lang_ops->name_of_child) (var, index);
@@ -2331,17 +2314,16 @@ value_of_root (struct varobj **var_handle, int *type_changed)
   if (var->root->floating)
     {
       struct varobj *tmp_var;
-      char *old_type, *new_type;
 
-      tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0,
+      tmp_var = varobj_create (NULL, var->name.c_str (), (CORE_ADDR) 0,
 			       USE_SELECTED_FRAME);
       if (tmp_var == NULL)
 	{
 	  return NULL;
 	}
-      old_type = varobj_get_type (var);
-      new_type = varobj_get_type (tmp_var);
-      if (strcmp (old_type, new_type) == 0)
+      std::string old_type = varobj_get_type (var);
+      std::string new_type = varobj_get_type (tmp_var);
+      if (old_type == new_type)
 	{
 	  /* The expression presently stored inside var->root->exp
 	     remembers the locations of local variables relatively to
@@ -2356,7 +2338,7 @@ value_of_root (struct varobj **var_handle, int *type_changed)
 	}
       else
 	{
-	  tmp_var->obj_name = xstrdup (var->obj_name);
+	  tmp_var->obj_name = var->obj_name;
 	  tmp_var->from = var->from;
 	  tmp_var->to = var->to;
 	  varobj_delete (var, 0);
@@ -2366,8 +2348,6 @@ value_of_root (struct varobj **var_handle, int *type_changed)
 	  var = *var_handle;
 	  *type_changed = 1;
 	}
-      xfree (old_type);
-      xfree (new_type);
     }
   else
     {
@@ -2410,7 +2390,7 @@ value_of_child (const struct varobj *parent, int index)
 }
 
 /* GDB already has a command called "value_of_variable".  Sigh.  */
-static char *
+static std::string
 my_value_of_variable (struct varobj *var, enum varobj_display_formats format)
 {
   if (var->root->is_valid)
@@ -2420,7 +2400,7 @@ my_value_of_variable (struct varobj *var, enum varobj_display_formats format)
       return (*var->root->lang_ops->value_of_variable) (var, format);
     }
   else
-    return NULL;
+    return std::string ();
 }
 
 void
@@ -2432,14 +2412,13 @@ varobj_formatted_print_options (struct value_print_options *opts,
   opts->raw = 1;
 }
 
-char *
+std::string
 varobj_value_get_print_value (struct value *value,
 			      enum varobj_display_formats format,
 			      const struct varobj *var)
 {
   struct ui_file *stb;
   struct cleanup *old_chain;
-  char *thevalue = NULL;
   struct value_print_options opts;
   struct type *type = NULL;
   long len = 0;
@@ -2449,11 +2428,13 @@ varobj_value_get_print_value (struct value *value,
   int string_print = 0;
 
   if (value == NULL)
-    return NULL;
+    return std::string ();
 
   stb = mem_fileopen ();
   old_chain = make_cleanup_ui_file_delete (stb);
 
+  std::string thevalue;
+
 #if HAVE_PYTHON
   if (gdb_python_initialized)
     {
@@ -2518,8 +2499,8 @@ varobj_value_get_print_value (struct value *value,
 			      xfree (hint);
 			    }
 
-			  len = strlen (s);
-			  thevalue = (char *) xmemdup (s, len + 1, len + 1);
+			  thevalue = std::string (s);
+			  len = thevalue.size ();
 			  gdbarch = get_type_arch (value_type (value));
 			  type = builtin_type (gdbarch)->builtin_char;
 			  xfree (s);
@@ -2529,8 +2510,6 @@ varobj_value_get_print_value (struct value *value,
 			      do_cleanups (old_chain);
 			      return thevalue;
 			    }
-
-			  make_cleanup (xfree, thevalue);
 			}
 		      else
 			gdbpy_print_stack ();
@@ -2549,8 +2528,9 @@ varobj_value_get_print_value (struct value *value,
   varobj_formatted_print_options (&opts, format);
 
   /* If the THEVALUE has contents, it is a regular string.  */
-  if (thevalue)
-    LA_PRINT_STRING (stb, type, (gdb_byte *) thevalue, len, encoding, 0, &opts);
+  if (!thevalue.empty ())
+    LA_PRINT_STRING (stb, type, (gdb_byte *) thevalue.c_str (),
+		     len, encoding, 0, &opts);
   else if (string_print)
     /* Otherwise, if string_print is set, and it is not a regular
        string, it is a lazy string.  */
@@ -2559,7 +2539,7 @@ varobj_value_get_print_value (struct value *value,
     /* All other cases.  */
     common_val_print (value, stb, 0, &opts, current_language);
 
-  thevalue = ui_file_xstrdup (stb, NULL);
+  thevalue = ui_file_as_string (stb);
 
   do_cleanups (old_chain);
   return thevalue;
@@ -2672,11 +2652,11 @@ varobj_invalidate_iter (struct varobj *var, void *unused)
 
       /* Try to create a varobj with same expression.  If we succeed
 	 replace the old varobj, otherwise invalidate it.  */
-      tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0,
+      tmp_var = varobj_create (NULL, var->name.c_str (), (CORE_ADDR) 0,
 			       USE_CURRENT_FRAME);
       if (tmp_var != NULL) 
 	{ 
-	  tmp_var->obj_name = xstrdup (var->obj_name);
+	  tmp_var->obj_name = var->obj_name;
 	  varobj_delete (var, 0);
 	  install_variable (tmp_var);
 	}
diff --git a/gdb/varobj.h b/gdb/varobj.h
index 6b9a71f..7f4aad2 100644
--- a/gdb/varobj.h
+++ b/gdb/varobj.h
@@ -86,22 +86,22 @@ struct varobj_dynamic;
 
 /* Every variable in the system has a structure of this type defined
    for it.  This structure holds all information necessary to manipulate
-   a particular object variable.  Members which must be freed are noted.  */
+   a particular object variable.  */
 struct varobj
 {
-  /* Alloc'd name of the variable for this object.  If this variable is a
+  /* Name of the variable for this object.  If this variable is a
      child, then this name will be the child's source name.
      (bar, not foo.bar).  */
   /* NOTE: This is the "expression".  */
-  char *name;
+  std::string name;
 
-  /* Alloc'd expression for this child.  Can be used to create a
-     root variable corresponding to this child.  */
-  char *path_expr;
+  /* Expression for this child.  Can be used to create a root variable
+     corresponding to this child.  */
+  std::string path_expr;
 
-  /* The alloc'd name for this variable's object.  This is here for
+  /* The name for this variable's object.  This is here for
      convenience when constructing this object's children.  */
-  char *obj_name;
+  std::string obj_name;
 
   /* Index of this variable in its parent or -1.  */
   int index;
@@ -137,7 +137,7 @@ struct varobj
   int updated;
 
   /* Last print value.  */
-  char *print_value;
+  std::string print_value;
 
   /* Is this variable frozen.  Frozen variables are never implicitly
      updated by -var-update * 
@@ -170,18 +170,15 @@ struct lang_varobj_ops
   /* The number of children of PARENT.  */
   int (*number_of_children) (const struct varobj *parent);
 
-  /* The name (expression) of a root varobj.  The returned value must be freed
-     by the caller.  */
-  char *(*name_of_variable) (const struct varobj *parent);
+  /* The name (expression) of a root varobj.  */
+  std::string (*name_of_variable) (const struct varobj *parent);
 
-  /* The name of the INDEX'th child of PARENT.  The returned value must be
-     freed by the caller.  */
-  char *(*name_of_child) (const struct varobj *parent, int index);
+  /* The name of the INDEX'th child of PARENT.  */
+  std::string (*name_of_child) (const struct varobj *parent, int index);
 
   /* Returns the rooted expression of CHILD, which is a variable
-     obtain that has some parent.  The returned value must be freed by the
-     caller.  */
-  char *(*path_expr_of_child) (const struct varobj *child);
+     obtain that has some parent.  */
+  std::string (*path_expr_of_child) (const struct varobj *child);
 
   /* The ``struct value *'' of the INDEX'th child of PARENT.  */
   struct value *(*value_of_child) (const struct varobj *parent, int index);
@@ -189,10 +186,9 @@ struct lang_varobj_ops
   /* The type of the INDEX'th child of PARENT.  */
   struct type *(*type_of_child) (const struct varobj *parent, int index);
 
-  /* The current value of VAR.  The returned value must be freed by the
-     caller.  */
-  char *(*value_of_variable) (const struct varobj *var,
-			      enum varobj_display_formats format);
+  /* The current value of VAR.  */
+  std::string (*value_of_variable) (const struct varobj *var,
+				    enum varobj_display_formats format);
 
   /* Return non-zero if changes in value of VAR must be detected and
      reported by -var-update.  Return zero if -var-update should never
@@ -233,17 +229,17 @@ extern const struct lang_varobj_ops ada_varobj_ops;
 #define default_varobj_ops c_varobj_ops
 /* API functions */
 
-extern struct varobj *varobj_create (char *objname,
-				     char *expression, CORE_ADDR frame,
+extern struct varobj *varobj_create (const char *objname,
+				     const char *expression, CORE_ADDR frame,
 				     enum varobj_type type);
 
 extern char *varobj_gen_name (void);
 
-extern struct varobj *varobj_get_handle (char *name);
+extern struct varobj *varobj_get_handle (const char *name);
 
-extern char *varobj_get_objname (const struct varobj *var);
+extern const char *varobj_get_objname (const struct varobj *var);
 
-extern char *varobj_get_expression (const struct varobj *var);
+extern std::string varobj_get_expression (const struct varobj *var);
 
 /* Delete a varobj and all its children if only_children == 0, otherwise delete
    only the children.  Return the number of deleted variables.  */
@@ -283,23 +279,24 @@ extern int varobj_get_num_children (struct varobj *var);
 extern VEC (varobj_p)* varobj_list_children (struct varobj *var,
 					     int *from, int *to);
 
-extern char *varobj_get_type (struct varobj *var);
+extern std::string varobj_get_type (struct varobj *var);
 
 extern struct type *varobj_get_gdb_type (const struct varobj *var);
 
-extern char *varobj_get_path_expr (const struct varobj *var);
+extern const char *varobj_get_path_expr (const struct varobj *var);
 
 extern const struct language_defn *
   varobj_get_language (const struct varobj *var);
 
 extern int varobj_get_attributes (const struct varobj *var);
 
-extern char *varobj_get_formatted_value (struct varobj *var,
-					 enum varobj_display_formats format);
+extern std::string
+  varobj_get_formatted_value (struct varobj *var,
+			      enum varobj_display_formats format);
 
-extern char *varobj_get_value (struct varobj *var);
+extern std::string varobj_get_value (struct varobj *var);
 
-extern int varobj_set_value (struct varobj *var, char *expression);
+extern int varobj_set_value (struct varobj *var, const char *expression);
 
 extern void all_root_varobjs (void (*func) (struct varobj *var, void *data),
 			      void *data);
@@ -334,9 +331,10 @@ extern int varobj_is_anonymous_child (const struct varobj *child);
 extern const struct varobj *
   varobj_get_path_expr_parent (const struct varobj *var);
 
-extern char *varobj_value_get_print_value (struct value *value,
-					   enum varobj_display_formats format,
-					   const struct varobj *var);
+extern std::string
+  varobj_value_get_print_value (struct value *value,
+				enum varobj_display_formats format,
+				const struct varobj *var);
 
 extern void varobj_formatted_print_options (struct value_print_options *opts,
 					    enum varobj_display_formats format);
-- 
2.5.5

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

* Re: [PATCH v2 01/31] Introduce string_printf
  2016-10-19 21:02     ` Pedro Alves
@ 2016-11-08 15:35       ` Pedro Alves
  0 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-11-08 15:35 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

On 10/19/2016 10:02 PM, Pedro Alves wrote:

> And then thinking that people might dislike the hack, I changed
> it to consider the \0 as part of the initial string (std::string
> can contain embedded NULLs).
> 
> But I shouldn't have.  The "hack" is really not a problem:
> 
>   https://herbsutter.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/#comment-483
> 
> I.e., "everyone" does it like that.

Now that we assume C++11, it's no longer a hack.  Below's the version
that I pushed in.  This version also tweaks the selftests a bit:

- put them in a namespace.
- use string comparison instead of just checking the size.

From d4081a383e28db26c65298f7405554d4312b1342 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 8 Nov 2016 15:26:42 +0000
Subject: [PATCH] Introduce string_printf

This introduces the string_printf function.  Like asprintf, but
returns a std::string.

gdb/ChangeLog:
2016-11-08  Pedro Alves  <palves@redhat.com>

	* Makefile.in (COMMON_OBS): Add utils-selftests.o.
	* common/common-utils.c (string_printf): New function.
	* common/common-utils.h: Include <string>.
	(string_printf): Declare.
	* utils-selftests.c: New file.
---
 gdb/ChangeLog             |  8 +++++++
 gdb/Makefile.in           |  2 +-
 gdb/common/common-utils.c | 23 ++++++++++++++++++
 gdb/common/common-utils.h |  6 +++++
 gdb/utils-selftests.c     | 60 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 98 insertions(+), 1 deletion(-)
 create mode 100644 gdb/utils-selftests.c

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index cc7f9a0..1b647bb 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2016-11-08  Pedro Alves  <palves@redhat.com>
+
+	* Makefile.in (COMMON_OBS): Add utils-selftests.o.
+	* common/common-utils.c (string_printf): New function.
+	* common/common-utils.h: Include <string>.
+	(string_printf): Declare.
+	* utils-selftests.c: New file.
+
 2016-11-08  Yao Qi  <yao.qi@linaro.org>
 
 	* aarch64-tdep.c (aarch64_software_single_step): Return
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 6db63c7..3876cd9 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1066,7 +1066,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
 	ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
 	m2-valprint.o \
-	ser-event.o serial.o mdebugread.o top.o utils.o \
+	ser-event.o serial.o mdebugread.o top.o utils.o utils-selftests.o \
 	ui-file.o \
 	user-regs.o \
 	frame.o frame-unwind.o doublest.o \
diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c
index 5a346ec..e112b62 100644
--- a/gdb/common/common-utils.c
+++ b/gdb/common/common-utils.c
@@ -150,6 +150,29 @@ xsnprintf (char *str, size_t size, const char *format, ...)
   return ret;
 }
 
+/* See documentation in common-utils.h.  */
+
+std::string
+string_printf (const char* fmt, ...)
+{
+  va_list vp;
+  int size;
+
+  va_start (vp, fmt);
+  size = vsnprintf (NULL, 0, fmt, vp);
+  va_end (vp);
+
+  std::string str (size, '\0');
+
+  /* C++11 and later guarantee std::string uses contiguous memory and
+     always includes the terminating '\0'.  */
+  va_start (vp, fmt);
+  vsprintf (&str[0], fmt, vp);
+  va_end (vp);
+
+  return str;
+}
+
 char *
 savestring (const char *ptr, size_t len)
 {
diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h
index 47def11..a9053ff 100644
--- a/gdb/common/common-utils.h
+++ b/gdb/common/common-utils.h
@@ -20,6 +20,8 @@
 #ifndef COMMON_UTILS_H
 #define COMMON_UTILS_H
 
+#include <string>
+
 /* If possible, define FUNCTION_NAME, a macro containing the name of
    the function being defined.  Since this macro may not always be
    defined, all uses must be protected by appropriate macro definition
@@ -56,6 +58,10 @@ char *xstrvprintf (const char *format, va_list ap)
 int xsnprintf (char *str, size_t size, const char *format, ...)
      ATTRIBUTE_PRINTF (3, 4);
 
+/* Returns a std::string built from a printf-style format string.  */
+std::string string_printf (const char* fmt, ...)
+  ATTRIBUTE_PRINTF (1, 2);
+
 /* Make a copy of the string at PTR with LEN characters
    (and add a null character at the end in the copy).
    Uses malloc to get the space.  Returns the address of the copy.  */
diff --git a/gdb/utils-selftests.c b/gdb/utils-selftests.c
new file mode 100644
index 0000000..f424655
--- /dev/null
+++ b/gdb/utils-selftests.c
@@ -0,0 +1,60 @@
+/* Self tests for general utility routines for GDB, the GNU debugger.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+#include "defs.h"
+#include "selftest.h"
+
+#if GDB_SELF_TEST
+
+namespace selftests {
+
+/* common-utils self tests.  Defined here instead of in
+   common/common-utils.c because that file is shared with
+   gdbserver.  */
+
+static void
+common_utils_tests (void)
+{
+  SELF_CHECK (string_printf ("%s", "") == "");
+  SELF_CHECK (string_printf ("%d comes before 2", 1) == "1 comes before 2");
+  SELF_CHECK (string_printf ("hello %s", "world") == "hello world");
+
+#define X10 "0123456789"
+#define X100 X10 X10 X10 X10 X10 X10 X10 X10 X10 X10
+#define X1000 X100 X100 X100 X100 X100 X100 X100 X100 X100 X100
+#define X10000 X1000 X1000 X1000 X1000 X1000 X1000 X1000 X1000 X1000 X1000
+#define X100000 X10000 X10000 X10000 X10000 X10000 X10000 X10000 X10000 X10000 X10000
+  SELF_CHECK (string_printf ("%s", X10) == X10);
+  SELF_CHECK (string_printf ("%s", X100) == X100);
+  SELF_CHECK (string_printf ("%s", X1000) == X1000);
+  SELF_CHECK (string_printf ("%s", X10000) == X10000);
+  SELF_CHECK (string_printf ("%s", X100000) == X100000);
+}
+
+} /* namespace selftests */
+
+#endif
+
+void
+_initialize_utils_selftests (void)
+{
+#if GDB_SELF_TEST
+  register_self_test (selftests::common_utils_tests);
+#endif
+}
-- 
2.5.5


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

* Re: [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments
  2016-10-19  1:13 ` [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments Pedro Alves
  2016-10-19  6:29   ` Eli Zaretskii
  2016-10-19 11:33   ` Philipp Rudo
@ 2016-11-08 15:41   ` Pedro Alves
  2 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2016-11-08 15:41 UTC (permalink / raw)
  To: gdb-patches

On 10/19/2016 02:12 AM, Pedro Alves wrote:
> Should probably write a test for this.  Will do if people agree this
> is useful.

I've pushed the whole series in, except the this patch.

I wrote a test already, but it depends on a fix for:

  "eval" command inside user commands misses $arg0...$arg9 / $argc substitution
  https://sourceware.org/bugzilla/show_bug.cgi?id=20559

So I'll resend it separately soon.

Thanks,
Pedro Alves

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

* Re: [PATCH v2 28/31] Use ui_file_as_string throughout more
  2016-10-20 13:08 ` [PATCH v2 28/31] Use ui_file_as_string throughout more Pedro Alves
@ 2017-02-23 10:23   ` Yao Qi
  2017-02-23 10:53     ` Pedro Alves
  2017-02-23 10:35   ` Yao Qi
  1 sibling, 1 reply; 61+ messages in thread
From: Yao Qi @ 2017-02-23 10:23 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves <palves@redhat.com> writes:

Hi Pedro,

> std::string as member of a struct, I needed to adjust
> allocation/destruction of said struct to use new/delete instead of
> xmalloc/xfree.
>

> diff --git a/gdb/varobj-iter.h b/gdb/varobj-iter.h
> index bdbf661..1e7889b 100644
> --- a/gdb/varobj-iter.h
> +++ b/gdb/varobj-iter.h
> @@ -19,7 +19,7 @@
>  typedef struct varobj_item
>  {
>    /* Name of this item.  */
> -  char *name;
> +  std::string name;
>  
>    /* Value of this item.  */
>    struct value *value;
> @@ -67,6 +67,6 @@ struct varobj_iter_ops
>        if ((ITER) != NULL)		       \
>  	{				       \
>  	  (ITER)->ops->dtor (ITER);	       \
> -	  xfree (ITER);		       \
> +	  delete (ITER);		       \

We don't need to use "delete" for varobj_iter, because you didn't add
std::string member in varobj_iter.  This change causes an ASAN error,

-var-create container @ c^M
=================================================================^M
^[[1m^[[31m==12975==ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete) on 0x603000085e40^M
^[[1m^[[0m    #0 0x2b8ce74d15d7 in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x555d7)^M
    #1 0xc13d3c in update_dynamic_varobj_children /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:786^M
    #2 0xc1425f in varobj_get_num_children(varobj*) /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:846^M
    #3 0x59ffeb in print_varobj /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-cmd-var.c:61^M
    #4 0x5a0689 in mi_cmd_var_create(char*, char**, int) /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-cmd-var.c:145^M
    #5 0x5b5ac9 in mi_cmd_execute /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-main.c:2295^M
    #6 0x5b3de0 in captured_mi_execute_command /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-main.c:1997^M
.....
^M
^[[1m^[[32m0x603000085e40 is located 0 bytes inside of 32-byte region [0x603000085e40,0x603000085e60)^M
^[[1m^[[0m^[[1m^[[35mallocated by thread T0 here:^[[1m^[[0m^M
    #0 0x2b8ce74d0862 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x54862)^M
    #1 0x80df7f in xmalloc /home/yao/SourceCode/gnu/gdb/git/gdb/common/common-utils.c:43^M
    #2 0x6364ec in py_varobj_iter_new /home/yao/SourceCode/gnu/gdb/git/gdb/python/py-varobj.c:154^M
    #3 0x636710 in py_varobj_get_iterator(varobj*, _object*) /home/yao/SourceCode/gnu/gdb/git/gdb/python/py-varobj.c:188^M
    #4 0xc13580 in varobj_get_iterator /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:712^M
    #5 0xc138fa in update_dynamic_varobj_children /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:750^M
    #6 0xc1425f in varobj_get_num_children(varobj*) /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:846^M

reverting the change above fixes the error.  We can also C++-fy
varobj_iter, but I'd like to do in another patch.  How is the patch below?

>  	}				       \
>      } while (0)

> diff --git a/gdb/varobj.h b/gdb/varobj.h
> index 6b9a71f..7f4aad2 100644
> --- a/gdb/varobj.h
> +++ b/gdb/varobj.h
> @@ -86,22 +86,22 @@ struct varobj_dynamic;
>  
>  /* Every variable in the system has a structure of this type defined
>     for it.  This structure holds all information necessary to manipulate
> -   a particular object variable.  Members which must be freed are noted.  */
> +   a particular object variable.  */
>  struct varobj
>  {
> -  /* Alloc'd name of the variable for this object.  If this variable is a
> +  /* Name of the variable for this object.  If this variable is a
>       child, then this name will be the child's source name.
>       (bar, not foo.bar).  */
>    /* NOTE: This is the "expression".  */
> -  char *name;
> +  std::string name;
>  
> -  /* Alloc'd expression for this child.  Can be used to create a
> -     root variable corresponding to this child.  */
> -  char *path_expr;
> +  /* Expression for this child.  Can be used to create a root variable
> +     corresponding to this child.  */
> +  std::string path_expr;
>  
> -  /* The alloc'd name for this variable's object.  This is here for
> +  /* The name for this variable's object.  This is here for
>       convenience when constructing this object's children.  */
> -  char *obj_name;
> +  std::string obj_name;
>  
>    /* Index of this variable in its parent or -1.  */
>    int index;
> @@ -137,7 +137,7 @@ struct varobj
>    int updated;
>  
>    /* Last print value.  */
> -  char *print_value;
> +  std::string print_value;
>  
>    /* Is this variable frozen.  Frozen variables are never implicitly
>       updated by -var-update * 
> @@ -170,18 +170,15 @@ struct lang_varobj_ops
>    /* The number of children of PARENT.  */
>    int (*number_of_children) (const struct varobj *parent);
>  
> -  /* The name (expression) of a root varobj.  The returned value must be freed
> -     by the caller.  */
> -  char *(*name_of_variable) (const struct varobj *parent);
> +  /* The name (expression) of a root varobj.  */
> +  std::string (*name_of_variable) (const struct varobj *parent);
>  
> -  /* The name of the INDEX'th child of PARENT.  The returned value must be
> -     freed by the caller.  */
> -  char *(*name_of_child) (const struct varobj *parent, int index);
> +  /* The name of the INDEX'th child of PARENT.  */
> +  std::string (*name_of_child) (const struct varobj *parent, int index);
>  
>    /* Returns the rooted expression of CHILD, which is a variable
> -     obtain that has some parent.  The returned value must be freed by the
> -     caller.  */
> -  char *(*path_expr_of_child) (const struct varobj *child);
> +     obtain that has some parent.  */
> +  std::string (*path_expr_of_child) (const struct varobj *child);
>  
>    /* The ``struct value *'' of the INDEX'th child of PARENT.  */
>    struct value *(*value_of_child) (const struct varobj *parent, int index);
> @@ -189,10 +186,9 @@ struct lang_varobj_ops
>    /* The type of the INDEX'th child of PARENT.  */
>    struct type *(*type_of_child) (const struct varobj *parent, int index);
>  
> -  /* The current value of VAR.  The returned value must be freed by the
> -     caller.  */
> -  char *(*value_of_variable) (const struct varobj *var,
> -			      enum varobj_display_formats format);
> +  /* The current value of VAR.  */
> +  std::string (*value_of_variable) (const struct varobj *var,
> +				    enum varobj_display_formats format);
>  
>    /* Return non-zero if changes in value of VAR must be detected and
>       reported by -var-update.  Return zero if -var-update should never

-- 
Yao (齐尧)
From 71dc64a061cfb1ec57b753e495c02665827c7a01 Mon Sep 17 00:00:00 2001
From: Yao Qi <yao.qi@linaro.org>
Date: Thu, 23 Feb 2017 09:29:48 +0000
Subject: [PATCH] Use xfree rather than delete for varobj_iter

ASAN reports an error,

-var-create container @ c^M
=================================================================^M
^[[1m^[[31m==21639==ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete) on 0x6030000805c0^M
^[[1m^[[0m    #0 0x7f2449b01b2a in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99b2a)^M
    #1 0xbb601d in update_dynamic_varobj_children ../../binutils-gdb/gdb/varobj.c:794^M
    #2 0xbb6556 in varobj_get_num_children(varobj*) ../../binutils-gdb/gdb/varobj.c:854^M
    #3 0x580cb4 in print_varobj ../../binutils-gdb/gdb/mi/mi-cmd-var.c:61^M
    #4 0x58138b in mi_cmd_var_create(char*, char**, int) ../../binutils-gdb/gdb/mi/mi-cmd-var.c:145^M
    #5 0x5967ce in mi_cmd_execute ../../binutils-gdb/gdb/mi/mi-main.c:2301^M
    #6 0x594b05 in captured_mi_execute_command ../../binutils-gdb/gdb/mi/mi-main.c:2001
....
^M
^[[1m^[[32m0x6030000805c0 is located 0 bytes inside of 32-byte region [0x6030000805c0,0x6030000805e0)^M
^[[1m^[[0m^[[1m^[[35mallocated by thread T0 here:^[[1m^[[0m^M
    #0 0x7f2449b00602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)^M
    #1 0x7d1596 in xmalloc ../../binutils-gdb/gdb/common/common-utils.c:43^M
    #2 0x604176 in py_varobj_iter_new ../../binutils-gdb/gdb/python/py-varobj.c:159^M
    #3 0x6042da in py_varobj_get_iterator(varobj*, _object*) ../../binutils-gdb/gdb/python/py-varobj.c:198^M
    #4 0xbb5806 in varobj_get_iterator ../../binutils-gdb/gdb/varobj.c:720^M
    #5 0xbb5b9b in update_dynamic_varobj_children ../../binutils-gdb/gdb/varobj.c:758^M

gdb:

2017-02-23  Yao Qi  <yao.qi@linaro.org>

	* varobj-iter.h (varobj_iter_delete): Call xfree instead of
	delete.

diff --git a/gdb/varobj-iter.h b/gdb/varobj-iter.h
index 34182e0..7eed4f1 100644
--- a/gdb/varobj-iter.h
+++ b/gdb/varobj-iter.h
@@ -67,6 +67,6 @@ struct varobj_iter_ops
       if ((ITER) != NULL)		       \
 	{				       \
 	  (ITER)->ops->dtor (ITER);	       \
-	  delete (ITER);		       \
+	  xfree (ITER);		       \
 	}				       \
     } while (0)

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

* Re: [PATCH v2 28/31] Use ui_file_as_string throughout more
  2016-10-20 13:08 ` [PATCH v2 28/31] Use ui_file_as_string throughout more Pedro Alves
  2017-02-23 10:23   ` Yao Qi
@ 2017-02-23 10:35   ` Yao Qi
  1 sibling, 0 replies; 61+ messages in thread
From: Yao Qi @ 2017-02-23 10:35 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves <palves@redhat.com> writes:

> diff --git a/gdb/python/py-varobj.c b/gdb/python/py-varobj.c
> index 7e74454..a6b1968 100644
> --- a/gdb/python/py-varobj.c
> +++ b/gdb/python/py-varobj.c
> @@ -113,11 +113,11 @@ py_varobj_iter_next (struct varobj_iter *self)
>        error (_("Invalid item from the child list"));
>      }
>  
> -  vitem = XNEW (struct varobj_item);
> +  vitem = new varobj_item ();
>    vitem->value = convert_value_from_python (py_v);
>    if (vitem->value == NULL)
>      gdbpy_print_stack ();

We started to use new but still use xfree somewhere in the code.  This
patches change xfree to delete.  Patch below is obvious.  I'll push it
in.

-- 
Yao (齐尧)
From 8b4e5d54c9fee2b1d890a9937696297b5cd7ef5c Mon Sep 17 00:00:00 2001
From: Yao Qi <yao.qi@linaro.org>
Date: Thu, 23 Feb 2017 10:28:44 +0000
Subject: [PATCH] Use delete instead of xfree for varobj_item

In commit 2f408ec (Use ui_file_as_string throughout more), we start to
new varobj_item,

> -  vitem = XNEW (struct varobj_item);
> +  vitem = new varobj_item ();

but we still use xfree.  This causes some ASAN errors,

-var-update container^M
=================================================================^M
^[[1m^[[31m==20660==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new vs free) on 0x602000090c10^M
^[[1m^[[0m    #0 0x2baa77d03631 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x54631)^M
    #1 0x80e0c8 in xfree(void*) /home/yao/SourceCode/gnu/gdb/git/gdb/common/common-utils.c:100^M
    #2 0xc13670 in varobj_clear_saved_item /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:727^M
    #3 0xc13957 in update_dynamic_varobj_children /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:752^M
    #4 0xc1841c in varobj_update(varobj**, int) /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:1699^M
    #5 0x5a2bf7 in varobj_update_one /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-cmd-var.c:712^M
    #6 0x5a2a41 in mi_cmd_var_update(char*, char**, int) /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-cmd-var.c:695^
........
^M
^[[1m^[[32m0x602000090c10 is located 0 bytes inside of 16-byte region [0x602000090c10,0x602000090c20)^M
^[[1m^[[0m^[[1m^[[35mallocated by thread T0 here:^[[1m^[[0m^M
    #0 0x2baa77d0415f in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x5515f)^M
    #1 0x63613e in py_varobj_iter_next /home/yao/SourceCode/gnu/gdb/git/gdb/python/py-varobj.c:112^M
    #2 0xc13b89 in update_dynamic_varobj_children /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:776^M
    #3 0xc1841c in varobj_update(varobj**, int) /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:1699^M
    #4 0x5a2bf7 in varobj_update_one /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-cmd-var.c:712^M
    #5 0x5a2a41 in mi_cmd_var_update(char*, char**, int) /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-cmd-var.c:695^M

gdb:

2017-02-23  Yao Qi  <yao.qi@linaro.org>

	* varobj.c (varobj_clear_saved_item): Use delete instead of
	xfree.
	(update_dynamic_varobj_children): Likewise.

diff --git a/gdb/varobj.c b/gdb/varobj.c
index 4b12826..173abf3 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -724,7 +724,7 @@ varobj_clear_saved_item (struct varobj_dynamic *var)
   if (var->saved_item != NULL)
     {
       value_free (var->saved_item->value);
-      xfree (var->saved_item);
+      delete var->saved_item;
       var->saved_item = NULL;
     }
 }
@@ -799,7 +799,7 @@ update_dynamic_varobj_children (struct varobj *var,
 				 can_mention ? cchanged : NULL, i,
 				 item);
 
-	  xfree (item);
+	  delete item;
 	}
       else
 	{

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

* Re: [PATCH v2 28/31] Use ui_file_as_string throughout more
  2017-02-23 10:23   ` Yao Qi
@ 2017-02-23 10:53     ` Pedro Alves
  0 siblings, 0 replies; 61+ messages in thread
From: Pedro Alves @ 2017-02-23 10:53 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 02/23/2017 10:22 AM, Yao Qi wrote:

>>  
>>    /* Value of this item.  */
>>    struct value *value;
>> @@ -67,6 +67,6 @@ struct varobj_iter_ops
>>        if ((ITER) != NULL)		       \
>>  	{				       \
>>  	  (ITER)->ops->dtor (ITER);	       \
>> -	  xfree (ITER);		       \
>> +	  delete (ITER);		       \
> 
> We don't need to use "delete" for varobj_iter, because you didn't add
> std::string member in varobj_iter.  This change causes an ASAN error,

Whoops.

> reverting the change above fixes the error.  We can also C++-fy
> varobj_iter, but I'd like to do in another patch.  How is the patch below?

LGTM.

Thanks,
Pedro Alves

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

end of thread, other threads:[~2017-02-23 10:53 UTC | newest]

Thread overview: 61+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-19  1:13 [PATCH v2 00/31] More cleanup elimination & unlimited args to user-defined funcs Pedro Alves
2016-10-19  1:12 ` [PATCH v2 12/31] Use ui_file_as_string in gdb/utils.c Pedro Alves
2016-10-19  1:12 ` [PATCH v2 19/31] Use ui_file_as_string in gdb/remote.c Pedro Alves
2016-10-19  1:12 ` [PATCH v2 06/31] Introduce ui_file_as_string Pedro Alves
2016-10-19  1:12 ` [PATCH v2 24/31] Use ui_file_as_string in gdb/ada-lang.c Pedro Alves
2016-10-19  1:12 ` [PATCH v2 07/31] Clean up tracepoint.h/c:collection_list Pedro Alves
2016-10-19  1:12 ` [PATCH v2 20/31] Use ui_file_as_string in gdb/cli/cli-setshow.c Pedro Alves
2016-10-19  1:12 ` [PATCH v2 01/31] Introduce string_printf Pedro Alves
2016-10-19 13:43   ` Trevor Saunders
2016-10-19 14:41     ` Pedro Alves
2016-10-19 17:18   ` Simon Marchi
2016-10-19 21:02     ` Pedro Alves
2016-11-08 15:35       ` Pedro Alves
2016-10-19  1:12 ` [PATCH v2 21/31] Use ui_file_as_string in gdb/compile/ Pedro Alves
2016-10-19 23:08   ` Simon Marchi
2016-10-19 23:48     ` Pedro Alves
2016-10-20  3:17       ` Simon Marchi
2016-10-20 12:13         ` Pedro Alves
2016-10-19  1:12 ` [PATCH v2 22/31] Use ui_file_as_string in gdb/c-exp.y Pedro Alves
2016-10-19  1:13 ` [PATCH v2 08/31] Use ui_file_as_string in dwarf2_compute_name Pedro Alves
2016-10-19  1:13 ` [PATCH v2 31/31] Support an "unlimited" number of user-defined arguments Pedro Alves
2016-10-19  6:29   ` Eli Zaretskii
2016-10-19 11:33   ` Philipp Rudo
2016-10-19 12:47     ` Pedro Alves
2016-10-19 17:40       ` Philipp Rudo
2016-10-19 17:45         ` Pedro Alves
2016-11-08 15:41   ` Pedro Alves
2016-10-19  1:13 ` [PATCH v2 02/31] cli/cli-script.c: Remove some dead NULL checks Pedro Alves
2016-10-19 17:24   ` Simon Marchi
2016-10-19 21:18     ` Pedro Alves
2016-10-19  1:13 ` [PATCH v2 15/31] Use ui_file_as_string in execute_command_to_string Pedro Alves
2016-10-19  1:13 ` [PATCH v2 03/31] breakpoint.c:commands_command_1 constification and cleanup Pedro Alves
2016-10-19  1:13 ` [PATCH v2 14/31] Use ui_file_as_string in gdb/guile/ Pedro Alves
2016-10-19  1:13 ` [PATCH v2 27/31] Use ui_file_as_string in gdb/language.c Pedro Alves
2016-10-19  1:13 ` [PATCH v2 29/31] 'struct agent_expr *' -> unique_ptr<agent_expr> Pedro Alves
2016-10-19 23:19   ` Simon Marchi
2016-10-19 23:58     ` Pedro Alves
2016-10-19  1:13 ` [PATCH v2 23/31] Use ui_file_as_string in gdbarch.sh/gdbarch.c Pedro Alves
2016-10-19  1:13 ` [PATCH v2 26/31] Use ui_file_as_string in gdb/rust-lang.c Pedro Alves
2016-10-19  1:17 ` [PATCH v2 09/31] Use ui_file_as_string in gdb/xtensa-tdep.c Pedro Alves
2016-10-19  1:17 ` [PATCH v2 11/31] Use ui_file_as_string in gdb/ui-out.c Pedro Alves
2016-10-19  1:17 ` [PATCH v2 10/31] Use ui_file_as_string in gdb/ada-valprint.c Pedro Alves
2016-10-19  1:17 ` [PATCH v2 25/31] Use ui_file_as_string in gdb/infrun.c Pedro Alves
2016-10-19  1:18 ` [PATCH v2 30/31] Eliminate agent_expr_p; VEC -> std::vector in struct bp_target_info Pedro Alves
2016-10-19  1:18 ` [PATCH v2 05/31] 'struct expression *' -> gdb::unique_xmalloc_ptr<expression> Pedro Alves
2016-10-19 18:45   ` Simon Marchi
2016-10-19 21:50     ` Pedro Alves
2016-10-19 22:25       ` Simon Marchi
2016-10-19 22:36         ` Pedro Alves
2016-10-19  1:19 ` [PATCH v2 04/31] cli-script.c: Simplify using std::string, eliminate cleanups Pedro Alves
2016-10-19 18:25   ` Simon Marchi
2016-10-19 21:45     ` Pedro Alves
2016-10-19  1:21 ` [PATCH v2 17/31] Use ui_file_as_string in gdb/printcmd.c Pedro Alves
2016-10-19  1:21 ` [PATCH v2 16/31] Use ui_file_as_string in gdb/top.c Pedro Alves
2016-10-19  1:21 ` [PATCH v2 18/31] Use ui_file_as_string in gdb/python/ Pedro Alves
2016-10-19  1:21 ` [PATCH v2 13/31] Use ui_file_as_string in gdb/arm-tdep.c Pedro Alves
2016-10-19 22:54   ` Simon Marchi
2016-10-20 13:08 ` [PATCH v2 28/31] Use ui_file_as_string throughout more Pedro Alves
2017-02-23 10:23   ` Yao Qi
2017-02-23 10:53     ` Pedro Alves
2017-02-23 10:35   ` Yao Qi

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).