public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFA 15/22] Use std::string in macho_symfile_read_all_oso
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
@ 2016-09-27  4:41 ` Tom Tromey
  2016-10-09 17:28   ` Pedro Alves
  2016-09-27  4:41 ` [RFA 07/22] Change scoped_minimal_symbol_reader to store objfile Tom Tromey
                   ` (21 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:41 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes macho_symfile_read_all_oso to use std::string.  This
avoids a cleanup.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* machoread.c (macho_symfile_read_all_oso): Use std::string.
---
 gdb/ChangeLog   |  4 ++++
 gdb/machoread.c | 20 +++++++-------------
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 42101fc..3744387 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,9 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* machoread.c (macho_symfile_read_all_oso): Use std::string.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* cli/cli-dump.c (dump_memory_to_file): Use std::vector.
 	(restore_binary_file): Likewise.
 
diff --git a/gdb/machoread.c b/gdb/machoread.c
index df0333a..eefc1bb 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -33,6 +33,7 @@
 #include "psympriv.h"
 #include "complaints.h"
 #include "gdb_bfd.h"
+#include <string>
 
 /* If non-zero displays debugging message.  */
 static unsigned int mach_o_debug_level = 0;
@@ -636,7 +637,6 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
   int ix;
   VEC (oso_el) *vec = *oso_vector_ptr;
   oso_el *oso;
-  struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
 
   /* Sort oso by name so that files from libraries are gathered.  */
   qsort (VEC_address (oso_el, vec), VEC_length (oso_el, vec),
@@ -652,37 +652,33 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
 	{
 	  bfd *archive_bfd;
 	  bfd *member_bfd;
-	  char *archive_name = XNEWVEC (char, pfx_len + 1);
           int last_ix;
           oso_el *oso2;
           int ix2;
 
-	  memcpy (archive_name, oso->name, pfx_len);
-	  archive_name[pfx_len] = '\0';
-
-	  make_cleanup (xfree, archive_name);
+	  std::string archive_name (oso->name, pfx_len);
 
           /* Compute number of oso for this archive.  */
           for (last_ix = ix;
                VEC_iterate (oso_el, vec, last_ix, oso2); last_ix++)
             {
-              if (strncmp (oso2->name, archive_name, pfx_len) != 0)
+              if (strncmp (oso2->name, archive_name.c_str (), pfx_len) != 0)
                 break;
             }
 
 	  /* Open the archive and check the format.  */
-	  archive_bfd = gdb_bfd_open (archive_name, gnutarget, -1);
+	  archive_bfd = gdb_bfd_open (archive_name.c_str (), gnutarget, -1);
 	  if (archive_bfd == NULL)
 	    {
 	      warning (_("Could not open OSO archive file \"%s\""),
-		       archive_name);
+		       archive_name.c_str ());
               ix = last_ix;
 	      continue;
 	    }
 	  if (!bfd_check_format (archive_bfd, bfd_archive))
 	    {
 	      warning (_("OSO archive file \"%s\" not an archive."),
-		       archive_name);
+		       archive_name.c_str ());
 	      gdb_bfd_unref (archive_bfd);
               ix = last_ix;
 	      continue;
@@ -693,7 +689,7 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
 	  if (member_bfd == NULL)
 	    {
 	      warning (_("Could not read archive members out of "
-			 "OSO archive \"%s\""), archive_name);
+			 "OSO archive \"%s\""), archive_name.c_str ());
 	      gdb_bfd_unref (archive_bfd);
               ix = last_ix;
 	      continue;
@@ -757,8 +753,6 @@ macho_symfile_read_all_oso (VEC (oso_el) **oso_vector_ptr,
           ix++;
         }
     }
-
-  do_cleanups (cleanup);
 }
 
 /* DSYM (debug symbols) files contain the debug info of an executable.
-- 
2.7.4

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

* [RFA 07/22] Change scoped_minimal_symbol_reader to store objfile
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
  2016-09-27  4:41 ` [RFA 15/22] Use std::string in macho_symfile_read_all_oso Tom Tromey
@ 2016-09-27  4:41 ` Tom Tromey
  2016-09-29  9:19   ` Trevor Saunders
  2016-09-27  4:42 ` [RFA 19/22] Convert tid_range_parser to class Tom Tromey
                   ` (20 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:41 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes scoped_minimal_symbol_reader to require the objfile to be
passed to the constructor.  The class now records the objfile and
automatically uses it later in "install".

This is a minor cleanup that will come in useful in the next patch.
It is separate from the first patch to keep that one a bit simpler to
understand.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* xcoffread.c (xcoff_initial_scan): Update.
	* mipsread.c (mipscoff_symfile_read): Update.
	* minsyms.c (scoped_minimal_symbol_reader): Add obj argument.
	Initialize member.
	(install): Remove objfile argument.
	* mdebugread.c (elfmdebug_build_psymtabs): Update.
	* machoread.c (macho_symfile_read): Update.
	* elfread.c (elf_read_minimal_symbols): Update.
	* dbxread.c (dbx_symfile_read): Update.
	* coffread.c (coff_symfile_read): Update.
	* minsyms.h (scoped_minimal_symbol_reader): Add objfile member.
	(constructor): Add objfile argument.
	(scoped_minimal_symbol_reader::install): Remove objfile argument.
---
 gdb/ChangeLog    | 16 ++++++++++++++++
 gdb/coffread.c   |  4 ++--
 gdb/dbxread.c    |  4 ++--
 gdb/elfread.c    |  4 ++--
 gdb/machoread.c  |  4 ++--
 gdb/mdebugread.c |  4 ++--
 gdb/minsyms.c    |  5 +++--
 gdb/minsyms.h    |  6 ++++--
 gdb/mipsread.c   |  4 ++--
 gdb/xcoffread.c  |  4 ++--
 10 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 81aeec9..dac71f3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,21 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* xcoffread.c (xcoff_initial_scan): Update.
+	* mipsread.c (mipscoff_symfile_read): Update.
+	* minsyms.c (scoped_minimal_symbol_reader): Add obj argument.
+	Initialize member.
+	(install): Remove objfile argument.
+	* mdebugread.c (elfmdebug_build_psymtabs): Update.
+	* machoread.c (macho_symfile_read): Update.
+	* elfread.c (elf_read_minimal_symbols): Update.
+	* dbxread.c (dbx_symfile_read): Update.
+	* coffread.c (coff_symfile_read): Update.
+	* minsyms.h (scoped_minimal_symbol_reader): Add objfile member.
+	(constructor): Add objfile argument.
+	(scoped_minimal_symbol_reader::install): Remove objfile argument.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* xcoffread.c (xcoff_initial_scan): Use
 	scoped_minimal_symbol_reader.
 	* mipsread.c (mipscoff_symfile_read): Use
diff --git a/gdb/coffread.c b/gdb/coffread.c
index e504cde..a86f223 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -645,7 +645,7 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags)
   if (val < 0)
     error (_("\"%s\": can't get string table"), name);
 
-  scoped_minimal_symbol_reader reader;
+  scoped_minimal_symbol_reader reader (objfile);
 
   /* Now that the executable file is positioned at symbol table,
      process it and define symbols accordingly.  */
@@ -655,7 +655,7 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags)
   /* Install any minimal symbols that have been collected as the
      current minimal symbols for this objfile.  */
 
-  reader.install (objfile);
+  reader.install ();
 
   if (pe_file)
     {
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index a0e1cac..59c809a 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -558,7 +558,7 @@ dbx_symfile_read (struct objfile *objfile, int symfile_flags)
   free_pending_blocks ();
   back_to = make_cleanup (really_free_pendings, 0);
 
-  scoped_minimal_symbol_reader reader;
+  scoped_minimal_symbol_reader reader (objfile);
 
   /* Read stabs data from executable file and define symbols.  */
 
@@ -571,7 +571,7 @@ dbx_symfile_read (struct objfile *objfile, int symfile_flags)
   /* Install any minimal symbols that have been collected as the current
      minimal symbols for this objfile.  */
 
-  reader.install (objfile);
+  reader.install ();
 
   do_cleanups (back_to);
 }
diff --git a/gdb/elfread.c b/gdb/elfread.c
index e1ae92a..98574ca 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1049,7 +1049,7 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
       return;
     }
 
-  scoped_minimal_symbol_reader reader;
+  scoped_minimal_symbol_reader reader (objfile);
   back_to = make_cleanup (null_cleanup, NULL);
 
   /* Allocate struct to keep track of the symfile.  */
@@ -1149,7 +1149,7 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
      responsibility to install them.  "mdebug" appears to be the only one
      which will do this.  */
 
-  reader.install (objfile);
+  reader.install ();
   do_cleanups (back_to);
 
   if (symtab_create_debug)
diff --git a/gdb/machoread.c b/gdb/machoread.c
index 19a2f42..0eb438a 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -861,7 +861,7 @@ macho_symfile_read (struct objfile *objfile, int symfile_flags)
 	  symbol_table = (asymbol **) xmalloc (storage_needed);
 	  make_cleanup (xfree, symbol_table);
 
-          scoped_minimal_symbol_reader reader;
+          scoped_minimal_symbol_reader reader (objfile);
 
 	  symcount = bfd_canonicalize_symtab (objfile->obfd, symbol_table);
 
@@ -872,7 +872,7 @@ macho_symfile_read (struct objfile *objfile, int symfile_flags)
 
 	  macho_symtab_read (objfile, symcount, symbol_table, &oso_vector);
 
-          reader.install (objfile);
+          reader.install ();
 	}
 
       /* Try to read .eh_frame / .debug_frame.  */
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index d07e683..b93024b 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -4875,7 +4875,7 @@ elfmdebug_build_psymtabs (struct objfile *objfile,
      information from .mdebug in an ELF file, or whether we will.
      Re-initialize the minimal symbol reader in case we do.  */
 
-  scoped_minimal_symbol_reader reader;
+  scoped_minimal_symbol_reader reader (objfile);
 
   info = ((struct ecoff_debug_info *)
 	  obstack_alloc (&objfile->objfile_obstack,
@@ -4887,7 +4887,7 @@ elfmdebug_build_psymtabs (struct objfile *objfile,
 
   mdebug_build_psymtabs (objfile, swap, info);
 
-  reader.install (objfile);
+  reader.install ();
 }
 
 void
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 7b316ce..b6f306b 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -921,7 +921,8 @@ get_symbol_leading_char (bfd *abfd)
 
 /* See minsyms.h.  */
 
-scoped_minimal_symbol_reader::scoped_minimal_symbol_reader ()
+scoped_minimal_symbol_reader::scoped_minimal_symbol_reader (struct objfile *obj)
+: objfile (obj)
 {
   msym_count = 0;
   msym_bunch = NULL;
@@ -1232,7 +1233,7 @@ build_minimal_symbol_hash_tables (struct objfile *objfile)
    attempts to demangle them if we later add more minimal symbols.  */
 
 void
-scoped_minimal_symbol_reader::install (struct objfile *objfile)
+scoped_minimal_symbol_reader::install ()
 {
   int bindex;
   int mcount;
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index 5ea3610..7ba5991 100644
--- a/gdb/minsyms.h
+++ b/gdb/minsyms.h
@@ -64,14 +64,14 @@ class scoped_minimal_symbol_reader
      Currently, minimal symbol table creation is not reentrant; it
      relies on global (static) variables in minsyms.c.  */
 
-  explicit scoped_minimal_symbol_reader ();
+  explicit scoped_minimal_symbol_reader (struct objfile *);
 
   ~scoped_minimal_symbol_reader ();
 
   /* Install the minimal symbols that have been collected into the
      given objfile.  */
 
-  void install (struct objfile *);
+  void install ();
 
  private:
 
@@ -79,6 +79,8 @@ class scoped_minimal_symbol_reader
   scoped_minimal_symbol_reader &operator=
     (const scoped_minimal_symbol_reader &);
   scoped_minimal_symbol_reader (const scoped_minimal_symbol_reader &);
+
+  struct objfile *objfile;
 };
 
 /* Record a new minimal symbol.  This is the "full" entry point;
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
index da09c03..e5285d2 100644
--- a/gdb/mipsread.c
+++ b/gdb/mipsread.c
@@ -70,7 +70,7 @@ mipscoff_symfile_read (struct objfile *objfile, int symfile_flags)
 {
   bfd *abfd = objfile->obfd;
 
-  scoped_minimal_symbol_reader reader;
+  scoped_minimal_symbol_reader reader (objfile);
 
   /* Now that the executable file is positioned at symbol table,
      process it and define symbols accordingly.  */
@@ -89,7 +89,7 @@ mipscoff_symfile_read (struct objfile *objfile, int symfile_flags)
   /* Install any minimal symbols that have been collected as the current
      minimal symbols for this objfile.  */
 
-  reader.install (objfile);
+  reader.install ();
 }
 
 /* Perform any local cleanups required when we are done with a
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 81b323c..6545e94 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -3006,7 +3006,7 @@ xcoff_initial_scan (struct objfile *objfile, int symfile_flags)
   free_pending_blocks ();
   back_to = make_cleanup (really_free_pendings, 0);
 
-  scoped_minimal_symbol_reader reader;
+  scoped_minimal_symbol_reader reader (objfile);
 
   /* Now that the symbol table data of the executable file are all in core,
      process them and define symbols accordingly.  */
@@ -3016,7 +3016,7 @@ xcoff_initial_scan (struct objfile *objfile, int symfile_flags)
   /* Install any minimal symbols that have been collected as the current
      minimal symbols for this objfile.  */
 
-  reader.install (objfile);
+  reader.install ();
 
   /* DWARF2 sections.  */
 
-- 
2.7.4

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

* [RFA 16/22] Use std::vector in elf_read_minimal_symbols
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (2 preceding siblings ...)
  2016-09-27  4:42 ` [RFA 19/22] Convert tid_range_parser to class Tom Tromey
@ 2016-09-27  4:42 ` Tom Tromey
  2016-10-09 17:30   ` Pedro Alves
  2016-09-27  4:43 ` [RFA 20/22] Initial conversion of dwarf_expr_ctx Tom Tromey
                   ` (18 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:42 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes elf_read_minimal_symbols to use std::vector rather than
an explicit allocation.  This removes a cleanup.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* elfread.c (elf_read_minimal_symbols): Use std::vector.
---
 gdb/ChangeLog |  4 ++++
 gdb/elfread.c | 11 +++--------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3744387..770a96f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,9 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* elfread.c (elf_read_minimal_symbols): Use std::vector.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* machoread.c (macho_symfile_read_all_oso): Use std::string.
 
 2016-09-26  Tom Tromey  <tom@tromey.com>
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 09ac507..ad38bfe 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -47,6 +47,7 @@
 #include "build-id.h"
 #include "location.h"
 #include "auxv.h"
+#include <vector>
 
 extern void _initialize_elfread (void);
 
@@ -1024,7 +1025,6 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
 			  const struct elfinfo *ei)
 {
   bfd *synth_abfd, *abfd = objfile->obfd;
-  struct cleanup *back_to;
   long symcount = 0, dynsymcount = 0, synthcount, storage_needed;
   asymbol **symbol_table = NULL, **dyn_symbol_table = NULL;
   asymbol *synthsyms;
@@ -1053,7 +1053,6 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
     }
 
   scoped_minimal_symbol_reader reader (objfile);
-  back_to = make_cleanup (null_cleanup, NULL);
 
   /* Allocate struct to keep track of the symfile.  */
   dbx = XCNEW (struct dbx_symfile_info);
@@ -1135,16 +1134,13 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
 					 &synthsyms);
   if (synthcount > 0)
     {
-      asymbol **synth_symbol_table;
       long i;
 
-      make_cleanup (xfree, synthsyms);
-      synth_symbol_table = XNEWVEC (asymbol *, synthcount);
+      std::vector<asymbol *> synth_symbol_table (synthcount);
       for (i = 0; i < synthcount; i++)
 	synth_symbol_table[i] = synthsyms + i;
-      make_cleanup (xfree, synth_symbol_table);
       elf_symtab_read (reader, objfile, ST_SYNTHETIC, synthcount,
-		       synth_symbol_table, 1);
+		       synth_symbol_table.data (), 1);
     }
 
   /* Install any minimal symbols that have been collected as the current
@@ -1154,7 +1150,6 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
      which will do this.  */
 
   reader.install ();
-  do_cleanups (back_to);
 
   if (symtab_create_debug)
     fprintf_unfiltered (gdb_stdlog, "Done reading minimal symbols.\n");
-- 
2.7.4

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

* [RFA 19/22] Convert tid_range_parser to class
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
  2016-09-27  4:41 ` [RFA 15/22] Use std::string in macho_symfile_read_all_oso Tom Tromey
  2016-09-27  4:41 ` [RFA 07/22] Change scoped_minimal_symbol_reader to store objfile Tom Tromey
@ 2016-09-27  4:42 ` Tom Tromey
  2016-09-30  1:41   ` Pedro Alves
  2016-09-27  4:42 ` [RFA 16/22] Use std::vector in elf_read_minimal_symbols Tom Tromey
                   ` (19 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:42 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This converts tid_range_parser to be a class, and converts various
tid_range_parser_* functions to be methods on this class; then it
updates the users to follow.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* tid-parse.h (tid_range_parser): New class.
	(tid_range_parser_get_tid, tid_range_parser_get_tid_range)
	(tid_range_parser_star_range, tid_range_parser_finished)
	(tid_range_parser_skip, tid_range_parser_qualified): Don't
	declare.
	* tid-parse.c (init, finished, get_string, skip, is_qualified)
	(get_tid_or_range, get_tid_range, get_tid, star_range): Rename;
	turn into methods.
	(tid_is_in_list): Update.
	* thread.c (thread_apply_command): Update.
---
 gdb/ChangeLog   |  13 +++++
 gdb/thread.c    |  26 ++++-----
 gdb/tid-parse.c | 128 ++++++++++++++++++++----------------------
 gdb/tid-parse.h | 169 +++++++++++++++++++++++++++++---------------------------
 4 files changed, 173 insertions(+), 163 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1e2fc29..bae4443 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,18 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* tid-parse.h (tid_range_parser): New class.
+	(tid_range_parser_get_tid, tid_range_parser_get_tid_range)
+	(tid_range_parser_star_range, tid_range_parser_finished)
+	(tid_range_parser_skip, tid_range_parser_qualified): Don't
+	declare.
+	* tid-parse.c (init, finished, get_string, skip, is_qualified)
+	(get_tid_or_range, get_tid_range, get_tid, star_range): Rename;
+	turn into methods.
+	(tid_is_in_list): Update.
+	* thread.c (thread_apply_command): Update.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* dwarf2loc.c: Include <vector>.
 	(read_pieced_value, write_pieced_value)
 	(dwarf2_compile_expr_to_ax): Use std::vector.
diff --git a/gdb/thread.c b/gdb/thread.c
index a66a2b5..718c567 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1825,20 +1825,18 @@ thread_apply_command (char *tidlist, int from_tty)
   char *cmd = NULL;
   struct cleanup *old_chain;
   char *saved_cmd;
-  struct tid_range_parser parser;
 
   if (tidlist == NULL || *tidlist == '\000')
     error (_("Please specify a thread ID list"));
 
-  tid_range_parser_init (&parser, tidlist, current_inferior ()->num);
-  while (!tid_range_parser_finished (&parser))
+  tid_range_parser parser (tidlist, current_inferior ()->num);
+  while (!parser.finished ())
     {
       int inf_num, thr_start, thr_end;
 
-      if (!tid_range_parser_get_tid_range (&parser,
-					   &inf_num, &thr_start, &thr_end))
+      if (!parser.get_tid_range (&inf_num, &thr_start, &thr_end))
 	{
-	  cmd = (char *) tid_range_parser_string (&parser);
+	  cmd = (char *) parser.get_string ();
 	  break;
 	}
     }
@@ -1856,32 +1854,31 @@ thread_apply_command (char *tidlist, int from_tty)
 
   make_cleanup_restore_current_thread ();
 
-  tid_range_parser_init (&parser, tidlist, current_inferior ()->num);
-  while (!tid_range_parser_finished (&parser)
-	 && tid_range_parser_string (&parser) < cmd)
+  parser.init (tidlist, current_inferior ()->num);
+  while (!parser.finished () && parser.get_string () < cmd)
     {
       struct thread_info *tp = NULL;
       struct inferior *inf;
       int inf_num, thr_num;
 
-      tid_range_parser_get_tid (&parser, &inf_num, &thr_num);
+      parser.get_tid (&inf_num, &thr_num);
       inf = find_inferior_id (inf_num);
       if (inf != NULL)
 	tp = find_thread_id (inf, thr_num);
 
-      if (tid_range_parser_star_range (&parser))
+      if (parser.star_range ())
 	{
 	  if (inf == NULL)
 	    {
 	      warning (_("Unknown inferior %d"), inf_num);
-	      tid_range_parser_skip (&parser);
+	      parser.skip ();
 	      continue;
 	    }
 
 	  /* No use looking for threads past the highest thread number
 	     the inferior ever had.  */
 	  if (thr_num >= inf->highest_thread_num)
-	    tid_range_parser_skip (&parser);
+	    parser.skip ();
 
 	  /* Be quiet about unknown threads numbers.  */
 	  if (tp == NULL)
@@ -1890,8 +1887,7 @@ thread_apply_command (char *tidlist, int from_tty)
 
       if (tp == NULL)
 	{
-	  if (show_inferior_qualified_tids ()
-	      || tid_range_parser_qualified (&parser))
+	  if (show_inferior_qualified_tids () || parser.is_qualified ())
 	    warning (_("Unknown thread %d.%d"), inf_num, thr_num);
 	  else
 	    warning (_("Unknown thread %d"), thr_num);
diff --git a/gdb/tid-parse.c b/gdb/tid-parse.c
index 68133c6..0e775bc 100644
--- a/gdb/tid-parse.c
+++ b/gdb/tid-parse.c
@@ -114,28 +114,27 @@ parse_thread_id (const char *tidstr, const char **end)
 /* See tid-parse.h.  */
 
 void
-tid_range_parser_init (struct tid_range_parser *parser, const char *tidlist,
-		       int default_inferior)
+tid_range_parser::init (const char *tidlist, int default_inferior)
 {
-  parser->state = TID_RANGE_STATE_INFERIOR;
-  parser->string = tidlist;
-  parser->inf_num = 0;
-  parser->qualified = 0;
-  parser->default_inferior = default_inferior;
+  this->state = TID_RANGE_STATE_INFERIOR;
+  this->string = tidlist;
+  this->inf_num = 0;
+  this->qualified = 0;
+  this->default_inferior = default_inferior;
 }
 
 /* See tid-parse.h.  */
 
 int
-tid_range_parser_finished (struct tid_range_parser *parser)
+tid_range_parser::finished () const
 {
-  switch (parser->state)
+  switch (this->state)
     {
     case TID_RANGE_STATE_INFERIOR:
-      return *parser->string == '\0';
+      return *this->string == '\0';
     case TID_RANGE_STATE_THREAD_RANGE:
     case TID_RANGE_STATE_STAR_RANGE:
-      return parser->range_parser.finished;
+      return this->range_parser.finished;
     }
 
   gdb_assert_not_reached (_("unhandled state"));
@@ -144,15 +143,15 @@ tid_range_parser_finished (struct tid_range_parser *parser)
 /* See tid-parse.h.  */
 
 const char *
-tid_range_parser_string (struct tid_range_parser *parser)
+tid_range_parser::get_string () const
 {
-  switch (parser->state)
+  switch (this->state)
     {
     case TID_RANGE_STATE_INFERIOR:
-      return parser->string;
+      return this->string;
     case TID_RANGE_STATE_THREAD_RANGE:
     case TID_RANGE_STATE_STAR_RANGE:
-      return parser->range_parser.string;
+      return this->range_parser.string;
     }
 
   gdb_assert_not_reached (_("unhandled state"));
@@ -161,40 +160,38 @@ tid_range_parser_string (struct tid_range_parser *parser)
 /* See tid-parse.h.  */
 
 void
-tid_range_parser_skip (struct tid_range_parser *parser)
+tid_range_parser::skip ()
 {
-  gdb_assert ((parser->state == TID_RANGE_STATE_THREAD_RANGE
-	       || parser->state == TID_RANGE_STATE_STAR_RANGE)
-	      && parser->range_parser.in_range);
+  gdb_assert ((this->state == TID_RANGE_STATE_THREAD_RANGE
+	       || this->state == TID_RANGE_STATE_STAR_RANGE)
+	      && this->range_parser.in_range);
 
-  tid_range_parser_init (parser, parser->range_parser.end_ptr,
-			 parser->default_inferior);
+  init (this->range_parser.end_ptr, this->default_inferior);
 }
 
 /* See tid-parse.h.  */
 
 int
-tid_range_parser_qualified (struct tid_range_parser *parser)
+tid_range_parser::is_qualified () const
 {
-  return parser->qualified;
+  return this->qualified;
 }
 
 /* Helper for tid_range_parser_get_tid and
    tid_range_parser_get_tid_range.  Return the next range if THR_END
    is non-NULL, return a single thread ID otherwise.  */
 
-static int
-get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
-		  int *thr_start, int *thr_end)
+int
+tid_range_parser::get_tid_or_range (int *inf_num, int *thr_start, int *thr_end)
 {
-  if (parser->state == TID_RANGE_STATE_INFERIOR)
+  if (this->state == TID_RANGE_STATE_INFERIOR)
     {
       const char *p;
       const char *space;
 
-      space = skip_to_space (parser->string);
+      space = skip_to_space (this->string);
 
-      p = parser->string;
+      p = this->string;
       while (p < space && *p != '.')
 	p++;
       if (p < space)
@@ -202,13 +199,13 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
 	  const char *dot = p;
 
 	  /* Parse number to the left of the dot.  */
-	  p = parser->string;
-	  parser->inf_num
-	    = get_positive_number_trailer (&p, '.', parser->string);
-	  if (parser->inf_num == 0)
+	  p = this->string;
+	  this->inf_num
+	    = get_positive_number_trailer (&p, '.', this->string);
+	  if (this->inf_num == 0)
 	    return 0;
 
-	  parser->qualified = 1;
+	  this->qualified = 1;
 	  p = dot + 1;
 
 	  if (isspace (*p))
@@ -216,42 +213,42 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
 	}
       else
 	{
-	  parser->inf_num = parser->default_inferior;
-	  parser->qualified = 0;
-	  p = parser->string;
+	  this->inf_num = this->default_inferior;
+	  this->qualified = 0;
+	  p = this->string;
 	}
 
-      init_number_or_range (&parser->range_parser, p);
+      init_number_or_range (&this->range_parser, p);
       if (p[0] == '*' && (p[1] == '\0' || isspace (p[1])))
 	{
 	  /* Setup the number range parser to return numbers in the
 	     whole [1,INT_MAX] range.  */
-	  number_range_setup_range (&parser->range_parser, 1, INT_MAX,
+	  number_range_setup_range (&this->range_parser, 1, INT_MAX,
 				    skip_spaces_const (p + 1));
-	  parser->state = TID_RANGE_STATE_STAR_RANGE;
+	  this->state = TID_RANGE_STATE_STAR_RANGE;
 	}
       else
-	parser->state = TID_RANGE_STATE_THREAD_RANGE;
+	this->state = TID_RANGE_STATE_THREAD_RANGE;
     }
 
-  *inf_num = parser->inf_num;
-  *thr_start = get_number_or_range (&parser->range_parser);
+  *inf_num = this->inf_num;
+  *thr_start = get_number_or_range (&this->range_parser);
   if (*thr_start < 0)
-    error (_("negative value: %s"), parser->string);
+    error (_("negative value: %s"), this->string);
   if (*thr_start == 0)
     {
-      parser->state = TID_RANGE_STATE_INFERIOR;
+      this->state = TID_RANGE_STATE_INFERIOR;
       return 0;
     }
 
   /* If we successfully parsed a thread number or finished parsing a
      thread range, switch back to assuming the next TID is
      inferior-qualified.  */
-  if (parser->range_parser.end_ptr == NULL
-      || parser->range_parser.string == parser->range_parser.end_ptr)
+  if (this->range_parser.end_ptr == NULL
+      || this->range_parser.string == this->range_parser.end_ptr)
     {
-      parser->state = TID_RANGE_STATE_INFERIOR;
-      parser->string = parser->range_parser.string;
+      this->state = TID_RANGE_STATE_INFERIOR;
+      this->string = this->range_parser.string;
 
       if (thr_end != NULL)
 	*thr_end = *thr_start;
@@ -260,11 +257,11 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
   /* If we're midway through a range, and the caller wants the end
      value, return it and skip to the end of the range.  */
   if (thr_end != NULL
-      && (parser->state == TID_RANGE_STATE_THREAD_RANGE
-	  || parser->state == TID_RANGE_STATE_STAR_RANGE))
+      && (this->state == TID_RANGE_STATE_THREAD_RANGE
+	  || this->state == TID_RANGE_STATE_STAR_RANGE))
     {
-      *thr_end = parser->range_parser.end_value;
-      tid_range_parser_skip (parser);
+      *thr_end = this->range_parser.end_value;
+      skip ();
     }
 
   return (*inf_num != 0 && *thr_start != 0);
@@ -273,31 +270,29 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
 /* See tid-parse.h.  */
 
 int
-tid_range_parser_get_tid_range (struct tid_range_parser *parser, int *inf_num,
-				int *thr_start, int *thr_end)
+tid_range_parser::get_tid_range (int *inf_num, int *thr_start, int *thr_end)
 {
   gdb_assert (inf_num != NULL && thr_start != NULL && thr_end != NULL);
 
-  return get_tid_or_range (parser, inf_num, thr_start, thr_end);
+  return get_tid_or_range (inf_num, thr_start, thr_end);
 }
 
 /* See tid-parse.h.  */
 
 int
-tid_range_parser_get_tid (struct tid_range_parser *parser,
-			  int *inf_num, int *thr_num)
+tid_range_parser::get_tid (int *inf_num, int *thr_num)
 {
   gdb_assert (inf_num != NULL && thr_num != NULL);
 
-  return get_tid_or_range (parser, inf_num, thr_num, NULL);
+  return get_tid_or_range (inf_num, thr_num, NULL);
 }
 
 /* See tid-parse.h.  */
 
 int
-tid_range_parser_star_range (struct tid_range_parser *parser)
+tid_range_parser::star_range ()
 {
-  return parser->state == TID_RANGE_STATE_STAR_RANGE;
+  return this->state == TID_RANGE_STATE_STAR_RANGE;
 }
 
 /* See gdbthread.h.  */
@@ -306,19 +301,16 @@ int
 tid_is_in_list (const char *list, int default_inferior,
 		int inf_num, int thr_num)
 {
-  struct tid_range_parser parser;
-
   if (list == NULL || *list == '\0')
     return 1;
 
-  tid_range_parser_init (&parser, list, default_inferior);
-  while (!tid_range_parser_finished (&parser))
+  tid_range_parser parser (list, default_inferior);
+  while (!parser.finished ())
     {
       int tmp_inf, tmp_thr_start, tmp_thr_end;
 
-      if (!tid_range_parser_get_tid_range (&parser, &tmp_inf,
-					   &tmp_thr_start, &tmp_thr_end))
-	invalid_thread_id_error (parser.string);
+      if (!parser.get_tid_range (&tmp_inf, &tmp_thr_start, &tmp_thr_end))
+	invalid_thread_id_error (parser.get_string ());
       if (tmp_inf == inf_num
 	  && tmp_thr_start <= thr_num && thr_num <= tmp_thr_end)
 	return 1;
diff --git a/gdb/tid-parse.h b/gdb/tid-parse.h
index 830cf36..e02dc16 100644
--- a/gdb/tid-parse.h
+++ b/gdb/tid-parse.h
@@ -49,119 +49,128 @@ enum tid_range_state
   TID_RANGE_STATE_STAR_RANGE,
 };
 
-/* An object of this type is passed to tid_range_parser_get_tid.  It
-   must be initialized by calling tid_range_parser_init.  This type is
-   defined here so that it can be stack-allocated, but all members
-   should be treated as opaque.  */
-struct tid_range_parser
+/* An object of this type is passed to tid_range_parser_get_tid.  */
+class tid_range_parser
 {
-  /* What sub-component are we expecting.  */
-  enum tid_range_state state;
-
-  /* The string being parsed.  When parsing has finished, this points
-     past the last parsed token.  */
-  const char *string;
-
-  /* The range parser state when we're parsing the thread number
-     sub-component.  */
-  struct get_number_or_range_state range_parser;
-
-  /* Last inferior number returned.  */
-  int inf_num;
-
-  /* True if the TID last parsed was explicitly inferior-qualified.
-     IOW, whether the spec specified an inferior number
-     explicitly.  */
-  int qualified;
+ public:
 
-  /* The inferior number to assume if the TID is not qualified.  */
-  int default_inferior;
-};
+  /* Initialize a tid_range_parser for use with get_tid.  TIDLIST is
+     the string to be parsed.  DEFAULT_INFERIOR is the inferior number
+     to assume if a non-qualified thread ID is found.  */
+  tid_range_parser (const char *tidlist, int default_inferior)
+  {
+    init (tidlist, default_inferior);
+  }
 
-/* Initialize a tid_range_parser for use with
-   tid_range_parser_get_tid.  TIDLIST is the string to be parsed.
-   DEFAULT_INFERIOR is the inferior number to assume if a
-   non-qualified thread ID is found.  */
-extern void tid_range_parser_init (struct tid_range_parser *parser,
-				   const char *tidlist,
-				   int default_inferior);
+  /* Initialize a tid_range_parser for use with get_tid.  TIDLIST is
+     the string to be parsed.  DEFAULT_INFERIOR is the inferior number
+     to assume if a non-qualified thread ID is found.  */
+  void init (const char *tidlist, int default_inferior);
 
-/* Parse a thread ID or a thread range list.
+  /* Parse a thread ID or a thread range list.
 
-   A range will be of the form
+     A range will be of the form
 
      <inferior_num>.<thread_number1>-<thread_number2>
 
-   and will represent all the threads of inferior INFERIOR_NUM with
-   number between THREAD_NUMBER1 and THREAD_NUMBER2, inclusive.
-   <inferior_num> can also be omitted, as in
+     and will represent all the threads of inferior INFERIOR_NUM with
+     number between THREAD_NUMBER1 and THREAD_NUMBER2, inclusive.
+     <inferior_num> can also be omitted, as in
 
      <thread_number1>-<thread_number2>
 
-   in which case GDB infers the inferior number from the default
-   passed to the tid_range_parser_init function.
+     in which case GDB infers the inferior number from the default
+     passed to the constructor.
 
-   This function is designed to be called iteratively.  While
-   processing a thread ID range list, at each call it will return (in
-   the INF_NUM and THR_NUM output parameters) the next thread ID in
-   the range (irrespective of whether the thread actually exists).
+     This function is designed to be called iteratively.  While
+     processing a thread ID range list, at each call it will return (in
+     the INF_NUM and THR_NUM output parameters) the next thread ID in
+     the range (irrespective of whether the thread actually exists).
 
-   At the beginning of parsing a thread range, the char pointer
-   PARSER->string will be advanced past <thread_number1> and left
-   pointing at the '-' token.  Subsequent calls will not advance the
-   pointer until the range is completed.  The call that completes the
-   range will advance the pointer past <thread_number2>.
+     At the beginning of parsing a thread range, the char pointer
+     THIS->string will be advanced past <thread_number1> and left
+     pointing at the '-' token.  Subsequent calls will not advance the
+     pointer until the range is completed.  The call that completes the
+     range will advance the pointer past <thread_number2>.
 
-   This function advances through the input string for as long you
-   call it.  Once the end of the input string is reached, a call to
-   tid_range_parser_finished returns false (see below).
+     This function advances through the input string for as long you
+     call it.  Once the end of the input string is reached, a call to
+     finished returns false (see below).
 
-   E.g., with list: "1.2 3.4-6":
+     E.g., with list: "1.2 3.4-6":
 
      1st call: *INF_NUM=1; *THR_NUM=2 (finished==0)
      2nd call: *INF_NUM=3; *THR_NUM=4 (finished==0)
      3rd call: *INF_NUM=3; *THR_NUM=5 (finished==0)
      4th call: *INF_NUM=3; *THR_NUM=6 (finished==1)
 
-   Returns true if parsed a thread/range successfully, false
-   otherwise.  */
-extern int tid_range_parser_get_tid (struct tid_range_parser *parser,
-				      int *inf_num, int *thr_num);
+     Returns true if parsed a thread/range successfully, false
+     otherwise.  */
+  int get_tid (int *inf_num, int *thr_num);
 
-/* Like tid_range_parser_get_tid, but return a thread ID range per
-   call, rather then a single thread ID.
+  /* Like get_tid, but return a thread ID range per
+     call, rather then a single thread ID.
 
-   If the next element in the list is a single thread ID, then
-   *THR_START and *THR_END are set to the same value.
+     If the next element in the list is a single thread ID, then
+     *THR_START and *THR_END are set to the same value.
 
-   E.g.,. with list: "1.2 3.4-6"
+     E.g.,. with list: "1.2 3.4-6"
 
      1st call: *INF_NUM=1; *THR_START=2; *THR_END=2 (finished==0)
      2nd call: *INF_NUM=3; *THR_START=4; *THR_END=6 (finished==1)
 
-   Returns true if parsed a thread/range successfully, false
-   otherwise.  */
-extern int tid_range_parser_get_tid_range (struct tid_range_parser *parser,
-					   int *inf_num,
-					   int *thr_start, int *thr_end);
+     Returns true if parsed a thread/range successfully, false
+     otherwise.  */
+  int get_tid_range (int *inf_num, int *thr_start, int *thr_end);
+
+  /* Returns non-zero if processing a star wildcard (e.g., "1.*")
+     range.  */
+  int star_range ();
+
+  /* Returns non-zero if parsing has completed.  */
+  int finished () const;
+
+  /* Return the string being parsed.  When parsing has finished, this
+     points past the last parsed token.  */
+  const char *get_string () const;
 
-/* Returns non-zero if processing a star wildcard (e.g., "1.*")
-   range.  */
-extern int tid_range_parser_star_range (struct tid_range_parser *parser);
+  /* When parsing a range, advance past the final token in the range.  */
+  void skip ();
 
-/* Returns non-zero if parsing has completed.  */
-extern int tid_range_parser_finished (struct tid_range_parser *parser);
+  /* True if the TID last parsed was explicitly inferior-qualified.
+     IOW, whether the spec specified an inferior number explicitly.  */
+  int is_qualified () const;
+
+ private:
+
+  // No need for these.  They are intentionally not defined anywhere.
+  tid_range_parser &operator= (const tid_range_parser &);
+  tid_range_parser (const tid_range_parser &);
+
+  int get_tid_or_range (int *inf_num, int *thr_start, int *thr_end);
+
+  /* What sub-component are we expecting.  */
+  enum tid_range_state state;
+
+  /* The string being parsed.  When parsing has finished, this points
+     past the last parsed token.  */
+  const char *string;
+
+  /* The range parser state when we're parsing the thread number
+     sub-component.  */
+  struct get_number_or_range_state range_parser;
 
-/* Return the string being parsed.  When parsing has finished, this
-   points past the last parsed token.  */
-const char *tid_range_parser_string (struct tid_range_parser *parser);
+  /* Last inferior number returned.  */
+  int inf_num;
 
-/* When parsing a range, advance past the final token in the range.  */
-extern void tid_range_parser_skip (struct tid_range_parser *parser);
+  /* True if the TID last parsed was explicitly inferior-qualified.
+     IOW, whether the spec specified an inferior number
+     explicitly.  */
+  int qualified;
 
-/* True if the TID last parsed was explicitly inferior-qualified.
-   IOW, whether the spec specified an inferior number explicitly.  */
-extern int tid_range_parser_qualified (struct tid_range_parser *parser);
+  /* The inferior number to assume if the TID is not qualified.  */
+  int default_inferior;
+};
 
 /* Accept a string-form list of thread IDs such as is accepted by
    tid_range_parser_get_tid.  Return true if the INF_NUM.THR.NUM
-- 
2.7.4

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

* [RFA 20/22] Initial conversion of dwarf_expr_ctx
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (3 preceding siblings ...)
  2016-09-27  4:42 ` [RFA 16/22] Use std::vector in elf_read_minimal_symbols Tom Tromey
@ 2016-09-27  4:43 ` Tom Tromey
  2016-10-09 17:40   ` Pedro Alves
  2016-09-27  4:45 ` [RFA 21/22] Convert DWARF expr functions to methods Tom Tromey
                   ` (17 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:43 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This is the first step in the conversion of dwarf_expr_ctx to a C++
class.  This conversion is done in steps to make the patches, and the
reviews, a bit simpler.  This patch changes dwarf_expr_ctx to be
stack-allocated and removes the assocatied cleanup.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Stack-allocate
	dwarf_expr_context.  Remove cleanups.
	(dwarf2_locexpr_baton_eval)
	(dwarf2_loc_desc_get_symbol_read_needs):  Likewise.
	* dwarf2expr.h (dwarf_expr_context, ~dwarf_expr_context): Add
	constructors and destructors.
	(new_dwarf_expr_context, free_dwarf_expr_context)
	(make_cleanup_free_dwarf_expr_context): Don't declare.
	* dwarf2-frame.c (execute_stack_op): Stack-allocate
	dwarf_expr_context.  Remove cleanups.
	(dwarf_expr_context): Rename from new_dwarf_expr_context.  Turn
	into constructor.
	(free_dwarf_expr_context, free_dwarf_expr_context_cleanup):
	Remove.
	(~dwarf_expr_context): Rename from
	make_cleanup_free_dwarf_expr_context.  Turn into destructor.
---
 gdb/ChangeLog      |  19 +++++++++
 gdb/dwarf2-frame.c |  30 +++++++-------
 gdb/dwarf2expr.c   |  55 ++++++++++---------------
 gdb/dwarf2expr.h   |   8 ++--
 gdb/dwarf2loc.c    | 115 ++++++++++++++++++++++++-----------------------------
 5 files changed, 110 insertions(+), 117 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index bae4443..e7de300 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,24 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Stack-allocate
+	dwarf_expr_context.  Remove cleanups.
+	(dwarf2_locexpr_baton_eval)
+	(dwarf2_loc_desc_get_symbol_read_needs):  Likewise.
+	* dwarf2expr.h (dwarf_expr_context, ~dwarf_expr_context): Add
+	constructors and destructors.
+	(new_dwarf_expr_context, free_dwarf_expr_context)
+	(make_cleanup_free_dwarf_expr_context): Don't declare.
+	* dwarf2-frame.c (execute_stack_op): Stack-allocate
+	dwarf_expr_context.  Remove cleanups.
+	(dwarf_expr_context): Rename from new_dwarf_expr_context.  Turn
+	into constructor.
+	(free_dwarf_expr_context, free_dwarf_expr_context_cleanup):
+	Remove.
+	(~dwarf_expr_context): Rename from
+	make_cleanup_free_dwarf_expr_context.  Turn into destructor.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* tid-parse.h (tid_range_parser): New class.
 	(tid_range_parser_get_tid, tid_range_parser_get_tid_range)
 	(tid_range_parser_star_range, tid_range_parser_finished)
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 11258ea..48963de 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -369,29 +369,27 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
 		  CORE_ADDR offset, struct frame_info *this_frame,
 		  CORE_ADDR initial, int initial_in_stack_memory)
 {
-  struct dwarf_expr_context *ctx;
   CORE_ADDR result;
   struct cleanup *old_chain;
 
-  ctx = new_dwarf_expr_context ();
-  old_chain = make_cleanup_free_dwarf_expr_context (ctx);
-  make_cleanup_value_free_to_mark (value_mark ());
+  dwarf_expr_context ctx;
+  old_chain = make_cleanup_value_free_to_mark (value_mark ());
 
-  ctx->gdbarch = get_frame_arch (this_frame);
-  ctx->addr_size = addr_size;
-  ctx->ref_addr_size = -1;
-  ctx->offset = offset;
-  ctx->baton = this_frame;
-  ctx->funcs = &dwarf2_frame_ctx_funcs;
+  ctx.gdbarch = get_frame_arch (this_frame);
+  ctx.addr_size = addr_size;
+  ctx.ref_addr_size = -1;
+  ctx.offset = offset;
+  ctx.baton = this_frame;
+  ctx.funcs = &dwarf2_frame_ctx_funcs;
 
-  dwarf_expr_push_address (ctx, initial, initial_in_stack_memory);
-  dwarf_expr_eval (ctx, exp, len);
+  dwarf_expr_push_address (&ctx, initial, initial_in_stack_memory);
+  dwarf_expr_eval (&ctx, exp, len);
 
-  if (ctx->location == DWARF_VALUE_MEMORY)
-    result = dwarf_expr_fetch_address (ctx, 0);
-  else if (ctx->location == DWARF_VALUE_REGISTER)
+  if (ctx.location == DWARF_VALUE_MEMORY)
+    result = dwarf_expr_fetch_address (&ctx, 0);
+  else if (ctx.location == DWARF_VALUE_REGISTER)
     result = read_addr_from_reg (this_frame,
-				 value_as_long (dwarf_expr_fetch (ctx, 0)));
+				 value_as_long (dwarf_expr_fetch (&ctx, 0)));
   else
     {
       /* This is actually invalid DWARF, but if we ever do run across
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index 7eb1982..a965987 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -91,45 +91,32 @@ dwarf_expr_address_type (struct dwarf_expr_context *ctx)
 
 /* Create a new context for the expression evaluator.  */
 
-struct dwarf_expr_context *
-new_dwarf_expr_context (void)
+dwarf_expr_context::dwarf_expr_context ()
+: stack (nullptr),
+  stack_len (0),
+  stack_allocated (10),
+  gdbarch (nullptr),
+  addr_size (0),
+  ref_addr_size (0),
+  offset (0),
+  recursion_depth (0),
+  max_recursion_depth (0x100),
+  location (DWARF_VALUE_MEMORY),
+  len (0),
+  data (nullptr),
+  initialized (0),
+  num_pieces (0),
+  pieces (nullptr)
 {
-  struct dwarf_expr_context *retval;
-
-  retval = XCNEW (struct dwarf_expr_context);
-  retval->stack_len = 0;
-  retval->stack_allocated = 10;
-  retval->stack = XNEWVEC (struct dwarf_stack_value, retval->stack_allocated);
-  retval->num_pieces = 0;
-  retval->pieces = 0;
-  retval->max_recursion_depth = 0x100;
-  return retval;
+  this->stack = XNEWVEC (struct dwarf_stack_value, this->stack_allocated);
 }
 
-/* Release the memory allocated to CTX.  */
+/* Clean up a dwarf_expr_context.  */
 
-void
-free_dwarf_expr_context (struct dwarf_expr_context *ctx)
-{
-  xfree (ctx->stack);
-  xfree (ctx->pieces);
-  xfree (ctx);
-}
-
-/* Helper for make_cleanup_free_dwarf_expr_context.  */
-
-static void
-free_dwarf_expr_context_cleanup (void *arg)
-{
-  free_dwarf_expr_context ((struct dwarf_expr_context *) arg);
-}
-
-/* Return a cleanup that calls free_dwarf_expr_context.  */
-
-struct cleanup *
-make_cleanup_free_dwarf_expr_context (struct dwarf_expr_context *ctx)
+dwarf_expr_context::~dwarf_expr_context ()
 {
-  return make_cleanup (free_dwarf_expr_context_cleanup, ctx);
+  xfree (this->stack);
+  xfree (this->pieces);
 }
 
 /* Expand the memory allocated to CTX's stack to contain at least
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index cbab45b..0f94f1e 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -130,6 +130,9 @@ struct dwarf_stack_value
    its current state and its callbacks.  */
 struct dwarf_expr_context
 {
+  dwarf_expr_context ();
+  ~dwarf_expr_context ();
+
   /* The stack of values, allocated with xmalloc.  */
   struct dwarf_stack_value *stack;
 
@@ -250,11 +253,6 @@ struct dwarf_expr_piece
   ULONGEST offset;
 };
 
-struct dwarf_expr_context *new_dwarf_expr_context (void);
-void free_dwarf_expr_context (struct dwarf_expr_context *ctx);
-struct cleanup *
-    make_cleanup_free_dwarf_expr_context (struct dwarf_expr_context *ctx);
-
 void dwarf_expr_push_address (struct dwarf_expr_context *ctx,
 			      CORE_ADDR value,
 			      int in_stack_memory);
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 7b3a2b2..066f55b 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2294,8 +2294,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 {
   struct value *retval;
   struct dwarf_expr_baton baton;
-  struct dwarf_expr_context *ctx;
-  struct cleanup *old_chain, *value_chain;
+  struct cleanup *value_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
   if (byte_offset < 0)
@@ -2308,26 +2307,25 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
   baton.per_cu = per_cu;
   baton.obj_address = 0;
 
-  ctx = new_dwarf_expr_context ();
-  old_chain = make_cleanup_free_dwarf_expr_context (ctx);
+  dwarf_expr_context ctx;
   value_chain = make_cleanup_value_free_to_mark (value_mark ());
 
-  ctx->gdbarch = get_objfile_arch (objfile);
-  ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
-  ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
-  ctx->offset = dwarf2_per_cu_text_offset (per_cu);
-  ctx->baton = &baton;
-  ctx->funcs = &dwarf_expr_ctx_funcs;
+  ctx.gdbarch = get_objfile_arch (objfile);
+  ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
+  ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
+  ctx.offset = dwarf2_per_cu_text_offset (per_cu);
+  ctx.baton = &baton;
+  ctx.funcs = &dwarf_expr_ctx_funcs;
 
   TRY
     {
-      dwarf_expr_eval (ctx, data, size);
+      dwarf_expr_eval (&ctx, data, size);
     }
   CATCH (ex, RETURN_MASK_ERROR)
     {
       if (ex.error == NOT_AVAILABLE_ERROR)
 	{
-	  do_cleanups (old_chain);
+	  do_cleanups (value_chain);
 	  retval = allocate_value (type);
 	  mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (type));
 	  return retval;
@@ -2336,7 +2334,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	{
 	  if (entry_values_debug)
 	    exception_print (gdb_stdout, ex);
-	  do_cleanups (old_chain);
+	  do_cleanups (value_chain);
 	  return allocate_optimized_out_value (type);
 	}
       else
@@ -2344,20 +2342,20 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
     }
   END_CATCH
 
-  if (ctx->num_pieces > 0)
+  if (ctx.num_pieces > 0)
     {
       struct piece_closure *c;
       struct frame_id frame_id = get_frame_id (frame);
       ULONGEST bit_size = 0;
       int i;
 
-      for (i = 0; i < ctx->num_pieces; ++i)
-	bit_size += ctx->pieces[i].size;
+      for (i = 0; i < ctx.num_pieces; ++i)
+	bit_size += ctx.pieces[i].size;
       if (8 * (byte_offset + TYPE_LENGTH (type)) > bit_size)
 	invalid_synthetic_pointer ();
 
-      c = allocate_piece_closure (per_cu, ctx->num_pieces, ctx->pieces,
-				  ctx->addr_size);
+      c = allocate_piece_closure (per_cu, ctx.num_pieces, ctx.pieces,
+				  ctx.addr_size);
       /* We must clean up the value chain after creating the piece
 	 closure but before allocating the result.  */
       do_cleanups (value_chain);
@@ -2367,13 +2365,13 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
     }
   else
     {
-      switch (ctx->location)
+      switch (ctx.location)
 	{
 	case DWARF_VALUE_REGISTER:
 	  {
 	    struct gdbarch *arch = get_frame_arch (frame);
 	    int dwarf_regnum
-	      = longest_to_int (value_as_long (dwarf_expr_fetch (ctx, 0)));
+	      = longest_to_int (value_as_long (dwarf_expr_fetch (&ctx, 0)));
 	    int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, dwarf_regnum);
 
 	    if (byte_offset != 0)
@@ -2401,8 +2399,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	case DWARF_VALUE_MEMORY:
 	  {
 	    struct type *ptr_type;
-	    CORE_ADDR address = dwarf_expr_fetch_address (ctx, 0);
-	    int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
+	    CORE_ADDR address = dwarf_expr_fetch_address (&ctx, 0);
+	    int in_stack_memory = dwarf_expr_fetch_in_stack_memory (&ctx, 0);
 
 	    /* DW_OP_deref_size (and possibly other operations too) may
 	       create a pointer instead of an address.  Ideally, the
@@ -2416,10 +2414,10 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	      {
 		case TYPE_CODE_FUNC:
 		case TYPE_CODE_METHOD:
-		  ptr_type = builtin_type (ctx->gdbarch)->builtin_func_ptr;
+		  ptr_type = builtin_type (ctx.gdbarch)->builtin_func_ptr;
 		  break;
 		default:
-		  ptr_type = builtin_type (ctx->gdbarch)->builtin_data_ptr;
+		  ptr_type = builtin_type (ctx.gdbarch)->builtin_data_ptr;
 		  break;
 	      }
 	    address = value_as_address (value_from_pointer (ptr_type, address));
@@ -2433,7 +2431,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 
 	case DWARF_VALUE_STACK:
 	  {
-	    struct value *value = dwarf_expr_fetch (ctx, 0);
+	    struct value *value = dwarf_expr_fetch (&ctx, 0);
 	    gdb_byte *contents;
 	    const gdb_byte *val_bytes;
 	    size_t n = TYPE_LENGTH (value_type (value));
@@ -2470,7 +2468,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	  {
 	    bfd_byte *contents;
 	    const bfd_byte *ldata;
-	    size_t n = ctx->len;
+	    size_t n = ctx.len;
 
 	    if (byte_offset + TYPE_LENGTH (type) > n)
 	      invalid_synthetic_pointer ();
@@ -2479,7 +2477,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	    retval = allocate_value (type);
 	    contents = value_contents_raw (retval);
 
-	    ldata = ctx->data + byte_offset;
+	    ldata = ctx.data + byte_offset;
 	    n -= byte_offset;
 
 	    if (n > TYPE_LENGTH (type))
@@ -2509,9 +2507,9 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	}
     }
 
-  set_value_initialized (retval, ctx->initialized);
+  set_value_initialized (retval, ctx.initialized);
 
-  do_cleanups (old_chain);
+  do_cleanups (value_chain);
 
   return retval;
 }
@@ -2539,7 +2537,6 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
 			   CORE_ADDR addr,
 			   CORE_ADDR *valp)
 {
-  struct dwarf_expr_context *ctx;
   struct dwarf_expr_baton baton;
   struct objfile *objfile;
   struct cleanup *cleanup;
@@ -2547,8 +2544,7 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
   if (dlbaton == NULL || dlbaton->size == 0)
     return 0;
 
-  ctx = new_dwarf_expr_context ();
-  cleanup = make_cleanup_free_dwarf_expr_context (ctx);
+  dwarf_expr_context ctx;
 
   baton.frame = frame;
   baton.per_cu = dlbaton->per_cu;
@@ -2556,29 +2552,27 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
 
   objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
 
-  ctx->gdbarch = get_objfile_arch (objfile);
-  ctx->addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
-  ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
-  ctx->offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
-  ctx->funcs = &dwarf_expr_ctx_funcs;
-  ctx->baton = &baton;
+  ctx.gdbarch = get_objfile_arch (objfile);
+  ctx.addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
+  ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
+  ctx.offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
+  ctx.funcs = &dwarf_expr_ctx_funcs;
+  ctx.baton = &baton;
 
-  dwarf_expr_eval (ctx, dlbaton->data, dlbaton->size);
+  dwarf_expr_eval (&ctx, dlbaton->data, dlbaton->size);
 
-  switch (ctx->location)
+  switch (ctx.location)
     {
     case DWARF_VALUE_REGISTER:
     case DWARF_VALUE_MEMORY:
     case DWARF_VALUE_STACK:
-      *valp = dwarf_expr_fetch_address (ctx, 0);
-      if (ctx->location == DWARF_VALUE_REGISTER)
+      *valp = dwarf_expr_fetch_address (&ctx, 0);
+      if (ctx.location == DWARF_VALUE_REGISTER)
 	*valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
-      do_cleanups (cleanup);
       return 1;
     case DWARF_VALUE_LITERAL:
-      *valp = extract_signed_integer (ctx->data, ctx->len,
-				      gdbarch_byte_order (ctx->gdbarch));
-      do_cleanups (cleanup);
+      *valp = extract_signed_integer (ctx.data, ctx.len,
+				      gdbarch_byte_order (ctx.gdbarch));
       return 1;
       /* Unsupported dwarf values.  */
     case DWARF_VALUE_OPTIMIZED_OUT:
@@ -2586,7 +2580,6 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
       break;
     }
 
-  do_cleanups (cleanup);
   return 0;
 }
 
@@ -2864,7 +2857,6 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
 				       struct dwarf2_per_cu_data *per_cu)
 {
   struct symbol_needs_baton baton;
-  struct dwarf_expr_context *ctx;
   int in_reg;
   struct cleanup *old_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
@@ -2872,29 +2864,28 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
   baton.needs = SYMBOL_NEEDS_NONE;
   baton.per_cu = per_cu;
 
-  ctx = new_dwarf_expr_context ();
-  old_chain = make_cleanup_free_dwarf_expr_context (ctx);
-  make_cleanup_value_free_to_mark (value_mark ());
+  dwarf_expr_context ctx;
+  old_chain = make_cleanup_value_free_to_mark (value_mark ());
 
-  ctx->gdbarch = get_objfile_arch (objfile);
-  ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
-  ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
-  ctx->offset = dwarf2_per_cu_text_offset (per_cu);
-  ctx->baton = &baton;
-  ctx->funcs = &symbol_needs_ctx_funcs;
+  ctx.gdbarch = get_objfile_arch (objfile);
+  ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
+  ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
+  ctx.offset = dwarf2_per_cu_text_offset (per_cu);
+  ctx.baton = &baton;
+  ctx.funcs = &symbol_needs_ctx_funcs;
 
-  dwarf_expr_eval (ctx, data, size);
+  dwarf_expr_eval (&ctx, data, size);
 
-  in_reg = ctx->location == DWARF_VALUE_REGISTER;
+  in_reg = ctx.location == DWARF_VALUE_REGISTER;
 
-  if (ctx->num_pieces > 0)
+  if (ctx.num_pieces > 0)
     {
       int i;
 
       /* If the location has several pieces, and any of them are in
          registers, then we will need a frame to fetch them from.  */
-      for (i = 0; i < ctx->num_pieces; i++)
-        if (ctx->pieces[i].location == DWARF_VALUE_REGISTER)
+      for (i = 0; i < ctx.num_pieces; i++)
+        if (ctx.pieces[i].location == DWARF_VALUE_REGISTER)
           in_reg = 1;
     }
 
-- 
2.7.4

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

* [RFA 21/22] Convert DWARF expr functions to methods
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (4 preceding siblings ...)
  2016-09-27  4:43 ` [RFA 20/22] Initial conversion of dwarf_expr_ctx Tom Tromey
@ 2016-09-27  4:45 ` Tom Tromey
  2016-10-09 19:18   ` Pedro Alves
  2016-09-27  4:47 ` [RFA 02/22] Use RAII to save and restore scalars Tom Tromey
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This converts various DWARF expr functions to be members on
dwarf_expr_context, then fixes up the various users.  This results in
somewhat less wordy code and sets the stage for the next patch.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* dwarf2loc.c (per_cu_dwarf_call)
	(dwarf_expr_push_dwarf_reg_entry_value)
	(dwarf2_evaluate_loc_desc_full, dwarf2_locexpr_baton_eval)
	(needs_dwarf_reg_entry_value)
	(dwarf2_loc_desc_get_symbol_read_needs): Update.
	* dwarf2expr.h (dwarf_expr_context) <push_address, eval, fetch,
	fetch_address, fetch_in_stack_memory, address_type, grow_stack,
	push, stack_empty_p, add_piece, get_base_type, execute_stack_op,
	pop>: New method declarations.
	(dwarf_expr_push_address, dwarf_expr_eval, dwarf_expr_fetch)
	(dwarf_expr_fetch_address, dwarf_expr_fetch_in_stack_memory):
	Don't declare.
	* dwarf2expr.c (address_type, grow_stack, push, push_address)
	(pop, fetch, fetch_address, fetch_in_stack_memory)
	(stack_empty_p, add_piece, eval, get_base_type)
	(execute_stack_op): Rename.  Turn into methods.
	* dwarf2-frame.c (execute_stack_op): Update.
---
 gdb/ChangeLog      |  20 +++
 gdb/dwarf2-frame.c |   8 +-
 gdb/dwarf2expr.c   | 374 ++++++++++++++++++++++++++---------------------------
 gdb/dwarf2expr.h   |  26 ++--
 gdb/dwarf2loc.c    |  22 ++--
 5 files changed, 234 insertions(+), 216 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e7de300..fbbd640 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,25 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* dwarf2loc.c (per_cu_dwarf_call)
+	(dwarf_expr_push_dwarf_reg_entry_value)
+	(dwarf2_evaluate_loc_desc_full, dwarf2_locexpr_baton_eval)
+	(needs_dwarf_reg_entry_value)
+	(dwarf2_loc_desc_get_symbol_read_needs): Update.
+	* dwarf2expr.h (dwarf_expr_context) <push_address, eval, fetch,
+	fetch_address, fetch_in_stack_memory, address_type, grow_stack,
+	push, stack_empty_p, add_piece, get_base_type, execute_stack_op,
+	pop>: New method declarations.
+	(dwarf_expr_push_address, dwarf_expr_eval, dwarf_expr_fetch)
+	(dwarf_expr_fetch_address, dwarf_expr_fetch_in_stack_memory):
+	Don't declare.
+	* dwarf2expr.c (address_type, grow_stack, push, push_address)
+	(pop, fetch, fetch_address, fetch_in_stack_memory)
+	(stack_empty_p, add_piece, eval, get_base_type)
+	(execute_stack_op): Rename.  Turn into methods.
+	* dwarf2-frame.c (execute_stack_op): Update.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): Stack-allocate
 	dwarf_expr_context.  Remove cleanups.
 	(dwarf2_locexpr_baton_eval)
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 48963de..c93c362 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -382,14 +382,14 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
   ctx.baton = this_frame;
   ctx.funcs = &dwarf2_frame_ctx_funcs;
 
-  dwarf_expr_push_address (&ctx, initial, initial_in_stack_memory);
-  dwarf_expr_eval (&ctx, exp, len);
+  ctx.push_address (initial, initial_in_stack_memory);
+  ctx.eval (exp, len);
 
   if (ctx.location == DWARF_VALUE_MEMORY)
-    result = dwarf_expr_fetch_address (&ctx, 0);
+    result = ctx.fetch_address (0);
   else if (ctx.location == DWARF_VALUE_REGISTER)
     result = read_addr_from_reg (this_frame,
-				 value_as_long (dwarf_expr_fetch (&ctx, 0)));
+				 value_as_long (ctx.fetch (0)));
   else
     {
       /* This is actually invalid DWARF, but if we ever do run across
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index a965987..2b22e0b 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -28,11 +28,6 @@
 #include "dwarf2expr.h"
 #include "dwarf2loc.h"
 
-/* Local prototypes.  */
-
-static void execute_stack_op (struct dwarf_expr_context *,
-			      const gdb_byte *, const gdb_byte *);
-
 /* Cookie for gdbarch data.  */
 
 static struct gdbarch_data *dwarf_arch_cookie;
@@ -62,28 +57,28 @@ dwarf_gdbarch_types_init (struct gdbarch *gdbarch)
    unspecified in the DWARF spec.  Only certain sizes are
    supported.  */
 
-static struct type *
-dwarf_expr_address_type (struct dwarf_expr_context *ctx)
+struct type *
+dwarf_expr_context::address_type () const
 {
   struct dwarf_gdbarch_types *types
-    = (struct dwarf_gdbarch_types *) gdbarch_data (ctx->gdbarch,
+    = (struct dwarf_gdbarch_types *) gdbarch_data (this->gdbarch,
 						   dwarf_arch_cookie);
   int ndx;
 
-  if (ctx->addr_size == 2)
+  if (this->addr_size == 2)
     ndx = 0;
-  else if (ctx->addr_size == 4)
+  else if (this->addr_size == 4)
     ndx = 1;
-  else if (ctx->addr_size == 8)
+  else if (this->addr_size == 8)
     ndx = 2;
   else
     error (_("Unsupported address size in DWARF expressions: %d bits"),
-	   8 * ctx->addr_size);
+	   8 * this->addr_size);
 
   if (types->dw_types[ndx] == NULL)
     types->dw_types[ndx]
-      = arch_integer_type (ctx->gdbarch,
-			   8 * ctx->addr_size,
+      = arch_integer_type (this->gdbarch,
+			   8 * this->addr_size,
 			   0, "<signed DWARF address type>");
 
   return types->dw_types[ndx];
@@ -122,28 +117,27 @@ dwarf_expr_context::~dwarf_expr_context ()
 /* Expand the memory allocated to CTX's stack to contain at least
    NEED more elements than are currently used.  */
 
-static void
-dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need)
+void
+dwarf_expr_context::grow_stack (size_t need)
 {
-  if (ctx->stack_len + need > ctx->stack_allocated)
+  if (this->stack_len + need > this->stack_allocated)
     {
-      size_t newlen = ctx->stack_len + need + 10;
+      size_t newlen = this->stack_len + need + 10;
 
-      ctx->stack = XRESIZEVEC (struct dwarf_stack_value, ctx->stack, newlen);
-      ctx->stack_allocated = newlen;
+      this->stack = XRESIZEVEC (struct dwarf_stack_value, this->stack, newlen);
+      this->stack_allocated = newlen;
     }
 }
 
 /* Push VALUE onto CTX's stack.  */
 
-static void
-dwarf_expr_push (struct dwarf_expr_context *ctx, struct value *value,
-		 int in_stack_memory)
+void
+dwarf_expr_context::push (struct value *value, int in_stack_memory)
 {
   struct dwarf_stack_value *v;
 
-  dwarf_expr_grow_stack (ctx, 1);
-  v = &ctx->stack[ctx->stack_len++];
+  grow_stack (1);
+  v = &this->stack[this->stack_len++];
   v->value = value;
   v->in_stack_memory = in_stack_memory;
 }
@@ -151,34 +145,31 @@ dwarf_expr_push (struct dwarf_expr_context *ctx, struct value *value,
 /* Push VALUE onto CTX's stack.  */
 
 void
-dwarf_expr_push_address (struct dwarf_expr_context *ctx, CORE_ADDR value,
-			 int in_stack_memory)
+dwarf_expr_context::push_address (CORE_ADDR value, int in_stack_memory)
 {
-  dwarf_expr_push (ctx,
-		   value_from_ulongest (dwarf_expr_address_type (ctx), value),
-		   in_stack_memory);
+  push (value_from_ulongest (address_type (), value), in_stack_memory);
 }
 
 /* Pop the top item off of CTX's stack.  */
 
-static void
-dwarf_expr_pop (struct dwarf_expr_context *ctx)
+void
+dwarf_expr_context::pop ()
 {
-  if (ctx->stack_len <= 0)
+  if (this->stack_len <= 0)
     error (_("dwarf expression stack underflow"));
-  ctx->stack_len--;
+  this->stack_len--;
 }
 
 /* Retrieve the N'th item on CTX's stack.  */
 
 struct value *
-dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
+dwarf_expr_context::fetch (int n)
 {
-  if (ctx->stack_len <= n)
+  if (this->stack_len <= n)
      error (_("Asked for position %d of stack, "
 	      "stack only has %d elements on it."),
-	    n, ctx->stack_len);
-  return ctx->stack[ctx->stack_len - (1 + n)].value;
+	    n, this->stack_len);
+  return this->stack[this->stack_len - (1 + n)].value;
 }
 
 /* Require that TYPE be an integral type; throw an exception if not.  */
@@ -239,10 +230,10 @@ get_signed_type (struct gdbarch *gdbarch, struct type *type)
 /* Retrieve the N'th item on CTX's stack, converted to an address.  */
 
 CORE_ADDR
-dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n)
+dwarf_expr_context::fetch_address (int n)
 {
-  struct value *result_val = dwarf_expr_fetch (ctx, n);
-  enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
+  struct value *result_val = fetch (n);
+  enum bfd_endian byte_order = gdbarch_byte_order (this->gdbarch);
   ULONGEST result;
 
   dwarf_require_integral (value_type (result_val));
@@ -256,14 +247,14 @@ dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n)
      extract_unsigned_integer() will not produce a correct
      result.  Make sure we invoke gdbarch_integer_to_address()
      for those architectures which require it.  */
-  if (gdbarch_integer_to_address_p (ctx->gdbarch))
+  if (gdbarch_integer_to_address_p (this->gdbarch))
     {
-      gdb_byte *buf = (gdb_byte *) alloca (ctx->addr_size);
-      struct type *int_type = get_unsigned_type (ctx->gdbarch,
+      gdb_byte *buf = (gdb_byte *) alloca (this->addr_size);
+      struct type *int_type = get_unsigned_type (this->gdbarch,
 						 value_type (result_val));
 
-      store_unsigned_integer (buf, ctx->addr_size, byte_order, result);
-      return gdbarch_integer_to_address (ctx->gdbarch, int_type, buf);
+      store_unsigned_integer (buf, this->addr_size, byte_order, result);
+      return gdbarch_integer_to_address (this->gdbarch, int_type, buf);
     }
 
   return (CORE_ADDR) result;
@@ -272,68 +263,68 @@ dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n)
 /* Retrieve the in_stack_memory flag of the N'th item on CTX's stack.  */
 
 int
-dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n)
+dwarf_expr_context::fetch_in_stack_memory (int n)
 {
-  if (ctx->stack_len <= n)
+  if (this->stack_len <= n)
      error (_("Asked for position %d of stack, "
 	      "stack only has %d elements on it."),
-	    n, ctx->stack_len);
-  return ctx->stack[ctx->stack_len - (1 + n)].in_stack_memory;
+	    n, this->stack_len);
+  return this->stack[this->stack_len - (1 + n)].in_stack_memory;
 }
 
 /* Return true if the expression stack is empty.  */
 
-static int
-dwarf_expr_stack_empty_p (struct dwarf_expr_context *ctx)
+int
+dwarf_expr_context::stack_empty_p () const
 {
-  return ctx->stack_len == 0;
+  return this->stack_len == 0;
 }
 
-/* Add a new piece to CTX's piece list.  */
-static void
-add_piece (struct dwarf_expr_context *ctx, ULONGEST size, ULONGEST offset)
+/* Add a new piece to the dwarf_expr_context's piece list.  */
+void
+dwarf_expr_context::add_piece (ULONGEST size, ULONGEST offset)
 {
   struct dwarf_expr_piece *p;
 
-  ctx->num_pieces++;
+  this->num_pieces++;
 
-  ctx->pieces
-    = XRESIZEVEC (struct dwarf_expr_piece, ctx->pieces, ctx->num_pieces);
+  this->pieces
+    = XRESIZEVEC (struct dwarf_expr_piece, this->pieces, this->num_pieces);
 
-  p = &ctx->pieces[ctx->num_pieces - 1];
-  p->location = ctx->location;
+  p = &this->pieces[this->num_pieces - 1];
+  p->location = this->location;
   p->size = size;
   p->offset = offset;
 
   if (p->location == DWARF_VALUE_LITERAL)
     {
-      p->v.literal.data = ctx->data;
-      p->v.literal.length = ctx->len;
+      p->v.literal.data = this->data;
+      p->v.literal.length = this->len;
     }
-  else if (dwarf_expr_stack_empty_p (ctx))
+  else if (stack_empty_p ())
     {
       p->location = DWARF_VALUE_OPTIMIZED_OUT;
       /* Also reset the context's location, for our callers.  This is
 	 a somewhat strange approach, but this lets us avoid setting
 	 the location to DWARF_VALUE_MEMORY in all the individual
 	 cases in the evaluator.  */
-      ctx->location = DWARF_VALUE_OPTIMIZED_OUT;
+      this->location = DWARF_VALUE_OPTIMIZED_OUT;
     }
   else if (p->location == DWARF_VALUE_MEMORY)
     {
-      p->v.mem.addr = dwarf_expr_fetch_address (ctx, 0);
-      p->v.mem.in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
+      p->v.mem.addr = fetch_address (0);
+      p->v.mem.in_stack_memory = fetch_in_stack_memory (0);
     }
   else if (p->location == DWARF_VALUE_IMPLICIT_POINTER)
     {
-      p->v.ptr.die.sect_off = ctx->len;
-      p->v.ptr.offset = value_as_long (dwarf_expr_fetch (ctx, 0));
+      p->v.ptr.die.sect_off = this->len;
+      p->v.ptr.offset = value_as_long (fetch (0));
     }
   else if (p->location == DWARF_VALUE_REGISTER)
-    p->v.regno = value_as_long (dwarf_expr_fetch (ctx, 0));
+    p->v.regno = value_as_long (fetch (0));
   else
     {
-      p->v.value = dwarf_expr_fetch (ctx, 0);
+      p->v.value = fetch (0);
     }
 }
 
@@ -341,16 +332,15 @@ add_piece (struct dwarf_expr_context *ctx, ULONGEST size, ULONGEST offset)
    CTX.  */
 
 void
-dwarf_expr_eval (struct dwarf_expr_context *ctx, const gdb_byte *addr,
-		 size_t len)
+dwarf_expr_context::eval (const gdb_byte *addr, size_t len)
 {
-  int old_recursion_depth = ctx->recursion_depth;
+  int old_recursion_depth = this->recursion_depth;
 
-  execute_stack_op (ctx, addr, addr + len);
+  execute_stack_op (addr, addr + len);
 
   /* CTX RECURSION_DEPTH becomes invalid if an exception was thrown here.  */
 
-  gdb_assert (ctx->recursion_depth == old_recursion_depth);
+  gdb_assert (this->recursion_depth == old_recursion_depth);
 }
 
 /* Helper to read a uleb128 value or throw an error.  */
@@ -423,14 +413,14 @@ base_types_equal_p (struct type *t1, struct type *t2)
    this function should verify that the resulting type has the correct
    size.  */
 
-static struct type *
-dwarf_get_base_type (struct dwarf_expr_context *ctx, cu_offset die, int size)
+struct type *
+dwarf_expr_context::get_base_type (cu_offset die, int size)
 {
   struct type *result;
 
-  if (ctx->funcs->get_base_type)
+  if (this->funcs->get_base_type)
     {
-      result = ctx->funcs->get_base_type (ctx, die);
+      result = this->funcs->get_base_type (this, die);
       if (result == NULL)
 	error (_("Could not find type for DW_OP_GNU_const_type"));
       if (size != 0 && TYPE_LENGTH (result) != size)
@@ -438,7 +428,7 @@ dwarf_get_base_type (struct dwarf_expr_context *ctx, cu_offset die, int size)
     }
   else
     /* Anything will do.  */
-    result = builtin_type (ctx->gdbarch)->builtin_int;
+    result = builtin_type (this->gdbarch)->builtin_int;
 
   return result;
 }
@@ -613,14 +603,14 @@ dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf,
   return 1;
 }
 
-/* The engine for the expression evaluator.  Using the context in CTX,
-   evaluate the expression between OP_PTR and OP_END.  */
+/* The engine for the expression evaluator.  Using the context in this
+   object, evaluate the expression between OP_PTR and OP_END.  */
 
-static void
-execute_stack_op (struct dwarf_expr_context *ctx,
-		  const gdb_byte *op_ptr, const gdb_byte *op_end)
+void
+dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
+				      const gdb_byte *op_end)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (this->gdbarch);
   /* Old-style "untyped" DWARF values need special treatment in a
      couple of places, specifically DW_OP_mod and DW_OP_shr.  We need
      a special type for these values so we can distinguish them from
@@ -628,15 +618,15 @@ execute_stack_op (struct dwarf_expr_context *ctx,
      values do not need special treatment.  This special type must be
      different (in the `==' sense) from any base type coming from the
      CU.  */
-  struct type *address_type = dwarf_expr_address_type (ctx);
+  struct type *address_type = this->address_type ();
 
-  ctx->location = DWARF_VALUE_MEMORY;
-  ctx->initialized = 1;  /* Default is initialized.  */
+  this->location = DWARF_VALUE_MEMORY;
+  this->initialized = 1;  /* Default is initialized.  */
 
-  if (ctx->recursion_depth > ctx->max_recursion_depth)
+  if (this->recursion_depth > this->max_recursion_depth)
     error (_("DWARF-2 expression error: Loop detected (%d)."),
-	   ctx->recursion_depth);
-  ctx->recursion_depth++;
+	   this->recursion_depth);
+  this->recursion_depth++;
 
   while (op_ptr < op_end)
     {
@@ -697,26 +687,26 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
 	case DW_OP_addr:
 	  result = extract_unsigned_integer (op_ptr,
-					     ctx->addr_size, byte_order);
-	  op_ptr += ctx->addr_size;
+					     this->addr_size, byte_order);
+	  op_ptr += this->addr_size;
 	  /* Some versions of GCC emit DW_OP_addr before
 	     DW_OP_GNU_push_tls_address.  In this case the value is an
 	     index, not an address.  We don't support things like
 	     branching between the address and the TLS op.  */
 	  if (op_ptr >= op_end || *op_ptr != DW_OP_GNU_push_tls_address)
-	    result += ctx->offset;
+	    result += this->offset;
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 
 	case DW_OP_GNU_addr_index:
 	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
-	  result = (ctx->funcs->get_addr_index) (ctx->baton, uoffset);
-	  result += ctx->offset;
+	  result = (this->funcs->get_addr_index) (this->baton, uoffset);
+	  result += this->offset;
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 	case DW_OP_GNU_const_index:
 	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
-	  result = (ctx->funcs->get_addr_index) (ctx->baton, uoffset);
+	  result = (this->funcs->get_addr_index) (this->baton, uoffset);
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 
@@ -815,7 +805,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
 	  result = op - DW_OP_reg0;
 	  result_val = value_from_ulongest (address_type, result);
-	  ctx->location = DWARF_VALUE_REGISTER;
+	  this->location = DWARF_VALUE_REGISTER;
 	  break;
 
 	case DW_OP_regx:
@@ -824,7 +814,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
 	  result = reg;
 	  result_val = value_from_ulongest (address_type, result);
-	  ctx->location = DWARF_VALUE_REGISTER;
+	  this->location = DWARF_VALUE_REGISTER;
 	  break;
 
 	case DW_OP_implicit_value:
@@ -834,9 +824,9 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &len);
 	    if (op_ptr + len > op_end)
 	      error (_("DW_OP_implicit_value: too few bytes available."));
-	    ctx->len = len;
-	    ctx->data = op_ptr;
-	    ctx->location = DWARF_VALUE_LITERAL;
+	    this->len = len;
+	    this->data = op_ptr;
+	    this->location = DWARF_VALUE_LITERAL;
 	    op_ptr += len;
 	    dwarf_expr_require_composition (op_ptr, op_end,
 					    "DW_OP_implicit_value");
@@ -844,7 +834,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	  goto no_push;
 
 	case DW_OP_stack_value:
-	  ctx->location = DWARF_VALUE_STACK;
+	  this->location = DWARF_VALUE_STACK;
 	  dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_stack_value");
 	  goto no_push;
 
@@ -852,21 +842,21 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	  {
 	    int64_t len;
 
-	    if (ctx->ref_addr_size == -1)
+	    if (this->ref_addr_size == -1)
 	      error (_("DWARF-2 expression error: DW_OP_GNU_implicit_pointer "
 		       "is not allowed in frame context"));
 
 	    /* The referred-to DIE of sect_offset kind.  */
-	    ctx->len = extract_unsigned_integer (op_ptr, ctx->ref_addr_size,
+	    this->len = extract_unsigned_integer (op_ptr, this->ref_addr_size,
 						 byte_order);
-	    op_ptr += ctx->ref_addr_size;
+	    op_ptr += this->ref_addr_size;
 
 	    /* The byte offset into the data.  */
 	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &len);
 	    result = (ULONGEST) len;
 	    result_val = value_from_ulongest (address_type, result);
 
-	    ctx->location = DWARF_VALUE_IMPLICIT_POINTER;
+	    this->location = DWARF_VALUE_IMPLICIT_POINTER;
 	    dwarf_expr_require_composition (op_ptr, op_end,
 					    "DW_OP_GNU_implicit_pointer");
 	  }
@@ -906,7 +896,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	case DW_OP_breg31:
 	  {
 	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
-	    result = (ctx->funcs->read_addr_from_reg) (ctx->baton,
+	    result = (this->funcs->read_addr_from_reg) (this->baton,
 						       op - DW_OP_breg0);
 	    result += offset;
 	    result_val = value_from_ulongest (address_type, result);
@@ -916,7 +906,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	  {
 	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
 	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
-	    result = (ctx->funcs->read_addr_from_reg) (ctx->baton, reg);
+	    result = (this->funcs->read_addr_from_reg) (this->baton, reg);
 	    result += offset;
 	    result_val = value_from_ulongest (address_type, result);
 	  }
@@ -932,78 +922,78 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	       record the stack length before execution, then reset it
 	       afterwards, effectively erasing whatever the recursive
 	       call put there.  */
-	    before_stack_len = ctx->stack_len;
+	    before_stack_len = this->stack_len;
 	    /* FIXME: cagney/2003-03-26: This code should be using
                get_frame_base_address(), and then implement a dwarf2
                specific this_base method.  */
-	    (ctx->funcs->get_frame_base) (ctx->baton, &datastart, &datalen);
-	    dwarf_expr_eval (ctx, datastart, datalen);
-	    if (ctx->location == DWARF_VALUE_MEMORY)
-	      result = dwarf_expr_fetch_address (ctx, 0);
-	    else if (ctx->location == DWARF_VALUE_REGISTER)
-	      result = (ctx->funcs->read_addr_from_reg)
-			  (ctx->baton,
-			   value_as_long (dwarf_expr_fetch (ctx, 0)));
+	    (this->funcs->get_frame_base) (this->baton, &datastart, &datalen);
+	    eval (datastart, datalen);
+	    if (this->location == DWARF_VALUE_MEMORY)
+	      result = fetch_address (0);
+	    else if (this->location == DWARF_VALUE_REGISTER)
+	      result = (this->funcs->read_addr_from_reg)
+			  (this->baton,
+			   value_as_long (fetch (0)));
 	    else
 	      error (_("Not implemented: computing frame "
 		       "base using explicit value operator"));
 	    result = result + offset;
 	    result_val = value_from_ulongest (address_type, result);
 	    in_stack_memory = 1;
-	    ctx->stack_len = before_stack_len;
-	    ctx->location = DWARF_VALUE_MEMORY;
+	    this->stack_len = before_stack_len;
+	    this->location = DWARF_VALUE_MEMORY;
 	  }
 	  break;
 
 	case DW_OP_dup:
-	  result_val = dwarf_expr_fetch (ctx, 0);
-	  in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
+	  result_val = fetch (0);
+	  in_stack_memory = fetch_in_stack_memory (0);
 	  break;
 
 	case DW_OP_drop:
-	  dwarf_expr_pop (ctx);
+	  pop ();
 	  goto no_push;
 
 	case DW_OP_pick:
 	  offset = *op_ptr++;
-	  result_val = dwarf_expr_fetch (ctx, offset);
-	  in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, offset);
+	  result_val = fetch (offset);
+	  in_stack_memory = fetch_in_stack_memory (offset);
 	  break;
 	  
 	case DW_OP_swap:
 	  {
 	    struct dwarf_stack_value t1, t2;
 
-	    if (ctx->stack_len < 2)
+	    if (this->stack_len < 2)
 	       error (_("Not enough elements for "
 			"DW_OP_swap.  Need 2, have %d."),
-		      ctx->stack_len);
-	    t1 = ctx->stack[ctx->stack_len - 1];
-	    t2 = ctx->stack[ctx->stack_len - 2];
-	    ctx->stack[ctx->stack_len - 1] = t2;
-	    ctx->stack[ctx->stack_len - 2] = t1;
+		      this->stack_len);
+	    t1 = this->stack[this->stack_len - 1];
+	    t2 = this->stack[this->stack_len - 2];
+	    this->stack[this->stack_len - 1] = t2;
+	    this->stack[this->stack_len - 2] = t1;
 	    goto no_push;
 	  }
 
 	case DW_OP_over:
-	  result_val = dwarf_expr_fetch (ctx, 1);
-	  in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 1);
+	  result_val = fetch (1);
+	  in_stack_memory = fetch_in_stack_memory (1);
 	  break;
 
 	case DW_OP_rot:
 	  {
 	    struct dwarf_stack_value t1, t2, t3;
 
-	    if (ctx->stack_len < 3)
+	    if (this->stack_len < 3)
 	       error (_("Not enough elements for "
 			"DW_OP_rot.  Need 3, have %d."),
-		      ctx->stack_len);
-	    t1 = ctx->stack[ctx->stack_len - 1];
-	    t2 = ctx->stack[ctx->stack_len - 2];
-	    t3 = ctx->stack[ctx->stack_len - 3];
-	    ctx->stack[ctx->stack_len - 1] = t2;
-	    ctx->stack[ctx->stack_len - 2] = t3;
-	    ctx->stack[ctx->stack_len - 3] = t1;
+		      this->stack_len);
+	    t1 = this->stack[this->stack_len - 1];
+	    t2 = this->stack[this->stack_len - 2];
+	    t3 = this->stack[this->stack_len - 3];
+	    this->stack[this->stack_len - 1] = t2;
+	    this->stack[this->stack_len - 2] = t3;
+	    this->stack[this->stack_len - 3] = t1;
 	    goto no_push;
 	  }
 
@@ -1011,12 +1001,12 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	case DW_OP_deref_size:
 	case DW_OP_GNU_deref_type:
 	  {
-	    int addr_size = (op == DW_OP_deref ? ctx->addr_size : *op_ptr++);
+	    int addr_size = (op == DW_OP_deref ? this->addr_size : *op_ptr++);
 	    gdb_byte *buf = (gdb_byte *) alloca (addr_size);
-	    CORE_ADDR addr = dwarf_expr_fetch_address (ctx, 0);
+	    CORE_ADDR addr = fetch_address (0);
 	    struct type *type;
 
-	    dwarf_expr_pop (ctx);
+	    pop ();
 
 	    if (op == DW_OP_GNU_deref_type)
 	      {
@@ -1024,12 +1014,12 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
 		op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
 		type_die.cu_off = uoffset;
-		type = dwarf_get_base_type (ctx, type_die, 0);
+		type = get_base_type (type_die, 0);
 	      }
 	    else
 	      type = address_type;
 
-	    (ctx->funcs->read_mem) (ctx->baton, buf, addr, addr_size);
+	    (this->funcs->read_mem) (this->baton, buf, addr, addr_size);
 
 	    /* If the size of the object read from memory is different
 	       from the type length, we need to zero-extend it.  */
@@ -1053,8 +1043,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	case DW_OP_plus_uconst:
 	  {
 	    /* Unary operations.  */
-	    result_val = dwarf_expr_fetch (ctx, 0);
-	    dwarf_expr_pop (ctx);
+	    result_val = fetch (0);
+	    pop ();
 
 	    switch (op)
 	      {
@@ -1102,11 +1092,11 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	    /* Binary operations.  */
 	    struct value *first, *second;
 
-	    second = dwarf_expr_fetch (ctx, 0);
-	    dwarf_expr_pop (ctx);
+	    second = fetch (0);
+	    pop ();
 
-	    first = dwarf_expr_fetch (ctx, 0);
-	    dwarf_expr_pop (ctx);
+	    first = fetch (0);
+	    pop ();
 
 	    if (! base_types_equal_p (value_type (first), value_type (second)))
 	      error (_("Incompatible types on DWARF stack"));
@@ -1135,7 +1125,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 		  if (orig_type == address_type)
 		    {
 		      struct type *utype
-			= get_unsigned_type (ctx->gdbarch, orig_type);
+			= get_unsigned_type (this->gdbarch, orig_type);
 
 		      cast_back = 1;
 		      first = value_cast (utype, first);
@@ -1170,7 +1160,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 		if (!TYPE_UNSIGNED (value_type (first)))
 		  {
 		    struct type *utype
-		      = get_unsigned_type (ctx->gdbarch, value_type (first));
+		      = get_unsigned_type (this->gdbarch, value_type (first));
 
 		    first = value_cast (utype, first);
 		  }
@@ -1187,7 +1177,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 		if (TYPE_UNSIGNED (value_type (first)))
 		  {
 		    struct type *stype
-		      = get_signed_type (ctx->gdbarch, value_type (first));
+		      = get_signed_type (this->gdbarch, value_type (first));
 
 		    first = value_cast (stype, first);
 		  }
@@ -1238,7 +1228,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	  break;
 
 	case DW_OP_call_frame_cfa:
-	  result = (ctx->funcs->get_frame_cfa) (ctx->baton);
+	  result = (this->funcs->get_frame_cfa) (this->baton);
 	  result_val = value_from_ulongest (address_type, result);
 	  in_stack_memory = 1;
 	  break;
@@ -1253,9 +1243,9 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	  control block at which the variable is located.  Nothing
 	  should follow this operator, so the top of stack would be
 	  returned.  */
-	  result = value_as_long (dwarf_expr_fetch (ctx, 0));
-	  dwarf_expr_pop (ctx);
-	  result = (ctx->funcs->get_tls_address) (ctx->baton, result);
+	  result = value_as_long (fetch (0));
+	  pop ();
+	  result = (this->funcs->get_tls_address) (this->baton, result);
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 
@@ -1271,11 +1261,11 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
 	    offset = extract_signed_integer (op_ptr, 2, byte_order);
 	    op_ptr += 2;
-	    val = dwarf_expr_fetch (ctx, 0);
+	    val = fetch (0);
 	    dwarf_require_integral (value_type (val));
 	    if (value_as_long (val) != 0)
 	      op_ptr += offset;
-	    dwarf_expr_pop (ctx);
+	    pop ();
 	  }
 	  goto no_push;
 
@@ -1288,14 +1278,14 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
             /* Record the piece.  */
             op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
-	    add_piece (ctx, 8 * size, 0);
+	    add_piece (8 * size, 0);
 
             /* Pop off the address/regnum, and reset the location
 	       type.  */
-	    if (ctx->location != DWARF_VALUE_LITERAL
-		&& ctx->location != DWARF_VALUE_OPTIMIZED_OUT)
-	      dwarf_expr_pop (ctx);
-            ctx->location = DWARF_VALUE_MEMORY;
+	    if (this->location != DWARF_VALUE_LITERAL
+		&& this->location != DWARF_VALUE_OPTIMIZED_OUT)
+	      pop ();
+            this->location = DWARF_VALUE_MEMORY;
           }
           goto no_push;
 
@@ -1306,14 +1296,14 @@ execute_stack_op (struct dwarf_expr_context *ctx,
             /* Record the piece.  */
 	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
 	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &offset);
-	    add_piece (ctx, size, offset);
+	    add_piece (size, offset);
 
             /* Pop off the address/regnum, and reset the location
 	       type.  */
-	    if (ctx->location != DWARF_VALUE_LITERAL
-		&& ctx->location != DWARF_VALUE_OPTIMIZED_OUT)
-	      dwarf_expr_pop (ctx);
-            ctx->location = DWARF_VALUE_MEMORY;
+	    if (this->location != DWARF_VALUE_LITERAL
+		&& this->location != DWARF_VALUE_OPTIMIZED_OUT)
+	      pop ();
+            this->location = DWARF_VALUE_MEMORY;
 	  }
 	  goto no_push;
 
@@ -1322,7 +1312,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	    error (_("DWARF-2 expression error: DW_OP_GNU_uninit must always "
 		   "be the very last op."));
 
-	  ctx->initialized = 0;
+	  this->initialized = 0;
 	  goto no_push;
 
 	case DW_OP_call2:
@@ -1331,7 +1321,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
 	    offset.cu_off = extract_unsigned_integer (op_ptr, 2, byte_order);
 	    op_ptr += 2;
-	    ctx->funcs->dwarf_call (ctx, offset);
+	    this->funcs->dwarf_call (this, offset);
 	  }
 	  goto no_push;
 
@@ -1341,7 +1331,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
 	    offset.cu_off = extract_unsigned_integer (op_ptr, 4, byte_order);
 	    op_ptr += 4;
-	    ctx->funcs->dwarf_call (ctx, offset);
+	    this->funcs->dwarf_call (this, offset);
 	  }
 	  goto no_push;
 	
@@ -1359,7 +1349,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	    if (kind_u.dwarf_reg != -1)
 	      {
 		op_ptr += len;
-		ctx->funcs->push_dwarf_reg_entry_value (ctx,
+		this->funcs->push_dwarf_reg_entry_value (this,
 						  CALL_SITE_PARAMETER_DWARF_REG,
 							kind_u,
 							-1 /* deref_size */);
@@ -1372,9 +1362,9 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	    if (kind_u.dwarf_reg != -1)
 	      {
 		if (deref_size == -1)
-		  deref_size = ctx->addr_size;
+		  deref_size = this->addr_size;
 		op_ptr += len;
-		ctx->funcs->push_dwarf_reg_entry_value (ctx,
+		this->funcs->push_dwarf_reg_entry_value (this,
 						  CALL_SITE_PARAMETER_DWARF_REG,
 							kind_u, deref_size);
 		goto no_push;
@@ -1392,7 +1382,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	    kind_u.param_offset.cu_off = extract_unsigned_integer (op_ptr, 4,
 								   byte_order);
 	    op_ptr += 4;
-	    ctx->funcs->push_dwarf_reg_entry_value (ctx,
+	    this->funcs->push_dwarf_reg_entry_value (this,
 					       CALL_SITE_PARAMETER_PARAM_OFFSET,
 						    kind_u,
 						    -1 /* deref_size */);
@@ -1412,7 +1402,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	    data = op_ptr;
 	    op_ptr += n;
 
-	    type = dwarf_get_base_type (ctx, type_die, n);
+	    type = get_base_type (type_die, n);
 	    result_val = value_from_contents (type, data);
 	  }
 	  break;
@@ -1426,8 +1416,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
 	    type_die.cu_off = uoffset;
 
-	    type = dwarf_get_base_type (ctx, type_die, 0);
-	    result_val = ctx->funcs->get_reg_value (ctx->baton, type, reg);
+	    type = get_base_type (type_die, 0);
+	    result_val = this->funcs->get_reg_value (this->baton, type, reg);
 	  }
 	  break;
 
@@ -1443,10 +1433,10 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	    if (type_die.cu_off == 0)
 	      type = address_type;
 	    else
-	      type = dwarf_get_base_type (ctx, type_die, 0);
+	      type = get_base_type (type_die, 0);
 
-	    result_val = dwarf_expr_fetch (ctx, 0);
-	    dwarf_expr_pop (ctx);
+	    result_val = fetch (0);
+	    pop ();
 
 	    if (op == DW_OP_GNU_convert)
 	      result_val = value_cast (type, result_val);
@@ -1466,7 +1456,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
 	case DW_OP_push_object_address:
 	  /* Return the address of the object we are currently observing.  */
-	  result = (ctx->funcs->get_object_address) (ctx->baton);
+	  result = (this->funcs->get_object_address) (this->baton);
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 
@@ -1476,7 +1466,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
       /* Most things push a result value.  */
       gdb_assert (result_val != NULL);
-      dwarf_expr_push (ctx, result_val, in_stack_memory);
+      push (result_val, in_stack_memory);
     no_push:
       ;
     }
@@ -1484,12 +1474,12 @@ execute_stack_op (struct dwarf_expr_context *ctx,
   /* To simplify our main caller, if the result is an implicit
      pointer, then make a pieced value.  This is ok because we can't
      have implicit pointers in contexts where pieces are invalid.  */
-  if (ctx->location == DWARF_VALUE_IMPLICIT_POINTER)
-    add_piece (ctx, 8 * ctx->addr_size, 0);
+  if (this->location == DWARF_VALUE_IMPLICIT_POINTER)
+    add_piece (8 * this->addr_size, 0);
 
 abort_expression:
-  ctx->recursion_depth--;
-  gdb_assert (ctx->recursion_depth >= 0);
+  this->recursion_depth--;
+  gdb_assert (this->recursion_depth >= 0);
 }
 
 /* Stub dwarf_expr_context_funcs.get_frame_base implementation.  */
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index 0f94f1e..4706bb3 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -133,6 +133,12 @@ struct dwarf_expr_context
   dwarf_expr_context ();
   ~dwarf_expr_context ();
 
+  void push_address (CORE_ADDR value, int in_stack_memory);
+  void eval (const gdb_byte *addr, size_t len);
+  struct value *fetch (int n);
+  CORE_ADDR fetch_address (int n);
+  int fetch_in_stack_memory (int n);
+
   /* The stack of values, allocated with xmalloc.  */
   struct dwarf_stack_value *stack;
 
@@ -203,6 +209,17 @@ struct dwarf_expr_context
      two cases need to be handled separately.)  */
   int num_pieces;
   struct dwarf_expr_piece *pieces;
+
+private:
+
+  struct type *address_type () const;
+  void grow_stack (size_t need);
+  void push (struct value *value, int in_stack_memory);
+  int stack_empty_p () const;
+  void add_piece (ULONGEST size, ULONGEST offset);
+  struct type *get_base_type (cu_offset die, int size);
+  void execute_stack_op (const gdb_byte *op_ptr, const gdb_byte *op_end);
+  void pop ();
 };
 
 
@@ -253,15 +270,6 @@ struct dwarf_expr_piece
   ULONGEST offset;
 };
 
-void dwarf_expr_push_address (struct dwarf_expr_context *ctx,
-			      CORE_ADDR value,
-			      int in_stack_memory);
-void dwarf_expr_eval (struct dwarf_expr_context *ctx, const gdb_byte *addr,
-		      size_t len);
-struct value *dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n);
-CORE_ADDR dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n);
-int dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n);
-
 void dwarf_expr_require_composition (const gdb_byte *, const gdb_byte *,
 				     const char *);
 
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 066f55b..d6ffd85 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -561,7 +561,7 @@ per_cu_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset,
   /* DW_OP_call_ref is currently not supported.  */
   gdb_assert (block.per_cu == per_cu);
 
-  dwarf_expr_eval (ctx, block.data, block.size);
+  ctx->eval (block.data, block.size);
 }
 
 /* Helper interface of per_cu_dwarf_call for dwarf2_evaluate_loc_desc.  */
@@ -1300,7 +1300,7 @@ dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
   ctx->offset = dwarf2_per_cu_text_offset (baton_local.per_cu);
   ctx->baton = &baton_local;
 
-  dwarf_expr_eval (ctx, data_src, size);
+  ctx->eval (data_src, size);
 
   ctx->gdbarch = saved_ctx.gdbarch;
   ctx->addr_size = saved_ctx.addr_size;
@@ -2319,7 +2319,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 
   TRY
     {
-      dwarf_expr_eval (&ctx, data, size);
+      ctx.eval (data, size);
     }
   CATCH (ex, RETURN_MASK_ERROR)
     {
@@ -2371,7 +2371,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	  {
 	    struct gdbarch *arch = get_frame_arch (frame);
 	    int dwarf_regnum
-	      = longest_to_int (value_as_long (dwarf_expr_fetch (&ctx, 0)));
+	      = longest_to_int (value_as_long (ctx.fetch (0)));
 	    int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, dwarf_regnum);
 
 	    if (byte_offset != 0)
@@ -2399,8 +2399,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	case DWARF_VALUE_MEMORY:
 	  {
 	    struct type *ptr_type;
-	    CORE_ADDR address = dwarf_expr_fetch_address (&ctx, 0);
-	    int in_stack_memory = dwarf_expr_fetch_in_stack_memory (&ctx, 0);
+	    CORE_ADDR address = ctx.fetch_address (0);
+	    int in_stack_memory = ctx.fetch_in_stack_memory (0);
 
 	    /* DW_OP_deref_size (and possibly other operations too) may
 	       create a pointer instead of an address.  Ideally, the
@@ -2431,7 +2431,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 
 	case DWARF_VALUE_STACK:
 	  {
-	    struct value *value = dwarf_expr_fetch (&ctx, 0);
+	    struct value *value = ctx.fetch (0);
 	    gdb_byte *contents;
 	    const gdb_byte *val_bytes;
 	    size_t n = TYPE_LENGTH (value_type (value));
@@ -2559,14 +2559,14 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
   ctx.funcs = &dwarf_expr_ctx_funcs;
   ctx.baton = &baton;
 
-  dwarf_expr_eval (&ctx, dlbaton->data, dlbaton->size);
+  ctx.eval (dlbaton->data, dlbaton->size);
 
   switch (ctx.location)
     {
     case DWARF_VALUE_REGISTER:
     case DWARF_VALUE_MEMORY:
     case DWARF_VALUE_STACK:
-      *valp = dwarf_expr_fetch_address (&ctx, 0);
+      *valp = ctx.fetch_address (0);
       if (ctx.location == DWARF_VALUE_REGISTER)
 	*valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
       return 1;
@@ -2809,7 +2809,7 @@ needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
   nf_baton->needs = SYMBOL_NEEDS_FRAME;
 
   /* The expression may require some stub values on DWARF stack.  */
-  dwarf_expr_push_address (ctx, 0, 0);
+  ctx->push_address (0, 0);
 }
 
 /* DW_OP_GNU_addr_index doesn't require a frame.  */
@@ -2874,7 +2874,7 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
   ctx.baton = &baton;
   ctx.funcs = &symbol_needs_ctx_funcs;
 
-  dwarf_expr_eval (&ctx, data, size);
+  ctx.eval (data, size);
 
   in_reg = ctx.location == DWARF_VALUE_REGISTER;
 
-- 
2.7.4

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

* [RFA 02/22] Use RAII to save and restore scalars
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (5 preceding siblings ...)
  2016-09-27  4:45 ` [RFA 21/22] Convert DWARF expr functions to methods Tom Tromey
@ 2016-09-27  4:47 ` Tom Tromey
  2016-09-27 10:24   ` Trevor Saunders
  2016-09-27  4:47 ` [RFA 04/22] Use scoped_restore for current_ui Tom Tromey
                   ` (15 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:47 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch replaces many (but not all) uses of
make_cleanup_restore_integer with a simple RAII-based template class.
It also removes the similar restore_execution_direction cleanup in
favor of this new class.  Subsequent patches will replace other
similar cleanups with this class.

I chose the name "scoped_restore" for this class.  I considered that
perhaps "auto_restore" might be clearer.  Or maybe something else;
it's simple enough to change.

I had hoped that template parameter deduction would work here, but it
did not, and so the patch uses explicit template parameters
everywhere.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* utils.h (class scoped_restore): New class.
	* top.c (execute_command_to_string): Use scoped_restore.
	* python/python.c (python_interactive_command): Use
	scoped_restore.
	(python_command, execute_gdb_command): Likewise.
	* printcmd.c (do_one_display): Use scoped_restore.
	* mi/mi-main.c (exec_continue): Use scoped_restore.
	* mi/mi-cmd-var.c (mi_cmd_var_assign): Use scoped_restore.
	* linux-fork.c (checkpoint_command): Use scoped_restore.
	* infrun.c (restore_execution_direction): Remove.
	(fetch_inferior_event): Use scoped_restore.
	* compile/compile.c (compile_file_command): Use
	scoped_restore.
	(compile_code_command, compile_print_command): Likewise.
	* cli/cli-script.c (execute_user_command): Use
	scoped_restore.
	(while_command, if_command, script_from_file): Likewise.
	* arm-tdep.c (arm_insert_single_step_breakpoint): Use
	scoped_restore.
---
 gdb/ChangeLog         | 22 ++++++++++++++++++++++
 gdb/arm-tdep.c        |  8 ++------
 gdb/cli/cli-script.c  | 18 ++++--------------
 gdb/compile/compile.c | 23 ++++++++---------------
 gdb/infrun.c          | 16 ++--------------
 gdb/linux-fork.c      | 11 ++++++-----
 gdb/mi/mi-cmd-var.c   |  7 +------
 gdb/mi/mi-main.c      |  3 +--
 gdb/printcmd.c        |  5 +----
 gdb/python/python.c   | 12 +++---------
 gdb/top.c             |  3 +--
 gdb/utils.h           | 44 ++++++++++++++++++++++++++++++++++++++++++++
 12 files changed, 95 insertions(+), 77 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2f28e54..104048f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,27 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* utils.h (class scoped_restore): New class.
+	* top.c (execute_command_to_string): Use scoped_restore.
+	* python/python.c (python_interactive_command): Use
+	scoped_restore.
+	(python_command, execute_gdb_command): Likewise.
+	* printcmd.c (do_one_display): Use scoped_restore.
+	* mi/mi-main.c (exec_continue): Use scoped_restore.
+	* mi/mi-cmd-var.c (mi_cmd_var_assign): Use scoped_restore.
+	* linux-fork.c (checkpoint_command): Use scoped_restore.
+	* infrun.c (restore_execution_direction): Remove.
+	(fetch_inferior_event): Use scoped_restore.
+	* compile/compile.c (compile_file_command): Use
+	scoped_restore.
+	(compile_code_command, compile_print_command): Likewise.
+	* cli/cli-script.c (execute_user_command): Use
+	scoped_restore.
+	(while_command, if_command, script_from_file): Likewise.
+	* arm-tdep.c (arm_insert_single_step_breakpoint): Use
+	scoped_restore.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* selftest.c: Include <vector>, not "vec.h".
 	(self_test_function_ptr): Remove.
 	(tests): Now a std::vector.
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 4dfd76b..d7a8799 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -4205,15 +4205,11 @@ arm_insert_single_step_breakpoint (struct gdbarch *gdbarch,
 				   struct address_space *aspace,
 				   CORE_ADDR pc)
 {
-  struct cleanup *old_chain
-    = make_cleanup_restore_integer (&arm_override_mode);
-
-  arm_override_mode = IS_THUMB_ADDR (pc);
+  scoped_restore<int> save_override_mode (&arm_override_mode,
+					  IS_THUMB_ADDR (pc));
   pc = gdbarch_addr_bits_remove (gdbarch, pc);
 
   insert_single_step_breakpoint (gdbarch, aspace, pc);
-
-  do_cleanups (old_chain);
 }
 
 /* Given BUF, which is OLD_LEN bytes ending at ENDADDR, expand
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 579d0a4..bf18226 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -380,8 +380,7 @@ execute_user_command (struct cmd_list_element *c, char *args)
      not confused with Insight.  */
   in_user_command = 1;
 
-  make_cleanup_restore_integer (&current_ui->async);
-  current_ui->async = 0;
+  scoped_restore<int> save_async (&current_ui->async, 0);
 
   command_nest_depth++;
   while (cmdlines)
@@ -654,7 +653,6 @@ static void
 while_command (char *arg, int from_tty)
 {
   struct command_line *command = NULL;
-  struct cleanup *old_chain;
 
   control_level = 1;
   command = get_command_line (while_control, arg);
@@ -662,13 +660,10 @@ while_command (char *arg, int from_tty)
   if (command == NULL)
     return;
 
-  old_chain = make_cleanup_restore_integer (&current_ui->async);
-  current_ui->async = 0;
+  scoped_restore<int> save_async (&current_ui->async, 0);
 
   execute_control_command_untraced (command);
   free_command_lines (&command);
-
-  do_cleanups (old_chain);
 }
 
 /* "if" command support.  Execute either the true or false arm depending
@@ -686,13 +681,10 @@ if_command (char *arg, int from_tty)
   if (command == NULL)
     return;
 
-  old_chain = make_cleanup_restore_integer (&current_ui->async);
-  current_ui->async = 0;
+  scoped_restore<int> save_async (&current_ui->async, 0);
 
   execute_control_command_untraced (command);
   free_command_lines (&command);
-
-  do_cleanups (old_chain);
 }
 
 /* Cleanup */
@@ -1693,10 +1685,8 @@ script_from_file (FILE *stream, const char *file)
   source_line_number = 0;
   source_file_name = file;
 
-  make_cleanup_restore_integer (&current_ui->async);
-  current_ui->async = 0;
-
   {
+    scoped_restore<int> save_async (&current_ui->async, 0);
 
     TRY
       {
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 0c4a738..e2be115 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -91,8 +91,7 @@ compile_file_command (char *arg, int from_tty)
   char *buffer;
   struct cleanup *cleanup;
 
-  cleanup = make_cleanup_restore_integer (&current_ui->async);
-  current_ui->async = 0;
+  scoped_restore<int> save_async (&current_ui->async, 0);
 
   /* Check the user did not just <enter> after command.  */
   if (arg == NULL)
@@ -115,7 +114,7 @@ compile_file_command (char *arg, int from_tty)
 
   arg = skip_spaces (arg);
   arg = gdb_abspath (arg);
-  make_cleanup (xfree, arg);
+  cleanup = make_cleanup (xfree, arg);
   buffer = xstrprintf ("#include \"%s\"\n", arg);
   make_cleanup (xfree, buffer);
   eval_compile_command (NULL, buffer, scope, NULL);
@@ -130,11 +129,9 @@ compile_file_command (char *arg, int from_tty)
 static void
 compile_code_command (char *arg, int from_tty)
 {
-  struct cleanup *cleanup;
   enum compile_i_scope_types scope = COMPILE_I_SIMPLE_SCOPE;
 
-  cleanup = make_cleanup_restore_integer (&current_ui->async);
-  current_ui->async = 0;
+  scoped_restore<int> save_async (&current_ui->async, 0);
 
   if (arg != NULL && check_raw_argument (&arg))
     {
@@ -155,13 +152,12 @@ compile_code_command (char *arg, int from_tty)
   else
     {
       struct command_line *l = get_command_line (compile_control, "");
+      struct cleanup *cleanup = make_cleanup_free_command_lines (&l);
 
-      make_cleanup_free_command_lines (&l);
       l->control_u.compile.scope = scope;
       execute_control_command_untraced (l);
+      do_cleanups (cleanup);
     }
-
-  do_cleanups (cleanup);
 }
 
 /* Callback for compile_print_command.  */
@@ -183,12 +179,10 @@ static void
 compile_print_command (char *arg_param, int from_tty)
 {
   const char *arg = arg_param;
-  struct cleanup *cleanup;
   enum compile_i_scope_types scope = COMPILE_I_PRINT_ADDRESS_SCOPE;
   struct format_data fmt;
 
-  cleanup = make_cleanup_restore_integer (&current_ui->async);
-  current_ui->async = 0;
+  scoped_restore<int> save_async (&current_ui->async, 0);
 
   /* Passing &FMT as SCOPE_DATA is safe as do_module_cleanup will not
      touch the stale pointer if compile_object_run has already quit.  */
@@ -199,14 +193,13 @@ compile_print_command (char *arg_param, int from_tty)
   else
     {
       struct command_line *l = get_command_line (compile_control, "");
+      struct cleanup *cleanup = make_cleanup_free_command_lines (&l);
 
-      make_cleanup_free_command_lines (&l);
       l->control_u.compile.scope = scope;
       l->control_u.compile.scope_data = &fmt;
       execute_control_command_untraced (l);
+      do_cleanups (cleanup);
     }
-
-  do_cleanups (cleanup);
 }
 
 /* A cleanup function to remove a directory and all its contents.  */
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 2636a19..7832a5d 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3879,17 +3879,6 @@ all_uis_on_sync_execution_starting (void)
     }
 }
 
-/* A cleanup that restores the execution direction to the value saved
-   in *ARG.  */
-
-static void
-restore_execution_direction (void *arg)
-{
-  enum exec_direction_kind *save_exec_dir = (enum exec_direction_kind *) arg;
-
-  execution_direction = *save_exec_dir;
-}
-
 /* Asynchronous version of wait_for_inferior.  It is called by the
    event loop whenever a change of state is detected on the file
    descriptor corresponding to the target.  It can be called more than
@@ -3906,7 +3895,6 @@ fetch_inferior_event (void *client_data)
   struct execution_control_state *ecs = &ecss;
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   struct cleanup *ts_old_chain;
-  enum exec_direction_kind save_exec_dir = execution_direction;
   int cmd_done = 0;
   ptid_t waiton_ptid = minus_one_ptid;
 
@@ -3945,8 +3933,8 @@ fetch_inferior_event (void *client_data)
      event.  */
   target_dcache_invalidate ();
 
-  make_cleanup (restore_execution_direction, &save_exec_dir);
-  execution_direction = target_execution_direction ();
+  scoped_restore<enum exec_direction_kind>
+    save_exec_dir (&execution_direction, target_execution_direction ());
 
   ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws,
 			      target_can_async_p () ? TARGET_WNOHANG : 0);
diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c
index e7202dd..9c2cf8a 100644
--- a/gdb/linux-fork.c
+++ b/gdb/linux-fork.c
@@ -680,7 +680,6 @@ checkpoint_command (char *args, int from_tty)
   struct value *fork_fn = NULL, *ret;
   struct fork_info *fp;
   pid_t retpid;
-  struct cleanup *old_chain;
 
   if (!target_has_execution) 
     error (_("The program is not being run."));
@@ -704,11 +703,13 @@ checkpoint_command (char *args, int from_tty)
   ret = value_from_longest (builtin_type (gdbarch)->builtin_int, 0);
 
   /* Tell linux-nat.c that we're checkpointing this inferior.  */
-  old_chain = make_cleanup_restore_integer (&checkpointing_pid);
-  checkpointing_pid = ptid_get_pid (inferior_ptid);
+  {
+    scoped_restore<int> save_pid (&checkpointing_pid,
+				  ptid_get_pid (inferior_ptid));
+
+    ret = call_function_by_hand (fork_fn, 0, &ret);
+  }
 
-  ret = call_function_by_hand (fork_fn, 0, &ret);
-  do_cleanups (old_chain);
   if (!ret)	/* Probably can't happen.  */
     error (_("checkpoint: call_function_by_hand returned null."));
 
diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c
index 3bfe4f0..1c78104 100644
--- a/gdb/mi/mi-cmd-var.c
+++ b/gdb/mi/mi-cmd-var.c
@@ -608,7 +608,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)
     error (_("-var-assign: Usage: NAME EXPRESSION."));
@@ -623,9 +622,7 @@ mi_cmd_var_assign (char *command, char **argv, int argc)
 
   /* MI command '-var-assign' may write memory, so suppress memory
      changed notification if it does.  */
-  cleanup
-    = make_cleanup_restore_integer (&mi_suppress_notification.memory);
-  mi_suppress_notification.memory = 1;
+  scoped_restore<int> save_suppress (&mi_suppress_notification.memory, 1);
 
   if (!varobj_set_value (var, expression))
     error (_("-var-assign: Could not assign "
@@ -634,8 +631,6 @@ mi_cmd_var_assign (char *command, char **argv, int argc)
   val = varobj_get_value (var);
   ui_out_field_string (uiout, "value", val);
   xfree (val);
-
-  do_cleanups (cleanup);
 }
 
 /* Type used for parameters passing to mi_cmd_var_update_iter.  */
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 1913157..c6c7067 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -300,7 +300,7 @@ exec_continue (char **argv, int argc)
     }
   else
     {
-      struct cleanup *back_to = make_cleanup_restore_integer (&sched_multi);
+      scoped_restore<int> save_multi (&sched_multi);
 
       if (current_context->all)
 	{
@@ -315,7 +315,6 @@ exec_continue (char **argv, int argc)
 	     same.  */
 	  continue_1 (1);
 	}
-      do_cleanups (back_to);
     }
 }
 
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index d4a4b9e..1fccd26 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1938,7 +1938,6 @@ undisplay_command (char *args, int from_tty)
 static void
 do_one_display (struct display *d)
 {
-  struct cleanup *old_chain;
   int within_current_scope;
 
   if (d->enabled_p == 0)
@@ -1990,8 +1989,7 @@ do_one_display (struct display *d)
   if (!within_current_scope)
     return;
 
-  old_chain = make_cleanup_restore_integer (&current_display_number);
-  current_display_number = d->number;
+  scoped_restore<int> save_display_number (&current_display_number, d->number);
 
   annotate_display_begin ();
   printf_filtered ("%d", d->number);
@@ -2079,7 +2077,6 @@ do_one_display (struct display *d)
   annotate_display_end ();
 
   gdb_flush (gdb_stdout);
-  do_cleanups (old_chain);
 }
 
 /* Display all of the values on the auto-display chain which can be
diff --git a/gdb/python/python.c b/gdb/python/python.c
index b00b70b..9e4d610 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -319,11 +319,9 @@ static void
 python_interactive_command (char *arg, int from_tty)
 {
   struct ui *ui = current_ui;
-  struct cleanup *cleanup;
   int err;
 
-  cleanup = make_cleanup_restore_integer (&current_ui->async);
-  current_ui->async = 0;
+  scoped_restore<int> save_async (&current_ui->async, 0);
 
   arg = skip_spaces (arg);
 
@@ -351,8 +349,6 @@ python_interactive_command (char *arg, int from_tty)
       gdbpy_print_stack ();
       error (_("Error while executing Python code."));
     }
-
-  do_cleanups (cleanup);
 }
 
 /* A wrapper around PyRun_SimpleFile.  FILE is the Python script to run
@@ -467,8 +463,7 @@ python_command (char *arg, int from_tty)
 
   cleanup = ensure_python_env (get_current_arch (), current_language);
 
-  make_cleanup_restore_integer (&current_ui->async);
-  current_ui->async = 0;
+  scoped_restore<int> save_async (&current_ui->async, 0);
 
   arg = skip_spaces (arg);
   if (arg && *arg)
@@ -651,8 +646,7 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
       struct cleanup *cleanup = make_cleanup (xfree, copy);
       struct interp *interp;
 
-      make_cleanup_restore_integer (&current_ui->async);
-      current_ui->async = 0;
+      scoped_restore<int> save_async (&current_ui->async, 0);
 
       make_cleanup_restore_current_uiout ();
 
diff --git a/gdb/top.c b/gdb/top.c
index 3cfa113..84285b2 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -701,8 +701,7 @@ execute_command_to_string (char *p, int from_tty)
      restoration callbacks.  */
   cleanup = set_batch_flag_and_make_cleanup_restore_page_info ();
 
-  make_cleanup_restore_integer (&current_ui->async);
-  current_ui->async = 0;
+  scoped_restore<int> save_async (&current_ui->async, 0);
 
   str_file = mem_fileopen ();
 
diff --git a/gdb/utils.h b/gdb/utils.h
index 8635075..63583ed 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -84,6 +84,50 @@ extern struct cleanup *make_cleanup_bfd_unref (bfd *abfd);
 struct obstack;
 extern struct cleanup *make_cleanup_obstack_free (struct obstack *obstack);
 
+// An RAII-based object that saves a variable's value, and then
+// restores it again when this object is destroyed.
+template<typename T>
+class scoped_restore
+{
+ public:
+
+  // Create a new scoped_restore object that saves the current value
+  // of *VAR, and then sets *VAR to VALUE.  *VAR will be restored when
+  // this scoped_restore object is destroyed.
+  scoped_restore (T *var, T value)
+    : saved_var (var),
+      saved_value (*var)
+  {
+    *var = value;
+  }
+
+  // Create a new scoped_restore object that saves the current value
+  // of *VAR.  *VAR will be restored when this scoped_restore object
+  // is destroyed.
+  explicit scoped_restore (T *var)
+    : saved_var (var),
+      saved_value (*var)
+  {
+  }
+
+  ~scoped_restore ()
+  {
+    *saved_var = saved_value;
+  }
+
+ private:
+
+  // No need for these.  They are intentionally not defined anywhere.
+  scoped_restore &operator= (const scoped_restore &);
+  scoped_restore (const scoped_restore &);
+
+  // The saved variable.
+  T *saved_var;
+
+  // The saved value.
+  T saved_value;
+};
+
 extern struct cleanup *make_cleanup_restore_integer (int *variable);
 extern struct cleanup *make_cleanup_restore_uinteger (unsigned int *variable);
 
-- 
2.7.4

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

* [RFA 04/22] Use scoped_restore for current_ui
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (6 preceding siblings ...)
  2016-09-27  4:47 ` [RFA 02/22] Use RAII to save and restore scalars Tom Tromey
@ 2016-09-27  4:47 ` Tom Tromey
  2016-09-27  4:47 ` [RFA 05/22] Turn wchar iterator into a class Tom Tromey
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:47 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes most uses of make_cleanup_restore_current_ui to use
scoped_restore.  The use in switch_thru_all_uis_init still remains;
that can be dealt with by replacing this iterator with a real class.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* top.c (new_ui_command, wait_sync_command_done)
	(gdb_readline_wrapper): Use scoped_restore.
	* infrun.c (fetch_inferior_event): Use scoped_restore.
	* infcall.c (call_thread_fsm_should_stop): Use scoped_restore.
---
 gdb/ChangeLog |  7 +++++++
 gdb/infcall.c |  8 +-------
 gdb/infrun.c  |  3 +--
 gdb/top.c     | 44 ++++++++++++++++++++++----------------------
 4 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index da69ce8..42c432d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,12 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* top.c (new_ui_command, wait_sync_command_done)
+	(gdb_readline_wrapper): Use scoped_restore.
+	* infrun.c (fetch_inferior_event): Use scoped_restore.
+	* infcall.c (call_thread_fsm_should_stop): Use scoped_restore.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* utils.c (make_cleanup_restore_ui_file, do_restore_ui_file)
 	(struct restore_ui_file_closure): Remove.
 	* utils.h (make_cleanup_restore_ui_file): Don't declare.
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 3c33c11..60b0a70 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -519,8 +519,6 @@ call_thread_fsm_should_stop (struct thread_fsm *self,
 
   if (stop_stack_dummy == STOP_STACK_DUMMY)
     {
-      struct cleanup *old_chain;
-
       /* Done.  */
       thread_fsm_set_finished (self);
 
@@ -530,13 +528,9 @@ call_thread_fsm_should_stop (struct thread_fsm *self,
       f->return_value = get_call_return_value (&f->return_meta_info);
 
       /* Break out of wait_sync_command_done.  */
-      old_chain = make_cleanup_restore_current_ui ();
-      current_ui = f->waiting_ui;
+      scoped_restore<struct ui *> save_ui (&current_ui, f->waiting_ui);
       target_terminal_ours ();
       f->waiting_ui->prompt_state = PROMPT_NEEDED;
-
-      /* This restores the previous UI.  */
-      do_cleanups (old_chain);
     }
 
   return 1;
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 7832a5d..6d96af9 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3903,8 +3903,7 @@ fetch_inferior_event (void *client_data)
   /* Events are always processed with the main UI as current UI.  This
      way, warnings, debug output, etc. are always consistently sent to
      the main console.  */
-  make_cleanup_restore_current_ui ();
-  current_ui = main_ui;
+  scoped_restore<struct ui *> save_ui (&current_ui, main_ui);
 
   /* End up with readline processing input, if necessary.  */
   make_cleanup (reinstall_readline_callback_handler_cleanup, NULL);
diff --git a/gdb/top.c b/gdb/top.c
index d782466..77845c0 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -386,33 +386,35 @@ new_ui_command (char *args, int from_tty)
   interpreter_name = argv[0];
   tty_name = argv[1];
 
-  make_cleanup_restore_current_ui ();
+  {
+    scoped_restore<struct ui *> save_ui (&current_ui);
 
-  failure_chain = make_cleanup (null_cleanup, NULL);
+    failure_chain = make_cleanup (null_cleanup, NULL);
 
-  /* Open specified terminal, once for each of
-     stdin/stdout/stderr.  */
-  for (i = 0; i < 3; i++)
-    {
-      stream[i] = open_terminal_stream (tty_name);
-      make_cleanup_fclose (stream[i]);
-    }
+    /* Open specified terminal, once for each of
+       stdin/stdout/stderr.  */
+    for (i = 0; i < 3; i++)
+      {
+	stream[i] = open_terminal_stream (tty_name);
+	make_cleanup_fclose (stream[i]);
+      }
 
-  ui = new_ui (stream[0], stream[1], stream[2]);
-  make_cleanup (delete_ui_cleanup, ui);
+    ui = new_ui (stream[0], stream[1], stream[2]);
+    make_cleanup (delete_ui_cleanup, ui);
 
-  ui->async = 1;
+    ui->async = 1;
 
-  current_ui = ui;
+    current_ui = ui;
 
-  set_top_level_interpreter (interpreter_name);
+    set_top_level_interpreter (interpreter_name);
 
-  interp_pre_command_loop (top_level_interpreter ());
+    interp_pre_command_loop (top_level_interpreter ());
 
-  discard_cleanups (failure_chain);
+    discard_cleanups (failure_chain);
 
-  /* This restores the previous UI and frees argv.  */
-  do_cleanups (success_chain);
+    /* This restores the previous UI and frees argv.  */
+    do_cleanups (success_chain);
+  }
 
   printf_unfiltered ("New UI allocated\n");
 }
@@ -562,14 +564,12 @@ void
 wait_sync_command_done (void)
 {
   /* Processing events may change the current UI.  */
-  struct cleanup *old_chain = make_cleanup_restore_current_ui ();
+  scoped_restore<struct ui *> save_ui (&current_ui);
   struct ui *ui = current_ui;
 
   while (gdb_do_one_event () >= 0)
     if (ui->prompt_state != PROMPT_BLOCKED)
       break;
-
-  do_cleanups (old_chain);
 }
 
 /* See top.h.  */
@@ -1031,7 +1031,7 @@ gdb_readline_wrapper (const char *prompt)
   back_to = make_cleanup (gdb_readline_wrapper_cleanup, cleanup);
 
   /* Processing events may change the current UI.  */
-  make_cleanup_restore_current_ui ();
+  scoped_restore<struct ui *> save_ui (&current_ui);
 
   if (cleanup->target_is_async_orig)
     target_async (0);
-- 
2.7.4

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

* [RFA 22/22] Convert dwarf_expr_context_funcs to methods
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (8 preceding siblings ...)
  2016-09-27  4:47 ` [RFA 05/22] Turn wchar iterator into a class Tom Tromey
@ 2016-09-27  4:47 ` Tom Tromey
  2016-10-09 19:11   ` Pedro Alves
  2016-09-27  4:48 ` [RFA 09/22] Remove make_cleanup_restore_current_ui Tom Tromey
                   ` (12 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:47 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch converts the function pointers in dwarf_expr_context_funcs
into methods on dwarf_expr_context, and then updates the various
implementations and callers to follow.

NB this patch uses "override" (which caught a couple of renaming bugs
during development) -- but this is C++11, so this patch at least has
to wait for Pedro's patch that adds the OVERRIDE macro.

After this patch it would be possible to do one more, that makes
various members of dwarf_expr_context "protected"; but I haven't done
this.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* dwarf2loc.c (struct dwarf_expr_context_funcs): Don't declare.
	(dwarf_expr_read_addr_from_reg, dwarf_expr_get_reg_value)
	(dwarf_expr_read_mem, dwarf_expr_frame_base): Rename; turn into
	methods.
	(get_frame_pc_for_per_cu_dwarf_call): New function.
	(dwarf_expr_frame_cfa, dwarf_expr_frame_pc)
	(dwarf_expr_tls_address): Rename; turn into methods.
	(per_cu_dwarf_call): Remove arguments.  Use
	get_frame_pc_for_per_cu_dwarf_call.
	(dwarf_evaluate_loc_desc): New class.
	(dwarf_expr_dwarf_call, dwarf_expr_context)
	(dwarf_expr_push_dwarf_reg_entry_value)
	(dwarf_expr_get_addr_index, dwarf_expr_get_obj_addr): Rename; turn
	into methods.
	(dwarf_expr_ctx_funcs): Remove.
	(dwarf2_evaluate_loc_desc_full): Update.
	(dwarf2_locexpr_baton_eval): Update.
	(symbol_needs_eval_context): New class.
	(symbol_needs_read_addr_from_reg, symbol_needs_get_reg_value)
	(symbol_needs_read_mem, symbol_needs_frame_base)
	(symbol_needs_frame_cfa, symbol_needs_tls_address)
	(symbol_needs_dwarf_call, needs_dwarf_reg_entry_value): Rename;
	turn into methods.
	(needs_get_addr_index, needs_get_obj_addr): Remove; turn into
	methods.
	(symbol_needs_ctx_funcs): Remove.
	(dwarf2_loc_desc_get_symbol_read_needs): Update.
	* dwarf2expr.h (struct dwarf_expr_context_funcs): Remove; turn
	contents into methods.
	(struct dwarf_expr_context) <baton, funcs>: Remove.
	<read_addr_from_reg, get_reg_value, read_mem, get_frame_base,
	get_frame_cfa, get_frame_pc, get_tls_address, dwarf_call,
	impl_get_base_type, push_dwarf_block_entry_value, get_addr_index,
	get_object_address>: Declare new methods.
	(ctx_no_get_frame_base, ctx_no_get_frame_cfa)
	(ctx_no_get_frame_pc, ctx_no_get_tls_address, ctx_no_dwarf_call)
	(ctx_no_get_base_type, ctx_no_push_dwarf_reg_entry_value)
	(ctx_no_get_addr_index): Don't declare.
	* dwarf2expr.c (get_base_type): Use impl_get_base_type.
	(execute_stack_op): Update.
	(ctx_no_get_frame_base, ctx_no_get_frame_cfa)
	(ctx_no_get_frame_pc, ctx_no_get_tls_address, ctx_no_dwarf_call)
	(ctx_no_get_base_type, ctx_no_push_dwarf_reg_entry_value)
	(ctx_no_get_addr_index): Remove; now methods on
	dwarf_expr_context.
	* dwarf2-frame.c (read_addr_from_reg): Take a frame_info, not a
	baton.
	(class dwarf_expr_executor): New class.
	(get_reg_value, read_mem): Rename, turn into methods.
	(execute_stack_op): Use dwarf_expr_executor.
---
 gdb/ChangeLog      |  53 +++++
 gdb/dwarf2-frame.c |  65 +++---
 gdb/dwarf2expr.c   | 136 +++--------
 gdb/dwarf2expr.h   | 172 +++++++-------
 gdb/dwarf2loc.c    | 649 +++++++++++++++++++++++------------------------------
 5 files changed, 468 insertions(+), 607 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fbbd640..553ecda 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,58 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* dwarf2loc.c (struct dwarf_expr_context_funcs): Don't declare.
+	(dwarf_expr_read_addr_from_reg, dwarf_expr_get_reg_value)
+	(dwarf_expr_read_mem, dwarf_expr_frame_base): Rename; turn into
+	methods.
+	(get_frame_pc_for_per_cu_dwarf_call): New function.
+	(dwarf_expr_frame_cfa, dwarf_expr_frame_pc)
+	(dwarf_expr_tls_address): Rename; turn into methods.
+	(per_cu_dwarf_call): Remove arguments.  Use
+	get_frame_pc_for_per_cu_dwarf_call.
+	(dwarf_evaluate_loc_desc): New class.
+	(dwarf_expr_dwarf_call, dwarf_expr_context)
+	(dwarf_expr_push_dwarf_reg_entry_value)
+	(dwarf_expr_get_addr_index, dwarf_expr_get_obj_addr): Rename; turn
+	into methods.
+	(dwarf_expr_ctx_funcs): Remove.
+	(dwarf2_evaluate_loc_desc_full): Update.
+	(dwarf2_locexpr_baton_eval): Update.
+	(symbol_needs_eval_context): New class.
+	(symbol_needs_read_addr_from_reg, symbol_needs_get_reg_value)
+	(symbol_needs_read_mem, symbol_needs_frame_base)
+	(symbol_needs_frame_cfa, symbol_needs_tls_address)
+	(symbol_needs_dwarf_call, needs_dwarf_reg_entry_value): Rename;
+	turn into methods.
+	(needs_get_addr_index, needs_get_obj_addr): Remove; turn into
+	methods.
+	(symbol_needs_ctx_funcs): Remove.
+	(dwarf2_loc_desc_get_symbol_read_needs): Update.
+	* dwarf2expr.h (struct dwarf_expr_context_funcs): Remove; turn
+	contents into methods.
+	(struct dwarf_expr_context) <baton, funcs>: Remove.
+	<read_addr_from_reg, get_reg_value, read_mem, get_frame_base,
+	get_frame_cfa, get_frame_pc, get_tls_address, dwarf_call,
+	impl_get_base_type, push_dwarf_block_entry_value, get_addr_index,
+	get_object_address>: Declare new methods.
+	(ctx_no_get_frame_base, ctx_no_get_frame_cfa)
+	(ctx_no_get_frame_pc, ctx_no_get_tls_address, ctx_no_dwarf_call)
+	(ctx_no_get_base_type, ctx_no_push_dwarf_reg_entry_value)
+	(ctx_no_get_addr_index): Don't declare.
+	* dwarf2expr.c (get_base_type): Use impl_get_base_type.
+	(execute_stack_op): Update.
+	(ctx_no_get_frame_base, ctx_no_get_frame_cfa)
+	(ctx_no_get_frame_pc, ctx_no_get_tls_address, ctx_no_dwarf_call)
+	(ctx_no_get_base_type, ctx_no_push_dwarf_reg_entry_value)
+	(ctx_no_get_addr_index): Remove; now methods on
+	dwarf_expr_context.
+	* dwarf2-frame.c (read_addr_from_reg): Take a frame_info, not a
+	baton.
+	(class dwarf_expr_executor): New class.
+	(get_reg_value, read_mem): Rename, turn into methods.
+	(execute_stack_op): Use dwarf_expr_executor.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* dwarf2loc.c (per_cu_dwarf_call)
 	(dwarf_expr_push_dwarf_reg_entry_value)
 	(dwarf2_evaluate_loc_desc_full, dwarf2_locexpr_baton_eval)
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index c93c362..1988afb 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -288,33 +288,14 @@ dwarf2_frame_state_free (void *p)
 /* Helper functions for execute_stack_op.  */
 
 static CORE_ADDR
-read_addr_from_reg (void *baton, int reg)
+read_addr_from_reg (struct frame_info *this_frame, int reg)
 {
-  struct frame_info *this_frame = (struct frame_info *) baton;
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg);
 
   return address_from_register (regnum, this_frame);
 }
 
-/* Implement struct dwarf_expr_context_funcs' "get_reg_value" callback.  */
-
-static struct value *
-get_reg_value (void *baton, struct type *type, int reg)
-{
-  struct frame_info *this_frame = (struct frame_info *) baton;
-  struct gdbarch *gdbarch = get_frame_arch (this_frame);
-  int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg);
-
-  return value_from_register (type, regnum, this_frame);
-}
-
-static void
-read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
-{
-  read_memory (addr, buf, len);
-}
-
 /* Execute the required actions for both the DW_CFA_restore and
 DW_CFA_restore_extended instructions.  */
 static void
@@ -347,21 +328,29 @@ register %s (#%d) at %s"),
     }
 }
 
-/* Virtual method table for execute_stack_op below.  */
-
-static const struct dwarf_expr_context_funcs dwarf2_frame_ctx_funcs =
+class dwarf_expr_executor : public dwarf_expr_context
 {
-  read_addr_from_reg,
-  get_reg_value,
-  read_mem,
-  ctx_no_get_frame_base,
-  ctx_no_get_frame_cfa,
-  ctx_no_get_frame_pc,
-  ctx_no_get_tls_address,
-  ctx_no_dwarf_call,
-  ctx_no_get_base_type,
-  ctx_no_push_dwarf_reg_entry_value,
-  ctx_no_get_addr_index
+ public:
+
+  struct frame_info *this_frame;
+
+  CORE_ADDR read_addr_from_reg (int reg) override
+  {
+    return ::read_addr_from_reg (this_frame, reg);
+  }
+
+  struct value *get_reg_value (struct type *type, int reg) override
+  {
+    struct gdbarch *gdbarch = get_frame_arch (this_frame);
+    int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg);
+
+    return value_from_register (type, regnum, this_frame);
+  }
+
+  void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) override
+  {
+    read_memory (addr, buf, len);
+  }
 };
 
 static CORE_ADDR
@@ -372,15 +361,14 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
   CORE_ADDR result;
   struct cleanup *old_chain;
 
-  dwarf_expr_context ctx;
+  dwarf_expr_executor ctx;
   old_chain = make_cleanup_value_free_to_mark (value_mark ());
 
+  ctx.this_frame = this_frame;
   ctx.gdbarch = get_frame_arch (this_frame);
   ctx.addr_size = addr_size;
   ctx.ref_addr_size = -1;
   ctx.offset = offset;
-  ctx.baton = this_frame;
-  ctx.funcs = &dwarf2_frame_ctx_funcs;
 
   ctx.push_address (initial, initial_in_stack_memory);
   ctx.eval (exp, len);
@@ -388,8 +376,7 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
   if (ctx.location == DWARF_VALUE_MEMORY)
     result = ctx.fetch_address (0);
   else if (ctx.location == DWARF_VALUE_REGISTER)
-    result = read_addr_from_reg (this_frame,
-				 value_as_long (ctx.fetch (0)));
+    result = ctx.read_addr_from_reg (value_as_long (ctx.fetch (0)));
   else
     {
       /* This is actually invalid DWARF, but if we ever do run across
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index 2b22e0b..024c79b 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -416,20 +416,11 @@ base_types_equal_p (struct type *t1, struct type *t2)
 struct type *
 dwarf_expr_context::get_base_type (cu_offset die, int size)
 {
-  struct type *result;
-
-  if (this->funcs->get_base_type)
-    {
-      result = this->funcs->get_base_type (this, die);
-      if (result == NULL)
-	error (_("Could not find type for DW_OP_GNU_const_type"));
-      if (size != 0 && TYPE_LENGTH (result) != size)
-	error (_("DW_OP_GNU_const_type has different sizes for type and data"));
-    }
-  else
-    /* Anything will do.  */
-    result = builtin_type (this->gdbarch)->builtin_int;
-
+  struct type *result = this->impl_get_base_type (die);
+  if (result == NULL)
+    error (_("Could not find type for DW_OP_GNU_const_type"));
+  if (size != 0 && TYPE_LENGTH (result) != size)
+    error (_("DW_OP_GNU_const_type has different sizes for type and data"));
   return result;
 }
 
@@ -700,13 +691,13 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 
 	case DW_OP_GNU_addr_index:
 	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
-	  result = (this->funcs->get_addr_index) (this->baton, uoffset);
+	  result = (this->get_addr_index) (uoffset);
 	  result += this->offset;
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 	case DW_OP_GNU_const_index:
 	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
-	  result = (this->funcs->get_addr_index) (this->baton, uoffset);
+	  result = (this->get_addr_index) (uoffset);
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 
@@ -896,8 +887,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	case DW_OP_breg31:
 	  {
 	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
-	    result = (this->funcs->read_addr_from_reg) (this->baton,
-						       op - DW_OP_breg0);
+	    result = (this->read_addr_from_reg) (op - DW_OP_breg0);
 	    result += offset;
 	    result_val = value_from_ulongest (address_type, result);
 	  }
@@ -906,7 +896,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	  {
 	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
 	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
-	    result = (this->funcs->read_addr_from_reg) (this->baton, reg);
+	    result = (this->read_addr_from_reg) (reg);
 	    result += offset;
 	    result_val = value_from_ulongest (address_type, result);
 	  }
@@ -926,14 +916,12 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	    /* FIXME: cagney/2003-03-26: This code should be using
                get_frame_base_address(), and then implement a dwarf2
                specific this_base method.  */
-	    (this->funcs->get_frame_base) (this->baton, &datastart, &datalen);
+	    (this->get_frame_base) (&datastart, &datalen);
 	    eval (datastart, datalen);
 	    if (this->location == DWARF_VALUE_MEMORY)
 	      result = fetch_address (0);
 	    else if (this->location == DWARF_VALUE_REGISTER)
-	      result = (this->funcs->read_addr_from_reg)
-			  (this->baton,
-			   value_as_long (fetch (0)));
+	      result = (this->read_addr_from_reg) (value_as_long (fetch (0)));
 	    else
 	      error (_("Not implemented: computing frame "
 		       "base using explicit value operator"));
@@ -1019,7 +1007,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	    else
 	      type = address_type;
 
-	    (this->funcs->read_mem) (this->baton, buf, addr, addr_size);
+	    (this->read_mem) (buf, addr, addr_size);
 
 	    /* If the size of the object read from memory is different
 	       from the type length, we need to zero-extend it.  */
@@ -1228,7 +1216,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	  break;
 
 	case DW_OP_call_frame_cfa:
-	  result = (this->funcs->get_frame_cfa) (this->baton);
+	  result = (this->get_frame_cfa) ();
 	  result_val = value_from_ulongest (address_type, result);
 	  in_stack_memory = 1;
 	  break;
@@ -1245,7 +1233,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	  returned.  */
 	  result = value_as_long (fetch (0));
 	  pop ();
-	  result = (this->funcs->get_tls_address) (this->baton, result);
+	  result = (this->get_tls_address) (result);
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 
@@ -1321,7 +1309,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 
 	    offset.cu_off = extract_unsigned_integer (op_ptr, 2, byte_order);
 	    op_ptr += 2;
-	    this->funcs->dwarf_call (this, offset);
+	    this->dwarf_call (offset);
 	  }
 	  goto no_push;
 
@@ -1331,7 +1319,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 
 	    offset.cu_off = extract_unsigned_integer (op_ptr, 4, byte_order);
 	    op_ptr += 4;
-	    this->funcs->dwarf_call (this, offset);
+	    this->dwarf_call (offset);
 	  }
 	  goto no_push;
 	
@@ -1349,10 +1337,9 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	    if (kind_u.dwarf_reg != -1)
 	      {
 		op_ptr += len;
-		this->funcs->push_dwarf_reg_entry_value (this,
-						  CALL_SITE_PARAMETER_DWARF_REG,
-							kind_u,
-							-1 /* deref_size */);
+		this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_DWARF_REG,
+						  kind_u,
+						  -1 /* deref_size */);
 		goto no_push;
 	      }
 
@@ -1364,9 +1351,8 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 		if (deref_size == -1)
 		  deref_size = this->addr_size;
 		op_ptr += len;
-		this->funcs->push_dwarf_reg_entry_value (this,
-						  CALL_SITE_PARAMETER_DWARF_REG,
-							kind_u, deref_size);
+		this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_DWARF_REG,
+						  kind_u, deref_size);
 		goto no_push;
 	      }
 
@@ -1382,10 +1368,9 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	    kind_u.param_offset.cu_off = extract_unsigned_integer (op_ptr, 4,
 								   byte_order);
 	    op_ptr += 4;
-	    this->funcs->push_dwarf_reg_entry_value (this,
-					       CALL_SITE_PARAMETER_PARAM_OFFSET,
-						    kind_u,
-						    -1 /* deref_size */);
+	    this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_PARAM_OFFSET,
+					      kind_u,
+					      -1 /* deref_size */);
 	  }
 	  goto no_push;
 
@@ -1417,7 +1402,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	    type_die.cu_off = uoffset;
 
 	    type = get_base_type (type_die, 0);
-	    result_val = this->funcs->get_reg_value (this->baton, type, reg);
+	    result_val = this->get_reg_value (type, reg);
 	  }
 	  break;
 
@@ -1456,7 +1441,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 
 	case DW_OP_push_object_address:
 	  /* Return the address of the object we are currently observing.  */
-	  result = (this->funcs->get_object_address) (this->baton);
+	  result = (this->get_object_address) ();
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 
@@ -1482,75 +1467,6 @@ abort_expression:
   gdb_assert (this->recursion_depth >= 0);
 }
 
-/* Stub dwarf_expr_context_funcs.get_frame_base implementation.  */
-
-void
-ctx_no_get_frame_base (void *baton, const gdb_byte **start, size_t *length)
-{
-  error (_("%s is invalid in this context"), "DW_OP_fbreg");
-}
-
-/* Stub dwarf_expr_context_funcs.get_frame_cfa implementation.  */
-
-CORE_ADDR
-ctx_no_get_frame_cfa (void *baton)
-{
-  error (_("%s is invalid in this context"), "DW_OP_call_frame_cfa");
-}
-
-/* Stub dwarf_expr_context_funcs.get_frame_pc implementation.  */
-
-CORE_ADDR
-ctx_no_get_frame_pc (void *baton)
-{
-  error (_("%s is invalid in this context"), "DW_OP_GNU_implicit_pointer");
-}
-
-/* Stub dwarf_expr_context_funcs.get_tls_address implementation.  */
-
-CORE_ADDR
-ctx_no_get_tls_address (void *baton, CORE_ADDR offset)
-{
-  error (_("%s is invalid in this context"), "DW_OP_form_tls_address");
-}
-
-/* Stub dwarf_expr_context_funcs.dwarf_call implementation.  */
-
-void
-ctx_no_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
-{
-  error (_("%s is invalid in this context"), "DW_OP_call*");
-}
-
-/* Stub dwarf_expr_context_funcs.get_base_type implementation.  */
-
-struct type *
-ctx_no_get_base_type (struct dwarf_expr_context *ctx, cu_offset die)
-{
-  error (_("Support for typed DWARF is not supported in this context"));
-}
-
-/* Stub dwarf_expr_context_funcs.push_dwarf_block_entry_value
-   implementation.  */
-
-void
-ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
-				   enum call_site_parameter_kind kind,
-				   union call_site_parameter_u kind_u,
-				   int deref_size)
-{
-  internal_error (__FILE__, __LINE__,
-		  _("Support for DW_OP_GNU_entry_value is unimplemented"));
-}
-
-/* Stub dwarf_expr_context_funcs.get_addr_index implementation.  */
-
-CORE_ADDR
-ctx_no_get_addr_index (void *baton, unsigned int index)
-{
-  error (_("%s is invalid in this context"), "DW_OP_GNU_addr_index");
-}
-
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 extern initialize_file_ftype _initialize_dwarf2expr;
 
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index 4706bb3..37b3937 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -25,69 +25,6 @@
 #include "leb128.h"
 #include "gdbtypes.h"
 
-struct dwarf_expr_context;
-
-/* Virtual method table for struct dwarf_expr_context below.  */
-
-struct dwarf_expr_context_funcs
-{
-  /* Return the value of register number REGNUM (a DWARF register number),
-     read as an address.  */
-  CORE_ADDR (*read_addr_from_reg) (void *baton, int regnum);
-
-  /* Return a value of type TYPE, stored in register number REGNUM
-     of the frame associated to the given BATON.
-
-     REGNUM is a DWARF register number.  */
-  struct value *(*get_reg_value) (void *baton, struct type *type, int regnum);
-
-  /* Read LENGTH bytes at ADDR into BUF.  */
-  void (*read_mem) (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t length);
-
-  /* Return the location expression for the frame base attribute, in
-     START and LENGTH.  The result must be live until the current
-     expression evaluation is complete.  */
-  void (*get_frame_base) (void *baton, const gdb_byte **start, size_t *length);
-
-  /* Return the CFA for the frame.  */
-  CORE_ADDR (*get_frame_cfa) (void *baton);
-
-  /* Return the PC for the frame.  */
-  CORE_ADDR (*get_frame_pc) (void *baton);
-
-  /* Return the thread-local storage address for
-     DW_OP_GNU_push_tls_address or DW_OP_form_tls_address.  */
-  CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset);
-
-  /* Execute DW_AT_location expression for the DWARF expression subroutine in
-     the DIE at DIE_OFFSET in the CU from CTX.  Do not touch STACK while it
-     being passed to and returned from the called DWARF subroutine.  */
-  void (*dwarf_call) (struct dwarf_expr_context *ctx, cu_offset die_offset);
-
-  /* Return the base type given by the indicated DIE.  This can throw
-     an exception if the DIE is invalid or does not represent a base
-     type.  If can also be NULL in the special case where the
-     callbacks are not performing evaluation, and thus it is
-     meaningful to substitute a stub type of the correct size.  */
-  struct type *(*get_base_type) (struct dwarf_expr_context *ctx, cu_offset die);
-
-  /* Push on DWARF stack an entry evaluated for DW_TAG_GNU_call_site's
-     parameter matching KIND and KIND_U at the caller of specified BATON.
-     If DEREF_SIZE is not -1 then use DW_AT_GNU_call_site_data_value instead of
-     DW_AT_GNU_call_site_value.  */
-  void (*push_dwarf_reg_entry_value) (struct dwarf_expr_context *ctx,
-				      enum call_site_parameter_kind kind,
-				      union call_site_parameter_u kind_u,
-				      int deref_size);
-
-  /* Return the address indexed by DW_OP_GNU_addr_index.
-     This can throw an exception if the index is out of range.  */
-  CORE_ADDR (*get_addr_index) (void *baton, unsigned int index);
-
-  /* Return the `object address' for DW_OP_push_object_address.  */
-  CORE_ADDR (*get_object_address) (void *baton);
-};
-
 /* The location of a value.  */
 enum dwarf_value_location
 {
@@ -159,13 +96,6 @@ struct dwarf_expr_context
   /* Offset used to relocate DW_OP_addr and DW_OP_GNU_addr_index arguments.  */
   CORE_ADDR offset;
 
-  /* An opaque argument provided by the caller, which will be passed
-     to all of the callback functions.  */
-  void *baton;
-
-  /* Callback functions.  */
-  const struct dwarf_expr_context_funcs *funcs;
-
   /* The current depth of dwarf expression recursion, via DW_OP_call*,
      DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum
      depth we'll tolerate before raising an error.  */
@@ -210,6 +140,92 @@ struct dwarf_expr_context
   int num_pieces;
   struct dwarf_expr_piece *pieces;
 
+  /* Return the value of register number REGNUM (a DWARF register number),
+     read as an address.  */
+  virtual CORE_ADDR read_addr_from_reg (int regnum) = 0;
+
+  /* Return a value of type TYPE, stored in register number REGNUM
+     of the frame associated to the given BATON.
+
+     REGNUM is a DWARF register number.  */
+  virtual struct value *get_reg_value (struct type *type, int regnum) = 0;
+
+  /* Read LENGTH bytes at ADDR into BUF.  */
+  virtual void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t length) = 0;
+
+  /* Return the location expression for the frame base attribute, in
+     START and LENGTH.  The result must be live until the current
+     expression evaluation is complete.  */
+  virtual void get_frame_base (const gdb_byte **start, size_t *length)
+  {
+    error (_("%s is invalid in this context"), "DW_OP_fbreg");
+  }
+
+  /* Return the CFA for the frame.  */
+  virtual CORE_ADDR get_frame_cfa ()
+  {
+    error (_("%s is invalid in this context"), "DW_OP_call_frame_cfa");
+  }
+
+  /* Return the PC for the frame.  */
+  virtual CORE_ADDR get_frame_pc ()
+  {
+    error (_("%s is invalid in this context"), "DW_OP_GNU_implicit_pointer");
+  }
+
+  /* Return the thread-local storage address for
+     DW_OP_GNU_push_tls_address or DW_OP_form_tls_address.  */
+  virtual CORE_ADDR get_tls_address (CORE_ADDR offset)
+  {
+    error (_("%s is invalid in this context"), "DW_OP_form_tls_address");
+  }
+
+  /* Execute DW_AT_location expression for the DWARF expression subroutine in
+     the DIE at DIE_OFFSET in the CU from CTX.  Do not touch STACK while it
+     being passed to and returned from the called DWARF subroutine.  */
+  virtual void dwarf_call (cu_offset die_offset)
+  {
+    error (_("%s is invalid in this context"), "DW_OP_call*");
+  }
+
+  /* Return the base type given by the indicated DIE.  This can throw
+     an exception if the DIE is invalid or does not represent a base
+     type.  If can also be NULL in the special case where the
+     callbacks are not performing evaluation, and thus it is
+     meaningful to substitute a stub type of the correct size.  */
+  virtual struct type *impl_get_base_type (cu_offset die)
+  {
+    /* Anything will do.  */
+    return builtin_type (this->gdbarch)->builtin_int;
+  }
+
+  /* Push on DWARF stack an entry evaluated for DW_TAG_GNU_call_site's
+     parameter matching KIND and KIND_U at the caller of specified BATON.
+     If DEREF_SIZE is not -1 then use DW_AT_GNU_call_site_data_value instead of
+     DW_AT_GNU_call_site_value.  */
+  virtual void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
+					   union call_site_parameter_u kind_u,
+					   int deref_size)
+  {
+    internal_error (__FILE__, __LINE__,
+		    _("Support for DW_OP_GNU_entry_value is unimplemented"));
+  }
+
+  /* Return the address indexed by DW_OP_GNU_addr_index.
+     This can throw an exception if the index is out of range.  */
+  virtual CORE_ADDR get_addr_index (unsigned int index)
+  {
+    error (_("%s is invalid in this context"), "DW_OP_GNU_addr_index");
+  }
+
+  /* Return the `object address' for DW_OP_push_object_address.  */
+  virtual CORE_ADDR get_object_address ()
+  {
+    internal_error (__FILE__, __LINE__,
+		    _("Support for DW_OP_push_object_address "
+		      "is unimplemented"));
+  }
+
 private:
 
   struct type *address_type () const;
@@ -273,22 +289,6 @@ struct dwarf_expr_piece
 void dwarf_expr_require_composition (const gdb_byte *, const gdb_byte *,
 				     const char *);
 
-/* Stub dwarf_expr_context_funcs implementations.  */
-
-void ctx_no_get_frame_base (void *baton, const gdb_byte **start,
-			    size_t *length);
-CORE_ADDR ctx_no_get_frame_cfa (void *baton);
-CORE_ADDR ctx_no_get_frame_pc (void *baton);
-CORE_ADDR ctx_no_get_tls_address (void *baton, CORE_ADDR offset);
-void ctx_no_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset);
-struct type *ctx_no_get_base_type (struct dwarf_expr_context *ctx,
-				   cu_offset die);
-void ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
-					enum call_site_parameter_kind kind,
-					union call_site_parameter_u kind_u,
-					int deref_size);
-CORE_ADDR ctx_no_get_addr_index (void *baton, unsigned int index);
-
 int dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end);
 
 int dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf,
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index d6ffd85..37daf08 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -43,8 +43,6 @@
 
 extern int dwarf_always_disassemble;
 
-extern const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs;
-
 static struct value *dwarf2_evaluate_loc_desc_full (struct type *type,
 						    struct frame_info *frame,
 						    const gdb_byte *data,
@@ -52,6 +50,12 @@ static struct value *dwarf2_evaluate_loc_desc_full (struct type *type,
 						    struct dwarf2_per_cu_data *per_cu,
 						    LONGEST byte_offset);
 
+static struct call_site_parameter *dwarf_expr_reg_to_entry_parameter
+    (struct frame_info *frame,
+     enum call_site_parameter_kind kind,
+     union call_site_parameter_u kind_u,
+     struct dwarf2_per_cu_data **per_cu_return);
+
 /* Until these have formal names, we define these here.
    ref: http://gcc.gnu.org/wiki/DebugFission
    Each entry in .debug_loc.dwo begins with a byte that describes the entry,
@@ -311,71 +315,6 @@ struct dwarf_expr_baton
   CORE_ADDR obj_address;
 };
 
-/* Helper functions for dwarf2_evaluate_loc_desc.  */
-
-/* Using the frame specified in BATON, return the value of register
-   REGNUM, treated as a pointer.  */
-static CORE_ADDR
-dwarf_expr_read_addr_from_reg (void *baton, int dwarf_regnum)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  struct gdbarch *gdbarch = get_frame_arch (debaton->frame);
-  int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
-
-  return address_from_register (regnum, debaton->frame);
-}
-
-/* Implement struct dwarf_expr_context_funcs' "get_reg_value" callback.  */
-
-static struct value *
-dwarf_expr_get_reg_value (void *baton, struct type *type, int dwarf_regnum)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  struct gdbarch *gdbarch = get_frame_arch (debaton->frame);
-  int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
-
-  return value_from_register (type, regnum, debaton->frame);
-}
-
-/* Read memory at ADDR (length LEN) into BUF.  */
-
-static void
-dwarf_expr_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
-{
-  read_memory (addr, buf, len);
-}
-
-/* Using the frame specified in BATON, find the location expression
-   describing the frame base.  Return a pointer to it in START and
-   its length in LENGTH.  */
-static void
-dwarf_expr_frame_base (void *baton, const gdb_byte **start, size_t * length)
-{
-  /* FIXME: cagney/2003-03-26: This code should be using
-     get_frame_base_address(), and then implement a dwarf2 specific
-     this_base method.  */
-  struct symbol *framefunc;
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  const struct block *bl = get_frame_block (debaton->frame, NULL);
-
-  if (bl == NULL)
-    error (_("frame address is not available."));
-
-  /* Use block_linkage_function, which returns a real (not inlined)
-     function, instead of get_frame_function, which may return an
-     inlined function.  */
-  framefunc = block_linkage_function (bl);
-
-  /* If we found a frame-relative symbol then it was certainly within
-     some function associated with a frame. If we can't find the frame,
-     something has gone wrong.  */
-  gdb_assert (framefunc != NULL);
-
-  func_get_frame_base_dwarf_block (framefunc,
-				   get_frame_address_in_block (debaton->frame),
-				   start, length);
-}
-
 /* Implement find_frame_base_location method for LOC_BLOCK functions using
    DWARF expression for its DW_AT_frame_base.  */
 
@@ -511,52 +450,23 @@ func_get_frame_base_dwarf_block (struct symbol *framefunc, CORE_ADDR pc,
 	   SYMBOL_NATURAL_NAME (framefunc));
 }
 
-/* Helper function for dwarf2_evaluate_loc_desc.  Computes the CFA for
-   the frame in BATON.  */
-
 static CORE_ADDR
-dwarf_expr_frame_cfa (void *baton)
+get_frame_pc_for_per_cu_dwarf_call (void *baton)
 {
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
+  dwarf_expr_context *ctx = (dwarf_expr_context *) baton;
 
-  return dwarf2_frame_cfa (debaton->frame);
+  return ctx->get_frame_pc ();
 }
 
-/* Helper function for dwarf2_evaluate_loc_desc.  Computes the PC for
-   the frame in BATON.  */
-
-static CORE_ADDR
-dwarf_expr_frame_pc (void *baton)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
-  return get_frame_address_in_block (debaton->frame);
-}
-
-/* Using the objfile specified in BATON, find the address for the
-   current thread's thread-local storage with offset OFFSET.  */
-static CORE_ADDR
-dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  struct objfile *objfile = dwarf2_per_cu_objfile (debaton->per_cu);
-
-  return target_translate_tls_address (objfile, offset);
-}
-
-/* Call DWARF subroutine from DW_AT_location of DIE at DIE_OFFSET in
-   current CU (as is PER_CU).  State of the CTX is not affected by the
-   call and return.  */
-
 static void
 per_cu_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset,
-		   struct dwarf2_per_cu_data *per_cu,
-		   CORE_ADDR (*get_frame_pc) (void *baton),
-		   void *baton)
+		   struct dwarf2_per_cu_data *per_cu)
 {
   struct dwarf2_locexpr_baton block;
 
-  block = dwarf2_fetch_die_loc_cu_off (die_offset, per_cu, get_frame_pc, baton);
+  block = dwarf2_fetch_die_loc_cu_off (die_offset, per_cu,
+				       get_frame_pc_for_per_cu_dwarf_call,
+				       ctx);
 
   /* DW_OP_call_ref is currently not supported.  */
   gdb_assert (block.per_cu == per_cu);
@@ -564,27 +474,176 @@ per_cu_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset,
   ctx->eval (block.data, block.size);
 }
 
-/* Helper interface of per_cu_dwarf_call for dwarf2_evaluate_loc_desc.  */
-
-static void
-dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
+class dwarf_evaluate_loc_desc : public dwarf_expr_context
 {
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) ctx->baton;
+ public:
 
-  per_cu_dwarf_call (ctx, die_offset, debaton->per_cu,
-		     ctx->funcs->get_frame_pc, ctx->baton);
-}
-
-/* Callback function for dwarf2_evaluate_loc_desc.  */
-
-static struct type *
-dwarf_expr_get_base_type (struct dwarf_expr_context *ctx,
-			  cu_offset die_offset)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) ctx->baton;
+  struct frame_info *frame;
+  struct dwarf2_per_cu_data *per_cu;
+  CORE_ADDR obj_address;
 
-  return dwarf2_get_die_type (die_offset, debaton->per_cu);
-}
+  /* Helper function for dwarf2_evaluate_loc_desc.  Computes the CFA for
+     the frame in BATON.  */
+
+  CORE_ADDR get_frame_cfa () override
+  {
+    return dwarf2_frame_cfa (frame);
+  }
+
+  /* Helper function for dwarf2_evaluate_loc_desc.  Computes the PC for
+     the frame in BATON.  */
+
+  CORE_ADDR get_frame_pc () override
+  {
+    return get_frame_address_in_block (frame);
+  }
+
+  /* Using the objfile specified in BATON, find the address for the
+     current thread's thread-local storage with offset OFFSET.  */
+  CORE_ADDR get_tls_address (CORE_ADDR offset) override
+  {
+    struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
+
+    return target_translate_tls_address (objfile, offset);
+  }
+
+  /* Helper interface of per_cu_dwarf_call for
+     dwarf2_evaluate_loc_desc.  */
+
+  void dwarf_call (cu_offset die_offset) override
+  {
+    per_cu_dwarf_call (this, die_offset, per_cu);
+  }
+
+  /* Callback function for dwarf2_evaluate_loc_desc.  */
+  struct type *impl_get_base_type (cu_offset die_offset) override
+  {
+    return dwarf2_get_die_type (die_offset, per_cu);
+  }
+
+  /* Callback function for dwarf2_evaluate_loc_desc.
+     Fetch the address indexed by DW_OP_GNU_addr_index.  */
+
+  CORE_ADDR get_addr_index (unsigned int index) override
+  {
+    return dwarf2_read_addr_index (per_cu, index);
+  }
+
+  /* Callback function for get_object_address. Return the address of the VLA
+     object.  */
+
+  CORE_ADDR get_object_address () override
+  {
+    if (obj_address == 0)
+      error (_("Location address is not set."));
+    return obj_address;
+  }
+
+  /* Execute DWARF block of call_site_parameter which matches KIND and
+     KIND_U.  Choose DEREF_SIZE value of that parameter.  Search
+     caller of the CTX's frame.  CTX must be of dwarf_expr_ctx_funcs
+     kind.
+
+     The CTX caller can be from a different CU - per_cu_dwarf_call
+     implementation can be more simple as it does not support cross-CU
+     DWARF executions.  */
+
+  void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
+				   union call_site_parameter_u kind_u,
+				   int deref_size) override
+  {
+    struct frame_info *caller_frame;
+    struct dwarf2_per_cu_data *caller_per_cu;
+    struct dwarf_expr_baton baton_local;
+    struct call_site_parameter *parameter;
+    const gdb_byte *data_src;
+    size_t size;
+
+    caller_frame = get_prev_frame (frame);
+
+    parameter = dwarf_expr_reg_to_entry_parameter (frame, kind, kind_u,
+						   &caller_per_cu);
+    data_src = deref_size == -1 ? parameter->value : parameter->data_value;
+    size = deref_size == -1 ? parameter->value_size : parameter->data_value_size;
+
+    /* DEREF_SIZE size is not verified here.  */
+    if (data_src == NULL)
+      throw_error (NO_ENTRY_VALUE_ERROR,
+		   _("Cannot resolve DW_AT_GNU_call_site_data_value"));
+
+    baton_local.frame = caller_frame;
+    baton_local.per_cu = caller_per_cu;
+    baton_local.obj_address = 0;
+
+    scoped_restore<struct gdbarch *> save_arch
+      (&this->gdbarch,
+       get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu)));
+    scoped_restore<int> save_addr_size
+      (&this->addr_size,
+       dwarf2_per_cu_addr_size (baton_local.per_cu));
+    scoped_restore<CORE_ADDR>
+      save_offset (&this->offset,
+		   dwarf2_per_cu_text_offset (baton_local.per_cu));
+
+    this->eval (data_src, size);
+  }
+
+  /* Using the frame specified in BATON, find the location expression
+     describing the frame base.  Return a pointer to it in START and
+     its length in LENGTH.  */
+  void get_frame_base (const gdb_byte **start, size_t * length) override
+  {
+    /* FIXME: cagney/2003-03-26: This code should be using
+       get_frame_base_address(), and then implement a dwarf2 specific
+       this_base method.  */
+    struct symbol *framefunc;
+    const struct block *bl = get_frame_block (frame, NULL);
+
+    if (bl == NULL)
+      error (_("frame address is not available."));
+
+    /* Use block_linkage_function, which returns a real (not inlined)
+       function, instead of get_frame_function, which may return an
+       inlined function.  */
+    framefunc = block_linkage_function (bl);
+
+    /* If we found a frame-relative symbol then it was certainly within
+       some function associated with a frame. If we can't find the frame,
+       something has gone wrong.  */
+    gdb_assert (framefunc != NULL);
+
+    func_get_frame_base_dwarf_block (framefunc,
+				     get_frame_address_in_block (frame),
+				     start, length);
+  }
+
+  /* Read memory at ADDR (length LEN) into BUF.  */
+
+  void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) override
+  {
+    read_memory (addr, buf, len);
+  }
+
+  /* Using the frame specified in BATON, return the value of register
+     REGNUM, treated as a pointer.  */
+  CORE_ADDR read_addr_from_reg (int dwarf_regnum) override
+  {
+    struct gdbarch *gdbarch = get_frame_arch (frame);
+    int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
+
+    return address_from_register (regnum, frame);
+  }
+
+  /* Implement "get_reg_value" callback.  */
+
+  struct value *get_reg_value (struct type *type, int dwarf_regnum) override
+  {
+    struct gdbarch *gdbarch = get_frame_arch (frame);
+    int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
+
+    return value_from_register (type, regnum, frame);
+  }
+};
 
 /* See dwarf2loc.h.  */
 
@@ -1250,91 +1309,6 @@ dwarf_entry_parameter_to_value (struct call_site_parameter *parameter,
   return dwarf2_evaluate_loc_desc (type, caller_frame, data, size + 1, per_cu);
 }
 
-/* Execute DWARF block of call_site_parameter which matches KIND and KIND_U.
-   Choose DEREF_SIZE value of that parameter.  Search caller of the CTX's
-   frame.  CTX must be of dwarf_expr_ctx_funcs kind.
-
-   The CTX caller can be from a different CU - per_cu_dwarf_call implementation
-   can be more simple as it does not support cross-CU DWARF executions.  */
-
-static void
-dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
-				       enum call_site_parameter_kind kind,
-				       union call_site_parameter_u kind_u,
-				       int deref_size)
-{
-  struct dwarf_expr_baton *debaton;
-  struct frame_info *frame, *caller_frame;
-  struct dwarf2_per_cu_data *caller_per_cu;
-  struct dwarf_expr_baton baton_local;
-  struct dwarf_expr_context saved_ctx;
-  struct call_site_parameter *parameter;
-  const gdb_byte *data_src;
-  size_t size;
-
-  gdb_assert (ctx->funcs == &dwarf_expr_ctx_funcs);
-  debaton = (struct dwarf_expr_baton *) ctx->baton;
-  frame = debaton->frame;
-  caller_frame = get_prev_frame (frame);
-
-  parameter = dwarf_expr_reg_to_entry_parameter (frame, kind, kind_u,
-						 &caller_per_cu);
-  data_src = deref_size == -1 ? parameter->value : parameter->data_value;
-  size = deref_size == -1 ? parameter->value_size : parameter->data_value_size;
-
-  /* DEREF_SIZE size is not verified here.  */
-  if (data_src == NULL)
-    throw_error (NO_ENTRY_VALUE_ERROR,
-		 _("Cannot resolve DW_AT_GNU_call_site_data_value"));
-
-  baton_local.frame = caller_frame;
-  baton_local.per_cu = caller_per_cu;
-  baton_local.obj_address = 0;
-
-  saved_ctx.gdbarch = ctx->gdbarch;
-  saved_ctx.addr_size = ctx->addr_size;
-  saved_ctx.offset = ctx->offset;
-  saved_ctx.baton = ctx->baton;
-  ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu));
-  ctx->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu);
-  ctx->offset = dwarf2_per_cu_text_offset (baton_local.per_cu);
-  ctx->baton = &baton_local;
-
-  ctx->eval (data_src, size);
-
-  ctx->gdbarch = saved_ctx.gdbarch;
-  ctx->addr_size = saved_ctx.addr_size;
-  ctx->offset = saved_ctx.offset;
-  ctx->baton = saved_ctx.baton;
-}
-
-/* Callback function for dwarf2_evaluate_loc_desc.
-   Fetch the address indexed by DW_OP_GNU_addr_index.  */
-
-static CORE_ADDR
-dwarf_expr_get_addr_index (void *baton, unsigned int index)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
-  return dwarf2_read_addr_index (debaton->per_cu, index);
-}
-
-/* Callback function for get_object_address. Return the address of the VLA
-   object.  */
-
-static CORE_ADDR
-dwarf_expr_get_obj_addr (void *baton)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
-  gdb_assert (debaton != NULL);
-
-  if (debaton->obj_address == 0)
-    error (_("Location address is not set."));
-
-  return debaton->obj_address;
-}
-
 /* VALUE must be of type lval_computed with entry_data_value_funcs.  Perform
    the indirect method on it, that is use its stored target value, the sole
    purpose of entry_data_value_funcs..  */
@@ -2263,24 +2237,6 @@ static const struct lval_funcs pieced_value_funcs = {
   free_pieced_value_closure
 };
 
-/* Virtual method table for dwarf2_evaluate_loc_desc_full below.  */
-
-const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs =
-{
-  dwarf_expr_read_addr_from_reg,
-  dwarf_expr_get_reg_value,
-  dwarf_expr_read_mem,
-  dwarf_expr_frame_base,
-  dwarf_expr_frame_cfa,
-  dwarf_expr_frame_pc,
-  dwarf_expr_tls_address,
-  dwarf_expr_dwarf_call,
-  dwarf_expr_get_base_type,
-  dwarf_expr_push_dwarf_reg_entry_value,
-  dwarf_expr_get_addr_index,
-  dwarf_expr_get_obj_addr
-};
-
 /* Evaluate a location description, starting at DATA and with length
    SIZE, to find the current location of variable of TYPE in the
    context of FRAME.  BYTE_OFFSET is applied after the contents are
@@ -2293,7 +2249,6 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 			       LONGEST byte_offset)
 {
   struct value *retval;
-  struct dwarf_expr_baton baton;
   struct cleanup *value_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
@@ -2303,19 +2258,17 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
   if (size == 0)
     return allocate_optimized_out_value (type);
 
-  baton.frame = frame;
-  baton.per_cu = per_cu;
-  baton.obj_address = 0;
+  dwarf_evaluate_loc_desc ctx;
+  ctx.frame = frame;
+  ctx.per_cu = per_cu;
+  ctx.obj_address = 0;
 
-  dwarf_expr_context ctx;
   value_chain = make_cleanup_value_free_to_mark (value_mark ());
 
   ctx.gdbarch = get_objfile_arch (objfile);
   ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
   ctx.offset = dwarf2_per_cu_text_offset (per_cu);
-  ctx.baton = &baton;
-  ctx.funcs = &dwarf_expr_ctx_funcs;
 
   TRY
     {
@@ -2537,18 +2490,17 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
 			   CORE_ADDR addr,
 			   CORE_ADDR *valp)
 {
-  struct dwarf_expr_baton baton;
   struct objfile *objfile;
   struct cleanup *cleanup;
 
   if (dlbaton == NULL || dlbaton->size == 0)
     return 0;
 
-  dwarf_expr_context ctx;
+  dwarf_evaluate_loc_desc ctx;
 
-  baton.frame = frame;
-  baton.per_cu = dlbaton->per_cu;
-  baton.obj_address = addr;
+  ctx.frame = frame;
+  ctx.per_cu = dlbaton->per_cu;
+  ctx.obj_address = addr;
 
   objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
 
@@ -2556,8 +2508,6 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
   ctx.addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
   ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
   ctx.offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
-  ctx.funcs = &dwarf_expr_ctx_funcs;
-  ctx.baton = &baton;
 
   ctx.eval (dlbaton->data, dlbaton->size);
 
@@ -2568,7 +2518,7 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
     case DWARF_VALUE_STACK:
       *valp = ctx.fetch_address (0);
       if (ctx.location == DWARF_VALUE_REGISTER)
-	*valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
+	*valp = ctx.read_addr_from_reg (*valp);
       return 1;
     case DWARF_VALUE_LITERAL:
       *valp = extract_signed_integer (ctx.data, ctx.len,
@@ -2713,140 +2663,97 @@ dwarf2_compile_property_to_c (struct ui_file *stream,
 \f
 /* Helper functions and baton for dwarf2_loc_desc_get_symbol_read_needs.  */
 
-struct symbol_needs_baton
+class symbol_needs_eval_context : public dwarf_expr_context
 {
+ public:
+
   enum symbol_needs_kind needs;
   struct dwarf2_per_cu_data *per_cu;
-};
-
-/* Reads from registers do require a frame.  */
-static CORE_ADDR
-symbol_needs_read_addr_from_reg (void *baton, int regnum)
-{
-  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
-  return 1;
-}
-
-/* struct dwarf_expr_context_funcs' "get_reg_value" callback:
-   Reads from registers do require a frame.  */
-
-static struct value *
-symbol_needs_get_reg_value (void *baton, struct type *type, int regnum)
-{
-  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
-  return value_zero (type, not_lval);
-}
-
-/* Reads from memory do not require a frame.  */
-static void
-symbol_needs_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
-{
-  memset (buf, 0, len);
-}
-
-/* Frame-relative accesses do require a frame.  */
-static void
-symbol_needs_frame_base (void *baton, const gdb_byte **start, size_t * length)
-{
-  static gdb_byte lit0 = DW_OP_lit0;
-  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
-  *start = &lit0;
-  *length = 1;
-
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
-}
 
-/* CFA accesses require a frame.  */
-
-static CORE_ADDR
-symbol_needs_frame_cfa (void *baton)
-{
-  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
-  return 1;
-}
-
-/* Thread-local accesses require registers, but not a frame.  */
-static CORE_ADDR
-symbol_needs_tls_address (void *baton, CORE_ADDR offset)
-{
-  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
-  if (nf_baton->needs <= SYMBOL_NEEDS_REGISTERS)
-    nf_baton->needs = SYMBOL_NEEDS_REGISTERS;
-  return 1;
-}
-
-/* Helper interface of per_cu_dwarf_call for
-   dwarf2_loc_desc_get_symbol_read_needs.  */
-
-static void
-symbol_needs_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
-{
-  struct symbol_needs_baton *nf_baton =
-    (struct symbol_needs_baton *) ctx->baton;
-
-  per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu,
-		     ctx->funcs->get_frame_pc, ctx->baton);
-}
-
-/* DW_OP_GNU_entry_value accesses require a caller, therefore a frame.  */
-
-static void
-needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
-			     enum call_site_parameter_kind kind,
-			     union call_site_parameter_u kind_u, int deref_size)
-{
-  struct symbol_needs_baton *nf_baton =
-    (struct symbol_needs_baton *) ctx->baton;
+  /* Reads from registers do require a frame.  */
+  CORE_ADDR read_addr_from_reg (int regnum) override
+  {
+    needs = SYMBOL_NEEDS_FRAME;
+    return 1;
+  }
+
+  /* "get_reg_value" callback: Reads from registers do require a
+     frame.  */
+
+  struct value *get_reg_value (struct type *type, int regnum) override
+  {
+    needs = SYMBOL_NEEDS_FRAME;
+    return value_zero (type, not_lval);
+  }
+
+  /* Reads from memory do not require a frame.  */
+  void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) override
+  {
+    memset (buf, 0, len);
+  }
+
+  /* Frame-relative accesses do require a frame.  */
+  void get_frame_base (const gdb_byte **start, size_t *length) override
+  {
+    static gdb_byte lit0 = DW_OP_lit0;
+
+    *start = &lit0;
+    *length = 1;
+
+    needs = SYMBOL_NEEDS_FRAME;
+  }
+
+  /* CFA accesses require a frame.  */
+  CORE_ADDR get_frame_cfa () override
+  {
+    needs = SYMBOL_NEEDS_FRAME;
+    return 1;
+  }
+
+  /* Thread-local accesses require registers, but not a frame.  */
+  CORE_ADDR get_tls_address (CORE_ADDR offset) override
+  {
+    if (needs <= SYMBOL_NEEDS_REGISTERS)
+      needs = SYMBOL_NEEDS_REGISTERS;
+    return 1;
+  }
+
+  /* Helper interface of per_cu_dwarf_call for
+     dwarf2_loc_desc_get_symbol_read_needs.  */
+
+  void dwarf_call (cu_offset die_offset) override
+  {
+    per_cu_dwarf_call (this, die_offset, per_cu);
+  }
+
+  /* DW_OP_GNU_entry_value accesses require a caller, therefore a
+     frame.  */
+
+  void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
+				   union call_site_parameter_u kind_u,
+				   int deref_size) override
+  {
+    needs = SYMBOL_NEEDS_FRAME;
 
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
+    /* The expression may require some stub values on DWARF stack.  */
+    push_address (0, 0);
+  }
 
-  /* The expression may require some stub values on DWARF stack.  */
-  ctx->push_address (0, 0);
-}
+  /* DW_OP_GNU_addr_index doesn't require a frame.  */
 
-/* DW_OP_GNU_addr_index doesn't require a frame.  */
+   CORE_ADDR get_addr_index (unsigned int index) override
+   {
+     /* Nothing to do.  */
+     return 1;
+   }
 
-static CORE_ADDR
-needs_get_addr_index (void *baton, unsigned int index)
-{
-  /* Nothing to do.  */
-  return 1;
-}
+   /* DW_OP_push_object_address has a frame already passed through.  */
 
-/* DW_OP_push_object_address has a frame already passed through.  */
-
-static CORE_ADDR
-needs_get_obj_addr (void *baton)
-{
-  /* Nothing to do.  */
-  return 1;
-}
-
-/* Virtual method table for dwarf2_loc_desc_get_symbol_read_needs
-   below.  */
-
-static const struct dwarf_expr_context_funcs symbol_needs_ctx_funcs =
-{
-  symbol_needs_read_addr_from_reg,
-  symbol_needs_get_reg_value,
-  symbol_needs_read_mem,
-  symbol_needs_frame_base,
-  symbol_needs_frame_cfa,
-  symbol_needs_frame_cfa,	/* get_frame_pc */
-  symbol_needs_tls_address,
-  symbol_needs_dwarf_call,
-  NULL,				/* get_base_type */
-  needs_dwarf_reg_entry_value,
-  needs_get_addr_index,
-  needs_get_obj_addr
+   CORE_ADDR get_object_address () override
+   {
+     /* Nothing to do.  */
+     return 1;
+   }
 };
 
 /* Compute the correct symbol_needs_kind value for the location
@@ -2856,23 +2763,21 @@ static enum symbol_needs_kind
 dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
 				       struct dwarf2_per_cu_data *per_cu)
 {
-  struct symbol_needs_baton baton;
   int in_reg;
   struct cleanup *old_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
-  baton.needs = SYMBOL_NEEDS_NONE;
-  baton.per_cu = per_cu;
+  symbol_needs_eval_context ctx;
+
+  ctx.needs = SYMBOL_NEEDS_NONE;
+  ctx.per_cu = per_cu;
 
-  dwarf_expr_context ctx;
   old_chain = make_cleanup_value_free_to_mark (value_mark ());
 
   ctx.gdbarch = get_objfile_arch (objfile);
   ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
   ctx.offset = dwarf2_per_cu_text_offset (per_cu);
-  ctx.baton = &baton;
-  ctx.funcs = &symbol_needs_ctx_funcs;
 
   ctx.eval (data, size);
 
@@ -2892,8 +2797,8 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
   do_cleanups (old_chain);
 
   if (in_reg)
-    baton.needs = SYMBOL_NEEDS_FRAME;
-  return baton.needs;
+    ctx.needs = SYMBOL_NEEDS_FRAME;
+  return ctx.needs;
 }
 
 /* A helper function that throws an unimplemented error mentioning a
-- 
2.7.4

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

* [RFA 05/22] Turn wchar iterator into a class
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (7 preceding siblings ...)
  2016-09-27  4:47 ` [RFA 04/22] Use scoped_restore for current_ui Tom Tromey
@ 2016-09-27  4:47 ` Tom Tromey
  2016-10-06  1:01   ` Pedro Alves
  2016-09-27  4:47 ` [RFA 22/22] Convert dwarf_expr_context_funcs to methods Tom Tromey
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:47 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes wchar_iterator from charset.c into a real C++ class, then
updates the users to use the class.  This lets us remove some cleanups
in favor of the class' destructor.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* valprint.c (generic_emit_char, count_next_character)
	(generic_printstr): Update.
	* charset.c (struct wchar_iterator): Move to charset.h.
	(wchar_iterator::wchar_iterator): Rename from
	make_wchar_iterator, turn into a constructor.
	(wchar_iterator::~wchar_iterator): Rename from
	do_cleanup_iterator, turn into a destructor.
	(make_cleanup_wchar_iterator): Remove.
	(wchar_iterator::iterate): Rename from wchar_iterate.  Remove
	"iter" argument.  Update.
	* charset.h: Include <vector>.
	(class wchar_iterator): New class, from old struct
	wchar_iterator.
	(make_wchar_iterator, make_cleanup_wchar_iterator): Don't
	declare.
---
 gdb/ChangeLog  |  18 ++++++++++
 gdb/charset.c  | 106 +++++++++++++++++----------------------------------------
 gdb/charset.h  |  95 +++++++++++++++++++++++++++++----------------------
 gdb/valprint.c |  25 ++++++--------
 4 files changed, 114 insertions(+), 130 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 42c432d..b73b26e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,23 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* valprint.c (generic_emit_char, count_next_character)
+	(generic_printstr): Update.
+	* charset.c (struct wchar_iterator): Move to charset.h.
+	(wchar_iterator::wchar_iterator): Rename from
+	make_wchar_iterator, turn into a constructor.
+	(wchar_iterator::~wchar_iterator): Rename from
+	do_cleanup_iterator, turn into a destructor.
+	(make_cleanup_wchar_iterator): Remove.
+	(wchar_iterator::iterate): Rename from wchar_iterate.  Remove
+	"iter" argument.  Update.
+	* charset.h: Include <vector>.
+	(class wchar_iterator): New class, from old struct
+	wchar_iterator.
+	(make_wchar_iterator, make_cleanup_wchar_iterator): Don't
+	declare.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* top.c (new_ui_command, wait_sync_command_done)
 	(gdb_readline_wrapper): Use scoped_restore.
 	* infrun.c (fetch_inferior_event): Use scoped_restore.
diff --git a/gdb/charset.c b/gdb/charset.c
index abad901..66de30e 100644
--- a/gdb/charset.c
+++ b/gdb/charset.c
@@ -589,71 +589,30 @@ convert_between_encodings (const char *from, const char *to,
 
 \f
 
-/* An iterator that returns host wchar_t's from a target string.  */
-struct wchar_iterator
-{
-  /* The underlying iconv descriptor.  */
-  iconv_t desc;
-
-  /* The input string.  This is updated as convert characters.  */
-  const gdb_byte *input;
-  /* The number of bytes remaining in the input.  */
-  size_t bytes;
-
-  /* The width of an input character.  */
-  size_t width;
-
-  /* The output buffer and its size.  */
-  gdb_wchar_t *out;
-  size_t out_size;
-};
-
 /* Create a new iterator.  */
-struct wchar_iterator *
-make_wchar_iterator (const gdb_byte *input, size_t bytes, 
-		     const char *charset, size_t width)
+wchar_iterator::wchar_iterator (const gdb_byte *input, size_t bytes, 
+				const char *charset, size_t width)
+: input (input),
+  bytes (bytes),
+  width (width),
+  out (1)
 {
-  struct wchar_iterator *result;
-  iconv_t desc;
-
   desc = iconv_open (INTERMEDIATE_ENCODING, charset);
   if (desc == (iconv_t) -1)
     perror_with_name (_("Converting character sets"));
-
-  result = XNEW (struct wchar_iterator);
-  result->desc = desc;
-  result->input = input;
-  result->bytes = bytes;
-  result->width = width;
-
-  result->out = XNEW (gdb_wchar_t);
-  result->out_size = 1;
-
-  return result;
 }
 
-static void
-do_cleanup_iterator (void *p)
+wchar_iterator::~wchar_iterator ()
 {
-  struct wchar_iterator *iter = (struct wchar_iterator *) p;
-
-  iconv_close (iter->desc);
-  xfree (iter->out);
-  xfree (iter);
-}
-
-struct cleanup *
-make_cleanup_wchar_iterator (struct wchar_iterator *iter)
-{
-  return make_cleanup (do_cleanup_iterator, iter);
+  if (desc != (iconv_t) -1)
+    iconv_close (desc);
 }
 
 int
-wchar_iterate (struct wchar_iterator *iter,
-	       enum wchar_iterate_result *out_result,
-	       gdb_wchar_t **out_chars,
-	       const gdb_byte **ptr,
-	       size_t *len)
+wchar_iterator::iterate (enum wchar_iterate_result *out_result,
+			 gdb_wchar_t **out_chars,
+			 const gdb_byte **ptr,
+			 size_t *len)
 {
   size_t out_request;
 
@@ -663,17 +622,17 @@ wchar_iterate (struct wchar_iterator *iter,
      invalid input sequence -- but we want to reliably report this to
      our caller so it can emit an escape sequence.  */
   out_request = 1;
-  while (iter->bytes > 0)
+  while (bytes > 0)
     {
-      ICONV_CONST char *inptr = (ICONV_CONST char *) iter->input;
-      char *outptr = (char *) &iter->out[0];
-      const gdb_byte *orig_inptr = iter->input;
-      size_t orig_in = iter->bytes;
+      ICONV_CONST char *inptr = (ICONV_CONST char *) input;
+      char *outptr = (char *) out.data ();
+      const gdb_byte *orig_inptr = input;
+      size_t orig_in = bytes;
       size_t out_avail = out_request * sizeof (gdb_wchar_t);
       size_t num;
-      size_t r = iconv (iter->desc, &inptr, &iter->bytes, &outptr, &out_avail);
+      size_t r = iconv (desc, &inptr, &bytes, &outptr, &out_avail);
 
-      iter->input = (gdb_byte *) inptr;
+      input = (gdb_byte *) inptr;
 
       if (r == (size_t) -1)
 	{
@@ -688,10 +647,10 @@ wchar_iterate (struct wchar_iterator *iter,
 	      /* Otherwise skip the first invalid character, and let
 		 the caller know about it.  */
 	      *out_result = wchar_iterate_invalid;
-	      *ptr = iter->input;
-	      *len = iter->width;
-	      iter->input += iter->width;
-	      iter->bytes -= iter->width;
+	      *ptr = input;
+	      *len = width;
+	      input += width;
+	      bytes -= width;
 	      return 0;
 
 	    case E2BIG:
@@ -702,20 +661,17 @@ wchar_iterate (struct wchar_iterator *iter,
 		break;
 
 	      ++out_request;
-	      if (out_request > iter->out_size)
-		{
-		  iter->out_size = out_request;
-		  iter->out = XRESIZEVEC (gdb_wchar_t, iter->out, out_request);
-		}
+	      if (out_request > out.size ())
+		out.reserve (out_request);
 	      continue;
 
 	    case EINVAL:
 	      /* Incomplete input sequence.  Let the caller know, and
 		 arrange for future calls to see EOF.  */
 	      *out_result = wchar_iterate_incomplete;
-	      *ptr = iter->input;
-	      *len = iter->bytes;
-	      iter->bytes = 0;
+	      *ptr = input;
+	      *len = bytes;
+	      bytes = 0;
 	      return 0;
 
 	    default:
@@ -727,9 +683,9 @@ wchar_iterate (struct wchar_iterator *iter,
       /* We converted something.  */
       num = out_request - out_avail / sizeof (gdb_wchar_t);
       *out_result = wchar_iterate_ok;
-      *out_chars = iter->out;
+      *out_chars = out.data ();
       *ptr = orig_inptr;
-      *len = orig_in - iter->bytes;
+      *len = orig_in - bytes;
       return num;
     }
 
diff --git a/gdb/charset.h b/gdb/charset.h
index 559b328..891024c 100644
--- a/gdb/charset.h
+++ b/gdb/charset.h
@@ -19,6 +19,8 @@
 #ifndef CHARSET_H
 #define CHARSET_H
 
+#include <vector>
+
 /* If the target program uses a different character set than the host,
    GDB has some support for translating between the two; GDB converts
    characters and strings to the host character set before displaying
@@ -81,54 +83,67 @@ enum wchar_iterate_result
     wchar_iterate_eof
   };
 
-/* Declaration of the opaque wchar iterator type.  */
-struct wchar_iterator;
+/* An iterator that returns host wchar_t's from a target string.  */
+class wchar_iterator
+{
+ public:
 
-/* Create a new character iterator which returns wchar_t's.  INPUT is
-   the input buffer.  BYTES is the number of bytes in the input
-   buffer.  CHARSET is the name of the character set in which INPUT is
-   encoded.  WIDTH is the number of bytes in a base character of
-   CHARSET.
+  /* Create a new character iterator which returns wchar_t's.  INPUT is
+     the input buffer.  BYTES is the number of bytes in the input
+     buffer.  CHARSET is the name of the character set in which INPUT is
+     encoded.  WIDTH is the number of bytes in a base character of
+     CHARSET.
    
-   This function either returns a new character set iterator, or calls
-   error.  The result can be freed using a cleanup; see
-   make_cleanup_wchar_iterator.  */
-struct wchar_iterator *make_wchar_iterator (const gdb_byte *input,
-					    size_t bytes,
-					    const char *charset,
-					    size_t width);
-
-/* Return a new cleanup suitable for destroying the wchar iterator
-   ITER.  */
-struct cleanup *make_cleanup_wchar_iterator (struct wchar_iterator *iter);
-
-/* Perform a single iteration of a wchar_t iterator.
+     This function either returns a new character set iterator, or calls
+     error.  The result can be freed using a cleanup; see
+     make_cleanup_wchar_iterator.  */
+  wchar_iterator (const gdb_byte *input, size_t bytes, const char *charset,
+		  size_t width);
+
+  ~wchar_iterator ();
+
+  /* Perform a single iteration of a wchar_t iterator.
    
-   Returns the number of characters converted.  A negative result
-   means that EOF has been reached.  A positive result indicates the
-   number of valid wchar_ts in the result; *OUT_CHARS is updated to
-   point to the first valid character.
+     Returns the number of characters converted.  A negative result
+     means that EOF has been reached.  A positive result indicates the
+     number of valid wchar_ts in the result; *OUT_CHARS is updated to
+     point to the first valid character.
 
-   In all cases aside from EOF, *PTR is set to point to the first
-   converted target byte.  *LEN is set to the number of bytes
-   converted.
+     In all cases aside from EOF, *PTR is set to point to the first
+     converted target byte.  *LEN is set to the number of bytes
+     converted.
 
-   A zero result means one of several unusual results.  *OUT_RESULT is
-   set to indicate the type of un-ordinary return.
+     A zero result means one of several unusual results.  *OUT_RESULT is
+     set to indicate the type of un-ordinary return.
 
-   wchar_iterate_invalid means that an invalid input character was
-   seen.  The iterator is advanced by WIDTH (the argument to
-   make_wchar_iterator) bytes.
+     wchar_iterate_invalid means that an invalid input character was
+     seen.  The iterator is advanced by WIDTH (the argument to
+     the wchar_iterator constructor) bytes.
 
-   wchar_iterate_incomplete means that an incomplete character was
-   seen at the end of the input sequence.
+     wchar_iterate_incomplete means that an incomplete character was
+     seen at the end of the input sequence.
    
-   wchar_iterate_eof means that all bytes were successfully
-   converted.  The other output arguments are not set.  */
-int wchar_iterate (struct wchar_iterator *iter,
-		   enum wchar_iterate_result *out_result,
-		   gdb_wchar_t **out_chars,
-		   const gdb_byte **ptr, size_t *len);
+     wchar_iterate_eof means that all bytes were successfully
+     converted.  The other output arguments are not set.  */
+  int iterate (enum wchar_iterate_result *out_result, gdb_wchar_t **out_chars,
+	       const gdb_byte **ptr, size_t *len);
+
+ private:
+
+  /* The underlying iconv descriptor.  */
+  iconv_t desc;
+
+  /* The input string.  This is updated as convert characters.  */
+  const gdb_byte *input;
+  /* The number of bytes remaining in the input.  */
+  size_t bytes;
+
+  /* The width of an input character.  */
+  size_t width;
+
+  /* The output buffer.  */
+  std::vector<gdb_wchar_t> out;
+};
 
 \f
 
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 93607e5..ca30a7f 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -2404,19 +2404,16 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream,
   struct obstack wchar_buf, output;
   struct cleanup *cleanups;
   gdb_byte *buf;
-  struct wchar_iterator *iter;
   int need_escape = 0;
 
   buf = (gdb_byte *) alloca (TYPE_LENGTH (type));
   pack_long (buf, type, c);
 
-  iter = make_wchar_iterator (buf, TYPE_LENGTH (type),
-			      encoding, TYPE_LENGTH (type));
-  cleanups = make_cleanup_wchar_iterator (iter);
+  wchar_iterator iter (buf, TYPE_LENGTH (type), encoding, TYPE_LENGTH (type));
 
   /* This holds the printable form of the wchar_t data.  */
   obstack_init (&wchar_buf);
-  make_cleanup_obstack_free (&wchar_buf);
+  cleanups = make_cleanup_obstack_free (&wchar_buf);
 
   while (1)
     {
@@ -2427,7 +2424,7 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream,
       int print_escape = 1;
       enum wchar_iterate_result result;
 
-      num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen);
+      num_chars = iter.iterate (&result, &chars, &buf, &buflen);
       if (num_chars < 0)
 	break;
       if (num_chars > 0)
@@ -2481,7 +2478,7 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream,
    storing the result in VEC.  */
 
 static int
-count_next_character (struct wchar_iterator *iter,
+count_next_character (wchar_iterator *iter,
 		      VEC (converted_character_d) **vec)
 {
   struct converted_character *current;
@@ -2492,7 +2489,7 @@ count_next_character (struct wchar_iterator *iter,
       gdb_wchar_t *chars;
 
       tmp.num_chars
-	= wchar_iterate (iter, &tmp.result, &chars, &tmp.buf, &tmp.buflen);
+	= iter->iterate (&tmp.result, &chars, &tmp.buf, &tmp.buflen);
       if (tmp.num_chars > 0)
 	{
 	  gdb_assert (tmp.num_chars < MAX_WCHARS);
@@ -2521,8 +2518,7 @@ count_next_character (struct wchar_iterator *iter,
       while (1)
 	{
 	  /* Get the next character.  */
-	  d.num_chars
-	    = wchar_iterate (iter, &d.result, &chars, &d.buf, &d.buflen);
+	  d.num_chars = iter->iterate (&d.result, &chars, &d.buf, &d.buflen);
 
 	  /* If a character was successfully converted, save the character
 	     into the converted character.  */
@@ -2736,7 +2732,6 @@ generic_printstr (struct ui_file *stream, struct type *type,
   int width = TYPE_LENGTH (type);
   struct obstack wchar_buf, output;
   struct cleanup *cleanup;
-  struct wchar_iterator *iter;
   int finished = 0;
   struct converted_character *last;
   VEC (converted_character_d) *converted_chars;
@@ -2771,10 +2766,10 @@ generic_printstr (struct ui_file *stream, struct type *type,
     }
 
   /* Arrange to iterate over the characters, in wchar_t form.  */
-  iter = make_wchar_iterator (string, length * width, encoding, width);
-  cleanup = make_cleanup_wchar_iterator (iter);
+  wchar_iterator iter (string, length * width, encoding, width);
   converted_chars = NULL;
-  make_cleanup (VEC_cleanup (converted_character_d), &converted_chars);
+  cleanup = make_cleanup (VEC_cleanup (converted_character_d),
+			  &converted_chars);
 
   /* Convert characters until the string is over or the maximum
      number of printed characters has been reached.  */
@@ -2786,7 +2781,7 @@ generic_printstr (struct ui_file *stream, struct type *type,
       QUIT;
 
       /* Grab the next character and repeat count.  */
-      r = count_next_character (iter, &converted_chars);
+      r = count_next_character (&iter, &converted_chars);
 
       /* If less than zero, the end of the input string was reached.  */
       if (r < 0)
-- 
2.7.4

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

* [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (9 preceding siblings ...)
  2016-09-27  4:47 ` [RFA 22/22] Convert dwarf_expr_context_funcs to methods Tom Tromey
@ 2016-09-27  4:48 ` Tom Tromey
  2016-09-29 11:55   ` Trevor Saunders
                     ` (3 more replies)
  2016-09-27  4:48 ` [RFA 08/22] Record minimal symbols directly in reader Tom Tromey
                   ` (11 subsequent siblings)
  22 siblings, 4 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This removes make_cleanup_restore_current_ui by converting the last
use.  The last use was in a few functions used to iterate over all
UIs.  This patch replaces these functions with a class, and arranges
for the class destructor to do the needed cleanup.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* tui/tui-interp.c (tui_on_normal_stop, tui_on_signal_received)
	(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
	(tui_on_no_history): Update.
	* top.h (switch_thru_all_uis): New class.
	(SWITCH_THRU_ALL_UIS): Rewrite.
	(make_cleanup_restore_current_ui, switch_thru_all_uis_init)
	(switch_thru_all_uis_cond, switch_thru_all_uis_next): Don't
	declare.
	* mi/mi-interp.c (mi_new_thread, mi_thread_exit)
	(mi_record_changed, mi_inferior_added, mi_inferior_appeared)
	(mi_inferior_exit, mi_inferior_removed, mi_on_signal_received)
	(mi_on_end_stepping_range, mi_on_signal_exited, mi_on_exited)
	(mi_on_no_history, mi_on_normal_stop, mi_traceframe_changed)
	(mi_tsv_created, mi_tsv_deleted, mi_tsv_modified)
	(mi_breakpoint_created, mi_breakpoint_deleted)
	(mi_breakpoint_modified, mi_output_running_pid, mi_on_resume)
	(mi_solib_loaded, mi_solib_unloaded, mi_command_param_changed)
	(mi_memory_changed): Update.
	* infrun.c (all_uis_check_sync_execution_done)
	(all_uis_on_sync_execution_starting, normal_stop): Update.
	* event-top.c (restore_ui_cleanup)
	(make_cleanup_restore_current_ui, switch_thru_all_uis_init)
	(switch_thru_all_uis_cond, switch_thru_all_uis_next): Remove.
	* cli/cli-interp.c (cli_on_normal_stop, cli_on_signal_received)
	(cli_on_end_stepping_range, cli_on_signal_exited, cli_on_exited)
	(cli_on_no_history): Update.
	* breakpoint.c (watchpoint_check): Update.
---
 gdb/ChangeLog        |  30 +++++++++++++++
 gdb/breakpoint.c     |   8 +---
 gdb/cli/cli-interp.c |  24 +++---------
 gdb/event-top.c      |  50 -------------------------
 gdb/infrun.c         |  15 +++-----
 gdb/mi/mi-interp.c   | 101 +++++++++++++--------------------------------------
 gdb/top.h            |  56 +++++++++++++++++++---------
 gdb/tui/tui-interp.c |  24 +++---------
 8 files changed, 114 insertions(+), 194 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 717408f..954d658 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,35 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* tui/tui-interp.c (tui_on_normal_stop, tui_on_signal_received)
+	(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
+	(tui_on_no_history): Update.
+	* top.h (switch_thru_all_uis): New class.
+	(SWITCH_THRU_ALL_UIS): Rewrite.
+	(make_cleanup_restore_current_ui, switch_thru_all_uis_init)
+	(switch_thru_all_uis_cond, switch_thru_all_uis_next): Don't
+	declare.
+	* mi/mi-interp.c (mi_new_thread, mi_thread_exit)
+	(mi_record_changed, mi_inferior_added, mi_inferior_appeared)
+	(mi_inferior_exit, mi_inferior_removed, mi_on_signal_received)
+	(mi_on_end_stepping_range, mi_on_signal_exited, mi_on_exited)
+	(mi_on_no_history, mi_on_normal_stop, mi_traceframe_changed)
+	(mi_tsv_created, mi_tsv_deleted, mi_tsv_modified)
+	(mi_breakpoint_created, mi_breakpoint_deleted)
+	(mi_breakpoint_modified, mi_output_running_pid, mi_on_resume)
+	(mi_solib_loaded, mi_solib_unloaded, mi_command_param_changed)
+	(mi_memory_changed): Update.
+	* infrun.c (all_uis_check_sync_execution_done)
+	(all_uis_on_sync_execution_starting, normal_stop): Update.
+	* event-top.c (restore_ui_cleanup)
+	(make_cleanup_restore_current_ui, switch_thru_all_uis_init)
+	(switch_thru_all_uis_cond, switch_thru_all_uis_next): Remove.
+	* cli/cli-interp.c (cli_on_normal_stop, cli_on_signal_received)
+	(cli_on_end_stepping_range, cli_on_signal_exited, cli_on_exited)
+	(cli_on_no_history): Update.
+	* breakpoint.c (watchpoint_check): Update.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* xcoffread.c (record_minimal_symbol, scan_xcoff_symtab): Add
 	"reader" argument.  Update.
 	(xcoff_initial_scan): Update.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 1e05932..7f0061a 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5238,8 +5238,6 @@ watchpoint_check (void *p)
     }
   else
     {
-      struct switch_thru_all_uis state;
-
       /* This seems like the only logical thing to do because
          if we temporarily ignored the watchpoint, then when
          we reenter the block in which it is valid it contains
@@ -5254,7 +5252,7 @@ watchpoint_check (void *p)
 	 already.  So we have no choice but print the information
 	 here.  */
 
-      SWITCH_THRU_ALL_UIS (state)
+      SWITCH_THRU_ALL_UIS ()
         {
 	  struct ui_out *uiout = current_uiout;
 
@@ -5435,9 +5433,7 @@ bpstat_check_watchpoint (bpstat bs)
 	    case 0:
 	      /* Error from catch_errors.  */
 	      {
-		struct switch_thru_all_uis state;
-
-		SWITCH_THRU_ALL_UIS (state)
+		SWITCH_THRU_ALL_UIS ()
 	          {
 		    printf_filtered (_("Watchpoint %d deleted.\n"),
 				     b->base.number);
diff --git a/gdb/cli/cli-interp.c b/gdb/cli/cli-interp.c
index 5d67ba4..132ecdb 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -93,12 +93,10 @@ should_print_stop_to_console (struct interp *console_interp,
 static void
 cli_on_normal_stop (struct bpstats *bs, int print_frame)
 {
-  struct switch_thru_all_uis state;
-
   if (!print_frame)
     return;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct interp *interp = top_level_interpreter ();
       struct cli_interp *cli = as_cli_interp (interp);
@@ -118,9 +116,7 @@ cli_on_normal_stop (struct bpstats *bs, int print_frame)
 static void
 cli_on_signal_received (enum gdb_signal siggnal)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
 
@@ -136,9 +132,7 @@ cli_on_signal_received (enum gdb_signal siggnal)
 static void
 cli_on_end_stepping_range (void)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
 
@@ -154,9 +148,7 @@ cli_on_end_stepping_range (void)
 static void
 cli_on_signal_exited (enum gdb_signal siggnal)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
 
@@ -172,9 +164,7 @@ cli_on_signal_exited (enum gdb_signal siggnal)
 static void
 cli_on_exited (int exitstatus)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
 
@@ -190,9 +180,7 @@ cli_on_exited (int exitstatus)
 static void
 cli_on_no_history (void)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct cli_interp *cli = as_cli_interp (top_level_interpreter ());
 
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 576eded..9b0ccbc 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -447,56 +447,6 @@ struct ui *main_ui;
 struct ui *current_ui;
 struct ui *ui_list;
 
-/* A cleanup handler that restores the current UI.  */
-
-static void
-restore_ui_cleanup (void *data)
-{
-  current_ui = (struct ui *) data;
-}
-
-/* See top.h.  */
-
-struct cleanup *
-make_cleanup_restore_current_ui (void)
-{
-  return make_cleanup (restore_ui_cleanup, current_ui);
-}
-
-/* See top.h.  */
-
-void
-switch_thru_all_uis_init (struct switch_thru_all_uis *state)
-{
-  state->iter = ui_list;
-  state->old_chain = make_cleanup_restore_current_ui ();
-}
-
-/* See top.h.  */
-
-int
-switch_thru_all_uis_cond (struct switch_thru_all_uis *state)
-{
-  if (state->iter != NULL)
-    {
-      current_ui = state->iter;
-      return 1;
-    }
-  else
-    {
-      do_cleanups (state->old_chain);
-      return 0;
-    }
-}
-
-/* See top.h.  */
-
-void
-switch_thru_all_uis_next (struct switch_thru_all_uis *state)
-{
-  state->iter = state->iter->next;
-}
-
 /* Get a pointer to the current UI's line buffer.  This is used to
    construct a whole line of input from partial input.  */
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 6d96af9..1736526 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3857,9 +3857,7 @@ check_curr_ui_sync_execution_done (void)
 void
 all_uis_check_sync_execution_done (void)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       check_curr_ui_sync_execution_done ();
     }
@@ -3870,9 +3868,7 @@ all_uis_check_sync_execution_done (void)
 void
 all_uis_on_sync_execution_starting (void)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       if (current_ui->prompt_state == PROMPT_NEEDED)
 	async_disable_stdin ();
@@ -8217,7 +8213,6 @@ normal_stop (void)
   ptid_t last_ptid;
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   ptid_t pid_ptid;
-  struct switch_thru_all_uis state;
 
   get_last_target_status (&last_ptid, &last);
 
@@ -8282,7 +8277,7 @@ normal_stop (void)
       && last.kind != TARGET_WAITKIND_EXITED
       && last.kind != TARGET_WAITKIND_NO_RESUMED)
     {
-      SWITCH_THRU_ALL_UIS (state)
+      SWITCH_THRU_ALL_UIS ()
 	{
 	  target_terminal_ours_for_output ();
 	  printf_filtered (_("[Switching to %s]\n"),
@@ -8294,7 +8289,7 @@ normal_stop (void)
 
   if (last.kind == TARGET_WAITKIND_NO_RESUMED)
     {
-      SWITCH_THRU_ALL_UIS (state)
+      SWITCH_THRU_ALL_UIS ()
 	if (current_ui->prompt_state == PROMPT_BLOCKED)
 	  {
 	    target_terminal_ours_for_output ();
@@ -8311,7 +8306,7 @@ normal_stop (void)
   if (stopped_by_random_signal)
     disable_current_display ();
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       async_enable_stdin ();
     }
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index e3c7dbd..9584cd8 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -344,11 +344,10 @@ static void
 mi_new_thread (struct thread_info *t)
 {
   struct inferior *inf = find_inferior_ptid (t->ptid);
-  struct switch_thru_all_uis state;
 
   gdb_assert (inf);
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -371,12 +370,10 @@ mi_new_thread (struct thread_info *t)
 static void
 mi_thread_exit (struct thread_info *t, int silent)
 {
-  struct switch_thru_all_uis state;
-
   if (silent)
     return;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -401,9 +398,7 @@ static void
 mi_record_changed (struct inferior *inferior, int started, const char *method,
 		   const char *format)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -447,9 +442,7 @@ mi_record_changed (struct inferior *inferior, int started, const char *method,
 static void
 mi_inferior_added (struct inferior *inf)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct interp *interp;
       struct mi_interp *mi;
@@ -480,9 +473,7 @@ mi_inferior_added (struct inferior *inf)
 static void
 mi_inferior_appeared (struct inferior *inf)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -504,9 +495,7 @@ mi_inferior_appeared (struct inferior *inf)
 static void
 mi_inferior_exit (struct inferior *inf)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -533,9 +522,7 @@ mi_inferior_exit (struct inferior *inf)
 static void
 mi_inferior_removed (struct inferior *inf)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -584,9 +571,7 @@ find_mi_interp (void)
 static void
 mi_on_signal_received (enum gdb_signal siggnal)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = find_mi_interp ();
 
@@ -603,9 +588,7 @@ mi_on_signal_received (enum gdb_signal siggnal)
 static void
 mi_on_end_stepping_range (void)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = find_mi_interp ();
 
@@ -622,9 +605,7 @@ mi_on_end_stepping_range (void)
 static void
 mi_on_signal_exited (enum gdb_signal siggnal)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = find_mi_interp ();
 
@@ -641,9 +622,7 @@ mi_on_signal_exited (enum gdb_signal siggnal)
 static void
 mi_on_exited (int exitstatus)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = find_mi_interp ();
 
@@ -660,9 +639,7 @@ mi_on_exited (int exitstatus)
 static void
 mi_on_no_history (void)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = find_mi_interp ();
 
@@ -734,9 +711,7 @@ mi_on_normal_stop_1 (struct bpstats *bs, int print_frame)
 static void
 mi_on_normal_stop (struct bpstats *bs, int print_frame)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       if (as_mi_interp (top_level_interpreter ()) == NULL)
 	continue;
@@ -776,12 +751,10 @@ struct mi_suppress_notification mi_suppress_notification =
 static void
 mi_traceframe_changed (int tfnum, int tpnum)
 {
-  struct switch_thru_all_uis state;
-
   if (mi_suppress_notification.traceframe)
     return;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -810,9 +783,7 @@ mi_traceframe_changed (int tfnum, int tpnum)
 static void
 mi_tsv_created (const struct trace_state_variable *tsv)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -838,9 +809,7 @@ mi_tsv_created (const struct trace_state_variable *tsv)
 static void
 mi_tsv_deleted (const struct trace_state_variable *tsv)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -868,9 +837,7 @@ mi_tsv_deleted (const struct trace_state_variable *tsv)
 static void
 mi_tsv_modified (const struct trace_state_variable *tsv)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *mi_uiout;
@@ -908,15 +875,13 @@ mi_tsv_modified (const struct trace_state_variable *tsv)
 static void
 mi_breakpoint_created (struct breakpoint *b)
 {
-  struct switch_thru_all_uis state;
-
   if (mi_suppress_notification.breakpoint)
     return;
 
   if (b->number <= 0)
     return;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *mi_uiout;
@@ -962,15 +927,13 @@ mi_breakpoint_created (struct breakpoint *b)
 static void
 mi_breakpoint_deleted (struct breakpoint *b)
 {
-  struct switch_thru_all_uis state;
-
   if (mi_suppress_notification.breakpoint)
     return;
 
   if (b->number <= 0)
     return;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -995,15 +958,13 @@ mi_breakpoint_deleted (struct breakpoint *b)
 static void
 mi_breakpoint_modified (struct breakpoint *b)
 {
-  struct switch_thru_all_uis state;
-
   if (mi_suppress_notification.breakpoint)
     return;
 
   if (b->number <= 0)
     return;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -1044,9 +1005,8 @@ static int
 mi_output_running_pid (struct thread_info *info, void *arg)
 {
   ptid_t *ptid = (ptid_t *) arg;
-  struct switch_thru_all_uis state;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
 
@@ -1132,7 +1092,6 @@ static void
 mi_on_resume (ptid_t ptid)
 {
   struct thread_info *tp = NULL;
-  struct switch_thru_all_uis state;
 
   if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
     tp = inferior_thread ();
@@ -1143,7 +1102,7 @@ mi_on_resume (ptid_t ptid)
   if (tp->control.in_infcall)
     return;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct cleanup *old_chain;
@@ -1163,9 +1122,7 @@ mi_on_resume (ptid_t ptid)
 static void
 mi_solib_loaded (struct so_list *solib)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *uiout;
@@ -1204,9 +1161,7 @@ mi_solib_loaded (struct so_list *solib)
 static void
 mi_solib_unloaded (struct so_list *solib)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *uiout;
@@ -1246,12 +1201,10 @@ mi_solib_unloaded (struct so_list *solib)
 static void
 mi_command_param_changed (const char *param, const char *value)
 {
-  struct switch_thru_all_uis state;
-
   if (mi_suppress_notification.cmd_param_changed)
     return;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *mi_uiout;
@@ -1286,12 +1239,10 @@ static void
 mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr,
 		   ssize_t len, const bfd_byte *myaddr)
 {
-  struct switch_thru_all_uis state;
-
   if (mi_suppress_notification.memory)
     return;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
       struct ui_out *mi_uiout;
diff --git a/gdb/top.h b/gdb/top.h
index acdb8e9..ca1ae17 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -155,27 +155,52 @@ extern struct ui *current_ui;
 /* The list of all UIs.  */
 extern struct ui *ui_list;
 
-/* State for SWITCH_THRU_ALL_UIS.  Declared here because it is meant
-   to be created on the stack, but should be treated as opaque.  */
-struct switch_thru_all_uis
+/* State for SWITCH_THRU_ALL_UIS.  */
+class switch_thru_all_uis
 {
+public:
+
+  switch_thru_all_uis () : iter (nullptr), save_ui (&current_ui)
+  {
+    iter = ui_list;
+  }
+
+  ~switch_thru_all_uis ()
+  {
+  }
+
+  // If done iterating, return true; otherwise return false.
+  bool done () const
+  {
+    return iter == nullptr;
+  }
+
+  // Move to the next UI, setting current_ui if iteration is not yet
+  // complete.
+  void next ()
+  {
+    iter = iter->next;
+    if (iter != nullptr)
+      current_ui = iter;
+  }
+
+ private:
+
+  // No need for these.  They are intentionally not defined anywhere.
+  switch_thru_all_uis &operator= (const switch_thru_all_uis &);
+  switch_thru_all_uis (const switch_thru_all_uis &);
+
+  // Used to iterate through the UIs.
   struct ui *iter;
-  struct cleanup *old_chain;
-};
 
-/* Functions to drive SWITCH_THRU_ALL_UIS.  Though declared here by
-   necessity, these functions should not be used other than via the
-   SWITCH_THRU_ALL_UIS macro defined below.  */
-extern void switch_thru_all_uis_init (struct switch_thru_all_uis *state);
-extern int switch_thru_all_uis_cond (struct switch_thru_all_uis *state);
-extern void switch_thru_all_uis_next (struct switch_thru_all_uis *state);
+  // Save and restore current_ui.
+  scoped_restore<struct ui *> save_ui;
+};
 
   /* Traverse through all UI, and switch the current UI to the one
      being iterated.  */
 #define SWITCH_THRU_ALL_UIS(STATE)		\
-  for (switch_thru_all_uis_init (&STATE);		\
-       switch_thru_all_uis_cond (&STATE);		\
-       switch_thru_all_uis_next (&STATE))
+  for (switch_thru_all_uis stau_state; !stau_state.done (); stau_state.next ())
 
 /* Traverse over all UIs.  */
 #define ALL_UIS(UI)				\
@@ -188,9 +213,6 @@ extern void delete_ui (struct ui *todel);
 /* Cleanup that deletes a UI.  */
 extern struct cleanup *make_delete_ui_cleanup (struct ui *ui);
 
-/* Make a cleanup that restores the current UI.  */
-extern struct cleanup *make_cleanup_restore_current_ui (void);
-
 /* Register the UI's input file descriptor in the event loop.  */
 extern void ui_register_input_event_handler (struct ui *ui);
 
diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c
index 3856382..ba468b4 100644
--- a/gdb/tui/tui-interp.c
+++ b/gdb/tui/tui-interp.c
@@ -70,12 +70,10 @@ tui_exit (void)
 static void
 tui_on_normal_stop (struct bpstats *bs, int print_frame)
 {
-  struct switch_thru_all_uis state;
-
   if (!print_frame)
     return;
 
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct interp *interp = top_level_interpreter ();
       struct interp *tui = as_tui_interp (interp);
@@ -95,9 +93,7 @@ tui_on_normal_stop (struct bpstats *bs, int print_frame)
 static void
 tui_on_signal_received (enum gdb_signal siggnal)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct interp *tui = as_tui_interp (top_level_interpreter ());
 
@@ -113,9 +109,7 @@ tui_on_signal_received (enum gdb_signal siggnal)
 static void
 tui_on_end_stepping_range (void)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct interp *tui = as_tui_interp (top_level_interpreter ());
 
@@ -131,9 +125,7 @@ tui_on_end_stepping_range (void)
 static void
 tui_on_signal_exited (enum gdb_signal siggnal)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct interp *tui = as_tui_interp (top_level_interpreter ());
 
@@ -149,9 +141,7 @@ tui_on_signal_exited (enum gdb_signal siggnal)
 static void
 tui_on_exited (int exitstatus)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct interp *tui = as_tui_interp (top_level_interpreter ());
 
@@ -167,9 +157,7 @@ tui_on_exited (int exitstatus)
 static void
 tui_on_no_history (void)
 {
-  struct switch_thru_all_uis state;
-
-  SWITCH_THRU_ALL_UIS (state)
+  SWITCH_THRU_ALL_UIS ()
     {
       struct interp *tui = as_tui_interp (top_level_interpreter ());
 
-- 
2.7.4

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

* [RFA 08/22] Record minimal symbols directly in reader.
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (10 preceding siblings ...)
  2016-09-27  4:48 ` [RFA 09/22] Remove make_cleanup_restore_current_ui Tom Tromey
@ 2016-09-27  4:48 ` Tom Tromey
  2016-10-01  4:29   ` Simon Marchi
  2016-09-27  4:48 ` [RFA 01/22] Change selttest.c to use use std::vector Tom Tromey
                   ` (10 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch changes minimal symbol creation in two ways.  First, it
removes global variables in favor of members of
scoped_minimal_symbol_reader.  Second, it changes functions like
prim_record_minimal_symbol to be member functions of
scoped_minimal_symbol_reader.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* xcoffread.c (record_minimal_symbol, scan_xcoff_symtab): Add
	"reader" argument.  Update.
	(xcoff_initial_scan): Update.
	* symfile.h (mdebug_build_psymtabs): Add "reader" argument.
	* mipsread.c (mipscoff_symfile_read): Update.
	(read_alphacoff_dynamic_symtab): Add "reader" argument.  Update.
	* minsyms.h (scoped_minimal_symbol_reader) <record, record_full>:
	Declare.
	<msym_bunch, msym_bunch_index, msym_count>: New members.
	<record_with_info>: New function, renamed from
	prim_record_minimal_symbol_and_info.
	* minsyms.c (msym_bunch, msym_bunch_index, msym_count): Remove
	globals.
	(scoped_minimal_symbol_reader): Initialize new members.
	(scoped_minimal_symbol_reader::record): Renamed from
	prim_record_minimal_symbol.
	(scoped_minimal_symbol_reader::record_full): Renamed from
	prim_record_minimal_symbol_full.
	(prim_record_minimal_symbol_and_info): Move to minsyms.h; rename.
	* mdebugread.c (mdebug_build_psymtabs, parse_partial_symbols)
	(record_minimal_symbol): Add "reader" argument.  Update.
	(elfmdebug_build_psymtabs): Update.
	* machoread.c (macho_symtab_add_minsym, macho_symtab_read): Add
	"reader" argument.  Update.
	(macho_symfile_read): Update.
	* elfread.c (record_minimal_symbol, elf_symtab_read)
	(elf_rel_plt_read): Add "reader" argument.  Update.
	(elf_read_minimal_symbols): Update.
	* dbxread.c (record_minimal_symbol, read_dbx_dynamic_symtab)
	(read_dbx_symtab): Add "reader" argument.  Update.
	(dbx_symfile_read): Update.
	* coffread.c (record_minimal_symbol, coff_symtab_read): Add
	"reader" argument.  Update.
	(coff_symfile_read): Update.
	* coff-pe-read.h (read_pe_exported_syms): Add "reader" argument.
	* coff-pe-read.c (add_pe_exported_sym, add_pe_forwarded_sym)
	(read_pe_exported_syms): Add "reader" argument.  Update.
---
 gdb/ChangeLog      |  40 ++++++++++++++++++
 gdb/coff-pe-read.c |  30 +++++++-------
 gdb/coff-pe-read.h |   3 +-
 gdb/coffread.c     |  20 +++++----
 gdb/dbxread.c      |  30 +++++++-------
 gdb/elfread.c      |  38 +++++++++--------
 gdb/machoread.c    |  18 ++++----
 gdb/mdebugread.c   |  48 ++++++++++-----------
 gdb/minsyms.c      |  54 ++++++------------------
 gdb/minsyms.h      | 120 +++++++++++++++++++++++++++++------------------------
 gdb/mipsread.c     |  12 +++---
 gdb/symfile.h      |   3 +-
 gdb/xcoffread.c    |  35 ++++++++--------
 13 files changed, 245 insertions(+), 206 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index dac71f3..717408f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,45 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* xcoffread.c (record_minimal_symbol, scan_xcoff_symtab): Add
+	"reader" argument.  Update.
+	(xcoff_initial_scan): Update.
+	* symfile.h (mdebug_build_psymtabs): Add "reader" argument.
+	* mipsread.c (mipscoff_symfile_read): Update.
+	(read_alphacoff_dynamic_symtab): Add "reader" argument.  Update.
+	* minsyms.h (scoped_minimal_symbol_reader) <record, record_full>:
+	Declare.
+	<msym_bunch, msym_bunch_index, msym_count>: New members.
+	<record_with_info>: New function, renamed from
+	prim_record_minimal_symbol_and_info.
+	* minsyms.c (msym_bunch, msym_bunch_index, msym_count): Remove
+	globals.
+	(scoped_minimal_symbol_reader): Initialize new members.
+	(scoped_minimal_symbol_reader::record): Renamed from
+	prim_record_minimal_symbol.
+	(scoped_minimal_symbol_reader::record_full): Renamed from
+	prim_record_minimal_symbol_full.
+	(prim_record_minimal_symbol_and_info): Move to minsyms.h; rename.
+	* mdebugread.c (mdebug_build_psymtabs, parse_partial_symbols)
+	(record_minimal_symbol): Add "reader" argument.  Update.
+	(elfmdebug_build_psymtabs): Update.
+	* machoread.c (macho_symtab_add_minsym, macho_symtab_read): Add
+	"reader" argument.  Update.
+	(macho_symfile_read): Update.
+	* elfread.c (record_minimal_symbol, elf_symtab_read)
+	(elf_rel_plt_read): Add "reader" argument.  Update.
+	(elf_read_minimal_symbols): Update.
+	* dbxread.c (record_minimal_symbol, read_dbx_dynamic_symtab)
+	(read_dbx_symtab): Add "reader" argument.  Update.
+	(dbx_symfile_read): Update.
+	* coffread.c (record_minimal_symbol, coff_symtab_read): Add
+	"reader" argument.  Update.
+	(coff_symfile_read): Update.
+	* coff-pe-read.h (read_pe_exported_syms): Add "reader" argument.
+	* coff-pe-read.c (add_pe_exported_sym, add_pe_forwarded_sym)
+	(read_pe_exported_syms): Add "reader" argument.  Update.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* xcoffread.c (xcoff_initial_scan): Update.
 	* mipsread.c (mipscoff_symfile_read): Update.
 	* minsyms.c (scoped_minimal_symbol_reader): Add obj argument.
diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c
index 8836361..d0fa4a8 100644
--- a/gdb/coff-pe-read.c
+++ b/gdb/coff-pe-read.c
@@ -150,7 +150,8 @@ get_section_vmas (bfd *abfd, asection *sectp, void *context)
    OBJFILE is the objfile struct of DLL_NAME.  */
 
 static void
-add_pe_exported_sym (const char *sym_name,
+add_pe_exported_sym (scoped_minimal_symbol_reader &reader,
+		     const char *sym_name,
 		     unsigned long func_rva,
 		     int ordinal,
 		     const struct read_pe_section_data *section_data,
@@ -176,13 +177,12 @@ add_pe_exported_sym (const char *sym_name,
 			" for entry \"%s\" in dll \"%s\"\n"),
 			section_data->section_name, sym_name, dll_name);
 
-  prim_record_minimal_symbol_and_info (qualified_name, vma,
-				       section_data->ms_type,
-				       section_data->index, objfile);
+  reader.record_with_info (qualified_name, vma, section_data->ms_type,
+			   section_data->index);
 
   /* Enter the plain name as well, which might not be unique.  */
-  prim_record_minimal_symbol_and_info (bare_name, vma, section_data->ms_type,
-				       section_data->index, objfile);
+  reader.record_with_info (bare_name, vma, section_data->ms_type,
+			   section_data->index);
   if (debug_coff_pe_read > 1)
     fprintf_unfiltered (gdb_stdlog, _("Adding exported symbol \"%s\""
 			" in dll \"%s\"\n"), sym_name, dll_name);
@@ -200,7 +200,8 @@ add_pe_exported_sym (const char *sym_name,
    OBJFILE is the objfile struct of DLL_NAME.  */
 
 static int
-add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name,
+add_pe_forwarded_sym (scoped_minimal_symbol_reader &reader,
+		      const char *sym_name, const char *forward_dll_name,
 		      const char *forward_func_name, int ordinal,
 		      const char *dll_name, struct objfile *objfile)
 {
@@ -266,12 +267,10 @@ add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name,
      code.  */
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  prim_record_minimal_symbol_and_info (qualified_name, vma - baseaddr,
-				       msymtype, section, objfile);
+  reader.record_with_info (qualified_name, vma - baseaddr, msymtype, section);
 
   /* Enter the plain name as well, which might not be unique.  */
-  prim_record_minimal_symbol_and_info (bare_name, vma - baseaddr, msymtype,
-				       section, objfile);
+  reader.record_with_info (bare_name, vma - baseaddr, msymtype, section);
   xfree (qualified_name);
   xfree (bare_name);
 
@@ -331,7 +330,8 @@ pe_as32 (void *ptr)
    pe_implied_import_dll in pe-dll.c.  */
 
 void
-read_pe_exported_syms (struct objfile *objfile)
+read_pe_exported_syms (scoped_minimal_symbol_reader &reader,
+		       struct objfile *objfile)
 {
   bfd *dll = objfile->obfd;
   unsigned long nbnormal, nbforward;
@@ -580,7 +580,7 @@ read_pe_exported_syms (struct objfile *objfile)
 	      forward_dll_name[len] = '\0';
 	      forward_func_name = ++sep;
 	    }
-	  if (add_pe_forwarded_sym (funcname, forward_dll_name,
+	  if (add_pe_forwarded_sym (reader, funcname, forward_dll_name,
 				    forward_func_name, ordinal,
 				    dll_name, objfile) != 0)
 	    ++nbforward;
@@ -595,7 +595,7 @@ read_pe_exported_syms (struct objfile *objfile)
 	      char *sym_name = (char *) (erva + name_rva);
 
 	      section_found = 1;
-	      add_pe_exported_sym (sym_name, func_rva, ordinal,
+	      add_pe_exported_sym (reader, sym_name, func_rva, ordinal,
 				   section_data + sectix, dll_name, objfile);
 	      ++nbnormal;
 	      break;
@@ -607,7 +607,7 @@ read_pe_exported_syms (struct objfile *objfile)
 
 	  if (name_rva == 0)
 	    {
-	      add_pe_exported_sym (NULL, func_rva, ordinal,
+	      add_pe_exported_sym (reader, NULL, func_rva, ordinal,
 				   section_data, dll_name, objfile);
 	      ++nbnormal;
 	    }
diff --git a/gdb/coff-pe-read.h b/gdb/coff-pe-read.h
index 8a74a60..9f29a3d 100644
--- a/gdb/coff-pe-read.h
+++ b/gdb/coff-pe-read.h
@@ -27,7 +27,8 @@ struct bfd;
 
 /* Read the export table and convert it to minimal symbol table
    entries */
-extern void read_pe_exported_syms (struct objfile *objfile);
+extern void read_pe_exported_syms (scoped_minimal_symbol_reader &reader,
+				   struct objfile *objfile);
 
 /* Extract from ABFD the offset of the .text section.
    Returns default value 0x1000 if information is not found.  */
diff --git a/gdb/coffread.c b/gdb/coffread.c
index a86f223..8f8fe4b 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -207,7 +207,8 @@ static void read_one_sym (struct coff_symbol *,
 			  struct internal_syment *,
 			  union internal_auxent *);
 
-static void coff_symtab_read (long, unsigned int, struct objfile *);
+static void coff_symtab_read (scoped_minimal_symbol_reader &,
+			      long, unsigned int, struct objfile *);
 \f
 /* We are called once per section from coff_symfile_read.  We
    need to examine each section we are passed, check to see
@@ -461,7 +462,8 @@ is_import_fixup_symbol (struct coff_symbol *cs,
 }
 
 static struct minimal_symbol *
-record_minimal_symbol (struct coff_symbol *cs, CORE_ADDR address,
+record_minimal_symbol (scoped_minimal_symbol_reader &reader,
+		       struct coff_symbol *cs, CORE_ADDR address,
 		       enum minimal_symbol_type type, int section, 
 		       struct objfile *objfile)
 {
@@ -479,8 +481,7 @@ record_minimal_symbol (struct coff_symbol *cs, CORE_ADDR address,
       return NULL;
     }
 
-  return prim_record_minimal_symbol_and_info (cs->c_name, address,
-					      type, section, objfile);
+  return reader.record_with_info (cs->c_name, address, type, section);
 }
 \f
 /* coff_symfile_init ()
@@ -650,7 +651,7 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags)
   /* Now that the executable file is positioned at symbol table,
      process it and define symbols accordingly.  */
 
-  coff_symtab_read ((long) symtab_offset, num_symbols, objfile);
+  coff_symtab_read (reader, (long) symtab_offset, num_symbols, objfile);
 
   /* Install any minimal symbols that have been collected as the
      current minimal symbols for this objfile.  */
@@ -778,7 +779,8 @@ coff_symfile_finish (struct objfile *objfile)
    We read them one at a time using read_one_sym ().  */
 
 static void
-coff_symtab_read (long symtab_offset, unsigned int nsyms,
+coff_symtab_read (scoped_minimal_symbol_reader &reader,
+		  long symtab_offset, unsigned int nsyms,
 		  struct objfile *objfile)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
@@ -876,7 +878,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
 	  int section = cs_to_section (cs, objfile);
 
 	  tmpaddr = cs->c_value;
-	  record_minimal_symbol (cs, tmpaddr, mst_text,
+	  record_minimal_symbol (reader, cs, tmpaddr, mst_text,
 				 section, objfile);
 
 	  fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr;
@@ -1036,7 +1038,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
 		  ms_type = mst_unknown;
 	      }
 
-	    msym = record_minimal_symbol (cs, tmpaddr, ms_type,
+	    msym = record_minimal_symbol (reader, cs, tmpaddr, ms_type,
 					  sec, objfile);
 	    if (msym)
 	      gdbarch_coff_make_msymbol_special (gdbarch,
@@ -1198,7 +1200,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
     {
       /* We've got no debugging symbols, but it's a portable
 	 executable, so try to read the export table.  */
-      read_pe_exported_syms (objfile);
+      read_pe_exported_syms (reader, objfile);
     }
 
   if (get_last_source_file ())
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index 59c809a..2a666c3 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -262,9 +262,10 @@ static void dbx_read_symtab (struct partial_symtab *self,
 
 static void dbx_psymtab_to_symtab_1 (struct objfile *, struct partial_symtab *);
 
-static void read_dbx_dynamic_symtab (struct objfile *objfile);
+static void read_dbx_dynamic_symtab (scoped_minimal_symbol_reader &reader,
+				     struct objfile *objfile);
 
-static void read_dbx_symtab (struct objfile *);
+static void read_dbx_symtab (scoped_minimal_symbol_reader &, struct objfile *);
 
 static void free_bincl_list (struct objfile *);
 
@@ -286,7 +287,8 @@ static void dbx_symfile_read (struct objfile *, int);
 
 static void dbx_symfile_finish (struct objfile *);
 
-static void record_minimal_symbol (const char *, CORE_ADDR, int,
+static void record_minimal_symbol (scoped_minimal_symbol_reader &,
+				   const char *, CORE_ADDR, int,
 				   struct objfile *);
 
 static void add_new_header_file (char *, int);
@@ -429,7 +431,8 @@ explicit_lookup_type (int real_filenum, int index)
 #endif
 \f
 static void
-record_minimal_symbol (const char *name, CORE_ADDR address, int type,
+record_minimal_symbol (scoped_minimal_symbol_reader &reader,
+		       const char *name, CORE_ADDR address, int type,
 		       struct objfile *objfile)
 {
   enum minimal_symbol_type ms_type;
@@ -508,8 +511,7 @@ record_minimal_symbol (const char *name, CORE_ADDR address, int type,
       && address < lowest_text_address)
     lowest_text_address = address;
 
-  prim_record_minimal_symbol_and_info
-    (name, address, ms_type, section, objfile);
+  reader.record_with_info (name, address, ms_type, section);
 }
 \f
 /* Scan and build partial symbols for a symbol file.
@@ -562,11 +564,11 @@ dbx_symfile_read (struct objfile *objfile, int symfile_flags)
 
   /* Read stabs data from executable file and define symbols.  */
 
-  read_dbx_symtab (objfile);
+  read_dbx_symtab (reader, objfile);
 
   /* Add the dynamic symbols.  */
 
-  read_dbx_dynamic_symtab (objfile);
+  read_dbx_dynamic_symtab (reader, objfile);
 
   /* Install any minimal symbols that have been collected as the current
      minimal symbols for this objfile.  */
@@ -978,7 +980,8 @@ set_namestring (struct objfile *objfile, const struct internal_nlist *nlist)
    add them to the minimal symbol table.  */
 
 static void
-read_dbx_dynamic_symtab (struct objfile *objfile)
+read_dbx_dynamic_symtab (scoped_minimal_symbol_reader &reader,
+			 struct objfile *objfile)
 {
   bfd *abfd = objfile->obfd;
   struct cleanup *back_to;
@@ -1052,7 +1055,7 @@ read_dbx_dynamic_symtab (struct objfile *objfile)
 	  if (sym->flags & BSF_GLOBAL)
 	    type |= N_EXT;
 
-	  record_minimal_symbol (bfd_asymbol_name (sym), sym_value,
+	  record_minimal_symbol (reader, bfd_asymbol_name (sym), sym_value,
 				 type, objfile);
 	}
     }
@@ -1105,8 +1108,7 @@ read_dbx_dynamic_symtab (struct objfile *objfile)
 	}
 
       name = bfd_asymbol_name (*rel->sym_ptr_ptr);
-      prim_record_minimal_symbol (name, address, mst_solib_trampoline,
-				  objfile);
+      reader.record (name, address, mst_solib_trampoline);
     }
 
   do_cleanups (back_to);
@@ -1169,7 +1171,7 @@ function_outside_compilation_unit_complaint (const char *arg1)
    debugging information is available.  */
 
 static void
-read_dbx_symtab (struct objfile *objfile)
+read_dbx_symtab (scoped_minimal_symbol_reader &reader, struct objfile *objfile)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct external_nlist *bufp = 0;	/* =0 avoids gcc -Wall glitch.  */
@@ -1325,7 +1327,7 @@ read_dbx_symtab (struct objfile *objfile)
 	  record_it:
 	  namestring = set_namestring (objfile, &nlist);
 
-	  record_minimal_symbol (namestring, nlist.n_value,
+	  record_minimal_symbol (reader, namestring, nlist.n_value,
 				 nlist.n_type, objfile);	/* Always */
 	  continue;
 
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 98574ca..09ac507 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -191,7 +191,8 @@ elf_locate_sections (bfd *ignore_abfd, asection *sectp, void *eip)
 }
 
 static struct minimal_symbol *
-record_minimal_symbol (const char *name, int name_len, int copy_name,
+record_minimal_symbol (scoped_minimal_symbol_reader &reader,
+		       const char *name, int name_len, int copy_name,
 		       CORE_ADDR address,
 		       enum minimal_symbol_type ms_type,
 		       asection *bfd_section, struct objfile *objfile)
@@ -202,11 +203,10 @@ record_minimal_symbol (const char *name, int name_len, int copy_name,
       || ms_type == mst_text_gnu_ifunc)
     address = gdbarch_addr_bits_remove (gdbarch, address);
 
-  return prim_record_minimal_symbol_full (name, name_len, copy_name, address,
-					  ms_type,
-					  gdb_bfd_section_index (objfile->obfd,
-								 bfd_section),
-					  objfile);
+  return reader.record_full (name, name_len, copy_name, address,
+			     ms_type,
+			     gdb_bfd_section_index (objfile->obfd,
+						    bfd_section));
 }
 
 /* Read the symbol table of an ELF file.
@@ -226,7 +226,8 @@ record_minimal_symbol (const char *name, int name_len, int copy_name,
 #define ST_SYNTHETIC 2
 
 static void
-elf_symtab_read (struct objfile *objfile, int type,
+elf_symtab_read (scoped_minimal_symbol_reader &reader,
+		 struct objfile *objfile, int type,
 		 long number_of_symbols, asymbol **symbol_table,
 		 int copy_names)
 {
@@ -318,7 +319,7 @@ elf_symtab_read (struct objfile *objfile, int type,
 	    continue;
 
 	  msym = record_minimal_symbol
-	    (sym->name, strlen (sym->name), copy_names,
+	    (reader, sym->name, strlen (sym->name), copy_names,
 	     symaddr, mst_solib_trampoline, sect, objfile);
 	  if (msym != NULL)
 	    {
@@ -458,7 +459,7 @@ elf_symtab_read (struct objfile *objfile, int type,
 	      continue;	/* Skip this symbol.  */
 	    }
 	  msym = record_minimal_symbol
-	    (sym->name, strlen (sym->name), copy_names, symaddr,
+	    (reader, sym->name, strlen (sym->name), copy_names, symaddr,
 	     ms_type, sym->section, objfile);
 
 	  if (msym)
@@ -487,7 +488,7 @@ elf_symtab_read (struct objfile *objfile, int type,
 		{
 		  int len = atsign - sym->name;
 
-		  record_minimal_symbol (sym->name, len, 1, symaddr,
+		  record_minimal_symbol (reader, sym->name, len, 1, symaddr,
 					 ms_type, sym->section, objfile);
 		}
 	    }
@@ -504,7 +505,7 @@ elf_symtab_read (struct objfile *objfile, int type,
 		{
 		  struct minimal_symbol *mtramp;
 
-		  mtramp = record_minimal_symbol (sym->name, len - 4, 1,
+		  mtramp = record_minimal_symbol (reader, sym->name, len - 4, 1,
 						  symaddr,
 						  mst_solib_trampoline,
 						  sym->section, objfile);
@@ -531,7 +532,8 @@ elf_symtab_read (struct objfile *objfile, int type,
    DYN_SYMBOL_TABLE is no longer easily available for OBJFILE.  */
 
 static void
-elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table)
+elf_rel_plt_read (scoped_minimal_symbol_reader &reader,
+		  struct objfile *objfile, asymbol **dyn_symbol_table)
 {
   bfd *obfd = objfile->obfd;
   const struct elf_backend_data *bed = get_elf_backend_data (obfd);
@@ -608,7 +610,8 @@ elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table)
       memcpy (&string_buffer[name_len], SYMBOL_GOT_PLT_SUFFIX,
 	      got_suffix_len + 1);
 
-      msym = record_minimal_symbol (string_buffer, name_len + got_suffix_len,
+      msym = record_minimal_symbol (reader, string_buffer,
+				    name_len + got_suffix_len,
                                     1, address, mst_slot_got_plt, got_plt,
 				    objfile);
       if (msym)
@@ -1077,7 +1080,7 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
 	       bfd_get_filename (objfile->obfd),
 	       bfd_errmsg (bfd_get_error ()));
 
-      elf_symtab_read (objfile, ST_REGULAR, symcount, symbol_table, 0);
+      elf_symtab_read (reader, objfile, ST_REGULAR, symcount, symbol_table, 0);
     }
 
   /* Add the dynamic symbols.  */
@@ -1102,9 +1105,10 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
 	       bfd_get_filename (objfile->obfd),
 	       bfd_errmsg (bfd_get_error ()));
 
-      elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table, 0);
+      elf_symtab_read (reader, objfile, ST_DYNAMIC, dynsymcount,
+		       dyn_symbol_table, 0);
 
-      elf_rel_plt_read (objfile, dyn_symbol_table);
+      elf_rel_plt_read (reader, objfile, dyn_symbol_table);
     }
 
   /* Contrary to binutils --strip-debug/--only-keep-debug the strip command from
@@ -1139,7 +1143,7 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
       for (i = 0; i < synthcount; i++)
 	synth_symbol_table[i] = synthsyms + i;
       make_cleanup (xfree, synth_symbol_table);
-      elf_symtab_read (objfile, ST_SYNTHETIC, synthcount,
+      elf_symtab_read (reader, objfile, ST_SYNTHETIC, synthcount,
 		       synth_symbol_table, 1);
     }
 
diff --git a/gdb/machoread.c b/gdb/machoread.c
index 0eb438a..df0333a 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -96,7 +96,8 @@ macho_register_oso (VEC (oso_el) **oso_vector_ptr,
 /* Add symbol SYM to the minimal symbol table of OBJFILE.  */
 
 static void
-macho_symtab_add_minsym (struct objfile *objfile, const asymbol *sym)
+macho_symtab_add_minsym (scoped_minimal_symbol_reader &reader,
+			 struct objfile *objfile, const asymbol *sym)
 {
   if (sym->name == NULL || *sym->name == '\0')
     {
@@ -146,10 +147,9 @@ macho_symtab_add_minsym (struct objfile *objfile, const asymbol *sym)
       else
         return;	/* Skip this symbol.  */
 
-      prim_record_minimal_symbol_and_info
-        (sym->name, symaddr, ms_type,
-	 gdb_bfd_section_index (objfile->obfd, sym->section),
-	 objfile);
+      reader.record_with_info (sym->name, symaddr, ms_type,
+			       gdb_bfd_section_index (objfile->obfd,
+						      sym->section));
     }
 }
 
@@ -157,7 +157,8 @@ macho_symtab_add_minsym (struct objfile *objfile, const asymbol *sym)
    NUMBER_OF_SYMBOLS for OBJFILE.  Registers OSO filenames found.  */
 
 static void
-macho_symtab_read (struct objfile *objfile,
+macho_symtab_read (scoped_minimal_symbol_reader &reader,
+		   struct objfile *objfile,
 		   long number_of_symbols, asymbol **symbol_table,
 		   VEC (oso_el) **oso_vector_ptr)
 {
@@ -226,7 +227,7 @@ macho_symtab_read (struct objfile *objfile,
           else
             {
               /* Non-debugging symbols go to the minimal symbol table.  */
-              macho_symtab_add_minsym (objfile, sym);
+              macho_symtab_add_minsym (reader, objfile, sym);
             }
           break;
 
@@ -870,7 +871,8 @@ macho_symfile_read (struct objfile *objfile, int symfile_flags)
 		   bfd_get_filename (objfile->obfd),
 		   bfd_errmsg (bfd_get_error ()));
 
-	  macho_symtab_read (objfile, symcount, symbol_table, &oso_vector);
+	  macho_symtab_read (reader, objfile, symcount, symbol_table,
+			     &oso_vector);
 
           reader.install ();
 	}
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index b93024b..c2bdd6f 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -222,7 +222,8 @@ static int found_ecoff_debugging_info;
 static int upgrade_type (int, struct type **, int, union aux_ext *,
 			 int, char *);
 
-static void parse_partial_symbols (struct objfile *);
+static void parse_partial_symbols (scoped_minimal_symbol_reader &,
+				   struct objfile *);
 
 static int has_opaque_xref (FDR *, SYMR *);
 
@@ -336,7 +337,8 @@ fdr_name (FDR *f)
    different sections are relocated via the SECTION_OFFSETS.  */
 
 void
-mdebug_build_psymtabs (struct objfile *objfile,
+mdebug_build_psymtabs (scoped_minimal_symbol_reader &reader,
+		       struct objfile *objfile,
 		       const struct ecoff_debug_swap *swap,
 		       struct ecoff_debug_info *info)
 {
@@ -367,7 +369,7 @@ mdebug_build_psymtabs (struct objfile *objfile,
 	(*swap->swap_fdr_in) (objfile->obfd, fdr_src, fdr_ptr);
     }
 
-  parse_partial_symbols (objfile);
+  parse_partial_symbols (reader, objfile);
 
 #if 0
   /* Check to make sure file was compiled with -g.  If not, warn the
@@ -2260,7 +2262,8 @@ function_outside_compilation_unit_complaint (const char *arg1)
    belongs to, and then records this new minimal symbol.  */
 
 static void
-record_minimal_symbol (const char *name, const CORE_ADDR address,
+record_minimal_symbol (scoped_minimal_symbol_reader &reader,
+		       const char *name, const CORE_ADDR address,
                        enum minimal_symbol_type ms_type, int storage_class,
                        struct objfile *objfile)
 {
@@ -2316,15 +2319,15 @@ record_minimal_symbol (const char *name, const CORE_ADDR address,
         section = -1;
     }
 
-  prim_record_minimal_symbol_and_info (name, address, ms_type,
-                                       section, objfile);
+  reader.record_with_info (name, address, ms_type, section);
 }
 
 /* Master parsing procedure for first-pass reading of file symbols
    into a partial_symtab.  */
 
 static void
-parse_partial_symbols (struct objfile *objfile)
+parse_partial_symbols (scoped_minimal_symbol_reader &reader,
+		       struct objfile *objfile)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   const bfd_size_type external_sym_size = debug_swap->external_sym_size;
@@ -2624,7 +2627,7 @@ parse_partial_symbols (struct objfile *objfile)
 	  unknown_ext_complaint (name);
 	}
       if (!ECOFF_IN_ELF (cur_bfd))
-        record_minimal_symbol (name, svalue, ms_type, ext_in->asym.sc,
+        record_minimal_symbol (reader, name, svalue, ms_type, ext_in->asym.sc,
                                objfile);
     }
 
@@ -2741,7 +2744,7 @@ parse_partial_symbols (struct objfile *objfile)
 		      if (sh.st == stStaticProc)
 			{
 			  namestring = debug_info->ss + fh->issBase + sh.iss;
-                          record_minimal_symbol (namestring, sh.value,
+                          record_minimal_symbol (reader, namestring, sh.value,
                                                  mst_file_text, sh.sc,
                                                  objfile);
 			}
@@ -2786,7 +2789,7 @@ parse_partial_symbols (struct objfile *objfile)
 			case scPData:
 			case scXData:
 			  namestring = debug_info->ss + fh->issBase + sh.iss;
-                          record_minimal_symbol (namestring, sh.value,
+                          record_minimal_symbol (reader, namestring, sh.value,
                                                  mst_file_data, sh.sc,
                                                  objfile);
 			  sh.value += ANOFFSET (objfile->section_offsets,
@@ -2797,7 +2800,7 @@ parse_partial_symbols (struct objfile *objfile)
 			  /* FIXME!  Shouldn't this use cases for bss, 
 			     then have the default be abs?  */
 			  namestring = debug_info->ss + fh->issBase + sh.iss;
-                          record_minimal_symbol (namestring, sh.value,
+                          record_minimal_symbol (reader, namestring, sh.value,
                                                  mst_file_bss, sh.sc,
                                                  objfile);
 			  sh.value += ANOFFSET (objfile->section_offsets,
@@ -3467,10 +3470,9 @@ parse_partial_symbols (struct objfile *objfile)
 		  int new_sdx;
 
 		case stStaticProc:
-		  prim_record_minimal_symbol_and_info (name, minsym_value,
-						       mst_file_text,
-						       SECT_OFF_TEXT (objfile),
-						       objfile);
+		  reader.record_with_info (name, minsym_value,
+					   mst_file_text,
+					   SECT_OFF_TEXT (objfile));
 
 		  /* FALLTHROUGH */
 
@@ -3553,15 +3555,13 @@ parse_partial_symbols (struct objfile *objfile)
 
 		case stStatic:	/* Variable */
 		  if (SC_IS_DATA (sh.sc))
-		    prim_record_minimal_symbol_and_info (name, minsym_value,
-							 mst_file_data,
-							 SECT_OFF_DATA (objfile),
-							 objfile);
+		    reader.record_with_info (name, minsym_value,
+					     mst_file_data,
+					     SECT_OFF_DATA (objfile));
 		  else
-		    prim_record_minimal_symbol_and_info (name, minsym_value,
-							 mst_file_bss,
-							 SECT_OFF_BSS (objfile),
-							 objfile);
+		    reader.record_with_info (name, minsym_value,
+					     mst_file_bss,
+					     SECT_OFF_BSS (objfile));
 		  theclass = LOC_STATIC;
 		  break;
 
@@ -4885,7 +4885,7 @@ elfmdebug_build_psymtabs (struct objfile *objfile,
     error (_("Error reading ECOFF debugging information: %s"),
 	   bfd_errmsg (bfd_get_error ()));
 
-  mdebug_build_psymtabs (objfile, swap, info);
+  mdebug_build_psymtabs (reader, objfile, swap, info);
 
   reader.install ();
 }
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index b6f306b..8fa5bba 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -64,19 +64,6 @@ struct msym_bunch
     struct minimal_symbol contents[BUNCH_SIZE];
   };
 
-/* Bunch currently being filled up.
-   The next field points to chain of filled bunches.  */
-
-static struct msym_bunch *msym_bunch;
-
-/* Number of slots filled in current bunch.  */
-
-static int msym_bunch_index;
-
-/* Total number of minimal symbols recorded so far for the objfile.  */
-
-static int msym_count;
-
 /* See minsyms.h.  */
 
 unsigned int
@@ -922,14 +909,14 @@ get_symbol_leading_char (bfd *abfd)
 /* See minsyms.h.  */
 
 scoped_minimal_symbol_reader::scoped_minimal_symbol_reader (struct objfile *obj)
-: objfile (obj)
-{
-  msym_count = 0;
-  msym_bunch = NULL;
+: objfile (obj),
+  msym_bunch (NULL),
   /* Note that presetting msym_bunch_index to BUNCH_SIZE causes the
      first call to save a minimal symbol to allocate the memory for
      the first bunch.  */
-  msym_bunch_index = BUNCH_SIZE;
+  msym_bunch_index (BUNCH_SIZE),
+  msym_count (0)
+{
 }
 
 /* Discard the currently collected minimal symbols, if any.  If we wish
@@ -955,9 +942,8 @@ scoped_minimal_symbol_reader::~scoped_minimal_symbol_reader ()
 /* See minsyms.h.  */
 
 void
-prim_record_minimal_symbol (const char *name, CORE_ADDR address,
-			    enum minimal_symbol_type ms_type,
-			    struct objfile *objfile)
+scoped_minimal_symbol_reader::record (const char *name, CORE_ADDR address,
+				      enum minimal_symbol_type ms_type)
 {
   int section;
 
@@ -981,18 +967,17 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address,
       section = -1;
     }
 
-  prim_record_minimal_symbol_and_info (name, address, ms_type,
-				       section, objfile);
+  record_with_info (name, address, ms_type, section);
 }
 
 /* See minsyms.h.  */
 
 struct minimal_symbol *
-prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
-				 CORE_ADDR address,
-				 enum minimal_symbol_type ms_type,
-				 int section,
-				 struct objfile *objfile)
+scoped_minimal_symbol_reader::record_full (const char *name, int name_len,
+					   int copy_name,
+					   CORE_ADDR address,
+					   enum minimal_symbol_type ms_type,
+					   int section)
 {
   struct msym_bunch *newobj;
   struct minimal_symbol *msymbol;
@@ -1056,19 +1041,6 @@ prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
   return msymbol;
 }
 
-/* See minsyms.h.  */
-
-struct minimal_symbol *
-prim_record_minimal_symbol_and_info (const char *name, CORE_ADDR address,
-				     enum minimal_symbol_type ms_type,
-				     int section,
-				     struct objfile *objfile)
-{
-  return prim_record_minimal_symbol_full (name, strlen (name), 1,
-					  address, ms_type,
-					  section, objfile);
-}
-
 /* Compare two minimal symbols by address and return a signed result based
    on unsigned comparisons, so that we sort into unsigned numeric order.
    Within groups with the same address, sort by name.  */
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index 7ba5991..af75267 100644
--- a/gdb/minsyms.h
+++ b/gdb/minsyms.h
@@ -53,16 +53,17 @@ struct bound_minimal_symbol
    as opaque and use functions provided by minsyms.c to inspect them.
 */
 
+struct msym_bunch;
+
 // An RAII-based object that is used to record minimal symbols while
 // they are being read.
 class scoped_minimal_symbol_reader
 {
  public:
 
-  /* Prepare to start collecting minimal symbols.  This should be called
-     by a symbol reader to initialize the minimal symbol module.
-     Currently, minimal symbol table creation is not reentrant; it
-     relies on global (static) variables in minsyms.c.  */
+  /* Prepare to start collecting minimal symbols.  This should be
+     called by a symbol reader to initialize the minimal symbol
+     module.  */
 
   explicit scoped_minimal_symbol_reader (struct objfile *);
 
@@ -73,6 +74,56 @@ class scoped_minimal_symbol_reader
 
   void install ();
 
+  /* Record a new minimal symbol.  This is the "full" entry point;
+     simpler convenience entry points are also provided below.
+   
+     This returns a new minimal symbol.  It is ok to modify the returned
+     minimal symbol (though generally not necessary).  It is not ok,
+     though, to stash the pointer anywhere; as minimal symbols may be
+     moved after creation.  The memory for the returned minimal symbol
+     is still owned by the minsyms.c code, and should not be freed.
+   
+     Arguments are:
+
+     NAME - the symbol's name
+     NAME_LEN - the length of the name
+     COPY_NAME - if true, the minsym code must make a copy of NAME.  If
+     false, then NAME must be NUL-terminated, and must have a lifetime
+     that is at least as long as OBJFILE's lifetime.
+     ADDRESS - the address of the symbol
+     MS_TYPE - the type of the symbol
+     SECTION - the symbol's section
+     appropriate obj_section for the minimal symbol.  This can be NULL.
+     OBJFILE - the objfile associated with the minimal symbol.  */
+
+  struct minimal_symbol *record_full (const char *name,
+				      int name_len,
+				      int copy_name,
+				      CORE_ADDR address,
+				      enum minimal_symbol_type ms_type,
+				      int section);
+
+  /* Like record_full, but:
+     - uses strlen to compute NAME_LEN,
+     - passes COPY_NAME = 1,
+     - and passes a default SECTION, depending on the type
+
+     This variant does not return the new symbol.  */
+
+  void record (const char *, CORE_ADDR, enum minimal_symbol_type);
+
+  /* Like record_full, but:
+     - uses strlen to compute NAME_LEN,
+     - passes COPY_NAME = 1.  */
+
+  struct minimal_symbol *record_with_info (const char *name,
+					   CORE_ADDR address,
+					   enum minimal_symbol_type ms_type,
+					   int section)
+  {
+    return record_full (name, strlen (name), 1, address, ms_type, section);
+  }
+
  private:
 
   // No need for these.  They are intentionally not defined anywhere.
@@ -81,60 +132,21 @@ class scoped_minimal_symbol_reader
   scoped_minimal_symbol_reader (const scoped_minimal_symbol_reader &);
 
   struct objfile *objfile;
-};
 
-/* Record a new minimal symbol.  This is the "full" entry point;
-   simpler convenience entry points are also provided below.
-   
-   This returns a new minimal symbol.  It is ok to modify the returned
-   minimal symbol (though generally not necessary).  It is not ok,
-   though, to stash the pointer anywhere; as minimal symbols may be
-   moved after creation.  The memory for the returned minimal symbol
-   is still owned by the minsyms.c code, and should not be freed.
-   
-   Arguments are:
-
-   NAME - the symbol's name
-   NAME_LEN - the length of the name
-   COPY_NAME - if true, the minsym code must make a copy of NAME.  If
-   false, then NAME must be NUL-terminated, and must have a lifetime
-   that is at least as long as OBJFILE's lifetime.
-   ADDRESS - the address of the symbol
-   MS_TYPE - the type of the symbol
-   SECTION - the symbol's section
-   appropriate obj_section for the minimal symbol.  This can be NULL.
-   OBJFILE - the objfile associated with the minimal symbol.  */
-
-struct minimal_symbol *prim_record_minimal_symbol_full
-    (const char *name,
-     int name_len,
-     int copy_name,
-     CORE_ADDR address,
-     enum minimal_symbol_type ms_type,
-     int section,
-     struct objfile *objfile);
-
-/* Like prim_record_minimal_symbol_full, but:
-   - uses strlen to compute NAME_LEN,
-   - passes COPY_NAME = 1,
-   - and passes a default SECTION, depending on the type
-   
-   This variant does not return the new symbol.  */
+  /* Bunch currently being filled up.
+     The next field points to chain of filled bunches.  */
 
-void prim_record_minimal_symbol (const char *, CORE_ADDR,
-				 enum minimal_symbol_type,
-				 struct objfile *);
+  struct msym_bunch *msym_bunch;
 
-/* Like prim_record_minimal_symbol_full, but:
-   - uses strlen to compute NAME_LEN,
-   - passes COPY_NAME = 1.  */
+  /* Number of slots filled in current bunch.  */
 
-struct minimal_symbol *prim_record_minimal_symbol_and_info
-    (const char *,
-     CORE_ADDR,
-     enum minimal_symbol_type,
-     int section,
-     struct objfile *);
+  int msym_bunch_index;
+
+  /* Total number of minimal symbols recorded so far for the
+     objfile.  */
+
+  int msym_count;
+};
 
 /* Create the terminating entry of OBJFILE's minimal symbol table.
    If OBJFILE->msymbols is zero, allocate a single entry from
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
index e5285d2..ae59747 100644
--- a/gdb/mipsread.c
+++ b/gdb/mipsread.c
@@ -42,7 +42,8 @@
 #include "psymtab.h"
 
 static void
-read_alphacoff_dynamic_symtab (struct section_offsets *,
+read_alphacoff_dynamic_symtab (scoped_minimal_symbol_reader &,
+			       struct section_offsets *,
 			       struct objfile *objfile);
 
 /* Initialize anything that needs initializing when a completely new
@@ -79,12 +80,12 @@ mipscoff_symfile_read (struct objfile *objfile, int symfile_flags)
 	(abfd, (asection *) NULL, &ecoff_data (abfd)->debug_info)))
     error (_("Error reading symbol table: %s"), bfd_errmsg (bfd_get_error ()));
 
-  mdebug_build_psymtabs (objfile, &ecoff_backend (abfd)->debug_swap,
+  mdebug_build_psymtabs (reader, objfile, &ecoff_backend (abfd)->debug_swap,
 			 &ecoff_data (abfd)->debug_info);
 
   /* Add alpha coff dynamic symbols.  */
 
-  read_alphacoff_dynamic_symtab (objfile->section_offsets, objfile);
+  read_alphacoff_dynamic_symtab (reader, objfile->section_offsets, objfile);
 
   /* Install any minimal symbols that have been collected as the current
      minimal symbols for this objfile.  */
@@ -173,7 +174,8 @@ alphacoff_locate_sections (bfd *ignore_abfd, asection *sectp, void *sip)
    them to the minimal symbol table.  */
 
 static void
-read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets,
+read_alphacoff_dynamic_symtab (scoped_minimal_symbol_reader &reader,
+			       struct section_offsets *section_offsets,
 			       struct objfile *objfile)
 {
   bfd *abfd = objfile->obfd;
@@ -388,7 +390,7 @@ read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets,
 	    }
 	}
 
-      prim_record_minimal_symbol (name, sym_value, ms_type, objfile);
+      reader.record (name, sym_value, ms_type);
     }
 
   do_cleanups (cleanups);
diff --git a/gdb/symfile.h b/gdb/symfile.h
index a11c48a..aad9d88 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -652,7 +652,8 @@ void dwarf2_free_objfile (struct objfile *);
 
 /* From mdebugread.c */
 
-extern void mdebug_build_psymtabs (struct objfile *,
+extern void mdebug_build_psymtabs (scoped_minimal_symbol_reader &,
+				   struct objfile *,
 				   const struct ecoff_debug_swap *,
 				   struct ecoff_debug_info *);
 
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 6545e94..de18d7f 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -197,7 +197,8 @@ eb_complaint (int arg1)
 
 static void xcoff_initial_scan (struct objfile *, int);
 
-static void scan_xcoff_symtab (struct objfile *);
+static void scan_xcoff_symtab (scoped_minimal_symbol_reader &,
+			       struct objfile *);
 
 static char *xcoff_next_symbol_text (struct objfile *);
 
@@ -908,10 +909,10 @@ enter_line_range (struct subfile *subfile, unsigned beginoffset,
    This function can read past the end of the symbol table
    (into the string table) but this does no harm.  */
 
-/* Create a new minimal symbol (using prim_record_minimal_symbol_and_info).
+/* Create a new minimal symbol (using record_with_info).
 
    Creation of all new minimal symbols should go through this function
-   rather than calling the various prim_record_[...] functions in order
+   rather than calling the various record functions in order
    to make sure that all symbol addresses get properly relocated.
 
    Arguments are:
@@ -925,18 +926,17 @@ enter_line_range (struct subfile *subfile, unsigned beginoffset,
    OBJFILE - the objfile associated with the minimal symbol.  */
 
 static void
-record_minimal_symbol (const char *name, CORE_ADDR address,
+record_minimal_symbol (scoped_minimal_symbol_reader &reader,
+		       const char *name, CORE_ADDR address,
 		       enum minimal_symbol_type ms_type,
 		       int n_scnum,
 		       struct objfile *objfile)
 {
-
   if (name[0] == '.')
     ++name;
 
-  prim_record_minimal_symbol_and_info (name, address, ms_type,
-				       secnum_to_section (n_scnum, objfile),
-				       objfile);
+  reader.record_with_info (name, address, ms_type,
+			   secnum_to_section (n_scnum, objfile));
 }
 
 /* xcoff has static blocks marked in `.bs', `.es' pairs.  They cannot be
@@ -2178,7 +2178,8 @@ function_outside_compilation_unit_complaint (const char *arg1)
 }
 
 static void
-scan_xcoff_symtab (struct objfile *objfile)
+scan_xcoff_symtab (scoped_minimal_symbol_reader &reader,
+		   struct objfile *objfile)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   CORE_ADDR toc_offset = 0;	/* toc offset value in data section.  */
@@ -2288,7 +2289,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 			if (!misc_func_recorded)
 			  {
 			    record_minimal_symbol
-			      (last_csect_name, last_csect_val,
+			      (reader, last_csect_name, last_csect_val,
 			       mst_text, last_csect_sec, objfile);
 			    misc_func_recorded = 1;
 			  }
@@ -2343,7 +2344,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		       table, except for section symbols.  */
 		    if (*namestring != '.')
 		      record_minimal_symbol
-			(namestring, symbol.n_value,
+			(reader, namestring, symbol.n_value,
 			 sclass == C_HIDEXT ? mst_file_data : mst_data,
 			 symbol.n_scnum, objfile);
 		    break;
@@ -2381,7 +2382,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 			main_aux[0].x_sym.x_fcnary.x_fcn.x_lnnoptr;
 
 		    record_minimal_symbol
-		      (namestring, symbol.n_value,
+		      (reader, namestring, symbol.n_value,
 		       sclass == C_HIDEXT ? mst_file_text : mst_text,
 		       symbol.n_scnum, objfile);
 		    misc_func_recorded = 1;
@@ -2396,7 +2397,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		       symbols, we will choose mst_text over
 		       mst_solib_trampoline.  */
 		    record_minimal_symbol
-		      (namestring, symbol.n_value,
+		      (reader, namestring, symbol.n_value,
 		       mst_solib_trampoline, symbol.n_scnum, objfile);
 		    misc_func_recorded = 1;
 		    break;
@@ -2418,7 +2419,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		       XMC_BS might be possible too.  */
 		    if (*namestring != '.')
 		      record_minimal_symbol
-			(namestring, symbol.n_value,
+			(reader, namestring, symbol.n_value,
 			 sclass == C_HIDEXT ? mst_file_data : mst_data,
 			 symbol.n_scnum, objfile);
 		    break;
@@ -2434,7 +2435,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		       table, except for section symbols.  */
 		    if (*namestring != '.')
 		      record_minimal_symbol
-			(namestring, symbol.n_value,
+			(reader, namestring, symbol.n_value,
 			 sclass == C_HIDEXT ? mst_file_bss : mst_bss,
 			 symbol.n_scnum, objfile);
 		    break;
@@ -2462,7 +2463,7 @@ scan_xcoff_symtab (struct objfile *objfile)
 		   it as a function.  This will take care of functions like
 		   strcmp() compiled by xlc.  */
 
-		record_minimal_symbol (last_csect_name, last_csect_val,
+		record_minimal_symbol (reader, last_csect_name, last_csect_val,
 				       mst_text, last_csect_sec, objfile);
 		misc_func_recorded = 1;
 	      }
@@ -3011,7 +3012,7 @@ xcoff_initial_scan (struct objfile *objfile, int symfile_flags)
   /* Now that the symbol table data of the executable file are all in core,
      process them and define symbols accordingly.  */
 
-  scan_xcoff_symtab (objfile);
+  scan_xcoff_symtab (reader, objfile);
 
   /* Install any minimal symbols that have been collected as the current
      minimal symbols for this objfile.  */
-- 
2.7.4

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

* [RFA 01/22] Change selttest.c to use use std::vector
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (11 preceding siblings ...)
  2016-09-27  4:48 ` [RFA 08/22] Record minimal symbols directly in reader Tom Tromey
@ 2016-09-27  4:48 ` Tom Tromey
  2016-09-27  8:50   ` Trevor Saunders
  2016-09-30 14:43   ` Simon Marchi
  2016-09-27  4:48 ` [RFA 03/22] Use scoped_restore for ui_file Tom Tromey
                   ` (9 subsequent siblings)
  22 siblings, 2 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch changes selftest.c to use std::vector rather than VEC.

I think this is a small net plus.  Because we're using C++03, we
unfortunately don't all the possible benefits here; namely, iterating
over a vector is still a pain.  For reference, in C++11 the loop would
be just:

    for (auto f : tests)
      ...

2016-09-26  Tom Tromey  <tom@tromey.com>

	* selftest.c: Include <vector>, not "vec.h".
	(self_test_function_ptr): Remove.
	(tests): Now a std::vector.
	(register_self_test, run_self_tests): Update.
---
 gdb/ChangeLog  |  7 +++++++
 gdb/selftest.c | 22 +++++++++-------------
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a9ef3ee..2f28e54 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
+	* selftest.c: Include <vector>, not "vec.h".
+	(self_test_function_ptr): Remove.
+	(tests): Now a std::vector.
+	(register_self_test, run_self_tests): Update.
+
 2016-09-23  Jon Turney  <jon.turney@dronecode.org.uk>
 
 	* windows-nat.c (windows_delete_thread): Adjusting call to
diff --git a/gdb/selftest.c b/gdb/selftest.c
index c63c06d..bbd37b5 100644
--- a/gdb/selftest.c
+++ b/gdb/selftest.c
@@ -18,22 +18,18 @@
 
 #include "defs.h"
 #include "selftest.h"
-#include "vec.h"
-
-typedef self_test_function *self_test_function_ptr;
-
-DEF_VEC_P (self_test_function_ptr);
+#include <vector>
 
 /* All the tests that have been registered.  */
 
-static VEC (self_test_function_ptr) *tests;
+static std::vector<self_test_function *> tests;
 
 /* See selftest.h.  */
 
 void
 register_self_test (self_test_function *function)
 {
-  VEC_safe_push (self_test_function_ptr, tests, function);
+  tests.push_back (function);
 }
 
 /* See selftest.h.  */
@@ -41,17 +37,17 @@ register_self_test (self_test_function *function)
 void
 run_self_tests (void)
 {
-  int i;
-  self_test_function_ptr func;
   int failed = 0;
 
-  for (i = 0; VEC_iterate (self_test_function_ptr, tests, i, func); ++i)
+  for (std::vector<self_test_function *>::iterator iter = tests.begin ();
+       iter != tests.end ();
+       ++iter)
     {
       QUIT;
 
       TRY
 	{
-	  (*func) ();
+	  (*iter) ();
 	}
       CATCH (ex, RETURN_MASK_ERROR)
 	{
@@ -62,6 +58,6 @@ run_self_tests (void)
       END_CATCH
     }
 
-  printf_filtered (_("Ran %u unit tests, %d failed\n"),
-		   VEC_length (self_test_function_ptr, tests), failed);
+  printf_filtered (_("Ran %lu unit tests, %d failed\n"),
+		   tests.size (), failed);
 }
-- 
2.7.4

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

* [RFA 03/22] Use scoped_restore for ui_file
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (12 preceding siblings ...)
  2016-09-27  4:48 ` [RFA 01/22] Change selttest.c to use use std::vector Tom Tromey
@ 2016-09-27  4:48 ` Tom Tromey
  2016-10-01  4:28   ` Simon Marchi
  2016-09-27  4:50 ` [RFA 17/22] Remove make_cleanup_restore_current_uiout Tom Tromey
                   ` (8 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This replaces all the uses of make_cleanup_restore_ui_file with
scoped_restore.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* utils.c (make_cleanup_restore_ui_file, do_restore_ui_file)
	(struct restore_ui_file_closure): Remove.
	* utils.h (make_cleanup_restore_ui_file): Don't declare.
	* guile/scm-ports.c (ioscm_with_output_to_port_worker): Use
	scoped_restore.
	* top.c (execute_command_to_string): Use scoped_restore.
---
 gdb/ChangeLog         |  9 +++++++++
 gdb/guile/scm-ports.c | 10 ++++------
 gdb/top.c             | 15 +++++----------
 gdb/utils.c           | 29 -----------------------------
 gdb/utils.h           |  3 ---
 5 files changed, 18 insertions(+), 48 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 104048f..da69ce8 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* utils.c (make_cleanup_restore_ui_file, do_restore_ui_file)
+	(struct restore_ui_file_closure): Remove.
+	* utils.h (make_cleanup_restore_ui_file): Don't declare.
+	* guile/scm-ports.c (ioscm_with_output_to_port_worker): Use
+	scoped_restore.
+	* top.c (execute_command_to_string): Use scoped_restore.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* utils.h (class scoped_restore): New class.
 	* top.c (execute_command_to_string): Use scoped_restore.
 	* python/python.c (python_interactive_command): Use
diff --git a/gdb/guile/scm-ports.c b/gdb/guile/scm-ports.c
index 5559475..96e4372 100644
--- a/gdb/guile/scm-ports.c
+++ b/gdb/guile/scm-ports.c
@@ -524,15 +524,13 @@ ioscm_with_output_to_port_worker (SCM port, SCM thunk, enum oport oport,
 
   make_cleanup_ui_file_delete (port_file);
 
+  scoped_restore<ui_file *> save_file (oport == GDB_STDERR
+				       ? &gdb_stderr : &gdb_stdout);
+
   if (oport == GDB_STDERR)
-    {
-      make_cleanup_restore_ui_file (&gdb_stderr);
-      gdb_stderr = port_file;
-    }
+    gdb_stderr = port_file;
   else
     {
-      make_cleanup_restore_ui_file (&gdb_stdout);
-
       if (ui_out_redirect (current_uiout, port_file) < 0)
 	warning (_("Current output protocol does not support redirection"));
       else
diff --git a/gdb/top.c b/gdb/top.c
index 84285b2..d782466 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -706,22 +706,17 @@ execute_command_to_string (char *p, int from_tty)
   str_file = mem_fileopen ();
 
   make_cleanup_ui_file_delete (str_file);
-  make_cleanup_restore_ui_file (&gdb_stdout);
-  make_cleanup_restore_ui_file (&gdb_stderr);
-  make_cleanup_restore_ui_file (&gdb_stdlog);
-  make_cleanup_restore_ui_file (&gdb_stdtarg);
-  make_cleanup_restore_ui_file (&gdb_stdtargerr);
 
   if (ui_out_redirect (current_uiout, str_file) < 0)
     warning (_("Current output protocol does not support redirection"));
   else
     make_cleanup_ui_out_redirect_pop (current_uiout);
 
-  gdb_stdout = str_file;
-  gdb_stderr = str_file;
-  gdb_stdlog = str_file;
-  gdb_stdtarg = str_file;
-  gdb_stdtargerr = str_file;
+  scoped_restore<struct ui_file *> save_stdout (&gdb_stdout, str_file);
+  scoped_restore<struct ui_file *> save_stderr (&gdb_stderr, str_file);
+  scoped_restore<struct ui_file *> save_stdlog (&gdb_stdlog, str_file);
+  scoped_restore<struct ui_file *> save_stdtarg (&gdb_stdtarg, str_file);
+  scoped_restore<struct ui_file *> save_stdtargerr (&gdb_stdtargerr, str_file);
 
   execute_command (p, from_tty);
 
diff --git a/gdb/utils.c b/gdb/utils.c
index 9a83053..5fb4b28 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -319,35 +319,6 @@ make_cleanup_htab_delete (htab_t htab)
   return make_cleanup (do_htab_delete_cleanup, htab);
 }
 
-struct restore_ui_file_closure
-{
-  struct ui_file **variable;
-  struct ui_file *value;
-};
-
-static void
-do_restore_ui_file (void *p)
-{
-  struct restore_ui_file_closure *closure
-    = (struct restore_ui_file_closure *) p;
-
-  *(closure->variable) = closure->value;
-}
-
-/* Remember the current value of *VARIABLE and make it restored when
-   the cleanup is run.  */
-
-struct cleanup *
-make_cleanup_restore_ui_file (struct ui_file **variable)
-{
-  struct restore_ui_file_closure *c = XNEW (struct restore_ui_file_closure);
-
-  c->variable = variable;
-  c->value = *variable;
-
-  return make_cleanup_dtor (do_restore_ui_file, (void *) c, xfree);
-}
-
 /* Helper for make_cleanup_value_free_to_mark.  */
 
 static void
diff --git a/gdb/utils.h b/gdb/utils.h
index 63583ed..6179582 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -134,9 +134,6 @@ extern struct cleanup *make_cleanup_restore_uinteger (unsigned int *variable);
 struct target_ops;
 extern struct cleanup *make_cleanup_unpush_target (struct target_ops *ops);
 
-extern struct cleanup *
-  make_cleanup_restore_ui_file (struct ui_file **variable);
-
 extern struct cleanup *make_cleanup_value_free_to_mark (struct value *);
 extern struct cleanup *make_cleanup_value_free (struct value *);
 
-- 
2.7.4

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

* [RFA 00/22] More C++-ification
@ 2016-09-27  4:49 Tom Tromey
  2016-09-27  4:41 ` [RFA 15/22] Use std::string in macho_symfile_read_all_oso Tom Tromey
                   ` (22 more replies)
  0 siblings, 23 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:49 UTC (permalink / raw)
  To: gdb-patches

This patch series converts more random parts of gdb to C++.

Some of these patches get rid of cleanups, or convert them to RAII.
In a couple of cases, after removing cleanups I went further and
converted a given class more fully to C++.  There's also one random
patch to convert an iterator to a C++ class using RAII.

I didn't touch any spot where the cleanup removal would have benefited
from unique_ptr; Pedro has a branch with the needed bits there, and I
wanted to avoid conflicts with his work.

This was built and regtested on x86-64 Fedora 24.

I've appended the differences between the baseline run and the run
with this series in place.  I don't know whether these represent real
regressions or are just intermittent test failures; particularly
because the missing tests are either FAIL or KFAIL.

Tom

Missing tests:
gdb.threads/process-dies-while-handling-bp.exp: non_stop=off: cond_bp_target=0: inferior 1 exited (memory error): KFAIL
gdb.threads/process-dies-while-handling-bp.exp: non_stop=off: cond_bp_target=1: inferior 1 exited (prompt): KFAIL
gdb.threads/process-dies-while-handling-bp.exp: non_stop=on: cond_bp_target=0: inferior 1 exited (prompt): KFAIL
gdb.threads/watchpoint-fork.exp: child: multithreaded: breakpoint (A) after the second fork: FAIL

New tests:
gdb.threads/process-dies-while-handling-bp.exp: non_stop=off: cond_bp_target=1: inferior 1 exited (memory error): KFAIL
gdb.threads/process-dies-while-handling-bp.exp: non_stop=on: cond_bp_target=0: inferior 1 exited (memory error): KFAIL


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

* [RFA 17/22] Remove make_cleanup_restore_current_uiout
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (13 preceding siblings ...)
  2016-09-27  4:48 ` [RFA 03/22] Use scoped_restore for ui_file Tom Tromey
@ 2016-09-27  4:50 ` Tom Tromey
  2016-09-29 14:35   ` Trevor Saunders
  2016-09-27  4:51 ` [RFA 13/22] Remove unnecessary cleanup from stabsread.c Tom Tromey
                   ` (7 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This removes make_cleanup_restore_current_uiout in favor of an
RAII-based class.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* ui-out.c (make_cleanup_restore_current_uiout)
	(restore_current_uiout_cleanup): Remove.
	* infrun.c (print_stop_event): Use scoped_restore_uiout.
	* ui-out.h (scoped_restore_uiout): New class.
	(make_cleanup_restore_current_uiout): Don't declare.
---
 gdb/ChangeLog       |  8 ++++++++
 gdb/infrun.c        | 15 +++++++--------
 gdb/python/python.c |  3 +--
 gdb/ui-out.c        | 18 ------------------
 gdb/ui-out.h        | 25 +++++++++++++++++++++++--
 5 files changed, 39 insertions(+), 30 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 770a96f..89ce46f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* ui-out.c (make_cleanup_restore_current_uiout)
+	(restore_current_uiout_cleanup): Remove.
+	* infrun.c (print_stop_event): Use scoped_restore_uiout.
+	* ui-out.h (scoped_restore_uiout): New class.
+	(make_cleanup_restore_current_uiout): Don't declare.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* elfread.c (elf_read_minimal_symbols): Use std::vector.
 
 2016-09-26  Tom Tromey  <tom@tromey.com>
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 1736526..7136d00 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8084,22 +8084,21 @@ print_stop_location (struct target_waitstatus *ws)
 void
 print_stop_event (struct ui_out *uiout)
 {
-  struct cleanup *old_chain;
   struct target_waitstatus last;
   ptid_t last_ptid;
   struct thread_info *tp;
 
   get_last_target_status (&last_ptid, &last);
 
-  old_chain = make_cleanup_restore_current_uiout ();
-  current_uiout = uiout;
-
-  print_stop_location (&last);
+  {
+    scoped_restore_uiout save_uiout;
+    current_uiout = uiout;
 
-  /* Display the auto-display expressions.  */
-  do_displays ();
+    print_stop_location (&last);
 
-  do_cleanups (old_chain);
+    /* Display the auto-display expressions.  */
+    do_displays ();
+  }
 
   tp = inferior_thread ();
   if (tp->thread_fsm != NULL
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 9e4d610..b98ef90 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -647,8 +647,7 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
       struct interp *interp;
 
       scoped_restore<int> save_async (&current_ui->async, 0);
-
-      make_cleanup_restore_current_uiout ();
+      scoped_restore_uiout save_uiout;
 
       /* Use the console interpreter uiout to have the same print format
 	for console or MI.  */
diff --git a/gdb/ui-out.c b/gdb/ui-out.c
index ec44ab6..3972a56 100644
--- a/gdb/ui-out.c
+++ b/gdb/ui-out.c
@@ -953,24 +953,6 @@ ui_out_destroy (struct ui_out *uiout)
   xfree (uiout);
 }
 
-/* Cleanup that restores a previous current uiout.  */
-
-static void
-restore_current_uiout_cleanup (void *arg)
-{
-  struct ui_out *saved_uiout = (struct ui_out *) arg;
-
-  current_uiout = saved_uiout;
-}
-
-/* See ui-out.h.  */
-
-struct cleanup *
-make_cleanup_restore_current_uiout (void)
-{
-  return make_cleanup (restore_current_uiout_cleanup, current_uiout);
-}
-
 /* Standard gdb initialization hook.  */
 
 void
diff --git a/gdb/ui-out.h b/gdb/ui-out.h
index 6a4d78a..12daafd 100644
--- a/gdb/ui-out.h
+++ b/gdb/ui-out.h
@@ -247,8 +247,29 @@ extern void ui_out_destroy (struct ui_out *uiout);
 
 extern int ui_out_redirect (struct ui_out *uiout, struct ui_file *outstream);
 
-/* Make a cleanup that restores the previous current uiout.  */
+/* An RAII-based class that saves and restores the current uiout.  */
 
-extern struct cleanup *make_cleanup_restore_current_uiout (void);
+class scoped_restore_uiout
+{
+ public:
+
+  scoped_restore_uiout () : saved (current_uiout)
+  {
+  }
+
+  ~scoped_restore_uiout ()
+  {
+    current_uiout = saved;
+  }
+
+ private:
+
+  // No need for these.  They are intentionally not defined anywhere.
+  scoped_restore_uiout &operator= (const scoped_restore_uiout &);
+  scoped_restore_uiout (const scoped_restore_uiout &);
+
+  // The saved ui out.
+  struct ui_out *saved;
+};
 
 #endif /* UI_OUT_H */
-- 
2.7.4

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

* [RFA 13/22] Remove unnecessary cleanup from stabsread.c
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (14 preceding siblings ...)
  2016-09-27  4:50 ` [RFA 17/22] Remove make_cleanup_restore_current_uiout Tom Tromey
@ 2016-09-27  4:51 ` Tom Tromey
  2016-09-30 16:19   ` Tom Tromey
  2016-10-09 17:07   ` Pedro Alves
  2016-09-27  4:51 ` [RFA 12/22] Remove unnecessary null_cleanup Tom Tromey
                   ` (6 subsequent siblings)
  22 siblings, 2 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:51 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This removes an unnecessary cleanup from stabsread.c.  It's
unnecessary because nothing between the cleanup creation and use makes
a cleanup.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* stabsread.c (read_struct_type): Remove unnecessary cleanup.
---
 gdb/ChangeLog   | 4 ++++
 gdb/stabsread.c | 9 +--------
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d3b8a45..476dbb3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,9 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* stabsread.c (read_struct_type): Remove unnecessary cleanup.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* tracepoint.c (trace_dump_command): Remove unnecessary
 	null_cleanup.
 
diff --git a/gdb/stabsread.c b/gdb/stabsread.c
index e8ebadd..cc2fef3 100644
--- a/gdb/stabsread.c
+++ b/gdb/stabsread.c
@@ -3507,7 +3507,6 @@ static struct type *
 read_struct_type (char **pp, struct type *type, enum type_code type_code,
                   struct objfile *objfile)
 {
-  struct cleanup *back_to;
   struct field_info fi;
 
   fi.list = NULL;
@@ -3533,8 +3532,6 @@ read_struct_type (char **pp, struct type *type, enum type_code type_code,
       return type;
     }
 
-  back_to = make_cleanup (null_cleanup, 0);
-
   INIT_CPLUS_SPECIFIC (type);
   TYPE_CODE (type) = type_code;
   TYPE_STUB (type) = 0;
@@ -3546,10 +3543,7 @@ read_struct_type (char **pp, struct type *type, enum type_code type_code,
 
     TYPE_LENGTH (type) = read_huge_number (pp, 0, &nbits, 0);
     if (nbits != 0)
-      {
-	do_cleanups (back_to);
-	return error_type (pp, objfile);
-      }
+      return error_type (pp, objfile);
     set_length_in_type_chain (type);
   }
 
@@ -3568,7 +3562,6 @@ read_struct_type (char **pp, struct type *type, enum type_code type_code,
       type = error_type (pp, objfile);
     }
 
-  do_cleanups (back_to);
   return (type);
 }
 
-- 
2.7.4

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

* [RFA 14/22] Replace two xmallocs with vector
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (17 preceding siblings ...)
  2016-09-27  4:51 ` [RFA 18/22] Some cleanup removal in dwarf2loc.c Tom Tromey
@ 2016-09-27  4:51 ` Tom Tromey
  2016-10-09 17:20   ` Pedro Alves
  2016-09-27  4:52 ` [RFA 06/22] Introduce scoped_minimal_symbol_reader Tom Tromey
                   ` (3 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:51 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This replaces a couple of uses of xmalloc with a std::vector, also
removing a couple of cleanups.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* cli/cli-dump.c (dump_memory_to_file): Use std::vector.
	(restore_binary_file): Likewise.
---
 gdb/ChangeLog      |  5 +++++
 gdb/cli/cli-dump.c | 21 +++++++++------------
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 476dbb3..42101fc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* cli/cli-dump.c (dump_memory_to_file): Use std::vector.
+	(restore_binary_file): Likewise.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* stabsread.c (read_struct_type): Remove unnecessary cleanup.
 
 2016-09-26  Tom Tromey  <tom@tromey.com>
diff --git a/gdb/cli/cli-dump.c b/gdb/cli/cli-dump.c
index 611b0c3..2b4d1be 100644
--- a/gdb/cli/cli-dump.c
+++ b/gdb/cli/cli-dump.c
@@ -31,7 +31,7 @@
 #include "cli/cli-utils.h"
 #include "gdb_bfd.h"
 #include "filestuff.h"
-
+#include <vector>
 
 static const char *
 scan_expression_with_cleanup (const char **cmd, const char *def)
@@ -212,7 +212,6 @@ dump_memory_to_file (const char *cmd, const char *mode, const char *file_format)
   CORE_ADDR hi;
   ULONGEST count;
   const char *filename;
-  gdb_byte *buf;
   const char *lo_exp;
   const char *hi_exp;
 
@@ -237,18 +236,17 @@ dump_memory_to_file (const char *cmd, const char *mode, const char *file_format)
 
   /* FIXME: Should use read_memory_partial() and a magic blocking
      value.  */
-  buf = (gdb_byte *) xmalloc (count);
-  make_cleanup (xfree, buf);
-  read_memory (lo, buf, count);
+  std::vector<gdb_byte> buf (count);
+  read_memory (lo, buf.data (), count);
   
   /* Have everything.  Open/write the data.  */
   if (file_format == NULL || strcmp (file_format, "binary") == 0)
     {
-      dump_binary_file (filename, mode, buf, count);
+      dump_binary_file (filename, mode, buf.data (), count);
     }
   else
     {
-      dump_bfd_file (filename, mode, file_format, lo, buf, count);
+      dump_bfd_file (filename, mode, file_format, lo, buf.data (), count);
     }
 
   do_cleanups (old_cleanups);
@@ -518,7 +516,6 @@ restore_binary_file (const char *filename, struct callback_data *data)
 {
   struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
   FILE *file = fopen_with_cleanup (filename, FOPEN_RB);
-  gdb_byte *buf;
   long len;
 
   /* Get the file size for reading.  */
@@ -553,13 +550,13 @@ restore_binary_file (const char *filename, struct callback_data *data)
     perror_with_name (filename);
 
   /* Now allocate a buffer and read the file contents.  */
-  buf = (gdb_byte *) xmalloc (len);
-  make_cleanup (xfree, buf);
-  if (fread (buf, 1, len, file) != len)
+  std::vector<gdb_byte> buf (len);
+  if (fread (buf.data (), 1, len, file) != len)
     perror_with_name (filename);
 
   /* Now write the buffer into target memory.  */
-  len = target_write_memory (data->load_start + data->load_offset, buf, len);
+  len = target_write_memory (data->load_start + data->load_offset,
+			     buf.data (), len);
   if (len != 0)
     warning (_("restore: memory write failed (%s)."), safe_strerror (len));
   do_cleanups (cleanup);
-- 
2.7.4

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

* [RFA 18/22] Some cleanup removal in dwarf2loc.c
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (16 preceding siblings ...)
  2016-09-27  4:51 ` [RFA 12/22] Remove unnecessary null_cleanup Tom Tromey
@ 2016-09-27  4:51 ` Tom Tromey
  2016-10-09 17:37   ` Pedro Alves
  2016-09-27  4:51 ` [RFA 14/22] Replace two xmallocs with vector Tom Tromey
                   ` (4 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:51 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This removes some cleanups and manual allocation handling in
dwarf2loc.c with std::vector.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* dwarf2loc.c: Include <vector>.
	(read_pieced_value, write_pieced_value)
	(dwarf2_compile_expr_to_ax): Use std::vector.
---
 gdb/ChangeLog   |  6 ++++++
 gdb/dwarf2loc.c | 66 ++++++++++++++++++++++-----------------------------------
 2 files changed, 31 insertions(+), 41 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 89ce46f..1e2fc29 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* dwarf2loc.c: Include <vector>.
+	(read_pieced_value, write_pieced_value)
+	(dwarf2_compile_expr_to_ax): Use std::vector.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* ui-out.c (make_cleanup_restore_current_uiout)
 	(restore_current_uiout_cleanup): Remove.
 	* infrun.c (print_stop_event): Use scoped_restore_uiout.
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index f9f3216..7b3a2b2 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -39,6 +39,7 @@
 #include "dwarf2-frame.h"
 #include "compile/compile.h"
 #include <algorithm>
+#include <vector>
 
 extern int dwarf_always_disassemble;
 
@@ -1697,8 +1698,7 @@ read_pieced_value (struct value *v)
   struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (v));
   size_t type_len;
   size_t buffer_size = 0;
-  gdb_byte *buffer = NULL;
-  struct cleanup *cleanup;
+  std::vector<gdb_byte> buffer;
   int bits_big_endian
     = gdbarch_bits_big_endian (get_type_arch (value_type (v)));
 
@@ -1707,8 +1707,6 @@ read_pieced_value (struct value *v)
 		    _("Should not be able to create a lazy value with "
 		      "an enclosing type"));
 
-  cleanup = make_cleanup (free_current_contents, &buffer);
-
   contents = value_contents_raw (v);
   bits_to_skip = 8 * value_offset (v);
   if (value_bitsize (v))
@@ -1754,9 +1752,9 @@ read_pieced_value (struct value *v)
       if (buffer_size < this_size)
 	{
 	  buffer_size = this_size;
-	  buffer = (gdb_byte *) xrealloc (buffer, buffer_size);
+	  buffer.reserve (buffer_size);
 	}
-      intermediate_buffer = buffer;
+      intermediate_buffer = buffer.data ();
 
       /* Copy from the source to DEST_BUFFER.  */
       switch (p->location)
@@ -1779,11 +1777,11 @@ read_pieced_value (struct value *v)
 	      }
 
 	    if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset,
-					   this_size, buffer,
+					   this_size, buffer.data (),
 					   &optim, &unavail))
 	      {
 		/* Just so garbage doesn't ever shine through.  */
-		memset (buffer, 0, this_size);
+		memset (buffer.data (), 0, this_size);
 
 		if (optim)
 		  mark_value_bits_optimized_out (v, offset, this_size_bits);
@@ -1797,7 +1795,7 @@ read_pieced_value (struct value *v)
 	  read_value_memory (v, offset,
 			     p->v.mem.in_stack_memory,
 			     p->v.mem.addr + source_offset,
-			     buffer, this_size);
+			     buffer.data (), this_size);
 	  break;
 
 	case DWARF_VALUE_STACK:
@@ -1855,8 +1853,6 @@ read_pieced_value (struct value *v)
 
       offset += this_size_bits;
     }
-
-  do_cleanups (cleanup);
 }
 
 static void
@@ -1871,8 +1867,7 @@ write_pieced_value (struct value *to, struct value *from)
   struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (to));
   size_t type_len;
   size_t buffer_size = 0;
-  gdb_byte *buffer = NULL;
-  struct cleanup *cleanup;
+  std::vector<gdb_byte> buffer;
   int bits_big_endian
     = gdbarch_bits_big_endian (get_type_arch (value_type (to)));
 
@@ -1882,8 +1877,6 @@ write_pieced_value (struct value *to, struct value *from)
       return;
     }
 
-  cleanup = make_cleanup (free_current_contents, &buffer);
-
   contents = value_contents (from);
   bits_to_skip = 8 * value_offset (to);
   if (value_bitsize (to))
@@ -1936,9 +1929,9 @@ write_pieced_value (struct value *to, struct value *from)
 	  if (buffer_size < this_size)
 	    {
 	      buffer_size = this_size;
-	      buffer = (gdb_byte *) xrealloc (buffer, buffer_size);
+	      buffer.reserve (buffer_size);
 	    }
-	  source_buffer = buffer;
+	  source_buffer = buffer.data ();
 	  need_bitwise = 1;
 	}
 
@@ -1962,7 +1955,7 @@ write_pieced_value (struct value *to, struct value *from)
 		int optim, unavail;
 
 		if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset,
-					       this_size, buffer,
+					       this_size, buffer.data (),
 					       &optim, &unavail))
 		  {
 		    if (optim)
@@ -1976,7 +1969,7 @@ write_pieced_value (struct value *to, struct value *from)
 				     "bitfield; containing word "
 				     "is unavailable"));
 		  }
-		copy_bitwise (buffer, dest_offset_bits,
+		copy_bitwise (buffer.data (), dest_offset_bits,
 			      contents, source_offset_bits,
 			      this_size_bits,
 			      bits_big_endian);
@@ -1991,10 +1984,10 @@ write_pieced_value (struct value *to, struct value *from)
 	    {
 	      /* Only the first and last bytes can possibly have any
 		 bits reused.  */
-	      read_memory (p->v.mem.addr + dest_offset, buffer, 1);
+	      read_memory (p->v.mem.addr + dest_offset, buffer.data (), 1);
 	      read_memory (p->v.mem.addr + dest_offset + this_size - 1,
-			   buffer + this_size - 1, 1);
-	      copy_bitwise (buffer, dest_offset_bits,
+			   &buffer[this_size - 1], 1);
+	      copy_bitwise (buffer.data (), dest_offset_bits,
 			    contents, source_offset_bits,
 			    this_size_bits,
 			    bits_big_endian);
@@ -2009,8 +2002,6 @@ write_pieced_value (struct value *to, struct value *from)
 	}
       offset += this_size_bits;
     }
-
-  do_cleanups (cleanup);
 }
 
 /* An implementation of an lval_funcs method to see whether a value is
@@ -3054,9 +3045,8 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
 			   const gdb_byte *op_ptr, const gdb_byte *op_end,
 			   struct dwarf2_per_cu_data *per_cu)
 {
-  struct cleanup *cleanups;
-  int i, *offsets;
-  VEC(int) *dw_labels = NULL, *patches = NULL;
+  int i;
+  std::vector<int> dw_labels, patches;
   const gdb_byte * const base = op_ptr;
   const gdb_byte *previous_piece = op_ptr;
   enum bfd_endian byte_order = gdbarch_byte_order (arch);
@@ -3064,15 +3054,11 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
   unsigned int addr_size_bits = 8 * addr_size;
   int bits_big_endian = gdbarch_bits_big_endian (arch);
 
-  offsets = XNEWVEC (int, op_end - op_ptr);
-  cleanups = make_cleanup (xfree, offsets);
+  std::vector<int> offsets (op_end - op_ptr);
 
   for (i = 0; i < op_end - op_ptr; ++i)
     offsets[i] = -1;
 
-  make_cleanup (VEC_cleanup (int), &dw_labels);
-  make_cleanup (VEC_cleanup (int), &patches);
-
   /* By default we are making an address.  */
   loc->kind = axs_lvalue_memory;
 
@@ -3584,8 +3570,8 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
 	  offset = extract_signed_integer (op_ptr, 2, byte_order);
 	  op_ptr += 2;
 	  i = ax_goto (expr, aop_goto);
-	  VEC_safe_push (int, dw_labels, op_ptr + offset - base);
-	  VEC_safe_push (int, patches, i);
+	  dw_labels.push_back (op_ptr + offset - base);
+	  patches.push_back (i);
 	  break;
 
 	case DW_OP_bra:
@@ -3594,8 +3580,8 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
 	  /* Zero extend the operand.  */
 	  ax_zero_ext (expr, addr_size_bits);
 	  i = ax_goto (expr, aop_if_goto);
-	  VEC_safe_push (int, dw_labels, op_ptr + offset - base);
-	  VEC_safe_push (int, patches, i);
+	  dw_labels.push_back (op_ptr + offset - base);
+	  patches.push_back (i);
 	  break;
 
 	case DW_OP_nop:
@@ -3704,15 +3690,13 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
     }
 
   /* Patch all the branches we emitted.  */
-  for (i = 0; i < VEC_length (int, patches); ++i)
+  for (i = 0; i < patches.size (); ++i)
     {
-      int targ = offsets[VEC_index (int, dw_labels, i)];
+      int targ = offsets[dw_labels[i]];
       if (targ == -1)
 	internal_error (__FILE__, __LINE__, _("invalid label"));
-      ax_label (expr, VEC_index (int, patches, i), targ);
+      ax_label (expr, patches[i], targ);
     }
-
-  do_cleanups (cleanups);
 }
 
 \f
-- 
2.7.4

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

* [RFA 12/22] Remove unnecessary null_cleanup
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (15 preceding siblings ...)
  2016-09-27  4:51 ` [RFA 13/22] Remove unnecessary cleanup from stabsread.c Tom Tromey
@ 2016-09-27  4:51 ` Tom Tromey
  2016-10-09 17:06   ` Pedro Alves
  2016-09-27  4:51 ` [RFA 18/22] Some cleanup removal in dwarf2loc.c Tom Tromey
                   ` (5 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:51 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch removes an unnecessary null_cleanup.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* tracepoint.c (trace_dump_command): Remove unnecessary
	null_cleanup.
---
 gdb/ChangeLog    | 5 +++++
 gdb/tracepoint.c | 4 +---
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 66e9236..d3b8a45 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* tracepoint.c (trace_dump_command): Remove unnecessary
+	null_cleanup.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* maint.h (scoped_command_stats): New class.
 	(make_command_stats_cleanup): Don't declare.
 	* maint.c (struct cmd_stats): Remove.
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index c89c77e..e5c353c 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -3061,11 +3061,9 @@ trace_dump_command (char *args, int from_tty)
   printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
 		   tracepoint_number, traceframe_number);
 
-  old_chain = make_cleanup (null_cleanup, NULL);
-
   /* This command only makes sense for the current frame, not the
      selected frame.  */
-  make_cleanup_restore_current_thread ();
+  old_chain = make_cleanup_restore_current_thread ();
   select_frame (get_current_frame ());
 
   actions = all_tracepoint_actions_and_cleanup (loc->owner);
-- 
2.7.4

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

* [RFA 10/22] Remove some cleanups in MI
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (19 preceding siblings ...)
  2016-09-27  4:52 ` [RFA 06/22] Introduce scoped_minimal_symbol_reader Tom Tromey
@ 2016-09-27  4:52 ` Tom Tromey
  2016-10-06  1:42   ` Pedro Alves
  2016-09-27  8:32 ` [RFA 11/22] Change command stats reporting to use class Tom Tromey
  2016-10-08 13:57 ` [RFA 00/22] More C++-ification Simon Marchi
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:52 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch removes a couple of cleanups from MI.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* mi/mi-main.c (mi_cmd_data_read_memory): Use std::vector.  Remove
	some cleanups.
---
 gdb/ChangeLog    |  5 +++++
 gdb/mi/mi-main.c | 11 ++++-------
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 954d658..704de48 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* mi/mi-main.c (mi_cmd_data_read_memory): Use std::vector.  Remove
+	some cleanups.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* tui/tui-interp.c (tui_on_normal_stop, tui_on_signal_received)
 	(tui_on_end_stepping_range, tui_on_signal_exited, tui_on_exited)
 	(tui_on_no_history): Update.
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index c6c7067..50d82f1 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -56,6 +56,7 @@
 
 #include <ctype.h>
 #include "gdb_sys_time.h"
+#include <vector>
 
 #if defined HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
@@ -1403,7 +1404,6 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
 {
   struct gdbarch *gdbarch = get_current_arch ();
   struct ui_out *uiout = current_uiout;
-  struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
   CORE_ADDR addr;
   long total_bytes, nr_cols, nr_rows;
   char word_format;
@@ -1411,7 +1411,6 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
   long word_size;
   char word_asize;
   char aschar;
-  gdb_byte *mbuf;
   int nr_bytes;
   long offset = 0;
   int oind = 0;
@@ -1496,13 +1495,12 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
 
   /* Create a buffer and read it in.  */
   total_bytes = word_size * nr_rows * nr_cols;
-  mbuf = XCNEWVEC (gdb_byte, total_bytes);
-  make_cleanup (xfree, mbuf);
+  std::vector<gdb_byte> mbuf (total_bytes);
 
   /* Dispatch memory reads to the topmost target, not the flattened
      current_target.  */
   nr_bytes = target_read (current_target.beneath,
-			  TARGET_OBJECT_MEMORY, NULL, mbuf,
+			  TARGET_OBJECT_MEMORY, NULL, mbuf.data (),
 			  addr, total_bytes);
   if (nr_bytes <= 0)
     error (_("Unable to read memory."));
@@ -1556,7 +1554,7 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
 	    else
 	      {
 		ui_file_rewind (stream);
-		print_scalar_formatted (mbuf + col_byte, word_type, &opts,
+		print_scalar_formatted (&mbuf[col_byte], word_type, &opts,
 					word_asize, stream);
 		ui_out_field_stream (uiout, NULL, stream);
 	      }
@@ -1583,7 +1581,6 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc)
       }
     do_cleanups (cleanup_stream);
   }
-  do_cleanups (cleanups);
 }
 
 void
-- 
2.7.4

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

* [RFA 06/22] Introduce scoped_minimal_symbol_reader
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (18 preceding siblings ...)
  2016-09-27  4:51 ` [RFA 14/22] Replace two xmallocs with vector Tom Tromey
@ 2016-09-27  4:52 ` Tom Tromey
  2016-10-06  1:10   ` Pedro Alves
  2016-09-27  4:52 ` [RFA 10/22] Remove some cleanups in MI Tom Tromey
                   ` (2 subsequent siblings)
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  4:52 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch introduced scoped_minimal_symbol_reader, a RAII-based class
which replaces the current make_cleanup_discard_minimal_symbols.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* xcoffread.c (xcoff_initial_scan): Use
	scoped_minimal_symbol_reader.
	* mipsread.c (mipscoff_symfile_read): Use
	scoped_minimal_symbol_reader.
	* minsyms.h (scoped_minimal_symbol_reader): New class.
	(init_minimal_symbol_collection)
	(make_cleanup_discard_minimal_symbols, install_minimal_symbols):
	Don't declare.
	* minsyms.c (scoped_minimal_symbol_reader): Renamed from
	init_minimal_symbol_collection, turned into constructor.
	(~scoped_minimal_symbol_reader): Renamed from
	do_discard_minimal_symbols_cleanup, turned into destructor.
	(make_cleanup_discard_minimal_symbols): Remove.
	(scoped_minimal_symbol_reader::install): Rename form
	install_minimal_symbols.
	* mdebugread.c (elfmdebug_build_psymtabs): Use
	scoped_minimal_symbol_reader.
	* machoread.c (macho_symfile_read): Use
	scoped_minimal_symbol_reader.
	* elfread.c (elf_read_minimal_symbols): Use
	scoped_minimal_symbol_reader.
	* dbxread.c (dbx_symfile_read): Use scoped_minimal_symbol_reader.
	* coffread.c (coff_symfile_read): Use
	scoped_minimal_symbol_reader.
---
 gdb/ChangeLog    | 27 +++++++++++++++++++++++++++
 gdb/coffread.c   | 10 +++-------
 gdb/dbxread.c    |  5 ++---
 gdb/elfread.c    |  6 +++---
 gdb/machoread.c  |  5 ++---
 gdb/mdebugread.c |  7 ++-----
 gdb/minsyms.c    | 56 ++++++++++++++++++++++----------------------------------
 gdb/minsyms.h    | 43 ++++++++++++++++++++++++-------------------
 gdb/mipsread.c   |  7 ++-----
 gdb/xcoffread.c  |  5 ++---
 10 files changed, 89 insertions(+), 82 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b73b26e..81aeec9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,32 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* xcoffread.c (xcoff_initial_scan): Use
+	scoped_minimal_symbol_reader.
+	* mipsread.c (mipscoff_symfile_read): Use
+	scoped_minimal_symbol_reader.
+	* minsyms.h (scoped_minimal_symbol_reader): New class.
+	(init_minimal_symbol_collection)
+	(make_cleanup_discard_minimal_symbols, install_minimal_symbols):
+	Don't declare.
+	* minsyms.c (scoped_minimal_symbol_reader): Renamed from
+	init_minimal_symbol_collection, turned into constructor.
+	(~scoped_minimal_symbol_reader): Renamed from
+	do_discard_minimal_symbols_cleanup, turned into destructor.
+	(make_cleanup_discard_minimal_symbols): Remove.
+	(scoped_minimal_symbol_reader::install): Rename form
+	install_minimal_symbols.
+	* mdebugread.c (elfmdebug_build_psymtabs): Use
+	scoped_minimal_symbol_reader.
+	* machoread.c (macho_symfile_read): Use
+	scoped_minimal_symbol_reader.
+	* elfread.c (elf_read_minimal_symbols): Use
+	scoped_minimal_symbol_reader.
+	* dbxread.c (dbx_symfile_read): Use scoped_minimal_symbol_reader.
+	* coffread.c (coff_symfile_read): Use
+	scoped_minimal_symbol_reader.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* valprint.c (generic_emit_char, count_next_character)
 	(generic_printstr): Update.
 	* charset.c (struct wchar_iterator): Move to charset.h.
diff --git a/gdb/coffread.c b/gdb/coffread.c
index 830deb5..e504cde 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -568,7 +568,7 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags)
   unsigned int num_symbols;
   int symtab_offset;
   int stringtab_offset;
-  struct cleanup *back_to, *cleanup_minimal_symbols;
+  struct cleanup *back_to;
   int stabstrsize;
   
   info = (struct coff_symfile_info *) objfile_data (objfile,
@@ -645,8 +645,7 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags)
   if (val < 0)
     error (_("\"%s\": can't get string table"), name);
 
-  init_minimal_symbol_collection ();
-  cleanup_minimal_symbols = make_cleanup_discard_minimal_symbols ();
+  scoped_minimal_symbol_reader reader;
 
   /* Now that the executable file is positioned at symbol table,
      process it and define symbols accordingly.  */
@@ -656,7 +655,7 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags)
   /* Install any minimal symbols that have been collected as the
      current minimal symbols for this objfile.  */
 
-  install_minimal_symbols (objfile);
+  reader.install (objfile);
 
   if (pe_file)
     {
@@ -699,9 +698,6 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags)
 	}
     }
 
-  /* Free the installed minimal symbol data.  */
-  do_cleanups (cleanup_minimal_symbols);
-
   bfd_map_over_sections (abfd, coff_locate_sections, (void *) info);
 
   if (info->stabsects)
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index d5a9587..a0e1cac 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -558,8 +558,7 @@ dbx_symfile_read (struct objfile *objfile, int symfile_flags)
   free_pending_blocks ();
   back_to = make_cleanup (really_free_pendings, 0);
 
-  init_minimal_symbol_collection ();
-  make_cleanup_discard_minimal_symbols ();
+  scoped_minimal_symbol_reader reader;
 
   /* Read stabs data from executable file and define symbols.  */
 
@@ -572,7 +571,7 @@ dbx_symfile_read (struct objfile *objfile, int symfile_flags)
   /* Install any minimal symbols that have been collected as the current
      minimal symbols for this objfile.  */
 
-  install_minimal_symbols (objfile);
+  reader.install (objfile);
 
   do_cleanups (back_to);
 }
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 84355cf..e1ae92a 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1049,8 +1049,8 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
       return;
     }
 
-  init_minimal_symbol_collection ();
-  back_to = make_cleanup_discard_minimal_symbols ();
+  scoped_minimal_symbol_reader reader;
+  back_to = make_cleanup (null_cleanup, NULL);
 
   /* Allocate struct to keep track of the symfile.  */
   dbx = XCNEW (struct dbx_symfile_info);
@@ -1149,7 +1149,7 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
      responsibility to install them.  "mdebug" appears to be the only one
      which will do this.  */
 
-  install_minimal_symbols (objfile);
+  reader.install (objfile);
   do_cleanups (back_to);
 
   if (symtab_create_debug)
diff --git a/gdb/machoread.c b/gdb/machoread.c
index 8abae47..19a2f42 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -861,8 +861,7 @@ macho_symfile_read (struct objfile *objfile, int symfile_flags)
 	  symbol_table = (asymbol **) xmalloc (storage_needed);
 	  make_cleanup (xfree, symbol_table);
 
-          init_minimal_symbol_collection ();
-          make_cleanup_discard_minimal_symbols ();
+          scoped_minimal_symbol_reader reader;
 
 	  symcount = bfd_canonicalize_symtab (objfile->obfd, symbol_table);
 
@@ -873,7 +872,7 @@ macho_symfile_read (struct objfile *objfile, int symfile_flags)
 
 	  macho_symtab_read (objfile, symcount, symbol_table, &oso_vector);
 
-          install_minimal_symbols (objfile);
+          reader.install (objfile);
 	}
 
       /* Try to read .eh_frame / .debug_frame.  */
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index 157ce77..d07e683 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -4870,14 +4870,12 @@ elfmdebug_build_psymtabs (struct objfile *objfile,
 {
   bfd *abfd = objfile->obfd;
   struct ecoff_debug_info *info;
-  struct cleanup *back_to;
 
   /* FIXME: It's not clear whether we should be getting minimal symbol
      information from .mdebug in an ELF file, or whether we will.
      Re-initialize the minimal symbol reader in case we do.  */
 
-  init_minimal_symbol_collection ();
-  back_to = make_cleanup_discard_minimal_symbols ();
+  scoped_minimal_symbol_reader reader;
 
   info = ((struct ecoff_debug_info *)
 	  obstack_alloc (&objfile->objfile_obstack,
@@ -4889,8 +4887,7 @@ elfmdebug_build_psymtabs (struct objfile *objfile,
 
   mdebug_build_psymtabs (objfile, swap, info);
 
-  install_minimal_symbols (objfile);
-  do_cleanups (back_to);
+  reader.install (objfile);
 }
 
 void
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index b478402..7b316ce 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -921,8 +921,7 @@ get_symbol_leading_char (bfd *abfd)
 
 /* See minsyms.h.  */
 
-void
-init_minimal_symbol_collection (void)
+scoped_minimal_symbol_reader::scoped_minimal_symbol_reader ()
 {
   msym_count = 0;
   msym_bunch = NULL;
@@ -932,6 +931,26 @@ init_minimal_symbol_collection (void)
   msym_bunch_index = BUNCH_SIZE;
 }
 
+/* Discard the currently collected minimal symbols, if any.  If we wish
+   to save them for later use, we must have already copied them somewhere
+   else before calling this function.
+
+   FIXME:  We could allocate the minimal symbol bunches on their own
+   obstack and then simply blow the obstack away when we are done with
+   it.  Is it worth the extra trouble though?  */
+
+scoped_minimal_symbol_reader::~scoped_minimal_symbol_reader ()
+{
+  struct msym_bunch *next;
+
+  while (msym_bunch != NULL)
+    {
+      next = msym_bunch->next;
+      xfree (msym_bunch);
+      msym_bunch = next;
+    }
+}
+
 /* See minsyms.h.  */
 
 void
@@ -1087,37 +1106,6 @@ compare_minimal_symbols (const void *fn1p, const void *fn2p)
     }
 }
 
-/* Discard the currently collected minimal symbols, if any.  If we wish
-   to save them for later use, we must have already copied them somewhere
-   else before calling this function.
-
-   FIXME:  We could allocate the minimal symbol bunches on their own
-   obstack and then simply blow the obstack away when we are done with
-   it.  Is it worth the extra trouble though?  */
-
-static void
-do_discard_minimal_symbols_cleanup (void *arg)
-{
-  struct msym_bunch *next;
-
-  while (msym_bunch != NULL)
-    {
-      next = msym_bunch->next;
-      xfree (msym_bunch);
-      msym_bunch = next;
-    }
-}
-
-/* See minsyms.h.  */
-
-struct cleanup *
-make_cleanup_discard_minimal_symbols (void)
-{
-  return make_cleanup (do_discard_minimal_symbols_cleanup, 0);
-}
-
-
-
 /* Compact duplicate entries out of a minimal symbol table by walking
    through the table and compacting out entries with duplicate addresses
    and matching names.  Return the number of entries remaining.
@@ -1244,7 +1232,7 @@ build_minimal_symbol_hash_tables (struct objfile *objfile)
    attempts to demangle them if we later add more minimal symbols.  */
 
 void
-install_minimal_symbols (struct objfile *objfile)
+scoped_minimal_symbol_reader::install (struct objfile *objfile)
 {
   int bindex;
   int mcount;
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index 8857f1a..5ea3610 100644
--- a/gdb/minsyms.h
+++ b/gdb/minsyms.h
@@ -53,21 +53,33 @@ struct bound_minimal_symbol
    as opaque and use functions provided by minsyms.c to inspect them.
 */
 
-/* Prepare to start collecting minimal symbols.  This should be called
-   by a symbol reader to initialize the minimal symbol module.
-   Currently, minimal symbol table creation is not reentrant; it
-   relies on global (static) variables in minsyms.c.  */
+// An RAII-based object that is used to record minimal symbols while
+// they are being read.
+class scoped_minimal_symbol_reader
+{
+ public:
+
+  /* Prepare to start collecting minimal symbols.  This should be called
+     by a symbol reader to initialize the minimal symbol module.
+     Currently, minimal symbol table creation is not reentrant; it
+     relies on global (static) variables in minsyms.c.  */
+
+  explicit scoped_minimal_symbol_reader ();
+
+  ~scoped_minimal_symbol_reader ();
 
-void init_minimal_symbol_collection (void);
+  /* Install the minimal symbols that have been collected into the
+     given objfile.  */
 
-/* Return a cleanup which is used to clean up the global state left
-   over by minimal symbol creation.  After calling
-   init_minimal_symbol_collection, a symbol reader should call this
-   function.  Then, after all minimal symbols have been read,
-   regardless of whether they are installed or not, the cleanup
-   returned by this function should be run.  */
+  void install (struct objfile *);
 
-struct cleanup *make_cleanup_discard_minimal_symbols (void);
+ private:
+
+  // No need for these.  They are intentionally not defined anywhere.
+  scoped_minimal_symbol_reader &operator=
+    (const scoped_minimal_symbol_reader &);
+  scoped_minimal_symbol_reader (const scoped_minimal_symbol_reader &);
+};
 
 /* Record a new minimal symbol.  This is the "full" entry point;
    simpler convenience entry points are also provided below.
@@ -122,13 +134,6 @@ struct minimal_symbol *prim_record_minimal_symbol_and_info
      int section,
      struct objfile *);
 
-/* Install the minimal symbols that have been collected into the given
-   objfile.  After this is called, the cleanup returned by
-   make_cleanup_discard_minimal_symbols should be run in order to
-   clean up global state.  */
-
-void install_minimal_symbols (struct objfile *);
-
 /* Create the terminating entry of OBJFILE's minimal symbol table.
    If OBJFILE->msymbols is zero, allocate a single entry from
    OBJFILE->objfile_obstack; otherwise, just initialize
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
index 27a59d2..da09c03 100644
--- a/gdb/mipsread.c
+++ b/gdb/mipsread.c
@@ -69,10 +69,8 @@ static void
 mipscoff_symfile_read (struct objfile *objfile, int symfile_flags)
 {
   bfd *abfd = objfile->obfd;
-  struct cleanup *back_to;
 
-  init_minimal_symbol_collection ();
-  back_to = make_cleanup_discard_minimal_symbols ();
+  scoped_minimal_symbol_reader reader;
 
   /* Now that the executable file is positioned at symbol table,
      process it and define symbols accordingly.  */
@@ -91,8 +89,7 @@ mipscoff_symfile_read (struct objfile *objfile, int symfile_flags)
   /* Install any minimal symbols that have been collected as the current
      minimal symbols for this objfile.  */
 
-  install_minimal_symbols (objfile);
-  do_cleanups (back_to);
+  reader.install (objfile);
 }
 
 /* Perform any local cleanups required when we are done with a
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 507baf2..81b323c 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -3006,8 +3006,7 @@ xcoff_initial_scan (struct objfile *objfile, int symfile_flags)
   free_pending_blocks ();
   back_to = make_cleanup (really_free_pendings, 0);
 
-  init_minimal_symbol_collection ();
-  make_cleanup_discard_minimal_symbols ();
+  scoped_minimal_symbol_reader reader;
 
   /* Now that the symbol table data of the executable file are all in core,
      process them and define symbols accordingly.  */
@@ -3017,7 +3016,7 @@ xcoff_initial_scan (struct objfile *objfile, int symfile_flags)
   /* Install any minimal symbols that have been collected as the current
      minimal symbols for this objfile.  */
 
-  install_minimal_symbols (objfile);
+  reader.install (objfile);
 
   /* DWARF2 sections.  */
 
-- 
2.7.4

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

* [RFA 11/22] Change command stats reporting to use class
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (20 preceding siblings ...)
  2016-09-27  4:52 ` [RFA 10/22] Remove some cleanups in MI Tom Tromey
@ 2016-09-27  8:32 ` Tom Tromey
  2016-10-09 17:01   ` Pedro Alves
  2016-10-08 13:57 ` [RFA 00/22] More C++-ification Simon Marchi
  22 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-27  8:32 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This removes make_command_stats_cleanup in favor of an RAII class.
The patch is reasonably straightforward, but keeping the same
semantics required reindenting much of captured_main.

2016-09-26  Tom Tromey  <tom@tromey.com>

	* maint.h (scoped_command_stats): New class.
	(make_command_stats_cleanup): Don't declare.
	* maint.c (struct cmd_stats): Remove.
	(~scoped_command_stats): Rename from report_command_stats.  Now a
	destructor.
	(scoped_command_stats): Rename from make_command_stats_cleanup.
	Now a constructor.
	* main.c (captured_main): Use scoped_command_stats.
	* event-top.c (command_handler): Use scoped_command_stats.
---
 gdb/ChangeLog   |   12 +
 gdb/event-top.c |    5 +-
 gdb/main.c      | 1101 +++++++++++++++++++++++++++----------------------------
 gdb/maint.c     |  112 ++----
 gdb/maint.h     |   39 +-
 5 files changed, 632 insertions(+), 637 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 704de48..66e9236 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
+	* maint.h (scoped_command_stats): New class.
+	(make_command_stats_cleanup): Don't declare.
+	* maint.c (struct cmd_stats): Remove.
+	(~scoped_command_stats): Rename from report_command_stats.  Now a
+	destructor.
+	(scoped_command_stats): Rename from make_command_stats_cleanup.
+	Now a constructor.
+	* main.c (captured_main): Use scoped_command_stats.
+	* event-top.c (command_handler): Use scoped_command_stats.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* mi/mi-main.c (mi_cmd_data_read_memory): Use std::vector.  Remove
 	some cleanups.
 
diff --git a/gdb/event-top.c b/gdb/event-top.c
index 9b0ccbc..c452501 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -562,13 +562,12 @@ void
 command_handler (char *command)
 {
   struct ui *ui = current_ui;
-  struct cleanup *stat_chain;
   char *c;
 
   if (ui->instream == ui->stdin_stream)
     reinitialize_more_filter ();
 
-  stat_chain = make_command_stats_cleanup (1);
+  scoped_command_stats stat_reporter (1);
 
   /* Do not execute commented lines.  */
   for (c = command; *c == ' ' || *c == '\t'; c++)
@@ -580,8 +579,6 @@ command_handler (char *command)
       /* Do any commands attached to breakpoint we stopped at.  */
       bpstat_do_actions ();
     }
-
-  do_cleanups (stat_chain);
 }
 
 /* Append RL, an input line returned by readline or one of its
diff --git a/gdb/main.c b/gdb/main.c
index 2ea9466..f081136 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -486,661 +486,658 @@ captured_main (void *data)
   int save_auto_load;
   struct objfile *objfile;
 
-  struct cleanup *pre_stat_chain;
-
 #ifdef HAVE_SBRK
-  /* Set this before calling make_command_stats_cleanup.  */
+  /* Set this before constructing scoped_command_stats.  */
   lim_at_start = (char *) sbrk (0);
 #endif
 
-  pre_stat_chain = make_command_stats_cleanup (0);
+  {
+    scoped_command_stats stat_reporter (0);
 
 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
-  setlocale (LC_MESSAGES, "");
+    setlocale (LC_MESSAGES, "");
 #endif
 #if defined (HAVE_SETLOCALE)
-  setlocale (LC_CTYPE, "");
+    setlocale (LC_CTYPE, "");
 #endif
 #ifdef ENABLE_NLS
-  bindtextdomain (PACKAGE, LOCALEDIR);
-  textdomain (PACKAGE);
+    bindtextdomain (PACKAGE, LOCALEDIR);
+    textdomain (PACKAGE);
 #endif
 
-  bfd_init ();
-  notice_open_fds ();
-  save_original_signals_state ();
+    bfd_init ();
+    notice_open_fds ();
+    save_original_signals_state ();
 
-  make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec);
-  dirsize = 1;
-  dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
-  ndir = 0;
+    make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec);
+    dirsize = 1;
+    dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
+    ndir = 0;
 
-  saved_command_line = (char *) xstrdup ("");
+    saved_command_line = (char *) xstrdup ("");
 
 #ifdef __MINGW32__
-  /* Ensure stderr is unbuffered.  A Cygwin pty or pipe is implemented
-     as a Windows pipe, and Windows buffers on pipes.  */
-  setvbuf (stderr, NULL, _IONBF, BUFSIZ);
+    /* Ensure stderr is unbuffered.  A Cygwin pty or pipe is implemented
+       as a Windows pipe, and Windows buffers on pipes.  */
+    setvbuf (stderr, NULL, _IONBF, BUFSIZ);
 #endif
 
-  main_ui = new_ui (stdin, stdout, stderr);
-  current_ui = main_ui;
+    main_ui = new_ui (stdin, stdout, stderr);
+    current_ui = main_ui;
 
-  gdb_stdtargerr = gdb_stderr;	/* for moment */
-  gdb_stdtargin = gdb_stdin;	/* for moment */
+    gdb_stdtargerr = gdb_stderr;	/* for moment */
+    gdb_stdtargin = gdb_stdin;	/* for moment */
 
 #ifdef __MINGW32__
-  /* On Windows, argv[0] is not necessarily set to absolute form when
-     GDB is found along PATH, without which relocation doesn't work.  */
-  gdb_program_name = windows_get_absolute_argv0 (argv[0]);
+    /* On Windows, argv[0] is not necessarily set to absolute form when
+       GDB is found along PATH, without which relocation doesn't work.  */
+    gdb_program_name = windows_get_absolute_argv0 (argv[0]);
 #else
-  gdb_program_name = xstrdup (argv[0]);
+    gdb_program_name = xstrdup (argv[0]);
 #endif
 
-  /* Prefix warning messages with the command name.  */
-  warning_pre_print = xstrprintf ("%s: warning: ", gdb_program_name);
+    /* Prefix warning messages with the command name.  */
+    warning_pre_print = xstrprintf ("%s: warning: ", gdb_program_name);
 
-  if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
-    perror_warning_with_name (_("error finding working directory"));
+    if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf)))
+      perror_warning_with_name (_("error finding working directory"));
 
-  current_directory = gdb_dirbuf;
+    current_directory = gdb_dirbuf;
 
-  /* Set the sysroot path.  */
-  gdb_sysroot = relocate_gdb_directory (TARGET_SYSTEM_ROOT,
-					TARGET_SYSTEM_ROOT_RELOCATABLE);
+    /* Set the sysroot path.  */
+    gdb_sysroot = relocate_gdb_directory (TARGET_SYSTEM_ROOT,
+					  TARGET_SYSTEM_ROOT_RELOCATABLE);
 
-  if (gdb_sysroot == NULL || *gdb_sysroot == '\0')
-    {
-      xfree (gdb_sysroot);
-      gdb_sysroot = xstrdup (TARGET_SYSROOT_PREFIX);
-    }
+    if (gdb_sysroot == NULL || *gdb_sysroot == '\0')
+      {
+	xfree (gdb_sysroot);
+	gdb_sysroot = xstrdup (TARGET_SYSROOT_PREFIX);
+      }
 
-  debug_file_directory = relocate_gdb_directory (DEBUGDIR,
-						 DEBUGDIR_RELOCATABLE);
+    debug_file_directory = relocate_gdb_directory (DEBUGDIR,
+						   DEBUGDIR_RELOCATABLE);
 
-  gdb_datadir = relocate_gdb_directory (GDB_DATADIR,
-					GDB_DATADIR_RELOCATABLE);
+    gdb_datadir = relocate_gdb_directory (GDB_DATADIR,
+					  GDB_DATADIR_RELOCATABLE);
 
 #ifdef WITH_PYTHON_PATH
-  {
-    /* For later use in helping Python find itself.  */
-    char *tmp = concat (WITH_PYTHON_PATH, SLASH_STRING, "lib", (char *) NULL);
+    {
+      /* For later use in helping Python find itself.  */
+      char *tmp = concat (WITH_PYTHON_PATH, SLASH_STRING, "lib", (char *) NULL);
 
-    python_libdir = relocate_gdb_directory (tmp, PYTHON_PATH_RELOCATABLE);
-    xfree (tmp);
-  }
+      python_libdir = relocate_gdb_directory (tmp, PYTHON_PATH_RELOCATABLE);
+      xfree (tmp);
+    }
 #endif
 
 #ifdef RELOC_SRCDIR
-  add_substitute_path_rule (RELOC_SRCDIR,
-			    make_relative_prefix (gdb_program_name, BINDIR,
-						  RELOC_SRCDIR));
+    add_substitute_path_rule (RELOC_SRCDIR,
+			      make_relative_prefix (gdb_program_name, BINDIR,
+						    RELOC_SRCDIR));
 #endif
 
-  /* There will always be an interpreter.  Either the one passed into
-     this captured main, or one specified by the user at start up, or
-     the console.  Initialize the interpreter to the one requested by 
-     the application.  */
-  interpreter_p = xstrdup (context->interpreter_p);
+    /* There will always be an interpreter.  Either the one passed into
+       this captured main, or one specified by the user at start up, or
+       the console.  Initialize the interpreter to the one requested by 
+       the application.  */
+    interpreter_p = xstrdup (context->interpreter_p);
 
-  /* Parse arguments and options.  */
-  {
-    int c;
-    /* When var field is 0, use flag field to record the equivalent
-       short option (or arbitrary numbers starting at 10 for those
-       with no equivalent).  */
-    enum {
-      OPT_SE = 10,
-      OPT_CD,
-      OPT_ANNOTATE,
-      OPT_STATISTICS,
-      OPT_TUI,
-      OPT_NOWINDOWS,
-      OPT_WINDOWS,
-      OPT_IX,
-      OPT_IEX
-    };
-    static struct option long_options[] =
+    /* Parse arguments and options.  */
     {
-      {"tui", no_argument, 0, OPT_TUI},
-      {"dbx", no_argument, &dbx_commands, 1},
-      {"readnow", no_argument, &readnow_symbol_files, 1},
-      {"r", no_argument, &readnow_symbol_files, 1},
-      {"quiet", no_argument, &quiet, 1},
-      {"q", no_argument, &quiet, 1},
-      {"silent", no_argument, &quiet, 1},
-      {"nh", no_argument, &inhibit_home_gdbinit, 1},
-      {"nx", no_argument, &inhibit_gdbinit, 1},
-      {"n", no_argument, &inhibit_gdbinit, 1},
-      {"batch-silent", no_argument, 0, 'B'},
-      {"batch", no_argument, &batch_flag, 1},
-
-    /* This is a synonym for "--annotate=1".  --annotate is now
-       preferred, but keep this here for a long time because people
-       will be running emacses which use --fullname.  */
-      {"fullname", no_argument, 0, 'f'},
-      {"f", no_argument, 0, 'f'},
-
-      {"annotate", required_argument, 0, OPT_ANNOTATE},
-      {"help", no_argument, &print_help, 1},
-      {"se", required_argument, 0, OPT_SE},
-      {"symbols", required_argument, 0, 's'},
-      {"s", required_argument, 0, 's'},
-      {"exec", required_argument, 0, 'e'},
-      {"e", required_argument, 0, 'e'},
-      {"core", required_argument, 0, 'c'},
-      {"c", required_argument, 0, 'c'},
-      {"pid", required_argument, 0, 'p'},
-      {"p", required_argument, 0, 'p'},
-      {"command", required_argument, 0, 'x'},
-      {"eval-command", required_argument, 0, 'X'},
-      {"version", no_argument, &print_version, 1},
-      {"configuration", no_argument, &print_configuration, 1},
-      {"x", required_argument, 0, 'x'},
-      {"ex", required_argument, 0, 'X'},
-      {"init-command", required_argument, 0, OPT_IX},
-      {"init-eval-command", required_argument, 0, OPT_IEX},
-      {"ix", required_argument, 0, OPT_IX},
-      {"iex", required_argument, 0, OPT_IEX},
+      int c;
+      /* When var field is 0, use flag field to record the equivalent
+	 short option (or arbitrary numbers starting at 10 for those
+	 with no equivalent).  */
+      enum {
+	OPT_SE = 10,
+	OPT_CD,
+	OPT_ANNOTATE,
+	OPT_STATISTICS,
+	OPT_TUI,
+	OPT_NOWINDOWS,
+	OPT_WINDOWS,
+	OPT_IX,
+	OPT_IEX
+      };
+      static struct option long_options[] =
+	{
+	  {"tui", no_argument, 0, OPT_TUI},
+	  {"dbx", no_argument, &dbx_commands, 1},
+	  {"readnow", no_argument, &readnow_symbol_files, 1},
+	  {"r", no_argument, &readnow_symbol_files, 1},
+	  {"quiet", no_argument, &quiet, 1},
+	  {"q", no_argument, &quiet, 1},
+	  {"silent", no_argument, &quiet, 1},
+	  {"nh", no_argument, &inhibit_home_gdbinit, 1},
+	  {"nx", no_argument, &inhibit_gdbinit, 1},
+	  {"n", no_argument, &inhibit_gdbinit, 1},
+	  {"batch-silent", no_argument, 0, 'B'},
+	  {"batch", no_argument, &batch_flag, 1},
+
+	  /* This is a synonym for "--annotate=1".  --annotate is now
+	     preferred, but keep this here for a long time because people
+	     will be running emacses which use --fullname.  */
+	  {"fullname", no_argument, 0, 'f'},
+	  {"f", no_argument, 0, 'f'},
+
+	  {"annotate", required_argument, 0, OPT_ANNOTATE},
+	  {"help", no_argument, &print_help, 1},
+	  {"se", required_argument, 0, OPT_SE},
+	  {"symbols", required_argument, 0, 's'},
+	  {"s", required_argument, 0, 's'},
+	  {"exec", required_argument, 0, 'e'},
+	  {"e", required_argument, 0, 'e'},
+	  {"core", required_argument, 0, 'c'},
+	  {"c", required_argument, 0, 'c'},
+	  {"pid", required_argument, 0, 'p'},
+	  {"p", required_argument, 0, 'p'},
+	  {"command", required_argument, 0, 'x'},
+	  {"eval-command", required_argument, 0, 'X'},
+	  {"version", no_argument, &print_version, 1},
+	  {"configuration", no_argument, &print_configuration, 1},
+	  {"x", required_argument, 0, 'x'},
+	  {"ex", required_argument, 0, 'X'},
+	  {"init-command", required_argument, 0, OPT_IX},
+	  {"init-eval-command", required_argument, 0, OPT_IEX},
+	  {"ix", required_argument, 0, OPT_IX},
+	  {"iex", required_argument, 0, OPT_IEX},
 #ifdef GDBTK
-      {"tclcommand", required_argument, 0, 'z'},
-      {"enable-external-editor", no_argument, 0, 'y'},
-      {"editor-command", required_argument, 0, 'w'},
+	  {"tclcommand", required_argument, 0, 'z'},
+	  {"enable-external-editor", no_argument, 0, 'y'},
+	  {"editor-command", required_argument, 0, 'w'},
 #endif
-      {"ui", required_argument, 0, 'i'},
-      {"interpreter", required_argument, 0, 'i'},
-      {"i", required_argument, 0, 'i'},
-      {"directory", required_argument, 0, 'd'},
-      {"d", required_argument, 0, 'd'},
-      {"data-directory", required_argument, 0, 'D'},
-      {"D", required_argument, 0, 'D'},
-      {"cd", required_argument, 0, OPT_CD},
-      {"tty", required_argument, 0, 't'},
-      {"baud", required_argument, 0, 'b'},
-      {"b", required_argument, 0, 'b'},
-      {"nw", no_argument, NULL, OPT_NOWINDOWS},
-      {"nowindows", no_argument, NULL, OPT_NOWINDOWS},
-      {"w", no_argument, NULL, OPT_WINDOWS},
-      {"windows", no_argument, NULL, OPT_WINDOWS},
-      {"statistics", no_argument, 0, OPT_STATISTICS},
-      {"write", no_argument, &write_files, 1},
-      {"args", no_argument, &set_args, 1},
-      {"l", required_argument, 0, 'l'},
-      {"return-child-result", no_argument, &return_child_result, 1},
-      {0, no_argument, 0, 0}
-    };
-
-    while (1)
-      {
-	int option_index;
+	  {"ui", required_argument, 0, 'i'},
+	  {"interpreter", required_argument, 0, 'i'},
+	  {"i", required_argument, 0, 'i'},
+	  {"directory", required_argument, 0, 'd'},
+	  {"d", required_argument, 0, 'd'},
+	  {"data-directory", required_argument, 0, 'D'},
+	  {"D", required_argument, 0, 'D'},
+	  {"cd", required_argument, 0, OPT_CD},
+	  {"tty", required_argument, 0, 't'},
+	  {"baud", required_argument, 0, 'b'},
+	  {"b", required_argument, 0, 'b'},
+	  {"nw", no_argument, NULL, OPT_NOWINDOWS},
+	  {"nowindows", no_argument, NULL, OPT_NOWINDOWS},
+	  {"w", no_argument, NULL, OPT_WINDOWS},
+	  {"windows", no_argument, NULL, OPT_WINDOWS},
+	  {"statistics", no_argument, 0, OPT_STATISTICS},
+	  {"write", no_argument, &write_files, 1},
+	  {"args", no_argument, &set_args, 1},
+	  {"l", required_argument, 0, 'l'},
+	  {"return-child-result", no_argument, &return_child_result, 1},
+	  {0, no_argument, 0, 0}
+	};
+
+      while (1)
+	{
+	  int option_index;
 
-	c = getopt_long_only (argc, argv, "",
-			      long_options, &option_index);
-	if (c == EOF || set_args)
-	  break;
+	  c = getopt_long_only (argc, argv, "",
+				long_options, &option_index);
+	  if (c == EOF || set_args)
+	    break;
 
-	/* Long option that takes an argument.  */
-	if (c == 0 && long_options[option_index].flag == 0)
-	  c = long_options[option_index].val;
+	  /* Long option that takes an argument.  */
+	  if (c == 0 && long_options[option_index].flag == 0)
+	    c = long_options[option_index].val;
 
-	switch (c)
-	  {
-	  case 0:
-	    /* Long option that just sets a flag.  */
-	    break;
-	  case OPT_SE:
-	    symarg = optarg;
-	    execarg = optarg;
-	    break;
-	  case OPT_CD:
-	    cdarg = optarg;
-	    break;
-	  case OPT_ANNOTATE:
-	    /* FIXME: what if the syntax is wrong (e.g. not digits)?  */
-	    annotation_level = atoi (optarg);
-	    break;
-	  case OPT_STATISTICS:
-	    /* Enable the display of both time and space usage.  */
-	    set_per_command_time (1);
-	    set_per_command_space (1);
-	    break;
-	  case OPT_TUI:
-	    /* --tui is equivalent to -i=tui.  */
+	  switch (c)
+	    {
+	    case 0:
+	      /* Long option that just sets a flag.  */
+	      break;
+	    case OPT_SE:
+	      symarg = optarg;
+	      execarg = optarg;
+	      break;
+	    case OPT_CD:
+	      cdarg = optarg;
+	      break;
+	    case OPT_ANNOTATE:
+	      /* FIXME: what if the syntax is wrong (e.g. not digits)?  */
+	      annotation_level = atoi (optarg);
+	      break;
+	    case OPT_STATISTICS:
+	      /* Enable the display of both time and space usage.  */
+	      set_per_command_time (1);
+	      set_per_command_space (1);
+	      break;
+	    case OPT_TUI:
+	      /* --tui is equivalent to -i=tui.  */
 #ifdef TUI
-	    xfree (interpreter_p);
-	    interpreter_p = xstrdup (INTERP_TUI);
+	      xfree (interpreter_p);
+	      interpreter_p = xstrdup (INTERP_TUI);
 #else
-	    error (_("%s: TUI mode is not supported"), gdb_program_name);
+	      error (_("%s: TUI mode is not supported"), gdb_program_name);
 #endif
-	    break;
-	  case OPT_WINDOWS:
-	    /* FIXME: cagney/2003-03-01: Not sure if this option is
-               actually useful, and if it is, what it should do.  */
+	      break;
+	    case OPT_WINDOWS:
+	      /* FIXME: cagney/2003-03-01: Not sure if this option is
+		 actually useful, and if it is, what it should do.  */
 #ifdef GDBTK
-	    /* --windows is equivalent to -i=insight.  */
-	    xfree (interpreter_p);
-	    interpreter_p = xstrdup (INTERP_INSIGHT);
+	      /* --windows is equivalent to -i=insight.  */
+	      xfree (interpreter_p);
+	      interpreter_p = xstrdup (INTERP_INSIGHT);
 #endif
-	    break;
-	  case OPT_NOWINDOWS:
-	    /* -nw is equivalent to -i=console.  */
-	    xfree (interpreter_p);
-	    interpreter_p = xstrdup (INTERP_CONSOLE);
-	    break;
-	  case 'f':
-	    annotation_level = 1;
-	    break;
-	  case 's':
-	    symarg = optarg;
-	    break;
-	  case 'e':
-	    execarg = optarg;
-	    break;
-	  case 'c':
-	    corearg = optarg;
-	    break;
-	  case 'p':
-	    pidarg = optarg;
-	    break;
-	  case 'x':
-	    {
-	      struct cmdarg cmdarg = { CMDARG_FILE, optarg };
+	      break;
+	    case OPT_NOWINDOWS:
+	      /* -nw is equivalent to -i=console.  */
+	      xfree (interpreter_p);
+	      interpreter_p = xstrdup (INTERP_CONSOLE);
+	      break;
+	    case 'f':
+	      annotation_level = 1;
+	      break;
+	    case 's':
+	      symarg = optarg;
+	      break;
+	    case 'e':
+	      execarg = optarg;
+	      break;
+	    case 'c':
+	      corearg = optarg;
+	      break;
+	    case 'p':
+	      pidarg = optarg;
+	      break;
+	    case 'x':
+	      {
+		struct cmdarg cmdarg = { CMDARG_FILE, optarg };
 
-	      VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
-	    }
-	    break;
-	  case 'X':
-	    {
-	      struct cmdarg cmdarg = { CMDARG_COMMAND, optarg };
+		VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
+	      }
+	      break;
+	    case 'X':
+	      {
+		struct cmdarg cmdarg = { CMDARG_COMMAND, optarg };
 
-	      VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
-	    }
-	    break;
-	  case OPT_IX:
-	    {
-	      struct cmdarg cmdarg = { CMDARG_INIT_FILE, optarg };
+		VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
+	      }
+	      break;
+	    case OPT_IX:
+	      {
+		struct cmdarg cmdarg = { CMDARG_INIT_FILE, optarg };
 
-	      VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
-	    }
-	    break;
-	  case OPT_IEX:
-	    {
-	      struct cmdarg cmdarg = { CMDARG_INIT_COMMAND, optarg };
+		VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
+	      }
+	      break;
+	    case OPT_IEX:
+	      {
+		struct cmdarg cmdarg = { CMDARG_INIT_COMMAND, optarg };
 
-	      VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
-	    }
-	    break;
-	  case 'B':
-	    batch_flag = batch_silent = 1;
-	    gdb_stdout = ui_file_new();
-	    break;
-	  case 'D':
-	    if (optarg[0] == '\0')
-	      error (_("%s: empty path for `--data-directory'"),
-		     gdb_program_name);
-	    set_gdb_data_directory (optarg);
-	    gdb_datadir_provided = 1;
-	    break;
+		VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
+	      }
+	      break;
+	    case 'B':
+	      batch_flag = batch_silent = 1;
+	      gdb_stdout = ui_file_new();
+	      break;
+	    case 'D':
+	      if (optarg[0] == '\0')
+		error (_("%s: empty path for `--data-directory'"),
+		       gdb_program_name);
+	      set_gdb_data_directory (optarg);
+	      gdb_datadir_provided = 1;
+	      break;
 #ifdef GDBTK
-	  case 'z':
-	    {
-	      extern int gdbtk_test (char *);
+	    case 'z':
+	      {
+		extern int gdbtk_test (char *);
 
-	      if (!gdbtk_test (optarg))
-		error (_("%s: unable to load tclcommand file \"%s\""),
-		       gdb_program_name, optarg);
+		if (!gdbtk_test (optarg))
+		  error (_("%s: unable to load tclcommand file \"%s\""),
+			 gdb_program_name, optarg);
+		break;
+	      }
+	    case 'y':
+	      /* Backwards compatibility only.  */
 	      break;
-	    }
-	  case 'y':
-	    /* Backwards compatibility only.  */
-	    break;
-	  case 'w':
-	    {
-	      /* Set the external editor commands when gdb is farming out files
-		 to be edited by another program.  */
-	      extern char *external_editor_command;
+	    case 'w':
+	      {
+		/* Set the external editor commands when gdb is farming out files
+		   to be edited by another program.  */
+		extern char *external_editor_command;
 
-	      external_editor_command = xstrdup (optarg);
-	      break;
-	    }
+		external_editor_command = xstrdup (optarg);
+		break;
+	      }
 #endif /* GDBTK */
-	  case 'i':
-	    xfree (interpreter_p);
-	    interpreter_p = xstrdup (optarg);
-	    break;
-	  case 'd':
-	    dirarg[ndir++] = optarg;
-	    if (ndir >= dirsize)
+	    case 'i':
+	      xfree (interpreter_p);
+	      interpreter_p = xstrdup (optarg);
+	      break;
+	    case 'd':
+	      dirarg[ndir++] = optarg;
+	      if (ndir >= dirsize)
+		{
+		  dirsize *= 2;
+		  dirarg = (char **) xrealloc ((char *) dirarg,
+					       dirsize * sizeof (*dirarg));
+		}
+	      break;
+	    case 't':
+	      ttyarg = optarg;
+	      break;
+	    case 'q':
+	      quiet = 1;
+	      break;
+	    case 'b':
 	      {
-		dirsize *= 2;
-		dirarg = (char **) xrealloc ((char *) dirarg,
-					     dirsize * sizeof (*dirarg));
+		int i;
+		char *p;
+
+		i = strtol (optarg, &p, 0);
+		if (i == 0 && p == optarg)
+		  warning (_("could not set baud rate to `%s'."),
+			   optarg);
+		else
+		  baud_rate = i;
 	      }
-	    break;
-	  case 't':
-	    ttyarg = optarg;
-	    break;
-	  case 'q':
-	    quiet = 1;
-	    break;
-	  case 'b':
-	    {
-	      int i;
-	      char *p;
-
-	      i = strtol (optarg, &p, 0);
-	      if (i == 0 && p == optarg)
-		warning (_("could not set baud rate to `%s'."),
-			 optarg);
-	      else
-		baud_rate = i;
-	    }
-            break;
-	  case 'l':
-	    {
-	      int i;
-	      char *p;
+	      break;
+	    case 'l':
+	      {
+		int i;
+		char *p;
+
+		i = strtol (optarg, &p, 0);
+		if (i == 0 && p == optarg)
+		  warning (_("could not set timeout limit to `%s'."),
+			   optarg);
+		else
+		  remote_timeout = i;
+	      }
+	      break;
 
-	      i = strtol (optarg, &p, 0);
-	      if (i == 0 && p == optarg)
-		warning (_("could not set timeout limit to `%s'."),
-			 optarg);
-	      else
-		remote_timeout = i;
+	    case '?':
+	      error (_("Use `%s --help' for a complete list of options."),
+		     gdb_program_name);
 	    }
-	    break;
-
-	  case '?':
-	    error (_("Use `%s --help' for a complete list of options."),
-		   gdb_program_name);
-	  }
-      }
+	}
 
-    if (batch_flag)
-      quiet = 1;
-  }
+      if (batch_flag)
+	quiet = 1;
+    }
 
-  /* Try to set up an alternate signal stack for SIGSEGV handlers.  */
-  setup_alternate_signal_stack ();
+    /* Try to set up an alternate signal stack for SIGSEGV handlers.  */
+    setup_alternate_signal_stack ();
 
-  /* Initialize all files.  */
-  gdb_init (gdb_program_name);
+    /* Initialize all files.  */
+    gdb_init (gdb_program_name);
 
-  /* Now that gdb_init has created the initial inferior, we're in
-     position to set args for that inferior.  */
-  if (set_args)
-    {
-      /* The remaining options are the command-line options for the
-	 inferior.  The first one is the sym/exec file, and the rest
-	 are arguments.  */
-      if (optind >= argc)
-	error (_("%s: `--args' specified but no program specified"),
-	       gdb_program_name);
-
-      symarg = argv[optind];
-      execarg = argv[optind];
-      ++optind;
-      set_inferior_args_vector (argc - optind, &argv[optind]);
-    }
-  else
-    {
-      /* OK, that's all the options.  */
+    /* Now that gdb_init has created the initial inferior, we're in
+       position to set args for that inferior.  */
+    if (set_args)
+      {
+	/* The remaining options are the command-line options for the
+	   inferior.  The first one is the sym/exec file, and the rest
+	   are arguments.  */
+	if (optind >= argc)
+	  error (_("%s: `--args' specified but no program specified"),
+		 gdb_program_name);
+
+	symarg = argv[optind];
+	execarg = argv[optind];
+	++optind;
+	set_inferior_args_vector (argc - optind, &argv[optind]);
+      }
+    else
+      {
+	/* OK, that's all the options.  */
 
-      /* The first argument, if specified, is the name of the
-	 executable.  */
-      if (optind < argc)
-	{
-	  symarg = argv[optind];
-	  execarg = argv[optind];
-	  optind++;
-	}
+	/* The first argument, if specified, is the name of the
+	   executable.  */
+	if (optind < argc)
+	  {
+	    symarg = argv[optind];
+	    execarg = argv[optind];
+	    optind++;
+	  }
 
-      /* If the user hasn't already specified a PID or the name of a
-	 core file, then a second optional argument is allowed.  If
-	 present, this argument should be interpreted as either a
-	 PID or a core file, whichever works.  */
-      if (pidarg == NULL && corearg == NULL && optind < argc)
-	{
-	  pid_or_core_arg = argv[optind];
-	  optind++;
-	}
+	/* If the user hasn't already specified a PID or the name of a
+	   core file, then a second optional argument is allowed.  If
+	   present, this argument should be interpreted as either a
+	   PID or a core file, whichever works.  */
+	if (pidarg == NULL && corearg == NULL && optind < argc)
+	  {
+	    pid_or_core_arg = argv[optind];
+	    optind++;
+	  }
 
-      /* Any argument left on the command line is unexpected and
-	 will be ignored.  Inform the user.  */
-      if (optind < argc)
-	fprintf_unfiltered (gdb_stderr,
-			    _("Excess command line "
-			      "arguments ignored. (%s%s)\n"),
-			    argv[optind],
-			    (optind == argc - 1) ? "" : " ...");
-    }
+	/* Any argument left on the command line is unexpected and
+	   will be ignored.  Inform the user.  */
+	if (optind < argc)
+	  fprintf_unfiltered (gdb_stderr,
+			      _("Excess command line "
+				"arguments ignored. (%s%s)\n"),
+			      argv[optind],
+			      (optind == argc - 1) ? "" : " ...");
+      }
 
-  /* Lookup gdbinit files.  Note that the gdbinit file name may be
-     overriden during file initialization, so get_init_files should be
-     called after gdb_init.  */
-  get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit);
+    /* Lookup gdbinit files.  Note that the gdbinit file name may be
+       overriden during file initialization, so get_init_files should be
+       called after gdb_init.  */
+    get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit);
 
-  /* Do these (and anything which might call wrap_here or *_filtered)
-     after initialize_all_files() but before the interpreter has been
-     installed.  Otherwize the help/version messages will be eaten by
-     the interpreter's output handler.  */
+    /* Do these (and anything which might call wrap_here or *_filtered)
+       after initialize_all_files() but before the interpreter has been
+       installed.  Otherwize the help/version messages will be eaten by
+       the interpreter's output handler.  */
 
-  if (print_version)
-    {
-      print_gdb_version (gdb_stdout);
-      wrap_here ("");
-      printf_filtered ("\n");
-      exit (0);
-    }
+    if (print_version)
+      {
+	print_gdb_version (gdb_stdout);
+	wrap_here ("");
+	printf_filtered ("\n");
+	exit (0);
+      }
 
-  if (print_help)
-    {
-      print_gdb_help (gdb_stdout);
-      fputs_unfiltered ("\n", gdb_stdout);
-      exit (0);
-    }
+    if (print_help)
+      {
+	print_gdb_help (gdb_stdout);
+	fputs_unfiltered ("\n", gdb_stdout);
+	exit (0);
+      }
 
-  if (print_configuration)
-    {
-      print_gdb_configuration (gdb_stdout);
-      wrap_here ("");
-      printf_filtered ("\n");
-      exit (0);
-    }
+    if (print_configuration)
+      {
+	print_gdb_configuration (gdb_stdout);
+	wrap_here ("");
+	printf_filtered ("\n");
+	exit (0);
+      }
 
-  /* FIXME: cagney/2003-02-03: The big hack (part 1 of 2) that lets
-     GDB retain the old MI1 interpreter startup behavior.  Output the
-     copyright message before the interpreter is installed.  That way
-     it isn't encapsulated in MI output.  */
-  if (!quiet && strcmp (interpreter_p, INTERP_MI1) == 0)
-    {
-      /* Print all the junk at the top, with trailing "..." if we are
-         about to read a symbol file (possibly slowly).  */
-      print_gdb_version (gdb_stdout);
-      if (symarg)
-	printf_filtered ("..");
-      wrap_here ("");
-      printf_filtered ("\n");
-      gdb_flush (gdb_stdout);	/* Force to screen during slow
+    /* FIXME: cagney/2003-02-03: The big hack (part 1 of 2) that lets
+       GDB retain the old MI1 interpreter startup behavior.  Output the
+       copyright message before the interpreter is installed.  That way
+       it isn't encapsulated in MI output.  */
+    if (!quiet && strcmp (interpreter_p, INTERP_MI1) == 0)
+      {
+	/* Print all the junk at the top, with trailing "..." if we are
+	   about to read a symbol file (possibly slowly).  */
+	print_gdb_version (gdb_stdout);
+	if (symarg)
+	  printf_filtered ("..");
+	wrap_here ("");
+	printf_filtered ("\n");
+	gdb_flush (gdb_stdout);	/* Force to screen during slow
 				   operations.  */
-    }
+      }
 
-  /* Install the default UI.  All the interpreters should have had a
-     look at things by now.  Initialize the default interpreter.  */
-  set_top_level_interpreter (interpreter_p);
+    /* Install the default UI.  All the interpreters should have had a
+       look at things by now.  Initialize the default interpreter.  */
+    set_top_level_interpreter (interpreter_p);
 
-  /* FIXME: cagney/2003-02-03: The big hack (part 2 of 2) that lets
-     GDB retain the old MI1 interpreter startup behavior.  Output the
-     copyright message after the interpreter is installed when it is
-     any sane interpreter.  */
-  if (!quiet && !current_interp_named_p (INTERP_MI1))
-    {
-      /* Print all the junk at the top, with trailing "..." if we are
-         about to read a symbol file (possibly slowly).  */
-      print_gdb_version (gdb_stdout);
-      if (symarg)
-	printf_filtered ("..");
-      wrap_here ("");
-      printf_filtered ("\n");
-      gdb_flush (gdb_stdout);	/* Force to screen during slow
+    /* FIXME: cagney/2003-02-03: The big hack (part 2 of 2) that lets
+       GDB retain the old MI1 interpreter startup behavior.  Output the
+       copyright message after the interpreter is installed when it is
+       any sane interpreter.  */
+    if (!quiet && !current_interp_named_p (INTERP_MI1))
+      {
+	/* Print all the junk at the top, with trailing "..." if we are
+	   about to read a symbol file (possibly slowly).  */
+	print_gdb_version (gdb_stdout);
+	if (symarg)
+	  printf_filtered ("..");
+	wrap_here ("");
+	printf_filtered ("\n");
+	gdb_flush (gdb_stdout);	/* Force to screen during slow
 				   operations.  */
-    }
+      }
 
-  /* Set off error and warning messages with a blank line.  */
-  xfree (warning_pre_print);
-  warning_pre_print = _("\nwarning: ");
+    /* Set off error and warning messages with a blank line.  */
+    xfree (warning_pre_print);
+    warning_pre_print = _("\nwarning: ");
 
-  /* Read and execute the system-wide gdbinit file, if it exists.
-     This is done *before* all the command line arguments are
-     processed; it sets global parameters, which are independent of
-     what file you are debugging or what directory you are in.  */
-  if (system_gdbinit && !inhibit_gdbinit)
-    catch_command_errors_const (source_script, system_gdbinit, 0);
+    /* Read and execute the system-wide gdbinit file, if it exists.
+       This is done *before* all the command line arguments are
+       processed; it sets global parameters, which are independent of
+       what file you are debugging or what directory you are in.  */
+    if (system_gdbinit && !inhibit_gdbinit)
+      catch_command_errors_const (source_script, system_gdbinit, 0);
 
-  /* Read and execute $HOME/.gdbinit file, if it exists.  This is done
+    /* Read and execute $HOME/.gdbinit file, if it exists.  This is done
      *before* all the command line arguments are processed; it sets
      global parameters, which are independent of what file you are
      debugging or what directory you are in.  */
 
-  if (home_gdbinit && !inhibit_gdbinit && !inhibit_home_gdbinit)
-    catch_command_errors_const (source_script, home_gdbinit, 0);
-
-  /* Process '-ix' and '-iex' options early.  */
-  for (i = 0; VEC_iterate (cmdarg_s, cmdarg_vec, i, cmdarg_p); i++)
-    switch (cmdarg_p->type)
-    {
-      case CMDARG_INIT_FILE:
-        catch_command_errors_const (source_script, cmdarg_p->string,
-				    !batch_flag);
-	break;
-      case CMDARG_INIT_COMMAND:
-        catch_command_errors (execute_command, cmdarg_p->string,
-			      !batch_flag);
-	break;
-    }
+    if (home_gdbinit && !inhibit_gdbinit && !inhibit_home_gdbinit)
+      catch_command_errors_const (source_script, home_gdbinit, 0);
 
-  /* Now perform all the actions indicated by the arguments.  */
-  if (cdarg != NULL)
-    {
-      catch_command_errors (cd_command, cdarg, 0);
-    }
+    /* Process '-ix' and '-iex' options early.  */
+    for (i = 0; VEC_iterate (cmdarg_s, cmdarg_vec, i, cmdarg_p); i++)
+      switch (cmdarg_p->type)
+	{
+	case CMDARG_INIT_FILE:
+	  catch_command_errors_const (source_script, cmdarg_p->string,
+				      !batch_flag);
+	  break;
+	case CMDARG_INIT_COMMAND:
+	  catch_command_errors (execute_command, cmdarg_p->string,
+				!batch_flag);
+	  break;
+	}
 
-  for (i = 0; i < ndir; i++)
-    catch_command_errors (directory_switch, dirarg[i], 0);
-  xfree (dirarg);
+    /* Now perform all the actions indicated by the arguments.  */
+    if (cdarg != NULL)
+      {
+	catch_command_errors (cd_command, cdarg, 0);
+      }
 
-  /* Skip auto-loading section-specified scripts until we've sourced
-     local_gdbinit (which is often used to augment the source search
-     path).  */
-  save_auto_load = global_auto_load;
-  global_auto_load = 0;
+    for (i = 0; i < ndir; i++)
+      catch_command_errors (directory_switch, dirarg[i], 0);
+    xfree (dirarg);
 
-  if (execarg != NULL
-      && symarg != NULL
-      && strcmp (execarg, symarg) == 0)
-    {
-      /* The exec file and the symbol-file are the same.  If we can't
-         open it, better only print one error message.
-         catch_command_errors returns non-zero on success!  */
-      if (catch_command_errors_const (exec_file_attach, execarg,
-				      !batch_flag))
-	catch_command_errors_const (symbol_file_add_main, symarg,
-				    !batch_flag);
-    }
-  else
-    {
-      if (execarg != NULL)
-	catch_command_errors_const (exec_file_attach, execarg,
-				    !batch_flag);
-      if (symarg != NULL)
-	catch_command_errors_const (symbol_file_add_main, symarg,
-				    !batch_flag);
-    }
+    /* Skip auto-loading section-specified scripts until we've sourced
+       local_gdbinit (which is often used to augment the source search
+       path).  */
+    save_auto_load = global_auto_load;
+    global_auto_load = 0;
 
-  if (corearg && pidarg)
-    error (_("Can't attach to process and specify "
-	     "a core file at the same time."));
+    if (execarg != NULL
+	&& symarg != NULL
+	&& strcmp (execarg, symarg) == 0)
+      {
+	/* The exec file and the symbol-file are the same.  If we can't
+	   open it, better only print one error message.
+	   catch_command_errors returns non-zero on success!  */
+	if (catch_command_errors_const (exec_file_attach, execarg,
+					!batch_flag))
+	  catch_command_errors_const (symbol_file_add_main, symarg,
+				      !batch_flag);
+      }
+    else
+      {
+	if (execarg != NULL)
+	  catch_command_errors_const (exec_file_attach, execarg,
+				      !batch_flag);
+	if (symarg != NULL)
+	  catch_command_errors_const (symbol_file_add_main, symarg,
+				      !batch_flag);
+      }
 
-  if (corearg != NULL)
-    catch_command_errors (core_file_command, corearg, !batch_flag);
-  else if (pidarg != NULL)
-    catch_command_errors (attach_command, pidarg, !batch_flag);
-  else if (pid_or_core_arg)
-    {
-      /* The user specified 'gdb program pid' or gdb program core'.
-	 If pid_or_core_arg's first character is a digit, try attach
-	 first and then corefile.  Otherwise try just corefile.  */
+    if (corearg && pidarg)
+      error (_("Can't attach to process and specify "
+	       "a core file at the same time."));
 
-      if (isdigit (pid_or_core_arg[0]))
-	{
-	  if (catch_command_errors (attach_command, pid_or_core_arg,
-				    !batch_flag) == 0)
-	    catch_command_errors (core_file_command, pid_or_core_arg,
-				  !batch_flag);
-	}
-      else /* Can't be a pid, better be a corefile.  */
-	catch_command_errors (core_file_command, pid_or_core_arg,
-			      !batch_flag);
-    }
+    if (corearg != NULL)
+      catch_command_errors (core_file_command, corearg, !batch_flag);
+    else if (pidarg != NULL)
+      catch_command_errors (attach_command, pidarg, !batch_flag);
+    else if (pid_or_core_arg)
+      {
+	/* The user specified 'gdb program pid' or gdb program core'.
+	   If pid_or_core_arg's first character is a digit, try attach
+	   first and then corefile.  Otherwise try just corefile.  */
 
-  if (ttyarg != NULL)
-    set_inferior_io_terminal (ttyarg);
+	if (isdigit (pid_or_core_arg[0]))
+	  {
+	    if (catch_command_errors (attach_command, pid_or_core_arg,
+				      !batch_flag) == 0)
+	      catch_command_errors (core_file_command, pid_or_core_arg,
+				    !batch_flag);
+	  }
+	else /* Can't be a pid, better be a corefile.  */
+	  catch_command_errors (core_file_command, pid_or_core_arg,
+				!batch_flag);
+      }
 
-  /* Error messages should no longer be distinguished with extra output.  */
-  warning_pre_print = _("warning: ");
+    if (ttyarg != NULL)
+      set_inferior_io_terminal (ttyarg);
 
-  /* Read the .gdbinit file in the current directory, *if* it isn't
-     the same as the $HOME/.gdbinit file (it should exist, also).  */
-  if (local_gdbinit)
-    {
-      auto_load_local_gdbinit_pathname = gdb_realpath (local_gdbinit);
+    /* Error messages should no longer be distinguished with extra output.  */
+    warning_pre_print = _("warning: ");
 
-      if (!inhibit_gdbinit && auto_load_local_gdbinit
-	  && file_is_auto_load_safe (local_gdbinit,
-				     _("auto-load: Loading .gdbinit "
-				       "file \"%s\".\n"),
-				     local_gdbinit))
-	{
-	  auto_load_local_gdbinit_loaded = 1;
+    /* Read the .gdbinit file in the current directory, *if* it isn't
+       the same as the $HOME/.gdbinit file (it should exist, also).  */
+    if (local_gdbinit)
+      {
+	auto_load_local_gdbinit_pathname = gdb_realpath (local_gdbinit);
 
-	  catch_command_errors_const (source_script, local_gdbinit, 0);
-	}
-    }
+	if (!inhibit_gdbinit && auto_load_local_gdbinit
+	    && file_is_auto_load_safe (local_gdbinit,
+				       _("auto-load: Loading .gdbinit "
+					 "file \"%s\".\n"),
+				       local_gdbinit))
+	  {
+	    auto_load_local_gdbinit_loaded = 1;
 
-  /* Now that all .gdbinit's have been read and all -d options have been
-     processed, we can read any scripts mentioned in SYMARG.
-     We wait until now because it is common to add to the source search
-     path in local_gdbinit.  */
-  global_auto_load = save_auto_load;
-  ALL_OBJFILES (objfile)
-    load_auto_scripts_for_objfile (objfile);
-
-  /* Process '-x' and '-ex' options.  */
-  for (i = 0; VEC_iterate (cmdarg_s, cmdarg_vec, i, cmdarg_p); i++)
-    switch (cmdarg_p->type)
-    {
-      case CMDARG_FILE:
-        catch_command_errors_const (source_script, cmdarg_p->string,
-				    !batch_flag);
-	break;
-      case CMDARG_COMMAND:
-        catch_command_errors (execute_command, cmdarg_p->string,
-			      !batch_flag);
-	break;
-    }
+	    catch_command_errors_const (source_script, local_gdbinit, 0);
+	  }
+      }
 
-  /* Read in the old history after all the command files have been
-     read.  */
-  init_history ();
+    /* Now that all .gdbinit's have been read and all -d options have been
+       processed, we can read any scripts mentioned in SYMARG.
+       We wait until now because it is common to add to the source search
+       path in local_gdbinit.  */
+    global_auto_load = save_auto_load;
+    ALL_OBJFILES (objfile)
+      load_auto_scripts_for_objfile (objfile);
+
+    /* Process '-x' and '-ex' options.  */
+    for (i = 0; VEC_iterate (cmdarg_s, cmdarg_vec, i, cmdarg_p); i++)
+      switch (cmdarg_p->type)
+	{
+	case CMDARG_FILE:
+	  catch_command_errors_const (source_script, cmdarg_p->string,
+				      !batch_flag);
+	  break;
+	case CMDARG_COMMAND:
+	  catch_command_errors (execute_command, cmdarg_p->string,
+				!batch_flag);
+	  break;
+	}
 
-  if (batch_flag)
-    {
-      /* We have hit the end of the batch file.  */
-      quit_force (NULL, 0);
-    }
+    /* Read in the old history after all the command files have been
+       read.  */
+    init_history ();
 
-  /* Show time and/or space usage.  */
-  do_cleanups (pre_stat_chain);
+    if (batch_flag)
+      {
+	/* We have hit the end of the batch file.  */
+	quit_force (NULL, 0);
+      }
+  }
 
   /* NOTE: cagney/1999-11-07: There is probably no reason for not
      moving this loop and the code found in captured_command_loop()
diff --git a/gdb/maint.c b/gdb/maint.c
index d2c9346..dad13fa 100644
--- a/gdb/maint.c
+++ b/gdb/maint.c
@@ -752,31 +752,6 @@ static int per_command_symtab;
 static struct cmd_list_element *per_command_setlist;
 static struct cmd_list_element *per_command_showlist;
 
-/* Records a run time and space usage to be used as a base for
-   reporting elapsed time or change in space.  */
-
-struct cmd_stats 
-{
-  /* Zero if the saved time is from the beginning of GDB execution.
-     One if from the beginning of an individual command execution.  */
-  int msg_type;
-  /* Track whether the stat was enabled at the start of the command
-     so that we can avoid printing anything if it gets turned on by
-     the current command.  */
-  int time_enabled : 1;
-  int space_enabled : 1;
-  int symtab_enabled : 1;
-  long start_cpu_time;
-  struct timeval start_wall_time;
-  long start_space;
-  /* Total number of symtabs (over all objfiles).  */
-  int start_nr_symtabs;
-  /* A count of the compunits.  */
-  int start_nr_compunit_symtabs;
-  /* Total number of blocks.  */
-  int start_nr_blocks;
-};
-
 /* Set whether to display time statistics to NEW_VALUE
    (non-zero means true).  */
 
@@ -827,25 +802,32 @@ count_symtabs_and_blocks (int *nr_symtabs_ptr, int *nr_compunit_symtabs_ptr,
   *nr_blocks_ptr = nr_blocks;
 }
 
-/* As indicated by display_time and display_space, report GDB's elapsed time
-   and space usage from the base time and space provided in ARG, which
-   must be a pointer to a struct cmd_stat.  This function is intended
-   to be called as a cleanup.  */
+/* As indicated by display_time and display_space, report GDB's
+   elapsed time and space usage from the base time and space recorded
+   in this object.  */
 
-static void
-report_command_stats (void *arg)
+scoped_command_stats::~scoped_command_stats ()
 {
-  struct cmd_stats *start_stats = (struct cmd_stats *) arg;
-  int msg_type = start_stats->msg_type;
+  /* Early exit if we're not reporting any stats.  It can be expensive to
+     compute the pre-command values so don't collect them at all if we're
+     not reporting stats.  Alas this doesn't work in the startup case because
+     we don't know yet whether we will be reporting the stats.  For the
+     startup case collect the data anyway (it should be cheap at this point),
+     and leave it to the reporter to decide whether to print them.  */
+  if (msg_type != 0
+      && !per_command_time
+      && !per_command_space
+      && !per_command_symtab)
+    return;
 
-  if (start_stats->time_enabled && per_command_time)
+  if (this->time_enabled && per_command_time)
     {
-      long cmd_time = get_run_time () - start_stats->start_cpu_time;
+      long cmd_time = get_run_time () - this->start_cpu_time;
       struct timeval now_wall_time, delta_wall_time, wait_time;
 
       gettimeofday (&now_wall_time, NULL);
       timeval_sub (&delta_wall_time,
-		   &now_wall_time, &start_stats->start_wall_time);
+		   &now_wall_time, &this->start_wall_time);
 
       /* Subtract time spend in prompt_for_continue from walltime.  */
       wait_time = get_prompt_for_continue_wait_time ();
@@ -859,13 +841,13 @@ report_command_stats (void *arg)
 			 (long) delta_wall_time.tv_usec);
     }
 
-  if (start_stats->space_enabled && per_command_space)
+  if (this->space_enabled && per_command_space)
     {
 #ifdef HAVE_SBRK
       char *lim = (char *) sbrk (0);
 
       long space_now = lim - lim_at_start;
-      long space_diff = space_now - start_stats->start_space;
+      long space_diff = space_now - this->start_space;
 
       printf_unfiltered (msg_type == 0
 			 ? _("Space used: %ld (%s%ld during startup)\n")
@@ -876,7 +858,7 @@ report_command_stats (void *arg)
 #endif
     }
 
-  if (start_stats->symtab_enabled && per_command_symtab)
+  if (this->symtab_enabled && per_command_symtab)
     {
       int nr_symtabs, nr_compunit_symtabs, nr_blocks;
 
@@ -885,54 +867,32 @@ report_command_stats (void *arg)
 			   " #compunits: %d (+%d),"
 			   " #blocks: %d (+%d)\n"),
 			 nr_symtabs,
-			 nr_symtabs - start_stats->start_nr_symtabs,
+			 nr_symtabs - this->start_nr_symtabs,
 			 nr_compunit_symtabs,
 			 (nr_compunit_symtabs
-			  - start_stats->start_nr_compunit_symtabs),
+			  - this->start_nr_compunit_symtabs),
 			 nr_blocks,
-			 nr_blocks - start_stats->start_nr_blocks);
+			 nr_blocks - this->start_nr_blocks);
     }
 }
 
-/* Create a cleanup that reports time and space used since its creation.
-   MSG_TYPE is zero for gdb startup, otherwise it is one(1) to report
-   data for individual commands.  */
-
-struct cleanup *
-make_command_stats_cleanup (int msg_type)
+scoped_command_stats::scoped_command_stats (int msg_type)
+: msg_type (msg_type)
 {
-  struct cmd_stats *new_stat;
-
-  /* Early exit if we're not reporting any stats.  It can be expensive to
-     compute the pre-command values so don't collect them at all if we're
-     not reporting stats.  Alas this doesn't work in the startup case because
-     we don't know yet whether we will be reporting the stats.  For the
-     startup case collect the data anyway (it should be cheap at this point),
-     and leave it to the reporter to decide whether to print them.  */
-  if (msg_type != 0
-      && !per_command_time
-      && !per_command_space
-      && !per_command_symtab)
-    return make_cleanup (null_cleanup, 0);
-
-  new_stat = XCNEW (struct cmd_stats);
-
-  new_stat->msg_type = msg_type;
-
   if (msg_type == 0 || per_command_space)
     {
 #ifdef HAVE_SBRK
       char *lim = (char *) sbrk (0);
-      new_stat->start_space = lim - lim_at_start;
-      new_stat->space_enabled = 1;
+      this->start_space = lim - lim_at_start;
+      this->space_enabled = 1;
 #endif
     }
 
   if (msg_type == 0 || per_command_time)
     {
-      new_stat->start_cpu_time = get_run_time ();
-      gettimeofday (&new_stat->start_wall_time, NULL);
-      new_stat->time_enabled = 1;
+      this->start_cpu_time = get_run_time ();
+      gettimeofday (&this->start_wall_time, NULL);
+      this->time_enabled = 1;
     }
 
   if (msg_type == 0 || per_command_symtab)
@@ -940,16 +900,14 @@ make_command_stats_cleanup (int msg_type)
       int nr_symtabs, nr_compunit_symtabs, nr_blocks;
 
       count_symtabs_and_blocks (&nr_symtabs, &nr_compunit_symtabs, &nr_blocks);
-      new_stat->start_nr_symtabs = nr_symtabs;
-      new_stat->start_nr_compunit_symtabs = nr_compunit_symtabs;
-      new_stat->start_nr_blocks = nr_blocks;
-      new_stat->symtab_enabled = 1;
+      this->start_nr_symtabs = nr_symtabs;
+      this->start_nr_compunit_symtabs = nr_compunit_symtabs;
+      this->start_nr_blocks = nr_blocks;
+      this->symtab_enabled = 1;
     }
 
   /* Initalize timer to keep track of how long we waited for the user.  */
   reset_prompt_for_continue_wait_time ();
-
-  return make_cleanup_dtor (report_command_stats, new_stat, xfree);
 }
 
 /* Handle unknown "mt set per-command" arguments.
diff --git a/gdb/maint.h b/gdb/maint.h
index 841e790..f517fa4 100644
--- a/gdb/maint.h
+++ b/gdb/maint.h
@@ -23,9 +23,40 @@ extern void set_per_command_time (int);
 
 extern void set_per_command_space (int);
 
-/* Note: There's no set_per_command_symtab on purpose.
-   Symtab stats aren't yet as useful for --statistics output.  */
-
-extern struct cleanup *make_command_stats_cleanup (int);
+/* Records a run time and space usage to be used as a base for
+   reporting elapsed time or change in space.  */
+
+class scoped_command_stats
+{
+ public:
+
+  scoped_command_stats (int msg_type);
+  ~scoped_command_stats ();
+
+ private:
+
+  // No need for these.  They are intentionally not defined anywhere.
+  scoped_command_stats &operator= (const scoped_command_stats &);
+  scoped_command_stats (const scoped_command_stats &);
+
+  /* Zero if the saved time is from the beginning of GDB execution.
+     One if from the beginning of an individual command execution.  */
+  int msg_type;
+  /* Track whether the stat was enabled at the start of the command
+     so that we can avoid printing anything if it gets turned on by
+     the current command.  */
+  int time_enabled : 1;
+  int space_enabled : 1;
+  int symtab_enabled : 1;
+  long start_cpu_time;
+  struct timeval start_wall_time;
+  long start_space;
+  /* Total number of symtabs (over all objfiles).  */
+  int start_nr_symtabs;
+  /* A count of the compunits.  */
+  int start_nr_compunit_symtabs;
+  /* Total number of blocks.  */
+  int start_nr_blocks;
+};
 
 #endif /* MAINT_H */
-- 
2.7.4

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

* Re: [RFA 01/22] Change selttest.c to use use std::vector
  2016-09-27  4:48 ` [RFA 01/22] Change selttest.c to use use std::vector Tom Tromey
@ 2016-09-27  8:50   ` Trevor Saunders
  2016-09-27 16:44     ` Tom Tromey
  2016-09-30 14:43   ` Simon Marchi
  1 sibling, 1 reply; 123+ messages in thread
From: Trevor Saunders @ 2016-09-27  8:50 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Mon, Sep 26, 2016 at 10:08:29PM -0600, Tom Tromey wrote:
> This patch changes selftest.c to use std::vector rather than VEC.
> 
> I think this is a small net plus.  Because we're using C++03, we

I'd agree, hopefully we can throw VEC in the trash some day.  Relatedly
we should probably move gcc's hash table stuff to include/ sooner rather
than later so we can similarly get rid of htab.

> unfortunately don't all the possible benefits here; namely, iterating

I think you missed get in that sentence.

> over a vector is still a pain.  For reference, in C++11 the loop would
> be just:
> 
>     for (auto f : tests)

its debatable, but imho its not necessarily obvious what the type of the
local is when you use auto to iterate over vectors especially when they
are members or globals like here.

> +static std::vector<self_test_function *> tests;

should we use a pointer to avoid the static initializer?

> -  for (i = 0; VEC_iterate (self_test_function_ptr, tests, i, func); ++i)
> +  for (std::vector<self_test_function *>::iterator iter = tests.begin ();
> +       iter != tests.end ();
> +       ++iter)

I believe you can "cheat" here and just use the function pointer type,
because the sane implementation of iterators over vectors is pointers.

Trev

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-09-27  4:47 ` [RFA 02/22] Use RAII to save and restore scalars Tom Tromey
@ 2016-09-27 10:24   ` Trevor Saunders
  2016-09-30  1:40     ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Trevor Saunders @ 2016-09-27 10:24 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Mon, Sep 26, 2016 at 10:08:30PM -0600, Tom Tromey wrote:
> This patch replaces many (but not all) uses of
> make_cleanup_restore_integer with a simple RAII-based template class.
> It also removes the similar restore_execution_direction cleanup in
> favor of this new class.  Subsequent patches will replace other
> similar cleanups with this class.
> 
> I chose the name "scoped_restore" for this class.  I considered that
> perhaps "auto_restore" might be clearer.  Or maybe something else;
> it's simple enough to change.

Its worth noting dmalcolm wants to add something similar to gcc for his
rtl front end work.

> I had hoped that template parameter deduction would work here, but it
> did not, and so the patch uses explicit template parameters
> everywhere.

yeah, you can't deduce template args from a constructor in C++

> +  // Create a new scoped_restore object that saves the current value
> +  // of *VAR, and then sets *VAR to VALUE.  *VAR will be restored when
> +  // this scoped_restore object is destroyed.
> +  scoped_restore (T *var, T value)
> +    : saved_var (var),
> +      saved_value (*var)
> +  {
> +    *var = value;

I wonder if it isn't clearer to create the scoped_restore and then set
the variable yourself.

> +  // The saved variable.
> +  T *saved_var;
> +
> +  // The saved value.
> +  T saved_value;

 I think you could use const T, but I doubt it matters, these objects
 really shouldn't have there address taken so the compiler should see
 everything about them.

Trev

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

* Re: [RFA 01/22] Change selttest.c to use use std::vector
  2016-09-27  8:50   ` Trevor Saunders
@ 2016-09-27 16:44     ` Tom Tromey
  2016-09-28 14:58       ` Trevor Saunders
                         ` (2 more replies)
  0 siblings, 3 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-27 16:44 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: Tom Tromey, gdb-patches

>>>>> "Trevor" == Trevor Saunders <tbsaunde@tbsaunde.org> writes:

Trevor> I'd agree, hopefully we can throw VEC in the trash some day.  Relatedly
Trevor> we should probably move gcc's hash table stuff to include/ sooner rather
Trevor> than later so we can similarly get rid of htab.

That would be nice; though we could probably use std::set and std::map
in gdb as well.  One wrinkle with hash tables is that they're sometimes
allocated on obstacks; would gcc's handle this?

>> for (auto f : tests)

Trevor> its debatable, but imho its not necessarily obvious what the type of the
Trevor> local is when you use auto to iterate over vectors especially when they
Trevor> are members or globals like here.

Yeah, that's one drawback.
Often one actually wants "auto &f" in there.

>> +static std::vector<self_test_function *> tests;

Trevor> should we use a pointer to avoid the static initializer?

I was on the fence about this one.
On the one hand, static initializers can be very bad.
On the other hand, this one in particular doesn't seem like it could
cause problems.

>> -  for (i = 0; VEC_iterate (self_test_function_ptr, tests, i, func); ++i)
>> +  for (std::vector<self_test_function *>::iterator iter = tests.begin ();
>> +       iter != tests.end ();
>> +       ++iter)

Trevor> I believe you can "cheat" here and just use the function pointer type,
Trevor> because the sane implementation of iterators over vectors is pointers.

Yeah, or just loop using an int and index into the vector.
I'll see if that looks cleaner.

Tom

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

* Re: [RFA 01/22] Change selttest.c to use use std::vector
  2016-09-27 16:44     ` Tom Tromey
@ 2016-09-28 14:58       ` Trevor Saunders
  2016-09-29  8:59         ` Tom Tromey
  2016-10-06  0:18       ` Pedro Alves
  2016-10-06  0:39       ` Pedro Alves
  2 siblings, 1 reply; 123+ messages in thread
From: Trevor Saunders @ 2016-09-28 14:58 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Tue, Sep 27, 2016 at 09:55:28AM -0600, Tom Tromey wrote:
> >>>>> "Trevor" == Trevor Saunders <tbsaunde@tbsaunde.org> writes:
> 
> Trevor> I'd agree, hopefully we can throw VEC in the trash some day.  Relatedly
> Trevor> we should probably move gcc's hash table stuff to include/ sooner rather
> Trevor> than later so we can similarly get rid of htab.
> 
> That would be nice; though we could probably use std::set and std::map
> in gdb as well.  One wrinkle with hash tables is that they're sometimes
> allocated on obstacks; would gcc's handle this?

No, they don't support that at the moment, though I suppose it would
be fine for keys or values to point into obstacks.  Is there a good
reason for this other than using obstacks to provide a sort of automatic
memory management?

> >> for (auto f : tests)
> 
> Trevor> its debatable, but imho its not necessarily obvious what the type of the
> Trevor> local is when you use auto to iterate over vectors especially when they
> Trevor> are members or globals like here.
> 
> Yeah, that's one drawback.
> Often one actually wants "auto &f" in there.

yeah, and not having that can sometimes be bad.

> >> +static std::vector<self_test_function *> tests;
> 
> Trevor> should we use a pointer to avoid the static initializer?
> 
> I was on the fence about this one.
> On the one hand, static initializers can be very bad.
> On the other hand, this one in particular doesn't seem like it could
> cause problems.


yeah, I think its just zeroing some memory and then registering a static
destructor.  So its silly that its necessary at all, but whether to
avoid it or not is just a perf question.

Trev

> >> -  for (i = 0; VEC_iterate (self_test_function_ptr, tests, i, func); ++i)
> >> +  for (std::vector<self_test_function *>::iterator iter = tests.begin ();
> >> +       iter != tests.end ();
> >> +       ++iter)
> 
> Trevor> I believe you can "cheat" here and just use the function pointer type,
> Trevor> because the sane implementation of iterators over vectors is pointers.
> 
> Yeah, or just loop using an int and index into the vector.
> I'll see if that looks cleaner.
> 
> Tom

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

* Re: [RFA 01/22] Change selttest.c to use use std::vector
  2016-09-28 14:58       ` Trevor Saunders
@ 2016-09-29  8:59         ` Tom Tromey
  0 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-29  8:59 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: Tom Tromey, gdb-patches

>>>>> "Trevor" == Trevor Saunders <tbsaunde@tbsaunde.org> writes:

Tom> That would be nice; though we could probably use std::set and std::map
Tom> in gdb as well.  One wrinkle with hash tables is that they're sometimes
Tom> allocated on obstacks; would gcc's handle this?

Trevor> No, they don't support that at the moment, though I suppose it
Trevor> would be fine for keys or values to point into obstacks.  Is
Trevor> there a good reason for this other than using obstacks to
Trevor> provide a sort of automatic memory management?

Sometimes it's just to avoid more work -- cleaning up an obstack is
easy.  E.g., see dwarf2loc.c:func_verify_no_selftailcall Uses like this
can easily be replaced.

There are also spots that allocate a hash table on the objfile obstack.
Now, this is a bit unfortunate because it means that hash table resizes
will create a kind of "leak" -- not a true leak (the memory is tracked
and will be freed), but basically some chunk of memory will no longer be
useful.

It's possible to address these cases in other ways, though more
difficult.

Tom

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

* Re: [RFA 07/22] Change scoped_minimal_symbol_reader to store objfile
  2016-09-27  4:41 ` [RFA 07/22] Change scoped_minimal_symbol_reader to store objfile Tom Tromey
@ 2016-09-29  9:19   ` Trevor Saunders
  2016-09-30 21:41     ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Trevor Saunders @ 2016-09-29  9:19 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

>       Currently, minimal symbol table creation is not reentrant; it
>       relies on global (static) variables in minsyms.c.  */
>  
> -  explicit scoped_minimal_symbol_reader ();
> +  explicit scoped_minimal_symbol_reader (struct objfile *);

C++ doesn't require the explicit struct / union  when refering to the
type, though of course you can keep them if you think it makes something
clearer.

> @@ -79,6 +79,8 @@ class scoped_minimal_symbol_reader
>    scoped_minimal_symbol_reader &operator=
>      (const scoped_minimal_symbol_reader &);
>    scoped_minimal_symbol_reader (const scoped_minimal_symbol_reader &);
> +
> +  struct objfile *objfile;

fwiw gcc convention is to prefix members with m_, so doing so in gdb as
well would be nice.

Trev

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-09-27  4:48 ` [RFA 09/22] Remove make_cleanup_restore_current_ui Tom Tromey
@ 2016-09-29 11:55   ` Trevor Saunders
  2016-10-01  3:47     ` Tom Tromey
  2016-10-01  4:29   ` Simon Marchi
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 123+ messages in thread
From: Trevor Saunders @ 2016-09-29 11:55 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> +  ~switch_thru_all_uis ()
> +  {
> +  }

So, you don't need to do anything  special here because of
scoped_restore.  So why not just use the compilers definition of this?

Trev

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

* Re: [RFA 17/22] Remove make_cleanup_restore_current_uiout
  2016-09-27  4:50 ` [RFA 17/22] Remove make_cleanup_restore_current_uiout Tom Tromey
@ 2016-09-29 14:35   ` Trevor Saunders
  2016-09-29 15:23     ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Trevor Saunders @ 2016-09-29 14:35 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> +class scoped_restore_uiout
> +{
> + public:
> +
> +  scoped_restore_uiout () : saved (current_uiout)
> +  {
> +  }
> +
> +  ~scoped_restore_uiout ()
> +  {
> +    current_uiout = saved;
> +  }
> +
> + private:
> +
> +  // No need for these.  They are intentionally not defined anywhere.
> +  scoped_restore_uiout &operator= (const scoped_restore_uiout &);
> +  scoped_restore_uiout (const scoped_restore_uiout &);
> +
> +  // The saved ui out.
> +  struct ui_out *saved;

isn't this just scoped_restore<ui_out *> ? why do you need a separate
class?

Trev

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

* Re: [RFA 17/22] Remove make_cleanup_restore_current_uiout
  2016-09-29 14:35   ` Trevor Saunders
@ 2016-09-29 15:23     ` Tom Tromey
  2016-09-29 17:55       ` Simon Marchi
  2016-09-30  2:45       ` Pedro Alves
  0 siblings, 2 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-29 15:23 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: Tom Tromey, gdb-patches

>>>>> "Trevor" == Trevor Saunders <tbsaunde@tbsaunde.org> writes:

Trevor> isn't this just scoped_restore<ui_out *> ? why do you need a separate
Trevor> class?

In an earlier thread there was a discussion of not having this cleanup
be over-general -- that is, it was intentionally specific to just
current_uiout.

Tom

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

* Re: [RFA 17/22] Remove make_cleanup_restore_current_uiout
  2016-09-29 15:23     ` Tom Tromey
@ 2016-09-29 17:55       ` Simon Marchi
  2016-09-29 20:34         ` Tom Tromey
  2016-09-30  2:45       ` Pedro Alves
  1 sibling, 1 reply; 123+ messages in thread
From: Simon Marchi @ 2016-09-29 17:55 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Trevor Saunders, gdb-patches

On 2016-09-29 10:05, Tom Tromey wrote:
>>>>>> "Trevor" == Trevor Saunders <tbsaunde@tbsaunde.org> writes:
> 
> Trevor> isn't this just scoped_restore<ui_out *> ? why do you need a 
> separate
> Trevor> class?
> 
> In an earlier thread there was a discussion of not having this cleanup
> be over-general -- that is, it was intentionally specific to just
> current_uiout.

In that case, may I suggest naming the class 
scoped_restore_current_uiout?

IIRC, the original comment was that it was not necessary to have a 
parametrized make_cleanup_restore_uiout, when the only uiout we restore 
is the current_ui.  And I don't think there was a cleanup to restore a 
generic pointer, so we had to have a specialized cleanup anyway.

Here we have the option to have one less class by using your 
scoped_restore:

     scoped_restore<ui_out *> uiout_restore (&current_uiout, 
other_uiout);

vs having a specific one:

     scoped_restore_current_uiout uiout_restore;
     current_uiout = other_uiout;

I am ok with both methods, it's not a big deal.

Simon

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

* Re: [RFA 17/22] Remove make_cleanup_restore_current_uiout
  2016-09-29 17:55       ` Simon Marchi
@ 2016-09-29 20:34         ` Tom Tromey
  0 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-29 20:34 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, Trevor Saunders, gdb-patches

Simon> Here we have the option to have one less class by using your
Simon> scoped_restore:

Simon>     scoped_restore<ui_out *> uiout_restore (&current_uiout,
Simon> other_uiout);

I don't mind if you don't mind.  I will make this change.

Tom

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-09-27 10:24   ` Trevor Saunders
@ 2016-09-30  1:40     ` Pedro Alves
  2016-09-30  9:22       ` Pedro Alves
                         ` (2 more replies)
  0 siblings, 3 replies; 123+ messages in thread
From: Pedro Alves @ 2016-09-30  1:40 UTC (permalink / raw)
  To: Trevor Saunders, Tom Tromey; +Cc: gdb-patches

On 09/27/2016 09:59 AM, Trevor Saunders wrote:

>> I had hoped that template parameter deduction would work here, but it
>> did not, and so the patch uses explicit template parameters
>> everywhere.
> 
> yeah, you can't deduce template args from a constructor in C++

I don't know whether the trick below is usual, but you can work
around that and end up with no-template-args-in-sight usage
like this:

void
foo ()
{
  scoped_restore scope = make_scoped_restore (&some_global);

  ...
}



You'd do something like this:


struct scoped_restore_base {};

template<typename T>
class scoped_restore_ : public scoped_restore_base
{
 public:
...
  explicit scoped_restore (T *var)
    : saved_var (var),
      saved_value (*var)
  {}

  ~scoped_restore ()
  {
    *saved_var = saved_value;
  }

 private:
  scoped_restore &operator= (const scoped_restore &rhs);

  // The saved variable.
  T *saved_var;

  // The saved value.
  T saved_value;
};

typedef const scoped_restore_base &scoped_restore;

template<class T>
scoped_restore_<T> make_scoped_restore (T *var)
{
  return scoped_restore_<T> (var);
}

The trick is making scoped_restore_ inherit a non-template
class, and make "scoped_restore" a typedef for a const reference
to the base class, since a const reference can bind to the
temporary that is returned by make_scoped_restore, and it
extends the temporary's lifetime.

While copy elision / RVO makes it so that the temporary returned by
value from make_scoped_restore is constructed directly in the caller
instead of constructed and then copied out, you still have to
provide the copy constructor, instead of "deleting" it as in your
original patch.  Copy elision was optional until C++17, but I
believe all compilers worth their salt implement it.  And if a compiler
doesn't implement it, it's not a real issue, anyway, the code
still works.

The downside is that printing a scoped_restore object from
gdb will just print the reference using the base type, so you
won't see stored fields.

(gdb) p scope
$1 = (const scoped_restore) @0x7fffffffd910: {<No data fields>}

To see the object's fields you'd have to downcast it manually, like:

(gdb) p (scoped_restore_<ui_out *>) scope
$1 = {<scoped_restore_base> = {<No data fields>}, saved_var = 0x601050 <current_uiout>, saved_value = 0x0}

Not sure whether that's an issue.

Thanks,
Pedro Alves

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

* Re: [RFA 19/22] Convert tid_range_parser to class
  2016-09-27  4:42 ` [RFA 19/22] Convert tid_range_parser to class Tom Tromey
@ 2016-09-30  1:41   ` Pedro Alves
  2016-09-30 14:52     ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-09-30  1:41 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This converts tid_range_parser to be a class, and converts various
> tid_range_parser_* functions to be methods on this class; then it
> updates the users to follow.

Whoops, we ended up duplicating work here.  I had done this too
last weekend, though I went all the way and converted
get_number_or_range too.

This had forced me to think of a better interface between
tid_range_parser and get_number_or_range, since the former
peeked into the latter's internals a bit too much.  That ended
up resulting mostly in these two not-just-straight-1-1 changes:

 void
-tid_range_parser_skip (struct tid_range_parser *parser)
+tid_range_parser::skip_range ()
 {
...
 
-  tid_range_parser_init (parser, parser->range_parser.end_ptr,
-			 parser->default_inferior);
+  m_range_parser.skip_range ();
+  init (m_range_parser.string (), m_default_inferior);
 }

and:

   /* If we successfully parsed a thread number or finished parsing a
      thread range, switch back to assuming the next TID is
      inferior-qualified.  */
-  if (parser->range_parser.end_ptr == NULL
-      || parser->range_parser.string == parser->range_parser.end_ptr)
+  if (!m_range_parser.in_range ())
     {


Additional differences compared to yours are:

- "bool" instead of "int".

- "m_" prefixes.

- I had moved the enum tid_range_state definition to within
  the tid_parser class's scope, since this private implementation
  detail.

I didn't prefix the getters with "get_", or "is_" but I think I
do like it better like you have it.

Let me know what you think.  It's super fine with me to rebase
mine on top of yours.  Did you have a follow up patch for
get_number_or_range too, perhaps?

Subject: [PATCH] C++-ify struct get_number_or_range and struct tid_parser

Provides better encapsulation.
---
 gdb/breakpoint.c    |  33 ++++------
 gdb/breakpoint.h    |   6 +-
 gdb/cli/cli-utils.c |  70 ++++++++++----------
 gdb/cli/cli-utils.h | 110 ++++++++++++++++++-------------
 gdb/inferior.c      |  32 ++++------
 gdb/linespec.c      |   9 +--
 gdb/memattr.c       |  32 ++++------
 gdb/printcmd.c      |   9 ++-
 gdb/reverse.c       |  19 ++----
 gdb/thread.c        |  26 ++++----
 gdb/tid-parse.c     | 170 ++++++++++++++++++++++++------------------------
 gdb/tid-parse.h     | 181 ++++++++++++++++++++++++++--------------------------
 12 files changed, 345 insertions(+), 352 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 1e05932..6b47541 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -14775,21 +14775,18 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *,
 {
   int num;
   struct breakpoint *b, *tmp;
-  int match;
-  struct get_number_or_range_state state;
 
   if (args == 0 || *args == '\0')
     error_no_arg (_("one or more breakpoint numbers"));
 
-  init_number_or_range (&state, args);
+  number_or_range_parser parser (args);
 
-  while (!state.finished)
+  while (!parser.finished ())
     {
-      const char *p = state.string;
+      const char *p = parser.string ();
+      bool match = false;
 
-      match = 0;
-
-      num = get_number_or_range (&state);
+      num = parser.get_next ();
       if (num == 0)
 	{
 	  warning (_("bad breakpoint number at or near '%s'"), p);
@@ -14799,11 +14796,11 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *,
 	  ALL_BREAKPOINTS_SAFE (b, tmp)
 	    if (b->number == num)
 	      {
-		match = 1;
+		match = true;
 		function (b, data);
 		break;
 	      }
-	  if (match == 0)
+	  if (!match)
 	    printf_unfiltered (_("No breakpoint number %d.\n"), num);
 	}
     }
@@ -15584,12 +15581,10 @@ trace_pass_command (char *args, int from_tty)
     }
   else
     {
-      struct get_number_or_range_state state;
-
-      init_number_or_range (&state, args);
-      while (!state.finished)
+      number_or_range_parser parser (args);
+      while (!parser.finished ())
 	{
-	  t1 = get_tracepoint_by_number (&args, &state);
+	  t1 = get_tracepoint_by_number (&args, &parser);
 	  if (t1)
 	    trace_pass_set_count (t1, count, from_tty);
 	}
@@ -15635,16 +15630,16 @@ get_tracepoint_by_number_on_target (int num)
 
 struct tracepoint *
 get_tracepoint_by_number (char **arg,
-			  struct get_number_or_range_state *state)
+			  number_or_range_parser *parser)
 {
   struct breakpoint *t;
   int tpnum;
   char *instring = arg == NULL ? NULL : *arg;
 
-  if (state)
+  if (parser != NULL)
     {
-      gdb_assert (!state->finished);
-      tpnum = get_number_or_range (state);
+      gdb_assert (!parser->finished ());
+      tpnum = parser->get_next ();
     }
   else if (arg == NULL || *arg == NULL || ! **arg)
     tpnum = tracepoint_count;
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 4bdf0d5..aaff3d5 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -31,7 +31,7 @@ struct value;
 struct block;
 struct gdbpy_breakpoint_object;
 struct gdbscm_breakpoint_object;
-struct get_number_or_range_state;
+struct number_or_range_parser;
 struct thread_info;
 struct bpstats;
 struct bp_location;
@@ -1587,8 +1587,8 @@ extern struct tracepoint *get_tracepoint_by_number_on_target (int num);
 
 /* Find a tracepoint by parsing a number in the supplied string.  */
 extern struct tracepoint *
-     get_tracepoint_by_number (char **arg, 
-			       struct get_number_or_range_state *state);
+  get_tracepoint_by_number (char **arg,
+			    number_or_range_parser *parser);
 
 /* Return a vector of all tracepoints currently defined.  The vector
    is newly allocated; the caller should free when done with it.  */
diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c
index 0946db0..379f341 100644
--- a/gdb/cli/cli-utils.c
+++ b/gdb/cli/cli-utils.c
@@ -121,39 +121,45 @@ get_number (char **pp)
 
 /* See documentation in cli-utils.h.  */
 
+number_or_range_parser::number_or_range_parser (const char *string)
+{
+  init (string);
+}
+
+/* See documentation in cli-utils.h.  */
+
 void
-init_number_or_range (struct get_number_or_range_state *state,
-		      const char *string)
+number_or_range_parser::init (const char *string)
 {
-  memset (state, 0, sizeof (*state));
-  state->string = string;
+  memset (this, 0, sizeof (*this));
+  m_string = string;
 }
 
 /* See documentation in cli-utils.h.  */
 
 int
-get_number_or_range (struct get_number_or_range_state *state)
+number_or_range_parser::get_next ()
 {
-  if (state->in_range)
+  if (m_in_range)
     {
       /* All number-parsing has already been done.  Return the next
 	 integer value (one greater than the saved previous value).
 	 Do not advance the token pointer until the end of range is
 	 reached.  */
 
-      if (++state->last_retval == state->end_value)
+      if (++m_last_retval == m_end_value)
 	{
 	  /* End of range reached; advance token pointer.  */
-	  state->string = state->end_ptr;
-	  state->in_range = 0;
+	  m_string = m_end_ptr;
+	  m_in_range = false;
 	}
     }
-  else if (*state->string != '-')
+  else if (*m_string != '-')
     {
       /* Default case: state->string is pointing either to a solo
 	 number, or to the first number of a range.  */
-      state->last_retval = get_number_trailer (&state->string, '-');
-      if (*state->string == '-')
+      m_last_retval = get_number_trailer (&m_string, '-');
+      if (*m_string == '-')
 	{
 	  const char **temp;
 
@@ -161,42 +167,42 @@ get_number_or_range (struct get_number_or_range_state *state)
 	     Skip the '-', parse and remember the second number,
 	     and also remember the end of the final token.  */
 
-	  temp = &state->end_ptr; 
-	  state->end_ptr = skip_spaces_const (state->string + 1);
-	  state->end_value = get_number_const (temp);
-	  if (state->end_value < state->last_retval) 
+	  temp = &m_end_ptr;
+	  m_end_ptr = skip_spaces_const (m_string + 1);
+	  m_end_value = get_number_const (temp);
+	  if (m_end_value < m_last_retval)
 	    {
 	      error (_("inverted range"));
 	    }
-	  else if (state->end_value == state->last_retval)
+	  else if (m_end_value == m_last_retval)
 	    {
 	      /* Degenerate range (number1 == number2).  Advance the
 		 token pointer so that the range will be treated as a
-		 single number.  */ 
-	      state->string = state->end_ptr;
+		 single number.  */
+	      m_string = m_end_ptr;
 	    }
 	  else
-	    state->in_range = 1;
+	    m_in_range = true;
 	}
     }
   else
     error (_("negative value"));
-  state->finished = *state->string == '\0';
-  return state->last_retval;
+  m_finished = *m_string == '\0';
+  return m_last_retval;
 }
 
 /* See documentation in cli-utils.h.  */
 
 void
-number_range_setup_range (struct get_number_or_range_state *state,
-			  int start_value, int end_value, const char *end_ptr)
+number_or_range_parser::setup_range (int start_value, int end_value,
+				     const char *end_ptr)
 {
   gdb_assert (start_value > 0);
 
-  state->in_range = 1;
-  state->end_ptr = end_ptr;
-  state->last_retval = start_value - 1;
-  state->end_value = end_value;
+  m_in_range = true;
+  m_end_ptr = end_ptr;
+  m_last_retval = start_value - 1;
+  m_end_value = end_value;
 }
 
 /* Accept a number and a string-form list of numbers such as is 
@@ -210,15 +216,13 @@ number_range_setup_range (struct get_number_or_range_state *state,
 int
 number_is_in_list (const char *list, int number)
 {
-  struct get_number_or_range_state state;
-
   if (list == NULL || *list == '\0')
     return 1;
 
-  init_number_or_range (&state, list);
-  while (!state.finished)
+  number_or_range_parser parser (list);
+  while (!parser.finished ())
     {
-      int gotnum = get_number_or_range (&state);
+      int gotnum = parser.get_next ();
 
       if (gotnum == 0)
 	error (_("Args must be numbers or '$' variables."));
diff --git a/gdb/cli/cli-utils.h b/gdb/cli/cli-utils.h
index a31fff5..41c3a58 100644
--- a/gdb/cli/cli-utils.h
+++ b/gdb/cli/cli-utils.h
@@ -39,65 +39,87 @@ extern int get_number_const (const char **);
 
 extern int get_number (char **);
 
-/* An object of this type is passed to get_number_or_range.  It must
-   be initialized by calling init_number_or_range.  This type is
-   defined here so that it can be stack-allocated, but all members
-   other than `finished' and `string' should be treated as opaque.  */
+/* Parse a number or a range.
+   A number will be of the form handled by get_number.
+   A range will be of the form <number1> - <number2>, and
+   will represent all the integers between number1 and number2,
+   inclusive.  */
 
-struct get_number_or_range_state
+class number_or_range_parser
 {
-  /* Non-zero if parsing has completed.  */
-  int finished;
+public:
+  /* Default construction.  Must call init before calling
+     get_next.  */
+  number_or_range_parser () {}
+
+  /* Calls init automatically.  */
+  number_or_range_parser (const char *string);
+
+  /* STRING is the string to be parsed.  */
+  void init (const char *string);
+
+  /* While processing a range, this fuction is called iteratively; At
+     each call it will return the next value in the range.
+
+     At the beginning of parsing a range, the char pointer
+     STATE->string will be advanced past <number1> and left pointing
+     at the '-' token.  Subsequent calls will not advance the pointer
+     until the range is completed.  The call that completes the range
+     will advance the pointer past <number2>.  */
+  int get_next ();
+
+  /* Setup internal state such that get_next() returns numbers in the
+     START_VALUE to END_VALUE range.  END_PTR is where the string is
+     advanced to when get_next() returns END_VALUE.  */
+  void setup_range (int start_value, int end_value,
+		    const char *end_ptr);
+
+  /* Returns true if parsing has completed.  */
+  bool finished ()
+  { return m_finished; }
+
+  /* Return the string being parsed.  When parsing has finished, this
+     points past the last parsed token.  */
+  const char *string ()
+  { return m_string; }
+
+  /* True when parsing a range.  */
+  bool in_range ()
+  { return m_in_range; }
+
+  /* When parsing a range, the final value in the range.  */
+  int end_value ()
+  { return m_end_value; }
+
+  /* When parsing a range, skip past the final token in the range.  */
+  void skip_range ()
+  {
+    gdb_assert (m_in_range);
+    m_string = m_end_ptr;
+  }
+
+private:
+  /* True if parsing has completed.  */
+  bool m_finished;
 
   /* The string being parsed.  When parsing has finished, this points
      past the last parsed token.  */
-  const char *string;
+  const char *m_string;
 
   /* Last value returned.  */
-  int last_retval;
+  int m_last_retval;
 
   /* When parsing a range, the final value in the range.  */
-  int end_value;
+  int m_end_value;
 
   /* When parsing a range, a pointer past the final token in the
      range.  */
-  const char *end_ptr;
+  const char *m_end_ptr;
 
-  /* Non-zero when parsing a range.  */
-  int in_range;
+  /* True when parsing a range.  */
+  bool m_in_range;
 };
 
-/* Initialize a get_number_or_range_state for use with
-   get_number_or_range_state.  STRING is the string to be parsed.  */
-
-extern void init_number_or_range (struct get_number_or_range_state *state,
-				  const char *string);
-
-/* Parse a number or a range.
-   A number will be of the form handled by get_number.
-   A range will be of the form <number1> - <number2>, and 
-   will represent all the integers between number1 and number2,
-   inclusive.
-
-   While processing a range, this fuction is called iteratively;
-   At each call it will return the next value in the range.
-
-   At the beginning of parsing a range, the char pointer STATE->string will
-   be advanced past <number1> and left pointing at the '-' token.
-   Subsequent calls will not advance the pointer until the range
-   is completed.  The call that completes the range will advance
-   the pointer past <number2>.  */
-
-extern int get_number_or_range (struct get_number_or_range_state *state);
-
-/* Setups STATE such that get_number_or_range returns numbers in range
-   START_VALUE to END_VALUE.  When get_number_or_range returns
-   END_VALUE, the STATE string is advanced to END_PTR.  */
-
-extern void number_range_setup_range (struct get_number_or_range_state *state,
-				      int start_value, int end_value,
-				      const char *end_ptr);
-
 /* Accept a number and a string-form list of numbers such as is 
    accepted by get_number_or_range.  Return TRUE if the number is
    in the list.
diff --git a/gdb/inferior.c b/gdb/inferior.c
index 47d91c7..4f590a5 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -633,17 +633,15 @@ print_inferior (struct ui_out *uiout, char *requested_inferiors)
 static void
 detach_inferior_command (char *args, int from_tty)
 {
-  int num, pid;
   struct thread_info *tp;
-  struct get_number_or_range_state state;
 
   if (!args || !*args)
     error (_("Requires argument (inferior id(s) to detach)"));
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      num = get_number_or_range (&state);
+      int num = parser.get_next ();
 
       if (!valid_gdb_inferior_id (num))
 	{
@@ -651,7 +649,7 @@ detach_inferior_command (char *args, int from_tty)
 	  continue;
 	}
 
-      pid = gdb_inferior_id_to_pid (num);
+      int pid = gdb_inferior_id_to_pid (num);
       if (pid == 0)
 	{
 	  warning (_("Inferior ID %d is not running."), num);
@@ -674,17 +672,15 @@ detach_inferior_command (char *args, int from_tty)
 static void
 kill_inferior_command (char *args, int from_tty)
 {
-  int num, pid;
   struct thread_info *tp;
-  struct get_number_or_range_state state;
 
   if (!args || !*args)
     error (_("Requires argument (inferior id(s) to kill)"));
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      num = get_number_or_range (&state);
+      int num = parser.get_next ();
 
       if (!valid_gdb_inferior_id (num))
 	{
@@ -692,7 +688,7 @@ kill_inferior_command (char *args, int from_tty)
 	  continue;
 	}
 
-      pid = gdb_inferior_id_to_pid (num);
+      int pid = gdb_inferior_id_to_pid (num);
       if (pid == 0)
 	{
 	  warning (_("Inferior ID %d is not running."), num);
@@ -782,18 +778,14 @@ info_inferiors_command (char *args, int from_tty)
 static void
 remove_inferior_command (char *args, int from_tty)
 {
-  int num;
-  struct inferior *inf;
-  struct get_number_or_range_state state;
-
   if (args == NULL || *args == '\0')
     error (_("Requires an argument (inferior id(s) to remove)"));
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      num = get_number_or_range (&state);
-      inf = find_inferior_id (num);
+      int num = parser.get_next ();
+      struct inferior *inf = find_inferior_id (num);
 
       if (inf == NULL)
 	{
diff --git a/gdb/linespec.c b/gdb/linespec.c
index ccedec8..7b1a77e 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -1328,7 +1328,6 @@ decode_line_2 (struct linespec_state *self,
   int i;
   struct cleanup *old_chain;
   VEC (const_char_ptr) *filters = NULL;
-  struct get_number_or_range_state state;
   struct decode_line_2_item *items;
   int items_count;
 
@@ -1409,12 +1408,10 @@ decode_line_2 (struct linespec_state *self,
   if (args == 0 || *args == 0)
     error_no_arg (_("one or more choice numbers"));
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      int num;
-
-      num = get_number_or_range (&state);
+      int num = parser.get_next ();
 
       if (num == 0)
 	error (_("canceled"));
diff --git a/gdb/memattr.c b/gdb/memattr.c
index c4a3b75..a33993a 100644
--- a/gdb/memattr.c
+++ b/gdb/memattr.c
@@ -578,12 +578,10 @@ mem_enable_command (char *args, int from_tty)
     }
   else
     {
-      struct get_number_or_range_state state;
-
-      init_number_or_range (&state, args);
-      while (!state.finished)
+      number_or_range_parser parser (args);
+      while (!parser.finished ())
 	{
-	  num = get_number_or_range (&state);
+	  num = parser.get_next ();
 	  mem_enable (num);
 	}
     }
@@ -610,27 +608,24 @@ mem_disable (int num)
 static void
 mem_disable_command (char *args, int from_tty)
 {
-  int num;
-  struct mem_region *m;
-  int ix;
-
   require_user_regions (from_tty);
 
   target_dcache_invalidate ();
 
   if (args == NULL || *args == '\0')
     {
+      struct mem_region *m;
+      int ix;
+
       for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
 	m->enabled_p = 0;
     }
   else
     {
-      struct get_number_or_range_state state;
-
-      init_number_or_range (&state, args);
-      while (!state.finished)
+      number_or_range_parser parser (args);
+      while (!parser.finished ())
 	{
-	  num = get_number_or_range (&state);
+	  int num = parser.get_next ();
 	  mem_disable (num);
 	}
     }
@@ -666,9 +661,6 @@ mem_delete (int num)
 static void
 mem_delete_command (char *args, int from_tty)
 {
-  int num;
-  struct get_number_or_range_state state;
-
   require_user_regions (from_tty);
 
   target_dcache_invalidate ();
@@ -681,10 +673,10 @@ mem_delete_command (char *args, int from_tty)
       return;
     }
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      num = get_number_or_range (&state);
+      int num = parser.get_next ();
       mem_delete (num);
     }
 
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index d4a4b9e..15f2395 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1876,19 +1876,18 @@ map_display_numbers (char *args,
 				       void *),
 		     void *data)
 {
-  struct get_number_or_range_state state;
   int num;
 
   if (args == NULL)
     error_no_arg (_("one or more display numbers"));
 
-  init_number_or_range (&state, args);
+  number_or_range_parser parser (args);
 
-  while (!state.finished)
+  while (!parser.finished ())
     {
-      const char *p = state.string;
+      const char *p = parser.string ();
 
-      num = get_number_or_range (&state);
+      num = parser.get_next ();
       if (num == 0)
 	warning (_("bad display number at or near '%s'"), p);
       else
diff --git a/gdb/reverse.c b/gdb/reverse.c
index a1b697f..461d1a4 100644
--- a/gdb/reverse.c
+++ b/gdb/reverse.c
@@ -216,9 +216,6 @@ delete_all_bookmarks (void)
 static void
 delete_bookmark_command (char *args, int from_tty)
 {
-  int num;
-  struct get_number_or_range_state state;
-
   if (bookmark_chain == NULL)
     {
       warning (_("No bookmarks."));
@@ -233,10 +230,10 @@ delete_bookmark_command (char *args, int from_tty)
       return;
     }
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      num = get_number_or_range (&state);
+      int num = parser.get_next ();
       if (!delete_one_bookmark (num))
 	/* Not found.  */
 	warning (_("No bookmark #%d."), num);
@@ -323,20 +320,16 @@ bookmark_1 (int bnum)
 static void
 bookmarks_info (char *args, int from_tty)
 {
-  int bnum = -1;
-
   if (!bookmark_chain)
     printf_filtered (_("No bookmarks.\n"));
   else if (args == NULL || *args == '\0')
     bookmark_1 (-1);
   else
     {
-      struct get_number_or_range_state state;
-
-      init_number_or_range (&state, args);
-      while (!state.finished)
+      number_or_range_parser parser (args);
+      while (!parser.finished ())
 	{
-	  bnum = get_number_or_range (&state);
+	  int bnum = parser.get_next ();
 	  bookmark_1 (bnum);
 	}
     }
diff --git a/gdb/thread.c b/gdb/thread.c
index a66a2b5..0febb42 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1825,20 +1825,19 @@ thread_apply_command (char *tidlist, int from_tty)
   char *cmd = NULL;
   struct cleanup *old_chain;
   char *saved_cmd;
-  struct tid_range_parser parser;
+  tid_range_parser parser;
 
   if (tidlist == NULL || *tidlist == '\000')
     error (_("Please specify a thread ID list"));
 
-  tid_range_parser_init (&parser, tidlist, current_inferior ()->num);
-  while (!tid_range_parser_finished (&parser))
+  parser.init (tidlist, current_inferior ()->num);
+  while (!parser.finished ())
     {
       int inf_num, thr_start, thr_end;
 
-      if (!tid_range_parser_get_tid_range (&parser,
-					   &inf_num, &thr_start, &thr_end))
+      if (!parser.get_tid_range (&inf_num, &thr_start, &thr_end))
 	{
-	  cmd = (char *) tid_range_parser_string (&parser);
+	  cmd = (char *) parser.string ();
 	  break;
 	}
     }
@@ -1856,32 +1855,31 @@ thread_apply_command (char *tidlist, int from_tty)
 
   make_cleanup_restore_current_thread ();
 
-  tid_range_parser_init (&parser, tidlist, current_inferior ()->num);
-  while (!tid_range_parser_finished (&parser)
-	 && tid_range_parser_string (&parser) < cmd)
+  parser.init (tidlist, current_inferior ()->num);
+  while (!parser.finished () && parser.string () < cmd)
     {
       struct thread_info *tp = NULL;
       struct inferior *inf;
       int inf_num, thr_num;
 
-      tid_range_parser_get_tid (&parser, &inf_num, &thr_num);
+      parser.get_tid (&inf_num, &thr_num);
       inf = find_inferior_id (inf_num);
       if (inf != NULL)
 	tp = find_thread_id (inf, thr_num);
 
-      if (tid_range_parser_star_range (&parser))
+      if (parser.star_range ())
 	{
 	  if (inf == NULL)
 	    {
 	      warning (_("Unknown inferior %d"), inf_num);
-	      tid_range_parser_skip (&parser);
+	      parser.skip_range ();
 	      continue;
 	    }
 
 	  /* No use looking for threads past the highest thread number
 	     the inferior ever had.  */
 	  if (thr_num >= inf->highest_thread_num)
-	    tid_range_parser_skip (&parser);
+	    parser.skip_range ();
 
 	  /* Be quiet about unknown threads numbers.  */
 	  if (tp == NULL)
@@ -1891,7 +1889,7 @@ thread_apply_command (char *tidlist, int from_tty)
       if (tp == NULL)
 	{
 	  if (show_inferior_qualified_tids ()
-	      || tid_range_parser_qualified (&parser))
+	      || parser.qualified ())
 	    warning (_("Unknown thread %d.%d"), inf_num, thr_num);
 	  else
 	    warning (_("Unknown thread %d"), thr_num);
diff --git a/gdb/tid-parse.c b/gdb/tid-parse.c
index 68133c6..9e49eba 100644
--- a/gdb/tid-parse.c
+++ b/gdb/tid-parse.c
@@ -113,29 +113,36 @@ parse_thread_id (const char *tidstr, const char **end)
 
 /* See tid-parse.h.  */
 
+tid_range_parser::tid_range_parser (const char *tidlist,
+				    int default_inferior)
+{
+  init (tidlist, default_inferior);
+}
+
+/* See tid-parse.h.  */
+
 void
-tid_range_parser_init (struct tid_range_parser *parser, const char *tidlist,
-		       int default_inferior)
+tid_range_parser::init (const char *tidlist, int default_inferior)
 {
-  parser->state = TID_RANGE_STATE_INFERIOR;
-  parser->string = tidlist;
-  parser->inf_num = 0;
-  parser->qualified = 0;
-  parser->default_inferior = default_inferior;
+  m_state = STATE_INFERIOR;
+  m_string = tidlist;
+  m_inf_num = 0;
+  m_qualified = 0;
+  m_default_inferior = default_inferior;
 }
 
 /* See tid-parse.h.  */
 
-int
-tid_range_parser_finished (struct tid_range_parser *parser)
+bool
+tid_range_parser::finished ()
 {
-  switch (parser->state)
+  switch (m_state)
     {
-    case TID_RANGE_STATE_INFERIOR:
-      return *parser->string == '\0';
-    case TID_RANGE_STATE_THREAD_RANGE:
-    case TID_RANGE_STATE_STAR_RANGE:
-      return parser->range_parser.finished;
+    case STATE_INFERIOR:
+      return *m_string == '\0';
+    case STATE_THREAD_RANGE:
+    case STATE_STAR_RANGE:
+      return m_range_parser.finished ();
     }
 
   gdb_assert_not_reached (_("unhandled state"));
@@ -144,57 +151,54 @@ tid_range_parser_finished (struct tid_range_parser *parser)
 /* See tid-parse.h.  */
 
 const char *
-tid_range_parser_string (struct tid_range_parser *parser)
+tid_range_parser::string ()
 {
-  switch (parser->state)
+  switch (m_state)
     {
-    case TID_RANGE_STATE_INFERIOR:
-      return parser->string;
-    case TID_RANGE_STATE_THREAD_RANGE:
-    case TID_RANGE_STATE_STAR_RANGE:
-      return parser->range_parser.string;
+    case STATE_INFERIOR:
+      return m_string;
+    case STATE_THREAD_RANGE:
+    case STATE_STAR_RANGE:
+      return m_range_parser.string ();
     }
 
   gdb_assert_not_reached (_("unhandled state"));
 }
 
-/* See tid-parse.h.  */
-
 void
-tid_range_parser_skip (struct tid_range_parser *parser)
+tid_range_parser::skip_range ()
 {
-  gdb_assert ((parser->state == TID_RANGE_STATE_THREAD_RANGE
-	       || parser->state == TID_RANGE_STATE_STAR_RANGE)
-	      && parser->range_parser.in_range);
+  gdb_assert (m_state == STATE_THREAD_RANGE
+	      || m_state == STATE_STAR_RANGE);
 
-  tid_range_parser_init (parser, parser->range_parser.end_ptr,
-			 parser->default_inferior);
+  m_range_parser.skip_range ();
+  init (m_range_parser.string (), m_default_inferior);
 }
 
 /* See tid-parse.h.  */
 
-int
-tid_range_parser_qualified (struct tid_range_parser *parser)
+bool
+tid_range_parser::qualified ()
 {
-  return parser->qualified;
+  return m_qualified;
 }
 
-/* Helper for tid_range_parser_get_tid and
-   tid_range_parser_get_tid_range.  Return the next range if THR_END
+/* Helper for tid_range_parser::get_tid and
+   tid_range_parser::get_tid_range.  Return the next range if THR_END
    is non-NULL, return a single thread ID otherwise.  */
 
-static int
-get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
-		  int *thr_start, int *thr_end)
+bool
+tid_range_parser::get_tid_or_range (int *inf_num,
+				    int *thr_start, int *thr_end)
 {
-  if (parser->state == TID_RANGE_STATE_INFERIOR)
+  if (m_state == STATE_INFERIOR)
     {
       const char *p;
       const char *space;
 
-      space = skip_to_space (parser->string);
+      space = skip_to_space (m_string);
 
-      p = parser->string;
+      p = m_string;
       while (p < space && *p != '.')
 	p++;
       if (p < space)
@@ -202,56 +206,53 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
 	  const char *dot = p;
 
 	  /* Parse number to the left of the dot.  */
-	  p = parser->string;
-	  parser->inf_num
-	    = get_positive_number_trailer (&p, '.', parser->string);
-	  if (parser->inf_num == 0)
+	  p = m_string;
+	  m_inf_num = get_positive_number_trailer (&p, '.', m_string);
+	  if (m_inf_num == 0)
 	    return 0;
 
-	  parser->qualified = 1;
+	  m_qualified = true;
 	  p = dot + 1;
 
 	  if (isspace (*p))
-	    return 0;
+	    return false;
 	}
       else
 	{
-	  parser->inf_num = parser->default_inferior;
-	  parser->qualified = 0;
-	  p = parser->string;
+	  m_inf_num = m_default_inferior;
+	  m_qualified = false;
+	  p = m_string;
 	}
 
-      init_number_or_range (&parser->range_parser, p);
+      m_range_parser.init (p);
       if (p[0] == '*' && (p[1] == '\0' || isspace (p[1])))
 	{
 	  /* Setup the number range parser to return numbers in the
 	     whole [1,INT_MAX] range.  */
-	  number_range_setup_range (&parser->range_parser, 1, INT_MAX,
-				    skip_spaces_const (p + 1));
-	  parser->state = TID_RANGE_STATE_STAR_RANGE;
+	  m_range_parser.setup_range (1, INT_MAX, skip_spaces_const (p + 1));
+	  m_state = STATE_STAR_RANGE;
 	}
       else
-	parser->state = TID_RANGE_STATE_THREAD_RANGE;
+	m_state = STATE_THREAD_RANGE;
     }
 
-  *inf_num = parser->inf_num;
-  *thr_start = get_number_or_range (&parser->range_parser);
+  *inf_num = m_inf_num;
+  *thr_start = m_range_parser.get_next ();
   if (*thr_start < 0)
-    error (_("negative value: %s"), parser->string);
+    error (_("negative value: %s"), m_string);
   if (*thr_start == 0)
     {
-      parser->state = TID_RANGE_STATE_INFERIOR;
-      return 0;
+      m_state = STATE_INFERIOR;
+      return false;
     }
 
   /* If we successfully parsed a thread number or finished parsing a
      thread range, switch back to assuming the next TID is
      inferior-qualified.  */
-  if (parser->range_parser.end_ptr == NULL
-      || parser->range_parser.string == parser->range_parser.end_ptr)
+  if (!m_range_parser.in_range ())
     {
-      parser->state = TID_RANGE_STATE_INFERIOR;
-      parser->string = parser->range_parser.string;
+      m_state = STATE_INFERIOR;
+      m_string = m_range_parser.string ();
 
       if (thr_end != NULL)
 	*thr_end = *thr_start;
@@ -260,11 +261,12 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
   /* If we're midway through a range, and the caller wants the end
      value, return it and skip to the end of the range.  */
   if (thr_end != NULL
-      && (parser->state == TID_RANGE_STATE_THREAD_RANGE
-	  || parser->state == TID_RANGE_STATE_STAR_RANGE))
+      && (m_state == STATE_THREAD_RANGE
+	  || m_state == STATE_STAR_RANGE))
     {
-      *thr_end = parser->range_parser.end_value;
-      tid_range_parser_skip (parser);
+      *thr_end = m_range_parser.end_value ();
+
+      skip_range ();
     }
 
   return (*inf_num != 0 && *thr_start != 0);
@@ -272,32 +274,31 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
 
 /* See tid-parse.h.  */
 
-int
-tid_range_parser_get_tid_range (struct tid_range_parser *parser, int *inf_num,
-				int *thr_start, int *thr_end)
+bool
+tid_range_parser::get_tid_range (int *inf_num,
+				 int *thr_start, int *thr_end)
 {
   gdb_assert (inf_num != NULL && thr_start != NULL && thr_end != NULL);
 
-  return get_tid_or_range (parser, inf_num, thr_start, thr_end);
+  return get_tid_or_range (inf_num, thr_start, thr_end);
 }
 
 /* See tid-parse.h.  */
 
-int
-tid_range_parser_get_tid (struct tid_range_parser *parser,
-			  int *inf_num, int *thr_num)
+bool
+tid_range_parser::get_tid (int *inf_num, int *thr_num)
 {
   gdb_assert (inf_num != NULL && thr_num != NULL);
 
-  return get_tid_or_range (parser, inf_num, thr_num, NULL);
+  return get_tid_or_range (inf_num, thr_num, NULL);
 }
 
 /* See tid-parse.h.  */
 
-int
-tid_range_parser_star_range (struct tid_range_parser *parser)
+bool
+tid_range_parser::star_range ()
 {
-  return parser->state == TID_RANGE_STATE_STAR_RANGE;
+  return m_state == STATE_STAR_RANGE;
 }
 
 /* See gdbthread.h.  */
@@ -306,19 +307,16 @@ int
 tid_is_in_list (const char *list, int default_inferior,
 		int inf_num, int thr_num)
 {
-  struct tid_range_parser parser;
-
   if (list == NULL || *list == '\0')
     return 1;
 
-  tid_range_parser_init (&parser, list, default_inferior);
-  while (!tid_range_parser_finished (&parser))
+  tid_range_parser parser (list, default_inferior);
+  while (!parser.finished ())
     {
       int tmp_inf, tmp_thr_start, tmp_thr_end;
 
-      if (!tid_range_parser_get_tid_range (&parser, &tmp_inf,
-					   &tmp_thr_start, &tmp_thr_end))
-	invalid_thread_id_error (parser.string);
+      if (!parser.get_tid_range (&tmp_inf, &tmp_thr_start, &tmp_thr_end))
+	invalid_thread_id_error (parser.string ());
       if (tmp_inf == inf_num
 	  && tmp_thr_start <= thr_num && thr_num <= tmp_thr_end)
 	return 1;
diff --git a/gdb/tid-parse.h b/gdb/tid-parse.h
index 830cf36..764facc 100644
--- a/gdb/tid-parse.h
+++ b/gdb/tid-parse.h
@@ -36,56 +36,6 @@ extern void ATTRIBUTE_NORETURN invalid_thread_id_error (const char *string);
    thrown.  */
 struct thread_info *parse_thread_id (const char *tidstr, const char **end);
 
-/* The possible states of the tid range parser's state machine.  */
-enum tid_range_state
-{
-  /* Parsing the inferior number.  */
-  TID_RANGE_STATE_INFERIOR,
-
-  /* Parsing the thread number or thread number range.  */
-  TID_RANGE_STATE_THREAD_RANGE,
-
-  /* Parsing a star wildcard thread range.  E.g., "1.*".  */
-  TID_RANGE_STATE_STAR_RANGE,
-};
-
-/* An object of this type is passed to tid_range_parser_get_tid.  It
-   must be initialized by calling tid_range_parser_init.  This type is
-   defined here so that it can be stack-allocated, but all members
-   should be treated as opaque.  */
-struct tid_range_parser
-{
-  /* What sub-component are we expecting.  */
-  enum tid_range_state state;
-
-  /* The string being parsed.  When parsing has finished, this points
-     past the last parsed token.  */
-  const char *string;
-
-  /* The range parser state when we're parsing the thread number
-     sub-component.  */
-  struct get_number_or_range_state range_parser;
-
-  /* Last inferior number returned.  */
-  int inf_num;
-
-  /* True if the TID last parsed was explicitly inferior-qualified.
-     IOW, whether the spec specified an inferior number
-     explicitly.  */
-  int qualified;
-
-  /* The inferior number to assume if the TID is not qualified.  */
-  int default_inferior;
-};
-
-/* Initialize a tid_range_parser for use with
-   tid_range_parser_get_tid.  TIDLIST is the string to be parsed.
-   DEFAULT_INFERIOR is the inferior number to assume if a
-   non-qualified thread ID is found.  */
-extern void tid_range_parser_init (struct tid_range_parser *parser,
-				   const char *tidlist,
-				   int default_inferior);
-
 /* Parse a thread ID or a thread range list.
 
    A range will be of the form
@@ -99,69 +49,122 @@ extern void tid_range_parser_init (struct tid_range_parser *parser,
      <thread_number1>-<thread_number2>
 
    in which case GDB infers the inferior number from the default
-   passed to the tid_range_parser_init function.
+   passed to the constructor or to the last call to the init
+   function.  */
+class tid_range_parser
+{
+public:
+  /* Default construction.  Must call init before calling get_*.  */
+  tid_range_parser () {}
 
-   This function is designed to be called iteratively.  While
-   processing a thread ID range list, at each call it will return (in
-   the INF_NUM and THR_NUM output parameters) the next thread ID in
-   the range (irrespective of whether the thread actually exists).
+  /* Calls init automatically.  */
+  tid_range_parser (const char *tidlist, int default_inferior);
 
-   At the beginning of parsing a thread range, the char pointer
-   PARSER->string will be advanced past <thread_number1> and left
-   pointing at the '-' token.  Subsequent calls will not advance the
-   pointer until the range is completed.  The call that completes the
-   range will advance the pointer past <thread_number2>.
+  /* Reinitialize a tid_range_parser.  TIDLIST is the string to be
+     parsed.  DEFAULT_INFERIOR is the inferior number to assume if a
+     non-qualified thread ID is found.  */
+  void init (const char *tidlist, int default_inferior);
 
-   This function advances through the input string for as long you
-   call it.  Once the end of the input string is reached, a call to
-   tid_range_parser_finished returns false (see below).
+  /* Parse a thread ID or a thread range list.
 
-   E.g., with list: "1.2 3.4-6":
+     This function is designed to be called iteratively.  While
+     processing a thread ID range list, at each call it will return
+     (in the INF_NUM and THR_NUM output parameters) the next thread ID
+     in the range (irrespective of whether the thread actually
+     exists).
+
+     At the beginning of parsing a thread range, the char pointer
+     PARSER->string will be advanced past <thread_number1> and left
+     pointing at the '-' token.  Subsequent calls will not advance the
+     pointer until the range is completed.  The call that completes
+     the range will advance the pointer past <thread_number2>.
+
+     This function advances through the input string for as long you
+     call it.  Once the end of the input string is reached, a call to
+     finished returns false (see below).
+
+     E.g., with list: "1.2 3.4-6":
 
      1st call: *INF_NUM=1; *THR_NUM=2 (finished==0)
      2nd call: *INF_NUM=3; *THR_NUM=4 (finished==0)
      3rd call: *INF_NUM=3; *THR_NUM=5 (finished==0)
      4th call: *INF_NUM=3; *THR_NUM=6 (finished==1)
 
-   Returns true if parsed a thread/range successfully, false
-   otherwise.  */
-extern int tid_range_parser_get_tid (struct tid_range_parser *parser,
-				      int *inf_num, int *thr_num);
+     Returns true if a thread/range is parsed successfully, false
+     otherwise.  */
+  bool get_tid (int *inf_num, int *thr_num);
 
-/* Like tid_range_parser_get_tid, but return a thread ID range per
-   call, rather then a single thread ID.
+  /* Like get_tid, but return a thread ID range per call, rather then
+     a single thread ID.
 
-   If the next element in the list is a single thread ID, then
-   *THR_START and *THR_END are set to the same value.
+     If the next element in the list is a single thread ID, then
+     *THR_START and *THR_END are set to the same value.
 
-   E.g.,. with list: "1.2 3.4-6"
+     E.g.,. with list: "1.2 3.4-6"
 
      1st call: *INF_NUM=1; *THR_START=2; *THR_END=2 (finished==0)
      2nd call: *INF_NUM=3; *THR_START=4; *THR_END=6 (finished==1)
 
-   Returns true if parsed a thread/range successfully, false
-   otherwise.  */
-extern int tid_range_parser_get_tid_range (struct tid_range_parser *parser,
-					   int *inf_num,
-					   int *thr_start, int *thr_end);
+     Returns true if parsed a thread/range successfully, false
+     otherwise.  */
+  bool get_tid_range (int *inf_num, int *thr_start, int *thr_end);
 
-/* Returns non-zero if processing a star wildcard (e.g., "1.*")
-   range.  */
-extern int tid_range_parser_star_range (struct tid_range_parser *parser);
+  /* Returns true if processing a star wildcard (e.g., "1.*")
+     range.  */
+  bool star_range ();
 
-/* Returns non-zero if parsing has completed.  */
-extern int tid_range_parser_finished (struct tid_range_parser *parser);
+  /* Returns true if parsing has completed.  */
+  bool finished ();
 
-/* Return the string being parsed.  When parsing has finished, this
-   points past the last parsed token.  */
-const char *tid_range_parser_string (struct tid_range_parser *parser);
+  /* Return the string being parsed.  When parsing has finished, this
+     points past the last parsed token.  */
+  const char *string ();
 
-/* When parsing a range, advance past the final token in the range.  */
-extern void tid_range_parser_skip (struct tid_range_parser *parser);
+  /* When parsing a range, advance past the final token in the
+     range.  */
+  void skip_range ();
 
 /* True if the TID last parsed was explicitly inferior-qualified.
    IOW, whether the spec specified an inferior number explicitly.  */
-extern int tid_range_parser_qualified (struct tid_range_parser *parser);
+  bool qualified ();
+
+private:
+  bool get_tid_or_range (int *inf_num, int *thr_start, int *thr_end);
+
+  /* The possible states of the tid range parser's state machine,
+     indicating what sub-component are we parsing.  */
+  enum
+    {
+      /* Parsing the inferior number.  */
+      STATE_INFERIOR,
+
+      /* Parsing the thread number or thread number range.  */
+      STATE_THREAD_RANGE,
+
+      /* Parsing a star wildcard thread range.  E.g., "1.*".  */
+      STATE_STAR_RANGE,
+    } m_state;
+
+  /* The string being parsed.  When parsing has finished, this points
+     past the last parsed token.  */
+  const char *m_string;
+
+  /* The range parser state when we're parsing the thread number
+     sub-component.  */
+  number_or_range_parser m_range_parser;
+
+  /* Last inferior number returned.  */
+  int m_inf_num;
+
+  /* True if the TID last parsed was explicitly inferior-qualified.
+     IOW, whether the spec specified an inferior number
+     explicitly.  */
+  bool m_qualified;
+
+  /* The inferior number to assume if the TID is not qualified.  */
+  int m_default_inferior;
+};
+
 
 /* Accept a string-form list of thread IDs such as is accepted by
    tid_range_parser_get_tid.  Return true if the INF_NUM.THR.NUM
-- 
2.5.5


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

* Re: [RFA 17/22] Remove make_cleanup_restore_current_uiout
  2016-09-29 15:23     ` Tom Tromey
  2016-09-29 17:55       ` Simon Marchi
@ 2016-09-30  2:45       ` Pedro Alves
  2016-09-30 23:48         ` Tom Tromey
  1 sibling, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-09-30  2:45 UTC (permalink / raw)
  To: Tom Tromey, Trevor Saunders; +Cc: gdb-patches

On 09/29/2016 03:05 PM, Tom Tromey wrote:
>>>>>> "Trevor" == Trevor Saunders <tbsaunde@tbsaunde.org> writes:
> 
> Trevor> isn't this just scoped_restore<ui_out *> ? why do you need a separate
> Trevor> class?
> 
> In an earlier thread there was a discussion of not having this cleanup
> be over-general -- that is, it was intentionally specific to just
> current_uiout.

how about:

struct scoped_restore_current_uiout : public scoped_restore<ui_out *>
{
  scoped_restore_current_uiout ()
    : scoped_restore (&current_uiout)
  {}
};

?

Thanks,
Pedro Alves

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-09-30  1:40     ` Pedro Alves
@ 2016-09-30  9:22       ` Pedro Alves
  2016-09-30 15:00       ` Tom Tromey
  2016-09-30 15:44       ` Tom Tromey
  2 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-09-30  9:22 UTC (permalink / raw)
  To: Trevor Saunders, Tom Tromey; +Cc: gdb-patches

On 09/30/2016 02:17 AM, Pedro Alves wrote:
> On 09/27/2016 09:59 AM, Trevor Saunders wrote:
> 
>>> I had hoped that template parameter deduction would work here, but it
>>> did not, and so the patch uses explicit template parameters
>>> everywhere.
>>
>> yeah, you can't deduce template args from a constructor in C++
> 
> I don't know whether the trick below is usual, 

Looks like it is -- Andrei Alexandrescu's ScopeGuard uses the
same trick:

  http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758

Thanks,
Pedro Alves

> but you can work
> around that and end up with no-template-args-in-sight usage
> like this:
> 
> void
> foo ()
> {
>   scoped_restore scope = make_scoped_restore (&some_global);
> 
>   ...
> }
> 
> You'd do something like this:
> 
> 
> struct scoped_restore_base {};
> 
> template<typename T>
> class scoped_restore_ : public scoped_restore_base
> {
>  public:
> ...
>   explicit scoped_restore (T *var)
>     : saved_var (var),
>       saved_value (*var)
>   {}
> 
>   ~scoped_restore ()
>   {
>     *saved_var = saved_value;
>   }
> 
>  private:
>   scoped_restore &operator= (const scoped_restore &rhs);
> 
>   // The saved variable.
>   T *saved_var;
> 
>   // The saved value.
>   T saved_value;
> };
> 
> typedef const scoped_restore_base &scoped_restore;
> 
> template<class T>
> scoped_restore_<T> make_scoped_restore (T *var)
> {
>   return scoped_restore_<T> (var);
> }
> 
> The trick is making scoped_restore_ inherit a non-template
> class, and make "scoped_restore" a typedef for a const reference
> to the base class, since a const reference can bind to the
> temporary that is returned by make_scoped_restore, and it
> extends the temporary's lifetime.
> 
> While copy elision / RVO makes it so that the temporary returned by
> value from make_scoped_restore is constructed directly in the caller
> instead of constructed and then copied out, you still have to
> provide the copy constructor, instead of "deleting" it as in your
> original patch.  Copy elision was optional until C++17, but I
> believe all compilers worth their salt implement it.  And if a compiler
> doesn't implement it, it's not a real issue, anyway, the code
> still works.
> 
> The downside is that printing a scoped_restore object from
> gdb will just print the reference using the base type, so you
> won't see stored fields.
> 
> (gdb) p scope
> $1 = (const scoped_restore) @0x7fffffffd910: {<No data fields>}
> 
> To see the object's fields you'd have to downcast it manually, like:
> 
> (gdb) p (scoped_restore_<ui_out *>) scope
> $1 = {<scoped_restore_base> = {<No data fields>}, saved_var = 0x601050 <current_uiout>, saved_value = 0x0}
> 
> Not sure whether that's an issue.
> 
> Thanks,
> Pedro Alves
> 


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

* Re: [RFA 01/22] Change selttest.c to use use std::vector
  2016-09-27  4:48 ` [RFA 01/22] Change selttest.c to use use std::vector Tom Tromey
  2016-09-27  8:50   ` Trevor Saunders
@ 2016-09-30 14:43   ` Simon Marchi
  2016-09-30 21:40     ` Tom Tromey
  1 sibling, 1 reply; 123+ messages in thread
From: Simon Marchi @ 2016-09-30 14:43 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 2016-09-27 00:08, Tom Tromey wrote:
> -  printf_filtered (_("Ran %u unit tests, %d failed\n"),
> -		   VEC_length (self_test_function_ptr, tests), failed);
> +  printf_filtered (_("Ran %lu unit tests, %d failed\n"),
> +		   tests.size (), failed);

This doesn't build on 32 bits:

selftest.c: In function ‘void run_self_tests()’:
selftest.c:62:27: error: format ‘%lu’ expects argument of type ‘long 
unsigned int’, but argument 2 has type ‘std::vector<void 
(*)()>::size_type {aka unsigned int}’ [-Werror=format=]
       tests.size (), failed);
                            ^
I think the right format size specifier would be 'z'.

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

* Re: [RFA 19/22] Convert tid_range_parser to class
  2016-09-30  1:41   ` Pedro Alves
@ 2016-09-30 14:52     ` Tom Tromey
       [not found]       ` <926126cb-b3c5-340b-ac1c-5bc14ca41bf9@redhat.com>
  0 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-30 14:52 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> Whoops, we ended up duplicating work here.

Oops :) But no big deal.

Pedro> Additional differences compared to yours are:
Pedro> - "bool" instead of "int".
Pedro> - "m_" prefixes.

Aha, the m_ prefix.  Cancel that earlier question...

Pedro> Let me know what you think.  It's super fine with me to rebase
Pedro> mine on top of yours.  Did you have a follow up patch for
Pedro> get_number_or_range too, perhaps?

I don't.  How about I just drop my patch?  That seems simplest to me.

Pedro>  void
Pedro> -init_number_or_range (struct get_number_or_range_state *state,
Pedro> -		      const char *string)
Pedro> +number_or_range_parser::init (const char *string)
Pedro>  {
Pedro> -  memset (state, 0, sizeof (*state));
Pedro> -  state->string = string;
Pedro> +  memset (this, 0, sizeof (*this));

I think it's better to do explicit initialization.
This will bite if this class ever is changed to have a vtable (unlikely
but it's better, IMO, to set a good example).

Tom

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-09-30  1:40     ` Pedro Alves
  2016-09-30  9:22       ` Pedro Alves
@ 2016-09-30 15:00       ` Tom Tromey
  2016-09-30 23:50         ` Pedro Alves
  2016-09-30 15:44       ` Tom Tromey
  2 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-30 15:00 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Trevor Saunders, Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> template<class T>
Pedro> scoped_restore_<T> make_scoped_restore (T *var)
Pedro> {
Pedro>   return scoped_restore_<T> (var);
Pedro> }

Yeah, I'll do this.  I don't know why I didn't remember this when
writing the patches.

I'd also appreciate it if you could say whether you want "m_" member
naming.

Tom

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-09-30  1:40     ` Pedro Alves
  2016-09-30  9:22       ` Pedro Alves
  2016-09-30 15:00       ` Tom Tromey
@ 2016-09-30 15:44       ` Tom Tromey
  2016-09-30 23:51         ` Pedro Alves
  2 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-30 15:44 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Trevor Saunders, Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro>   scoped_restore scope = make_scoped_restore (&some_global);

I made this change.  One minor oddity is that the 2-argument form of
make_scoped_restore required a copy constructor in the
scoped_restore_tmpl subclass.  I think that's harmless though.

Tom

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

* Re: [RFA 13/22] Remove unnecessary cleanup from stabsread.c
  2016-09-27  4:51 ` [RFA 13/22] Remove unnecessary cleanup from stabsread.c Tom Tromey
@ 2016-09-30 16:19   ` Tom Tromey
  2016-10-09 17:07   ` Pedro Alves
  1 sibling, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-30 16:19 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> This removes an unnecessary cleanup from stabsread.c.  It's
Tom> unnecessary because nothing between the cleanup creation and use makes
Tom> a cleanup.

I think this turns out to be incorrect, because read_struct_type calls
some functions that leave dangling cleanups.  So, I'm dropping this
patch from the series.

Tom

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

* Re: [RFA 01/22] Change selttest.c to use use std::vector
  2016-09-30 14:43   ` Simon Marchi
@ 2016-09-30 21:40     ` Tom Tromey
  2016-10-06  0:45       ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-30 21:40 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:
>> +  printf_filtered (_("Ran %lu unit tests, %d failed\n"),
>> +		   tests.size (), failed);

Simon> This doesn't build on 32 bits:

Thanks for trying that.
I will send it through buildbot before the next round.

Simon> I think the right format size specifier would be 'z'.

I will probably cast to long instead.
I don't see other uses of %zd in gdb.

Tom

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

* Re: [RFA 07/22] Change scoped_minimal_symbol_reader to store objfile
  2016-09-29  9:19   ` Trevor Saunders
@ 2016-09-30 21:41     ` Tom Tromey
  0 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-09-30 21:41 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: Tom Tromey, gdb-patches

>>>>> "Trevor" == Trevor Saunders <tbsaunde@tbsaunde.org> writes:

>> Currently, minimal symbol table creation is not reentrant; it
>> relies on global (static) variables in minsyms.c.  */
>> 
>> -  explicit scoped_minimal_symbol_reader ();
>> +  explicit scoped_minimal_symbol_reader (struct objfile *);

Trevor> C++ doesn't require the explicit struct / union  when refering to the
Trevor> type, though of course you can keep them if you think it makes something
Trevor> clearer.

I kept it just because "struct objfile" is used everywhere else in gdb.

>> @@ -79,6 +79,8 @@ class scoped_minimal_symbol_reader
>> scoped_minimal_symbol_reader &operator=
>> (const scoped_minimal_symbol_reader &);
>> scoped_minimal_symbol_reader (const scoped_minimal_symbol_reader &);
>> +
>> +  struct objfile *objfile;

Trevor> fwiw gcc convention is to prefix members with m_, so doing so in gdb as
Trevor> well would be nice.

I made this change.

Tom

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

* Re: [RFA 17/22] Remove make_cleanup_restore_current_uiout
  2016-09-30  2:45       ` Pedro Alves
@ 2016-09-30 23:48         ` Tom Tromey
  2016-09-30 23:52           ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-09-30 23:48 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, Trevor Saunders, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

>> In an earlier thread there was a discussion of not having this cleanup
>> be over-general -- that is, it was intentionally specific to just
>> current_uiout.

Pedro> how about:

Pedro> struct scoped_restore_current_uiout : public scoped_restore<ui_out *>

With the make_scoped_restore change it was simpler to just change the
few (one or two?  I forget) users to mention current_uiout explicitly.

Tom

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-09-30 15:00       ` Tom Tromey
@ 2016-09-30 23:50         ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-09-30 23:50 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Trevor Saunders, gdb-patches

On 09/30/2016 03:02 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> template<class T>
> Pedro> scoped_restore_<T> make_scoped_restore (T *var)
> Pedro> {
> Pedro>   return scoped_restore_<T> (var);
> Pedro> }
> 
> Yeah, I'll do this.  I don't know why I didn't remember this when
> writing the patches.

Great, thanks.

> 
> I'd also appreciate it if you could say whether you want "m_" member
> naming.
> 

Unless there's a good reason to deviate, I think it's a good idea
to follow gcc's coding conventions.  For that reason, my preference
is to use "m_" for private data members.

Thanks,
Pedro Alves

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-09-30 15:44       ` Tom Tromey
@ 2016-09-30 23:51         ` Pedro Alves
  2016-10-01  3:55           ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-09-30 23:51 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Trevor Saunders, gdb-patches

On 09/30/2016 04:17 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro>   scoped_restore scope = make_scoped_restore (&some_global);
> 
> I made this change.  One minor oddity is that the 2-argument form of
> make_scoped_restore required a copy constructor in the
> scoped_restore_tmpl subclass.  I think that's harmless though.

Yeah.  We just need to make sure that if a copy constructor does run,
the code behaves as if it hadn't.  My earlier comment on that
not mattering may have been incorrect - if the copied-from scoped_restore
is destructed before the make_scoped_restore function returns, then the
global will revert back to the original value too soon.  Guess we could
have the copy constructor actually move instead of copy, setting the
copied-from's pointer member to NULL, and then have the
destructor do nothing if the pointer is NULL.

Thanks,
Pedro Alves

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

* Re: [RFA 17/22] Remove make_cleanup_restore_current_uiout
  2016-09-30 23:48         ` Tom Tromey
@ 2016-09-30 23:52           ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-09-30 23:52 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Trevor Saunders, gdb-patches

On 09/30/2016 10:41 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
>>> In an earlier thread there was a discussion of not having this cleanup
>>> be over-general -- that is, it was intentionally specific to just
>>> current_uiout.
> 
> Pedro> how about:
> 
> Pedro> struct scoped_restore_current_uiout : public scoped_restore<ui_out *>
> 
> With the make_scoped_restore change it was simpler to just change the
> few (one or two?  I forget) users to mention current_uiout explicitly.

OK.

Thanks,
Pedro Alves

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-09-29 11:55   ` Trevor Saunders
@ 2016-10-01  3:47     ` Tom Tromey
  0 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-10-01  3:47 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: Tom Tromey, gdb-patches

>>>>> "Trevor" == Trevor Saunders <tbsaunde@tbsaunde.org> writes:

>> +  ~switch_thru_all_uis ()
>> +  {
>> +  }

Trev> So, you don't need to do anything  special here because of
Trev> scoped_restore.  So why not just use the compilers definition of this?

I made this change.

Tom

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-09-30 23:51         ` Pedro Alves
@ 2016-10-01  3:55           ` Tom Tromey
  2016-10-01  4:23             ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-01  3:55 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, Trevor Saunders, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> Guess we could have the copy constructor actually move instead of
Pedro> copy, setting the copied-from's pointer member to NULL, and then
Pedro> have the destructor do nothing if the pointer is NULL.

Yeah. I took this approach.  I'm not super thrilled with it, but at the
same time it's not *too* bad.

Tom

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-10-01  3:55           ` Tom Tromey
@ 2016-10-01  4:23             ` Tom Tromey
  2016-10-01 10:33               ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-01  4:23 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, Trevor Saunders, gdb-patches

Pedro> Guess we could have the copy constructor actually move instead of
Pedro> copy, setting the copied-from's pointer member to NULL, and then
Pedro> have the destructor do nothing if the pointer is NULL.

Tom> Yeah. I took this approach.  I'm not super thrilled with it, but at the
Tom> same time it's not *too* bad.

Scratch that, I spoke too soon.  I couldn't get this to work.

I don't understand why the 2-argument form of make_scoped_restore
requires a copy constructor while the 1-argument form does not.

However, once you need a copy constructor, it doesn't seem possible
without a move constructor.  The issue is that a copy constructor take a
const reference, so you can't modify the fields of the original.

Removing the 2-argument form seems to work.  Though like I said, I don't
know why.


Also, as an aside, I found I was using nullptr in my patches, but this
isn't C++03.  I think -std=c++03 is going to be needed or else it will
be too easy to slip in C++11-isms.  Now, I do think C++11 is really much
better, but my understanding is that C++03 is what gdb decided on.

Tom

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

* Re: [RFA 03/22] Use scoped_restore for ui_file
  2016-09-27  4:48 ` [RFA 03/22] Use scoped_restore for ui_file Tom Tromey
@ 2016-10-01  4:28   ` Simon Marchi
  2016-10-01  5:22     ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Simon Marchi @ 2016-10-01  4:28 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 2016-09-27 00:08, Tom Tromey wrote:
> This replaces all the uses of make_cleanup_restore_ui_file with
> scoped_restore.
> 
> 2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> 	* utils.c (make_cleanup_restore_ui_file, do_restore_ui_file)
> 	(struct restore_ui_file_closure): Remove.
> 	* utils.h (make_cleanup_restore_ui_file): Don't declare.
> 	* guile/scm-ports.c (ioscm_with_output_to_port_worker): Use
> 	scoped_restore.
> 	* top.c (execute_command_to_string): Use scoped_restore.
> ---
>  gdb/ChangeLog         |  9 +++++++++
>  gdb/guile/scm-ports.c | 10 ++++------
>  gdb/top.c             | 15 +++++----------
>  gdb/utils.c           | 29 -----------------------------
>  gdb/utils.h           |  3 ---
>  5 files changed, 18 insertions(+), 48 deletions(-)
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 104048f..da69ce8 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,5 +1,14 @@
>  2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> +	* utils.c (make_cleanup_restore_ui_file, do_restore_ui_file)
> +	(struct restore_ui_file_closure): Remove.
> +	* utils.h (make_cleanup_restore_ui_file): Don't declare.
> +	* guile/scm-ports.c (ioscm_with_output_to_port_worker): Use
> +	scoped_restore.
> +	* top.c (execute_command_to_string): Use scoped_restore.
> +
> +2016-09-26  Tom Tromey  <tom@tromey.com>
> +
>  	* utils.h (class scoped_restore): New class.
>  	* top.c (execute_command_to_string): Use scoped_restore.
>  	* python/python.c (python_interactive_command): Use
> diff --git a/gdb/guile/scm-ports.c b/gdb/guile/scm-ports.c
> index 5559475..96e4372 100644
> --- a/gdb/guile/scm-ports.c
> +++ b/gdb/guile/scm-ports.c
> @@ -524,15 +524,13 @@ ioscm_with_output_to_port_worker (SCM port, SCM
> thunk, enum oport oport,
> 
>    make_cleanup_ui_file_delete (port_file);
> 
> +  scoped_restore<ui_file *> save_file (oport == GDB_STDERR
> +				       ? &gdb_stderr : &gdb_stdout);
> +
>    if (oport == GDB_STDERR)
> -    {
> -      make_cleanup_restore_ui_file (&gdb_stderr);
> -      gdb_stderr = port_file;
> -    }
> +    gdb_stderr = port_file;
>    else
>      {
> -      make_cleanup_restore_ui_file (&gdb_stdout);
> -

I think that situations like this, where cleanups are created in an 
scope inner to the function scope, but ran at the end of the function 
scope, are quite frequent in gdb.  You obviously can't simply define the 
scoped_restore in the inner scope, as it wouldn't have the desired 
effect.  I think that it could be worked around using the general 
pattern:

   shared_ptr< scoped_restore<ui_file *> > save_file;

   if (...)
     {
       save_file = new scoped_restore<ui_file *>(&gdb_stderr, port_file)
     }
   else
     {
       save_file = new scoped_restore<ui_file *>(&gdb_stdout, port_file)
     }

We can't use std::shared_ptr, since it's only in c++11, but I think it's 
just a matter of time before we define our own version of it.

An alternative would be to have a default constructor for 
scoped_restore, that creates an inactive scoped_restore, and then assign 
it a variable to restore later with acquire(T* var)/acquire(T* var, T 
value) methods or something.  I am not sure which one is better.

To support some use cases where discard_cleanups is used, we might need 
a way to "release" the scoped_restore, which would essentially cancel 
it.  So if we have a "release" method, maybe having the symmetrical 
"acquire" would make sense.

What do you think?

Simon

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-09-27  4:48 ` [RFA 09/22] Remove make_cleanup_restore_current_ui Tom Tromey
  2016-09-29 11:55   ` Trevor Saunders
@ 2016-10-01  4:29   ` Simon Marchi
  2016-10-06  2:53     ` Tom Tromey
  2016-10-06  1:24   ` Pedro Alves
  2016-10-09  4:31   ` Simon Marchi
  3 siblings, 1 reply; 123+ messages in thread
From: Simon Marchi @ 2016-10-01  4:29 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 2016-09-27 00:08, Tom Tromey wrote:
> --- a/gdb/top.h
> +++ b/gdb/top.h
> @@ -155,27 +155,52 @@ extern struct ui *current_ui;
>  /* The list of all UIs.  */
>  extern struct ui *ui_list;
> 
> -/* State for SWITCH_THRU_ALL_UIS.  Declared here because it is meant
> -   to be created on the stack, but should be treated as opaque.  */
> -struct switch_thru_all_uis
> +/* State for SWITCH_THRU_ALL_UIS.  */
> +class switch_thru_all_uis
>  {
> +public:
> +
> +  switch_thru_all_uis () : iter (nullptr), save_ui (&current_ui)

We are targetting C++98, aren't we?  Or is it C++03?  Either way, 
nullptr appeared in C++11, so I guess we can't use it.

The fact that your compiler (and mine) did not catch this begs the 
question, should we have one of -std=c++98/gnu++98/c++03/gnu++03 in our 
compilation flags, instead of relying of the compiler's default mode?

> +  {
> +    iter = ui_list;
> +  }
> +
> +  ~switch_thru_all_uis ()
> +  {
> +  }
> +
> +  // If done iterating, return true; otherwise return false.
> +  bool done () const
> +  {
> +    return iter == nullptr;
> +  }
> +
> +  // Move to the next UI, setting current_ui if iteration is not yet
> +  // complete.
> +  void next ()
> +  {
> +    iter = iter->next;
> +    if (iter != nullptr)
> +      current_ui = iter;
> +  }
> +
> + private:
> +
> +  // No need for these.  They are intentionally not defined anywhere.
> +  switch_thru_all_uis &operator= (const switch_thru_all_uis &);
> +  switch_thru_all_uis (const switch_thru_all_uis &);
> +
> +  // Used to iterate through the UIs.
>    struct ui *iter;
> -  struct cleanup *old_chain;
> -};
> 
> -/* Functions to drive SWITCH_THRU_ALL_UIS.  Though declared here by
> -   necessity, these functions should not be used other than via the
> -   SWITCH_THRU_ALL_UIS macro defined below.  */
> -extern void switch_thru_all_uis_init (struct switch_thru_all_uis 
> *state);
> -extern int switch_thru_all_uis_cond (struct switch_thru_all_uis 
> *state);
> -extern void switch_thru_all_uis_next (struct switch_thru_all_uis 
> *state);
> +  // Save and restore current_ui.
> +  scoped_restore<struct ui *> save_ui;
> +};
> 
>    /* Traverse through all UI, and switch the current UI to the one
>       being iterated.  */
>  #define SWITCH_THRU_ALL_UIS(STATE)		\

You can remove STATE here.  I am surprised the preprocessor doesn't care 
about the missing argument in macro references.

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

* Re: [RFA 08/22] Record minimal symbols directly in reader.
  2016-09-27  4:48 ` [RFA 08/22] Record minimal symbols directly in reader Tom Tromey
@ 2016-10-01  4:29   ` Simon Marchi
  2016-10-06  1:12     ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Simon Marchi @ 2016-10-01  4:29 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 2016-09-27 00:08, Tom Tromey wrote:
> This patch changes minimal symbol creation in two ways.  First, it
> removes global variables in favor of members of
> scoped_minimal_symbol_reader.  Second, it changes functions like
> prim_record_minimal_symbol to be member functions of
> scoped_minimal_symbol_reader.

I think this patch (and the previous ones that lead to it) are great.  
That's the kind of thing that will make the data flow easier to 
understand.

About the naming, it's a bit of a nit, but since it might set the 
standard for future classes, I prefer to ask anyway.  Does it help in 
any way to prefix this class' name with "scoped_"?  All C++ 
class/objects are "scoped" when statically allocated in a scope, meaning 
that they get destroyed when execution goes out of that scope.  So it's 
not really the property of the class itself that it's scoped, more about 
how it's being used.  It would be a bit like naming "std::string" -> 
"std::scoped_string", since it frees its resources when being destroyed. 
  "minimal_symbol_reader" sounds like a perfect name for that class, 
doesn't it?

On the other hand, I think scoped_restore is appropriately named, since 
it conveys that its primary (and only?) reason to exist is to be used in 
conjunction with scopes to do some variable restoring.

Simon

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

* Re: [RFA 03/22] Use scoped_restore for ui_file
  2016-10-01  4:28   ` Simon Marchi
@ 2016-10-01  5:22     ` Tom Tromey
  2016-10-01 11:47       ` Simon Marchi
  0 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-01  5:22 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

Simon>   shared_ptr< scoped_restore<ui_file *> > save_file;

Why shared_ptr and not unique_ptr?

Simon> We can't use std::shared_ptr, since it's only in c++11, but I think
Simon> it's just a matter of time before we define our own version of it.

... Pedro's branch has unique_ptr :)

Simon> An alternative would be to have a default constructor for
Simon> scoped_restore, that creates an inactive scoped_restore, and then
Simon> assign it a variable to restore later with acquire(T* var)/acquire(T*
Simon> var, T value) methods or something.  I am not sure which one is
Simon> better.

FWIW Mozilla uses an Option class for this kind of thing.
It works like:

   Option< scoped_restore<ui_file *> > save_file;
   if (mumble) {
     save_file.emplace (make_scoped_restore (&var));
   }

The main advantage of this over *_ptr is that Option contains the
object, so no heap allocations are required.

Simon> To support some use cases where discard_cleanups is used, we might
Simon> need a way to "release" the scoped_restore, which would essentially
Simon> cancel it.  So if we have a "release" method, maybe having the
Simon> symmetrical "acquire" would make sense.

Simon> What do you think?

It seems sensible to me.

One idea to consider is whether it's better to have a separate
"discardable" variant of scoped_restore (or whatever else); the idea
being that then the type name serves as a signal to look more closely at
the logic.  I think most spots don't need discardable cleanups.

Tom

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-10-01  4:23             ` Tom Tromey
@ 2016-10-01 10:33               ` Pedro Alves
  2016-10-02 17:11                 ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-01 10:33 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Trevor Saunders, gdb-patches

On 10/01/2016 05:23 AM, Tom Tromey wrote:
> Pedro> Guess we could have the copy constructor actually move instead of
> Pedro> copy, setting the copied-from's pointer member to NULL, and then
> Pedro> have the destructor do nothing if the pointer is NULL.
> 
> Tom> Yeah. I took this approach.  I'm not super thrilled with it, but at the
> Tom> same time it's not *too* bad.
> 
> Scratch that, I spoke too soon.  I couldn't get this to work.
> 
> I don't understand why the 2-argument form of make_scoped_restore
> requires a copy constructor while the 1-argument form does not.
> 
> However, once you need a copy constructor, it doesn't seem possible
> without a move constructor.  The issue is that a copy constructor take a
> const reference, so you can't modify the fields of the original.

You can -- make the fields mutable.  That's what ScopeGuard does too.

> 
> Removing the 2-argument form seems to work.  Though like I said, I don't
> know why.

I can't tell off hand.  Maybe seeing the code would suggest something.

> 
> 
> Also, as an aside, I found I was using nullptr in my patches, but this
> isn't C++03.  I think -std=c++03 is going to be needed or else it will
> be too easy to slip in C++11-isms.  Now, I do think C++11 is really much
> better, but my understanding is that C++03 is what gdb decided on.

I'm very much against forcing -std=c++03.

My plan is to allow compiling with C++11 too, and use
some of its features, for extra safety and extra efficiency,
as long as we have C++03 fallbacks in place.  If we force -std=c++03,
that becomes impossible.  

I recently elaborated on this here:
 https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01624.html

The gist is that I think that the features supported by compilers that
people are using in practice to build gdb with is what matters
in the end, not really C++03 vs C++11.

The only reason we're not requiring C++11 is that some people
still wanted to build gdb with older compilers that don't support it.
That was last revisited a year ago when we discussed whether to
go C++ or not in the first place.  It may be that the baseline might have 
advanced meanwhile.

Thanks,
Pedro Alves

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

* Re: [RFA 03/22] Use scoped_restore for ui_file
  2016-10-01  5:22     ` Tom Tromey
@ 2016-10-01 11:47       ` Simon Marchi
  2016-10-13 14:56         ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Simon Marchi @ 2016-10-01 11:47 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 2016-10-01 01:22, Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:
> 
> Simon>   shared_ptr< scoped_restore<ui_file *> > save_file;
> 
> Why shared_ptr and not unique_ptr?

Right, I am not used yet to think about their differences, and which one 
applies to a particular situation.  unique_ptr is clearler a better 
choice.

> Simon> We can't use std::shared_ptr, since it's only in c++11, but I 
> think
> Simon> it's just a matter of time before we define our own version of 
> it.
> 
> ... Pedro's branch has unique_ptr :)

Oh, right!

> Simon> An alternative would be to have a default constructor for
> Simon> scoped_restore, that creates an inactive scoped_restore, and 
> then
> Simon> assign it a variable to restore later with acquire(T* 
> var)/acquire(T*
> Simon> var, T value) methods or something.  I am not sure which one is
> Simon> better.
> 
> FWIW Mozilla uses an Option class for this kind of thing.
> It works like:
> 
>    Option< scoped_restore<ui_file *> > save_file;
>    if (mumble) {
>      save_file.emplace (make_scoped_restore (&var));
>    }
> 
> The main advantage of this over *_ptr is that Option contains the
> object, so no heap allocations are required.

That sounds good, it ends up with the same behavior, but implemented 
better.

> Simon> To support some use cases where discard_cleanups is used, we 
> might
> Simon> need a way to "release" the scoped_restore, which would 
> essentially
> Simon> cancel it.  So if we have a "release" method, maybe having the
> Simon> symmetrical "acquire" would make sense.
> 
> Simon> What do you think?
> 
> It seems sensible to me.
> 
> One idea to consider is whether it's better to have a separate
> "discardable" variant of scoped_restore (or whatever else); the idea
> being that then the type name serves as a signal to look more closely 
> at
> the logic.  I think most spots don't need discardable cleanups.

Yep, alsop sounds good.

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-10-01 10:33               ` Pedro Alves
@ 2016-10-02 17:11                 ` Tom Tromey
  2016-10-05  0:06                   ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-02 17:11 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, Trevor Saunders, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

>> However, once you need a copy constructor, it doesn't seem possible
>> without a move constructor.  The issue is that a copy constructor take a
>> const reference, so you can't modify the fields of the original.

Pedro> You can -- make the fields mutable.

Ok, yeah, I had thought of this, but it seemed pretty ugly to me.

Instead I removed all the 2 argument forms in favor of a second explicit
assignment.  This solves the problem as well.

I can go back and do the mutable thing if you really prefer it though.


Pedro> The gist is that I think that the features supported by compilers that
Pedro> people are using in practice to build gdb with is what matters
Pedro> in the end, not really C++03 vs C++11.

The issue I see is that it's just too easy otherwise for C++11isms to
slip in, especially considering that everybody doing development is
likely to be using a compiler with all the C++11 features.  Maybe
buildbot can do C++03 builds to check.

Tom

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

* Re: [RFA 19/22] Convert tid_range_parser to class
       [not found]       ` <926126cb-b3c5-340b-ac1c-5bc14ca41bf9@redhat.com>
@ 2016-10-04 19:24         ` Pedro Alves
  2016-10-04 23:09           ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-04 19:24 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/01/2016 12:23 AM, Pedro Alves wrote:
> On 09/30/2016 03:07 PM, Tom Tromey wrote:
>>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
>>
>> Pedro> Whoops, we ended up duplicating work here.
>>
>> Oops :) But no big deal.
>>
>> Pedro> Additional differences compared to yours are:
>> Pedro> - "bool" instead of "int".
>> Pedro> - "m_" prefixes.
>>
>> Aha, the m_ prefix.  Cancel that earlier question...
>>
>> Pedro> Let me know what you think.  It's super fine with me to rebase
>> Pedro> mine on top of yours.  Did you have a follow up patch for
>> Pedro> get_number_or_range too, perhaps?
>>
>> I don't.  How about I just drop my patch?  That seems simplest to me.
> 
> OK.  I'll look at your patch in more detail and see what could be
> merged in.  I'll add your name to the ChangeLog.
> 
>>
>> Pedro>  void
>> Pedro> -init_number_or_range (struct get_number_or_range_state *state,
>> Pedro> -		      const char *string)
>> Pedro> +number_or_range_parser::init (const char *string)
>> Pedro>  {
>> Pedro> -  memset (state, 0, sizeof (*state));
>> Pedro> -  state->string = string;
>> Pedro> +  memset (this, 0, sizeof (*this));
>>
>> I think it's better to do explicit initialization.
> 
> I'll do this.
> 
>> This will bite if this class ever is changed to have a vtable (unlikely
>> but it's better, IMO, to set a good example).
> 
> Yeah, we'd notice bad things immediately, but I agree with setting
> a good example.

I did the change below locally.  I was looking at string() vs
get_string(), and not being super happy with either.  string()
is maybe too generic, doesn't really convey what the string is about,
and the get_ in get_string() makes me go "the other get_ members are about
parsing/producing a number, while this is peeking at parser state".  So in
the style of xkcd 927, I thought of an alternative name -- cur_tok(),
which seems to be at least somewhat of a common field/method name in
parser lingo, according to google.

I've also renamed get_next to get_number:

-      int gotnum = parser.get_next ();
+      int gotnum = parser.get_number ();

which seems more consistent.

Got rid of the memset too.

I'm now looking at finished() vs is_qualified() and pondering
whether to do something about that little inconsistency.  :-)

Anyway, I have to disappear now.  Will continue later.

From 4ae2903eee5b5c04f56658a02c486ba4c8edcd5f Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 4 Oct 2016 20:14:56 +0100
Subject: [PATCH] address review

---
 gdb/breakpoint.c    |  6 +++---
 gdb/cli/cli-utils.c | 28 ++++++++++++++++------------
 gdb/cli/cli-utils.h | 18 +++++++++---------
 gdb/inferior.c      |  6 +++---
 gdb/linespec.c      |  2 +-
 gdb/memattr.c       |  6 +++---
 gdb/printcmd.c      |  4 ++--
 gdb/reverse.c       |  4 ++--
 gdb/thread.c        |  7 +++----
 gdb/tid-parse.c     | 32 ++++++++++++++++----------------
 gdb/tid-parse.h     | 12 ++++++------
 11 files changed, 64 insertions(+), 61 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 6b47541..32d6a95 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -14783,10 +14783,10 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *,
 
   while (!parser.finished ())
     {
-      const char *p = parser.string ();
+      const char *p = parser.cur_tok ();
       bool match = false;
 
-      num = parser.get_next ();
+      num = parser.get_number ();
       if (num == 0)
 	{
 	  warning (_("bad breakpoint number at or near '%s'"), p);
@@ -15639,7 +15639,7 @@ get_tracepoint_by_number (char **arg,
   if (parser != NULL)
     {
       gdb_assert (!parser->finished ());
-      tpnum = parser->get_next ();
+      tpnum = parser->get_number ();
     }
   else if (arg == NULL || *arg == NULL || ! **arg)
     tpnum = tracepoint_count;
diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c
index 379f341..0fb68f2 100644
--- a/gdb/cli/cli-utils.c
+++ b/gdb/cli/cli-utils.c
@@ -131,14 +131,18 @@ number_or_range_parser::number_or_range_parser (const char *string)
 void
 number_or_range_parser::init (const char *string)
 {
-  memset (this, 0, sizeof (*this));
-  m_string = string;
+  m_finished = false;
+  m_cur_tok = string;
+  m_last_retval = 0;
+  m_end_value = 0;
+  m_end_ptr = NULL;
+  m_in_range = false;
 }
 
 /* See documentation in cli-utils.h.  */
 
 int
-number_or_range_parser::get_next ()
+number_or_range_parser::get_number ()
 {
   if (m_in_range)
     {
@@ -150,16 +154,16 @@ number_or_range_parser::get_next ()
       if (++m_last_retval == m_end_value)
 	{
 	  /* End of range reached; advance token pointer.  */
-	  m_string = m_end_ptr;
+	  m_cur_tok = m_end_ptr;
 	  m_in_range = false;
 	}
     }
-  else if (*m_string != '-')
+  else if (*m_cur_tok != '-')
     {
-      /* Default case: state->string is pointing either to a solo
+      /* Default case: state->m_cur_tok is pointing either to a solo
 	 number, or to the first number of a range.  */
-      m_last_retval = get_number_trailer (&m_string, '-');
-      if (*m_string == '-')
+      m_last_retval = get_number_trailer (&m_cur_tok, '-');
+      if (*m_cur_tok == '-')
 	{
 	  const char **temp;
 
@@ -168,7 +172,7 @@ number_or_range_parser::get_next ()
 	     and also remember the end of the final token.  */
 
 	  temp = &m_end_ptr;
-	  m_end_ptr = skip_spaces_const (m_string + 1);
+	  m_end_ptr = skip_spaces_const (m_cur_tok + 1);
 	  m_end_value = get_number_const (temp);
 	  if (m_end_value < m_last_retval)
 	    {
@@ -179,7 +183,7 @@ number_or_range_parser::get_next ()
 	      /* Degenerate range (number1 == number2).  Advance the
 		 token pointer so that the range will be treated as a
 		 single number.  */
-	      m_string = m_end_ptr;
+	      m_cur_tok = m_end_ptr;
 	    }
 	  else
 	    m_in_range = true;
@@ -187,7 +191,7 @@ number_or_range_parser::get_next ()
     }
   else
     error (_("negative value"));
-  m_finished = *m_string == '\0';
+  m_finished = *m_cur_tok == '\0';
   return m_last_retval;
 }
 
@@ -222,7 +226,7 @@ number_is_in_list (const char *list, int number)
   number_or_range_parser parser (list);
   while (!parser.finished ())
     {
-      int gotnum = parser.get_next ();
+      int gotnum = parser.get_number ();
 
       if (gotnum == 0)
 	error (_("Args must be numbers or '$' variables."));
diff --git a/gdb/cli/cli-utils.h b/gdb/cli/cli-utils.h
index 41c3a58..ab3f122 100644
--- a/gdb/cli/cli-utils.h
+++ b/gdb/cli/cli-utils.h
@@ -62,11 +62,11 @@ public:
      each call it will return the next value in the range.
 
      At the beginning of parsing a range, the char pointer
-     STATE->string will be advanced past <number1> and left pointing
-     at the '-' token.  Subsequent calls will not advance the pointer
-     until the range is completed.  The call that completes the range
-     will advance the pointer past <number2>.  */
-  int get_next ();
+     STATE->m_cur_tok will be advanced past <number1> and left
+     pointing at the '-' token.  Subsequent calls will not advance the
+     pointer until the range is completed.  The call that completes
+     the range will advance the pointer past <number2>.  */
+  int get_number ();
 
   /* Setup internal state such that get_next() returns numbers in the
      START_VALUE to END_VALUE range.  END_PTR is where the string is
@@ -80,8 +80,8 @@ public:
 
   /* Return the string being parsed.  When parsing has finished, this
      points past the last parsed token.  */
-  const char *string ()
-  { return m_string; }
+  const char *cur_tok ()
+  { return m_cur_tok; }
 
   /* True when parsing a range.  */
   bool in_range ()
@@ -95,7 +95,7 @@ public:
   void skip_range ()
   {
     gdb_assert (m_in_range);
-    m_string = m_end_ptr;
+    m_cur_tok = m_end_ptr;
   }
 
 private:
@@ -104,7 +104,7 @@ private:
 
   /* The string being parsed.  When parsing has finished, this points
      past the last parsed token.  */
-  const char *m_string;
+  const char *m_cur_tok;
 
   /* Last value returned.  */
   int m_last_retval;
diff --git a/gdb/inferior.c b/gdb/inferior.c
index 836adc9..1602483 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -659,7 +659,7 @@ detach_inferior_command (char *args, int from_tty)
   number_or_range_parser parser (args);
   while (!parser.finished ())
     {
-      int num = parser.get_next ();
+      int num = parser.get_number ();
 
       if (!valid_gdb_inferior_id (num))
 	{
@@ -698,7 +698,7 @@ kill_inferior_command (char *args, int from_tty)
   number_or_range_parser parser (args);
   while (!parser.finished ())
     {
-      int num = parser.get_next ();
+      int num = parser.get_number ();
 
       if (!valid_gdb_inferior_id (num))
 	{
@@ -790,7 +790,7 @@ remove_inferior_command (char *args, int from_tty)
   number_or_range_parser parser (args);
   while (!parser.finished ())
     {
-      int num = parser.get_next ();
+      int num = parser.get_number ();
       struct inferior *inf = find_inferior_id (num);
 
       if (inf == NULL)
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 7b1a77e..5182b45 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -1411,7 +1411,7 @@ decode_line_2 (struct linespec_state *self,
   number_or_range_parser parser (args);
   while (!parser.finished ())
     {
-      int num = parser.get_next ();
+      int num = parser.get_number ();
 
       if (num == 0)
 	error (_("canceled"));
diff --git a/gdb/memattr.c b/gdb/memattr.c
index a33993a..1c5c48f 100644
--- a/gdb/memattr.c
+++ b/gdb/memattr.c
@@ -581,7 +581,7 @@ mem_enable_command (char *args, int from_tty)
       number_or_range_parser parser (args);
       while (!parser.finished ())
 	{
-	  num = parser.get_next ();
+	  num = parser.get_number ();
 	  mem_enable (num);
 	}
     }
@@ -625,7 +625,7 @@ mem_disable_command (char *args, int from_tty)
       number_or_range_parser parser (args);
       while (!parser.finished ())
 	{
-	  int num = parser.get_next ();
+	  int num = parser.get_number ();
 	  mem_disable (num);
 	}
     }
@@ -676,7 +676,7 @@ mem_delete_command (char *args, int from_tty)
   number_or_range_parser parser (args);
   while (!parser.finished ())
     {
-      int num = parser.get_next ();
+      int num = parser.get_number ();
       mem_delete (num);
     }
 
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 15f2395..c7f477b 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1885,9 +1885,9 @@ map_display_numbers (char *args,
 
   while (!parser.finished ())
     {
-      const char *p = parser.string ();
+      const char *p = parser.cur_tok ();
 
-      num = parser.get_next ();
+      num = parser.get_number ();
       if (num == 0)
 	warning (_("bad display number at or near '%s'"), p);
       else
diff --git a/gdb/reverse.c b/gdb/reverse.c
index 461d1a4..2c1abdc 100644
--- a/gdb/reverse.c
+++ b/gdb/reverse.c
@@ -233,7 +233,7 @@ delete_bookmark_command (char *args, int from_tty)
   number_or_range_parser parser (args);
   while (!parser.finished ())
     {
-      int num = parser.get_next ();
+      int num = parser.get_number ();
       if (!delete_one_bookmark (num))
 	/* Not found.  */
 	warning (_("No bookmark #%d."), num);
@@ -329,7 +329,7 @@ bookmarks_info (char *args, int from_tty)
       number_or_range_parser parser (args);
       while (!parser.finished ())
 	{
-	  int bnum = parser.get_next ();
+	  int bnum = parser.get_number ();
 	  bookmark_1 (bnum);
 	}
     }
diff --git a/gdb/thread.c b/gdb/thread.c
index 819119d..f376211 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1837,7 +1837,7 @@ thread_apply_command (char *tidlist, int from_tty)
 
       if (!parser.get_tid_range (&inf_num, &thr_start, &thr_end))
 	{
-	  cmd = (char *) parser.string ();
+	  cmd = (char *) parser.cur_tok ();
 	  break;
 	}
     }
@@ -1856,7 +1856,7 @@ thread_apply_command (char *tidlist, int from_tty)
   make_cleanup_restore_current_thread ();
 
   parser.init (tidlist, current_inferior ()->num);
-  while (!parser.finished () && parser.string () < cmd)
+  while (!parser.finished () && parser.cur_tok () < cmd)
     {
       struct thread_info *tp = NULL;
       struct inferior *inf;
@@ -1888,8 +1888,7 @@ thread_apply_command (char *tidlist, int from_tty)
 
       if (tp == NULL)
 	{
-	  if (show_inferior_qualified_tids ()
-	      || parser.qualified ())
+	  if (show_inferior_qualified_tids () || parser.is_qualified ())
 	    warning (_("Unknown thread %d.%d"), inf_num, thr_num);
 	  else
 	    warning (_("Unknown thread %d"), thr_num);
diff --git a/gdb/tid-parse.c b/gdb/tid-parse.c
index 9e49eba..28c5286 100644
--- a/gdb/tid-parse.c
+++ b/gdb/tid-parse.c
@@ -125,7 +125,7 @@ void
 tid_range_parser::init (const char *tidlist, int default_inferior)
 {
   m_state = STATE_INFERIOR;
-  m_string = tidlist;
+  m_cur_tok = tidlist;
   m_inf_num = 0;
   m_qualified = 0;
   m_default_inferior = default_inferior;
@@ -139,7 +139,7 @@ tid_range_parser::finished ()
   switch (m_state)
     {
     case STATE_INFERIOR:
-      return *m_string == '\0';
+      return *m_cur_tok == '\0';
     case STATE_THREAD_RANGE:
     case STATE_STAR_RANGE:
       return m_range_parser.finished ();
@@ -151,15 +151,15 @@ tid_range_parser::finished ()
 /* See tid-parse.h.  */
 
 const char *
-tid_range_parser::string ()
+tid_range_parser::cur_tok ()
 {
   switch (m_state)
     {
     case STATE_INFERIOR:
-      return m_string;
+      return m_cur_tok;
     case STATE_THREAD_RANGE:
     case STATE_STAR_RANGE:
-      return m_range_parser.string ();
+      return m_range_parser.cur_tok ();
     }
 
   gdb_assert_not_reached (_("unhandled state"));
@@ -172,13 +172,13 @@ tid_range_parser::skip_range ()
 	      || m_state == STATE_STAR_RANGE);
 
   m_range_parser.skip_range ();
-  init (m_range_parser.string (), m_default_inferior);
+  init (m_range_parser.cur_tok (), m_default_inferior);
 }
 
 /* See tid-parse.h.  */
 
 bool
-tid_range_parser::qualified ()
+tid_range_parser::is_qualified ()
 {
   return m_qualified;
 }
@@ -196,9 +196,9 @@ tid_range_parser::get_tid_or_range (int *inf_num,
       const char *p;
       const char *space;
 
-      space = skip_to_space (m_string);
+      space = skip_to_space (m_cur_tok);
 
-      p = m_string;
+      p = m_cur_tok;
       while (p < space && *p != '.')
 	p++;
       if (p < space)
@@ -206,8 +206,8 @@ tid_range_parser::get_tid_or_range (int *inf_num,
 	  const char *dot = p;
 
 	  /* Parse number to the left of the dot.  */
-	  p = m_string;
-	  m_inf_num = get_positive_number_trailer (&p, '.', m_string);
+	  p = m_cur_tok;
+	  m_inf_num = get_positive_number_trailer (&p, '.', m_cur_tok);
 	  if (m_inf_num == 0)
 	    return 0;
 
@@ -221,7 +221,7 @@ tid_range_parser::get_tid_or_range (int *inf_num,
 	{
 	  m_inf_num = m_default_inferior;
 	  m_qualified = false;
-	  p = m_string;
+	  p = m_cur_tok;
 	}
 
       m_range_parser.init (p);
@@ -237,9 +237,9 @@ tid_range_parser::get_tid_or_range (int *inf_num,
     }
 
   *inf_num = m_inf_num;
-  *thr_start = m_range_parser.get_next ();
+  *thr_start = m_range_parser.get_number ();
   if (*thr_start < 0)
-    error (_("negative value: %s"), m_string);
+    error (_("negative value: %s"), m_cur_tok);
   if (*thr_start == 0)
     {
       m_state = STATE_INFERIOR;
@@ -252,7 +252,7 @@ tid_range_parser::get_tid_or_range (int *inf_num,
   if (!m_range_parser.in_range ())
     {
       m_state = STATE_INFERIOR;
-      m_string = m_range_parser.string ();
+      m_cur_tok = m_range_parser.cur_tok ();
 
       if (thr_end != NULL)
 	*thr_end = *thr_start;
@@ -316,7 +316,7 @@ tid_is_in_list (const char *list, int default_inferior,
       int tmp_inf, tmp_thr_start, tmp_thr_end;
 
       if (!parser.get_tid_range (&tmp_inf, &tmp_thr_start, &tmp_thr_end))
-	invalid_thread_id_error (parser.string ());
+	invalid_thread_id_error (parser.cur_tok ());
       if (tmp_inf == inf_num
 	  && tmp_thr_start <= thr_num && thr_num <= tmp_thr_end)
 	return 1;
diff --git a/gdb/tid-parse.h b/gdb/tid-parse.h
index 764facc..4ff74b7 100644
--- a/gdb/tid-parse.h
+++ b/gdb/tid-parse.h
@@ -74,7 +74,7 @@ public:
      exists).
 
      At the beginning of parsing a thread range, the char pointer
-     PARSER->string will be advanced past <thread_number1> and left
+     PARSER->m_cur_tok will be advanced past <thread_number1> and left
      pointing at the '-' token.  Subsequent calls will not advance the
      pointer until the range is completed.  The call that completes
      the range will advance the pointer past <thread_number2>.
@@ -116,9 +116,9 @@ public:
   /* Returns true if parsing has completed.  */
   bool finished ();
 
-  /* Return the string being parsed.  When parsing has finished, this
-     points past the last parsed token.  */
-  const char *string ();
+  /* Return the current token being parsed.  When parsing has
+     finished, this points past the last parsed token.  */
+  const char *cur_tok ();
 
   /* When parsing a range, advance past the final token in the
      range.  */
@@ -126,7 +126,7 @@ public:
 
 /* True if the TID last parsed was explicitly inferior-qualified.
    IOW, whether the spec specified an inferior number explicitly.  */
-  bool qualified ();
+  bool is_qualified ();
 
 private:
   bool get_tid_or_range (int *inf_num, int *thr_start, int *thr_end);
@@ -147,7 +147,7 @@ private:
 
   /* The string being parsed.  When parsing has finished, this points
      past the last parsed token.  */
-  const char *m_string;
+  const char *m_cur_tok;
 
   /* The range parser state when we're parsing the thread number
      sub-component.  */
-- 
2.5.5


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

* Re: [RFA 19/22] Convert tid_range_parser to class
  2016-10-04 19:24         ` Pedro Alves
@ 2016-10-04 23:09           ` Pedro Alves
  2016-10-05  2:16             ` Trevor Saunders
  2016-10-12  2:12             ` Tom Tromey
  0 siblings, 2 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-04 23:09 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/04/2016 08:24 PM, Pedro Alves wrote:

> Anyway, I have to disappear now.  Will continue later.

Here's what I ended up with, after reading your version
in more detail.  That brought in the "deleted" copy constructor/assignment
operators [1], and "const" in several methods, which I then propagated
to number_or_range_parser too.

WDYT?

[1] - I'm pondering making those use =delete if compiling with
a C++ compiler, behind some

  #define DISABLE_COPY_AND_ASSIGN(TYPE) ...

macro.

Or, maybe add a gdb::noncopyable class that non-copyable
classes inherit from privately, just like boost:noncopyable.
Anyone got experience on the latter, and whether that turns
out to be a bad idea?

Anyway, here's the current version of the patch.  Tested on 
x86_64 Fedora 23.

Let me know what you think.

From 4b57514dce9358f7e4367b9dcd870253e3ab249b Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 4 Oct 2016 23:28:31 +0100
Subject: [PATCH] Convert tid_range_parser and get_number_or_range to classes

This converts tid_range_parser and get_number_or_range to be classes.
The various tid_range_parser_* and get_number_or_range_* functions
become methods on the respective classes.  Then it updates the users
to follow.

The rationale for the change is that this provides better
encapsulation.  For example, this forced me to think of a better
interface between tid_range_parser and get_number_or_range, since the
former peeked into the latter's internals a bit too much.  That ended
up resulting mostly in these two not-just-straight-1-1 changes:

  void
 -tid_range_parser_skip (struct tid_range_parser *parser)
 +tid_range_parser::skip_range ()
  {
 ...

 -  tid_range_parser_init (parser, parser->range_parser.end_ptr,
 -			 parser->default_inferior);
 +  m_range_parser.skip_range ();
 +  init (m_range_parser.string (), m_default_inferior);
  }

 and:

    /* If we successfully parsed a thread number or finished parsing a
       thread range, switch back to assuming the next TID is
       inferior-qualified.  */
 -  if (parser->range_parser.end_ptr == NULL
 -      || parser->range_parser.string == parser->range_parser.end_ptr)
 +  if (!m_range_parser.in_range ())
      {

For the same reason (encapsulation), this moves the enum
tid_range_state definition to within the tid_parser class's scope,
since that is private implementation detail.

While at it, switch to use "bool" for booleans.

gdb/ChangeLog:
2016-10-04  Pedro Alves  <palves@redhat.com>
	    Tom Tromey  <tom@tromey.com>

	* tid-parse.h (tid_range_parser): New class.
	(enum tid_range_state): Move into tid_range_parser's scope.
	Remove TID_RANGE_ prefix from all values.
	(tid_range_parser_get_tid, tid_range_parser_get_tid_range)
	(tid_range_parser_star_range, tid_range_parser_finished)
	(tid_range_parser_skip, tid_range_parser_qualified): Don't
	declare.
	(tid_is_in_list): Update comment.
	* tid-parse.c (tid_range_parser::tid_range_parser): New.
	(init, finished, get_string, skip, tid_is_qualified)
	(get_tid_or_range, get_tid_range, get_tid, star_range): Rename;
	turn into methods.
	(tid_is_in_list): Adjust.
	* cli/cli-utils.h (number_or_range_parser): New class.
	(init_number_or_range, get_number_or_range)
	(number_range_setup_range): Don't declare.
	* cli/cli-utils.c
	(number_or_range_parser::number_or_range_parser): New.
	(init_number_or_range, get_number_or_range)
	(number_range_setup_range): Rename; turn into methods.
	(number_is_in_list): Adjust.
	* breakpoint.c (map_breakpoint_numbers): Adjust.  Use bool.
	(trace_pass_command, get_tracepoint_by_number): Adjust.
	* breakpoint.h (get_tracepoint_by_number): Adjust.
	* inferior.c (detach_inferior_command, kill_inferior_command)
	(remove_inferior_command): Adjust.
	* linespec.c (decode_line_2): Adjust.
	* memattr.c (mem_enable_command, mem_disable_command)
	(mem_delete_command): Adjust.
	* printcmd.c (map_display_numbers): Adjust.
	* reverse.c (delete_bookmark_command, bookmarks_info): Adjust.
	* thread.c (thread_apply_command): Adjust.
---
 gdb/breakpoint.c    |  33 ++++-----
 gdb/breakpoint.h    |   6 +-
 gdb/cli/cli-utils.c |  76 +++++++++++---------
 gdb/cli/cli-utils.h | 114 ++++++++++++++++++------------
 gdb/inferior.c      |  32 ++++-----
 gdb/linespec.c      |   9 +--
 gdb/memattr.c       |  32 ++++-----
 gdb/printcmd.c      |   9 ++-
 gdb/reverse.c       |  19 ++---
 gdb/thread.c        |  27 ++++---
 gdb/tid-parse.c     | 170 ++++++++++++++++++++++-----------------------
 gdb/tid-parse.h     | 197 +++++++++++++++++++++++++++-------------------------
 12 files changed, 365 insertions(+), 359 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 1e05932..32d6a95 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -14775,21 +14775,18 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *,
 {
   int num;
   struct breakpoint *b, *tmp;
-  int match;
-  struct get_number_or_range_state state;
 
   if (args == 0 || *args == '\0')
     error_no_arg (_("one or more breakpoint numbers"));
 
-  init_number_or_range (&state, args);
+  number_or_range_parser parser (args);
 
-  while (!state.finished)
+  while (!parser.finished ())
     {
-      const char *p = state.string;
+      const char *p = parser.cur_tok ();
+      bool match = false;
 
-      match = 0;
-
-      num = get_number_or_range (&state);
+      num = parser.get_number ();
       if (num == 0)
 	{
 	  warning (_("bad breakpoint number at or near '%s'"), p);
@@ -14799,11 +14796,11 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *,
 	  ALL_BREAKPOINTS_SAFE (b, tmp)
 	    if (b->number == num)
 	      {
-		match = 1;
+		match = true;
 		function (b, data);
 		break;
 	      }
-	  if (match == 0)
+	  if (!match)
 	    printf_unfiltered (_("No breakpoint number %d.\n"), num);
 	}
     }
@@ -15584,12 +15581,10 @@ trace_pass_command (char *args, int from_tty)
     }
   else
     {
-      struct get_number_or_range_state state;
-
-      init_number_or_range (&state, args);
-      while (!state.finished)
+      number_or_range_parser parser (args);
+      while (!parser.finished ())
 	{
-	  t1 = get_tracepoint_by_number (&args, &state);
+	  t1 = get_tracepoint_by_number (&args, &parser);
 	  if (t1)
 	    trace_pass_set_count (t1, count, from_tty);
 	}
@@ -15635,16 +15630,16 @@ get_tracepoint_by_number_on_target (int num)
 
 struct tracepoint *
 get_tracepoint_by_number (char **arg,
-			  struct get_number_or_range_state *state)
+			  number_or_range_parser *parser)
 {
   struct breakpoint *t;
   int tpnum;
   char *instring = arg == NULL ? NULL : *arg;
 
-  if (state)
+  if (parser != NULL)
     {
-      gdb_assert (!state->finished);
-      tpnum = get_number_or_range (state);
+      gdb_assert (!parser->finished ());
+      tpnum = parser->get_number ();
     }
   else if (arg == NULL || *arg == NULL || ! **arg)
     tpnum = tracepoint_count;
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 4bdf0d5..aaff3d5 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -31,7 +31,7 @@ struct value;
 struct block;
 struct gdbpy_breakpoint_object;
 struct gdbscm_breakpoint_object;
-struct get_number_or_range_state;
+struct number_or_range_parser;
 struct thread_info;
 struct bpstats;
 struct bp_location;
@@ -1587,8 +1587,8 @@ extern struct tracepoint *get_tracepoint_by_number_on_target (int num);
 
 /* Find a tracepoint by parsing a number in the supplied string.  */
 extern struct tracepoint *
-     get_tracepoint_by_number (char **arg, 
-			       struct get_number_or_range_state *state);
+  get_tracepoint_by_number (char **arg,
+			    number_or_range_parser *parser);
 
 /* Return a vector of all tracepoints currently defined.  The vector
    is newly allocated; the caller should free when done with it.  */
diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c
index 0946db0..0fb68f2 100644
--- a/gdb/cli/cli-utils.c
+++ b/gdb/cli/cli-utils.c
@@ -121,39 +121,49 @@ get_number (char **pp)
 
 /* See documentation in cli-utils.h.  */
 
+number_or_range_parser::number_or_range_parser (const char *string)
+{
+  init (string);
+}
+
+/* See documentation in cli-utils.h.  */
+
 void
-init_number_or_range (struct get_number_or_range_state *state,
-		      const char *string)
+number_or_range_parser::init (const char *string)
 {
-  memset (state, 0, sizeof (*state));
-  state->string = string;
+  m_finished = false;
+  m_cur_tok = string;
+  m_last_retval = 0;
+  m_end_value = 0;
+  m_end_ptr = NULL;
+  m_in_range = false;
 }
 
 /* See documentation in cli-utils.h.  */
 
 int
-get_number_or_range (struct get_number_or_range_state *state)
+number_or_range_parser::get_number ()
 {
-  if (state->in_range)
+  if (m_in_range)
     {
       /* All number-parsing has already been done.  Return the next
 	 integer value (one greater than the saved previous value).
 	 Do not advance the token pointer until the end of range is
 	 reached.  */
 
-      if (++state->last_retval == state->end_value)
+      if (++m_last_retval == m_end_value)
 	{
 	  /* End of range reached; advance token pointer.  */
-	  state->string = state->end_ptr;
-	  state->in_range = 0;
+	  m_cur_tok = m_end_ptr;
+	  m_in_range = false;
 	}
     }
-  else if (*state->string != '-')
+  else if (*m_cur_tok != '-')
     {
-      /* Default case: state->string is pointing either to a solo
+      /* Default case: state->m_cur_tok is pointing either to a solo
 	 number, or to the first number of a range.  */
-      state->last_retval = get_number_trailer (&state->string, '-');
-      if (*state->string == '-')
+      m_last_retval = get_number_trailer (&m_cur_tok, '-');
+      if (*m_cur_tok == '-')
 	{
 	  const char **temp;
 
@@ -161,42 +171,42 @@ get_number_or_range (struct get_number_or_range_state *state)
 	     Skip the '-', parse and remember the second number,
 	     and also remember the end of the final token.  */
 
-	  temp = &state->end_ptr; 
-	  state->end_ptr = skip_spaces_const (state->string + 1);
-	  state->end_value = get_number_const (temp);
-	  if (state->end_value < state->last_retval) 
+	  temp = &m_end_ptr;
+	  m_end_ptr = skip_spaces_const (m_cur_tok + 1);
+	  m_end_value = get_number_const (temp);
+	  if (m_end_value < m_last_retval)
 	    {
 	      error (_("inverted range"));
 	    }
-	  else if (state->end_value == state->last_retval)
+	  else if (m_end_value == m_last_retval)
 	    {
 	      /* Degenerate range (number1 == number2).  Advance the
 		 token pointer so that the range will be treated as a
-		 single number.  */ 
-	      state->string = state->end_ptr;
+		 single number.  */
+	      m_cur_tok = m_end_ptr;
 	    }
 	  else
-	    state->in_range = 1;
+	    m_in_range = true;
 	}
     }
   else
     error (_("negative value"));
-  state->finished = *state->string == '\0';
-  return state->last_retval;
+  m_finished = *m_cur_tok == '\0';
+  return m_last_retval;
 }
 
 /* See documentation in cli-utils.h.  */
 
 void
-number_range_setup_range (struct get_number_or_range_state *state,
-			  int start_value, int end_value, const char *end_ptr)
+number_or_range_parser::setup_range (int start_value, int end_value,
+				     const char *end_ptr)
 {
   gdb_assert (start_value > 0);
 
-  state->in_range = 1;
-  state->end_ptr = end_ptr;
-  state->last_retval = start_value - 1;
-  state->end_value = end_value;
+  m_in_range = true;
+  m_end_ptr = end_ptr;
+  m_last_retval = start_value - 1;
+  m_end_value = end_value;
 }
 
 /* Accept a number and a string-form list of numbers such as is 
@@ -210,15 +220,13 @@ number_range_setup_range (struct get_number_or_range_state *state,
 int
 number_is_in_list (const char *list, int number)
 {
-  struct get_number_or_range_state state;
-
   if (list == NULL || *list == '\0')
     return 1;
 
-  init_number_or_range (&state, list);
-  while (!state.finished)
+  number_or_range_parser parser (list);
+  while (!parser.finished ())
     {
-      int gotnum = get_number_or_range (&state);
+      int gotnum = parser.get_number ();
 
       if (gotnum == 0)
 	error (_("Args must be numbers or '$' variables."));
diff --git a/gdb/cli/cli-utils.h b/gdb/cli/cli-utils.h
index a31fff5..3188bb7 100644
--- a/gdb/cli/cli-utils.h
+++ b/gdb/cli/cli-utils.h
@@ -39,65 +39,91 @@ extern int get_number_const (const char **);
 
 extern int get_number (char **);
 
-/* An object of this type is passed to get_number_or_range.  It must
-   be initialized by calling init_number_or_range.  This type is
-   defined here so that it can be stack-allocated, but all members
-   other than `finished' and `string' should be treated as opaque.  */
+/* Parse a number or a range.
+   A number will be of the form handled by get_number.
+   A range will be of the form <number1> - <number2>, and
+   will represent all the integers between number1 and number2,
+   inclusive.  */
 
-struct get_number_or_range_state
+class number_or_range_parser
 {
-  /* Non-zero if parsing has completed.  */
-  int finished;
+public:
+  /* Default construction.  Must call init before calling
+     get_next.  */
+  number_or_range_parser () {}
+
+  /* Calls init automatically.  */
+  number_or_range_parser (const char *string);
+
+  /* STRING is the string to be parsed.  */
+  void init (const char *string);
+
+  /* While processing a range, this fuction is called iteratively; At
+     each call it will return the next value in the range.
+
+     At the beginning of parsing a range, the char pointer
+     STATE->m_cur_tok will be advanced past <number1> and left
+     pointing at the '-' token.  Subsequent calls will not advance the
+     pointer until the range is completed.  The call that completes
+     the range will advance the pointer past <number2>.  */
+  int get_number ();
+
+  /* Setup internal state such that get_next() returns numbers in the
+     START_VALUE to END_VALUE range.  END_PTR is where the string is
+     advanced to when get_next() returns END_VALUE.  */
+  void setup_range (int start_value, int end_value,
+		    const char *end_ptr);
+
+  /* Returns true if parsing has completed.  */
+  bool finished () const
+  { return m_finished; }
+
+  /* Return the string being parsed.  When parsing has finished, this
+     points past the last parsed token.  */
+  const char *cur_tok () const
+  { return m_cur_tok; }
+
+  /* True when parsing a range.  */
+  bool in_range () const
+  { return m_in_range; }
+
+  /* When parsing a range, the final value in the range.  */
+  int end_value () const
+  { return m_end_value; }
+
+  /* When parsing a range, skip past the final token in the range.  */
+  void skip_range ()
+  {
+    gdb_assert (m_in_range);
+    m_cur_tok = m_end_ptr;
+  }
+
+private:
+  /* No need for these.  They are intentionally not defined anywhere.  */
+  number_or_range_parser (const number_or_range_parser &);
+  number_or_range_parser &operator= (const number_or_range_parser &);
+
+  /* True if parsing has completed.  */
+  bool m_finished;
 
   /* The string being parsed.  When parsing has finished, this points
      past the last parsed token.  */
-  const char *string;
+  const char *m_cur_tok;
 
   /* Last value returned.  */
-  int last_retval;
+  int m_last_retval;
 
   /* When parsing a range, the final value in the range.  */
-  int end_value;
+  int m_end_value;
 
   /* When parsing a range, a pointer past the final token in the
      range.  */
-  const char *end_ptr;
+  const char *m_end_ptr;
 
-  /* Non-zero when parsing a range.  */
-  int in_range;
+  /* True when parsing a range.  */
+  bool m_in_range;
 };
 
-/* Initialize a get_number_or_range_state for use with
-   get_number_or_range_state.  STRING is the string to be parsed.  */
-
-extern void init_number_or_range (struct get_number_or_range_state *state,
-				  const char *string);
-
-/* Parse a number or a range.
-   A number will be of the form handled by get_number.
-   A range will be of the form <number1> - <number2>, and 
-   will represent all the integers between number1 and number2,
-   inclusive.
-
-   While processing a range, this fuction is called iteratively;
-   At each call it will return the next value in the range.
-
-   At the beginning of parsing a range, the char pointer STATE->string will
-   be advanced past <number1> and left pointing at the '-' token.
-   Subsequent calls will not advance the pointer until the range
-   is completed.  The call that completes the range will advance
-   the pointer past <number2>.  */
-
-extern int get_number_or_range (struct get_number_or_range_state *state);
-
-/* Setups STATE such that get_number_or_range returns numbers in range
-   START_VALUE to END_VALUE.  When get_number_or_range returns
-   END_VALUE, the STATE string is advanced to END_PTR.  */
-
-extern void number_range_setup_range (struct get_number_or_range_state *state,
-				      int start_value, int end_value,
-				      const char *end_ptr);
-
 /* Accept a number and a string-form list of numbers such as is 
    accepted by get_number_or_range.  Return TRUE if the number is
    in the list.
diff --git a/gdb/inferior.c b/gdb/inferior.c
index 277b988..1602483 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -651,17 +651,15 @@ print_inferior (struct ui_out *uiout, char *requested_inferiors)
 static void
 detach_inferior_command (char *args, int from_tty)
 {
-  int num, pid;
   struct thread_info *tp;
-  struct get_number_or_range_state state;
 
   if (!args || !*args)
     error (_("Requires argument (inferior id(s) to detach)"));
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      num = get_number_or_range (&state);
+      int num = parser.get_number ();
 
       if (!valid_gdb_inferior_id (num))
 	{
@@ -669,7 +667,7 @@ detach_inferior_command (char *args, int from_tty)
 	  continue;
 	}
 
-      pid = gdb_inferior_id_to_pid (num);
+      int pid = gdb_inferior_id_to_pid (num);
       if (pid == 0)
 	{
 	  warning (_("Inferior ID %d is not running."), num);
@@ -692,17 +690,15 @@ detach_inferior_command (char *args, int from_tty)
 static void
 kill_inferior_command (char *args, int from_tty)
 {
-  int num, pid;
   struct thread_info *tp;
-  struct get_number_or_range_state state;
 
   if (!args || !*args)
     error (_("Requires argument (inferior id(s) to kill)"));
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      num = get_number_or_range (&state);
+      int num = parser.get_number ();
 
       if (!valid_gdb_inferior_id (num))
 	{
@@ -710,7 +706,7 @@ kill_inferior_command (char *args, int from_tty)
 	  continue;
 	}
 
-      pid = gdb_inferior_id_to_pid (num);
+      int pid = gdb_inferior_id_to_pid (num);
       if (pid == 0)
 	{
 	  warning (_("Inferior ID %d is not running."), num);
@@ -788,18 +784,14 @@ info_inferiors_command (char *args, int from_tty)
 static void
 remove_inferior_command (char *args, int from_tty)
 {
-  int num;
-  struct inferior *inf;
-  struct get_number_or_range_state state;
-
   if (args == NULL || *args == '\0')
     error (_("Requires an argument (inferior id(s) to remove)"));
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      num = get_number_or_range (&state);
-      inf = find_inferior_id (num);
+      int num = parser.get_number ();
+      struct inferior *inf = find_inferior_id (num);
 
       if (inf == NULL)
 	{
diff --git a/gdb/linespec.c b/gdb/linespec.c
index ccedec8..5182b45 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -1328,7 +1328,6 @@ decode_line_2 (struct linespec_state *self,
   int i;
   struct cleanup *old_chain;
   VEC (const_char_ptr) *filters = NULL;
-  struct get_number_or_range_state state;
   struct decode_line_2_item *items;
   int items_count;
 
@@ -1409,12 +1408,10 @@ decode_line_2 (struct linespec_state *self,
   if (args == 0 || *args == 0)
     error_no_arg (_("one or more choice numbers"));
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      int num;
-
-      num = get_number_or_range (&state);
+      int num = parser.get_number ();
 
       if (num == 0)
 	error (_("canceled"));
diff --git a/gdb/memattr.c b/gdb/memattr.c
index c4a3b75..1c5c48f 100644
--- a/gdb/memattr.c
+++ b/gdb/memattr.c
@@ -578,12 +578,10 @@ mem_enable_command (char *args, int from_tty)
     }
   else
     {
-      struct get_number_or_range_state state;
-
-      init_number_or_range (&state, args);
-      while (!state.finished)
+      number_or_range_parser parser (args);
+      while (!parser.finished ())
 	{
-	  num = get_number_or_range (&state);
+	  num = parser.get_number ();
 	  mem_enable (num);
 	}
     }
@@ -610,27 +608,24 @@ mem_disable (int num)
 static void
 mem_disable_command (char *args, int from_tty)
 {
-  int num;
-  struct mem_region *m;
-  int ix;
-
   require_user_regions (from_tty);
 
   target_dcache_invalidate ();
 
   if (args == NULL || *args == '\0')
     {
+      struct mem_region *m;
+      int ix;
+
       for (ix = 0; VEC_iterate (mem_region_s, mem_region_list, ix, m); ix++)
 	m->enabled_p = 0;
     }
   else
     {
-      struct get_number_or_range_state state;
-
-      init_number_or_range (&state, args);
-      while (!state.finished)
+      number_or_range_parser parser (args);
+      while (!parser.finished ())
 	{
-	  num = get_number_or_range (&state);
+	  int num = parser.get_number ();
 	  mem_disable (num);
 	}
     }
@@ -666,9 +661,6 @@ mem_delete (int num)
 static void
 mem_delete_command (char *args, int from_tty)
 {
-  int num;
-  struct get_number_or_range_state state;
-
   require_user_regions (from_tty);
 
   target_dcache_invalidate ();
@@ -681,10 +673,10 @@ mem_delete_command (char *args, int from_tty)
       return;
     }
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      num = get_number_or_range (&state);
+      int num = parser.get_number ();
       mem_delete (num);
     }
 
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index d4a4b9e..c7f477b 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1876,19 +1876,18 @@ map_display_numbers (char *args,
 				       void *),
 		     void *data)
 {
-  struct get_number_or_range_state state;
   int num;
 
   if (args == NULL)
     error_no_arg (_("one or more display numbers"));
 
-  init_number_or_range (&state, args);
+  number_or_range_parser parser (args);
 
-  while (!state.finished)
+  while (!parser.finished ())
     {
-      const char *p = state.string;
+      const char *p = parser.cur_tok ();
 
-      num = get_number_or_range (&state);
+      num = parser.get_number ();
       if (num == 0)
 	warning (_("bad display number at or near '%s'"), p);
       else
diff --git a/gdb/reverse.c b/gdb/reverse.c
index a1b697f..2c1abdc 100644
--- a/gdb/reverse.c
+++ b/gdb/reverse.c
@@ -216,9 +216,6 @@ delete_all_bookmarks (void)
 static void
 delete_bookmark_command (char *args, int from_tty)
 {
-  int num;
-  struct get_number_or_range_state state;
-
   if (bookmark_chain == NULL)
     {
       warning (_("No bookmarks."));
@@ -233,10 +230,10 @@ delete_bookmark_command (char *args, int from_tty)
       return;
     }
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      num = get_number_or_range (&state);
+      int num = parser.get_number ();
       if (!delete_one_bookmark (num))
 	/* Not found.  */
 	warning (_("No bookmark #%d."), num);
@@ -323,20 +320,16 @@ bookmark_1 (int bnum)
 static void
 bookmarks_info (char *args, int from_tty)
 {
-  int bnum = -1;
-
   if (!bookmark_chain)
     printf_filtered (_("No bookmarks.\n"));
   else if (args == NULL || *args == '\0')
     bookmark_1 (-1);
   else
     {
-      struct get_number_or_range_state state;
-
-      init_number_or_range (&state, args);
-      while (!state.finished)
+      number_or_range_parser parser (args);
+      while (!parser.finished ())
 	{
-	  bnum = get_number_or_range (&state);
+	  int bnum = parser.get_number ();
 	  bookmark_1 (bnum);
 	}
     }
diff --git a/gdb/thread.c b/gdb/thread.c
index 13449a8..57b20ff 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1825,20 +1825,19 @@ thread_apply_command (char *tidlist, int from_tty)
   char *cmd = NULL;
   struct cleanup *old_chain;
   char *saved_cmd;
-  struct tid_range_parser parser;
+  tid_range_parser parser;
 
   if (tidlist == NULL || *tidlist == '\000')
     error (_("Please specify a thread ID list"));
 
-  tid_range_parser_init (&parser, tidlist, current_inferior ()->num);
-  while (!tid_range_parser_finished (&parser))
+  parser.init (tidlist, current_inferior ()->num);
+  while (!parser.finished ())
     {
       int inf_num, thr_start, thr_end;
 
-      if (!tid_range_parser_get_tid_range (&parser,
-					   &inf_num, &thr_start, &thr_end))
+      if (!parser.get_tid_range (&inf_num, &thr_start, &thr_end))
 	{
-	  cmd = (char *) tid_range_parser_string (&parser);
+	  cmd = (char *) parser.cur_tok ();
 	  break;
 	}
     }
@@ -1856,32 +1855,31 @@ thread_apply_command (char *tidlist, int from_tty)
 
   make_cleanup_restore_current_thread ();
 
-  tid_range_parser_init (&parser, tidlist, current_inferior ()->num);
-  while (!tid_range_parser_finished (&parser)
-	 && tid_range_parser_string (&parser) < cmd)
+  parser.init (tidlist, current_inferior ()->num);
+  while (!parser.finished () && parser.cur_tok () < cmd)
     {
       struct thread_info *tp = NULL;
       struct inferior *inf;
       int inf_num, thr_num;
 
-      tid_range_parser_get_tid (&parser, &inf_num, &thr_num);
+      parser.get_tid (&inf_num, &thr_num);
       inf = find_inferior_id (inf_num);
       if (inf != NULL)
 	tp = find_thread_id (inf, thr_num);
 
-      if (tid_range_parser_star_range (&parser))
+      if (parser.in_star_range ())
 	{
 	  if (inf == NULL)
 	    {
 	      warning (_("Unknown inferior %d"), inf_num);
-	      tid_range_parser_skip (&parser);
+	      parser.skip_range ();
 	      continue;
 	    }
 
 	  /* No use looking for threads past the highest thread number
 	     the inferior ever had.  */
 	  if (thr_num >= inf->highest_thread_num)
-	    tid_range_parser_skip (&parser);
+	    parser.skip_range ();
 
 	  /* Be quiet about unknown threads numbers.  */
 	  if (tp == NULL)
@@ -1890,8 +1888,7 @@ thread_apply_command (char *tidlist, int from_tty)
 
       if (tp == NULL)
 	{
-	  if (show_inferior_qualified_tids ()
-	      || tid_range_parser_qualified (&parser))
+	  if (show_inferior_qualified_tids () || parser.tid_is_qualified ())
 	    warning (_("Unknown thread %d.%d"), inf_num, thr_num);
 	  else
 	    warning (_("Unknown thread %d"), thr_num);
diff --git a/gdb/tid-parse.c b/gdb/tid-parse.c
index 68133c6..73bf673 100644
--- a/gdb/tid-parse.c
+++ b/gdb/tid-parse.c
@@ -113,29 +113,36 @@ parse_thread_id (const char *tidstr, const char **end)
 
 /* See tid-parse.h.  */
 
+tid_range_parser::tid_range_parser (const char *tidlist,
+				    int default_inferior)
+{
+  init (tidlist, default_inferior);
+}
+
+/* See tid-parse.h.  */
+
 void
-tid_range_parser_init (struct tid_range_parser *parser, const char *tidlist,
-		       int default_inferior)
+tid_range_parser::init (const char *tidlist, int default_inferior)
 {
-  parser->state = TID_RANGE_STATE_INFERIOR;
-  parser->string = tidlist;
-  parser->inf_num = 0;
-  parser->qualified = 0;
-  parser->default_inferior = default_inferior;
+  m_state = STATE_INFERIOR;
+  m_cur_tok = tidlist;
+  m_inf_num = 0;
+  m_qualified = false;
+  m_default_inferior = default_inferior;
 }
 
 /* See tid-parse.h.  */
 
-int
-tid_range_parser_finished (struct tid_range_parser *parser)
+bool
+tid_range_parser::finished () const
 {
-  switch (parser->state)
+  switch (m_state)
     {
-    case TID_RANGE_STATE_INFERIOR:
-      return *parser->string == '\0';
-    case TID_RANGE_STATE_THREAD_RANGE:
-    case TID_RANGE_STATE_STAR_RANGE:
-      return parser->range_parser.finished;
+    case STATE_INFERIOR:
+      return *m_cur_tok == '\0';
+    case STATE_THREAD_RANGE:
+    case STATE_STAR_RANGE:
+      return m_range_parser.finished ();
     }
 
   gdb_assert_not_reached (_("unhandled state"));
@@ -144,57 +151,54 @@ tid_range_parser_finished (struct tid_range_parser *parser)
 /* See tid-parse.h.  */
 
 const char *
-tid_range_parser_string (struct tid_range_parser *parser)
+tid_range_parser::cur_tok () const
 {
-  switch (parser->state)
+  switch (m_state)
     {
-    case TID_RANGE_STATE_INFERIOR:
-      return parser->string;
-    case TID_RANGE_STATE_THREAD_RANGE:
-    case TID_RANGE_STATE_STAR_RANGE:
-      return parser->range_parser.string;
+    case STATE_INFERIOR:
+      return m_cur_tok;
+    case STATE_THREAD_RANGE:
+    case STATE_STAR_RANGE:
+      return m_range_parser.cur_tok ();
     }
 
   gdb_assert_not_reached (_("unhandled state"));
 }
 
-/* See tid-parse.h.  */
-
 void
-tid_range_parser_skip (struct tid_range_parser *parser)
+tid_range_parser::skip_range ()
 {
-  gdb_assert ((parser->state == TID_RANGE_STATE_THREAD_RANGE
-	       || parser->state == TID_RANGE_STATE_STAR_RANGE)
-	      && parser->range_parser.in_range);
+  gdb_assert (m_state == STATE_THREAD_RANGE
+	      || m_state == STATE_STAR_RANGE);
 
-  tid_range_parser_init (parser, parser->range_parser.end_ptr,
-			 parser->default_inferior);
+  m_range_parser.skip_range ();
+  init (m_range_parser.cur_tok (), m_default_inferior);
 }
 
 /* See tid-parse.h.  */
 
-int
-tid_range_parser_qualified (struct tid_range_parser *parser)
+bool
+tid_range_parser::tid_is_qualified () const
 {
-  return parser->qualified;
+  return m_qualified;
 }
 
-/* Helper for tid_range_parser_get_tid and
-   tid_range_parser_get_tid_range.  Return the next range if THR_END
+/* Helper for tid_range_parser::get_tid and
+   tid_range_parser::get_tid_range.  Return the next range if THR_END
    is non-NULL, return a single thread ID otherwise.  */
 
-static int
-get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
-		  int *thr_start, int *thr_end)
+bool
+tid_range_parser::get_tid_or_range (int *inf_num,
+				    int *thr_start, int *thr_end)
 {
-  if (parser->state == TID_RANGE_STATE_INFERIOR)
+  if (m_state == STATE_INFERIOR)
     {
       const char *p;
       const char *space;
 
-      space = skip_to_space (parser->string);
+      space = skip_to_space (m_cur_tok);
 
-      p = parser->string;
+      p = m_cur_tok;
       while (p < space && *p != '.')
 	p++;
       if (p < space)
@@ -202,56 +206,53 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
 	  const char *dot = p;
 
 	  /* Parse number to the left of the dot.  */
-	  p = parser->string;
-	  parser->inf_num
-	    = get_positive_number_trailer (&p, '.', parser->string);
-	  if (parser->inf_num == 0)
+	  p = m_cur_tok;
+	  m_inf_num = get_positive_number_trailer (&p, '.', m_cur_tok);
+	  if (m_inf_num == 0)
 	    return 0;
 
-	  parser->qualified = 1;
+	  m_qualified = true;
 	  p = dot + 1;
 
 	  if (isspace (*p))
-	    return 0;
+	    return false;
 	}
       else
 	{
-	  parser->inf_num = parser->default_inferior;
-	  parser->qualified = 0;
-	  p = parser->string;
+	  m_inf_num = m_default_inferior;
+	  m_qualified = false;
+	  p = m_cur_tok;
 	}
 
-      init_number_or_range (&parser->range_parser, p);
+      m_range_parser.init (p);
       if (p[0] == '*' && (p[1] == '\0' || isspace (p[1])))
 	{
 	  /* Setup the number range parser to return numbers in the
 	     whole [1,INT_MAX] range.  */
-	  number_range_setup_range (&parser->range_parser, 1, INT_MAX,
-				    skip_spaces_const (p + 1));
-	  parser->state = TID_RANGE_STATE_STAR_RANGE;
+	  m_range_parser.setup_range (1, INT_MAX, skip_spaces_const (p + 1));
+	  m_state = STATE_STAR_RANGE;
 	}
       else
-	parser->state = TID_RANGE_STATE_THREAD_RANGE;
+	m_state = STATE_THREAD_RANGE;
     }
 
-  *inf_num = parser->inf_num;
-  *thr_start = get_number_or_range (&parser->range_parser);
+  *inf_num = m_inf_num;
+  *thr_start = m_range_parser.get_number ();
   if (*thr_start < 0)
-    error (_("negative value: %s"), parser->string);
+    error (_("negative value: %s"), m_cur_tok);
   if (*thr_start == 0)
     {
-      parser->state = TID_RANGE_STATE_INFERIOR;
-      return 0;
+      m_state = STATE_INFERIOR;
+      return false;
     }
 
   /* If we successfully parsed a thread number or finished parsing a
      thread range, switch back to assuming the next TID is
      inferior-qualified.  */
-  if (parser->range_parser.end_ptr == NULL
-      || parser->range_parser.string == parser->range_parser.end_ptr)
+  if (!m_range_parser.in_range ())
     {
-      parser->state = TID_RANGE_STATE_INFERIOR;
-      parser->string = parser->range_parser.string;
+      m_state = STATE_INFERIOR;
+      m_cur_tok = m_range_parser.cur_tok ();
 
       if (thr_end != NULL)
 	*thr_end = *thr_start;
@@ -260,11 +261,12 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
   /* If we're midway through a range, and the caller wants the end
      value, return it and skip to the end of the range.  */
   if (thr_end != NULL
-      && (parser->state == TID_RANGE_STATE_THREAD_RANGE
-	  || parser->state == TID_RANGE_STATE_STAR_RANGE))
+      && (m_state == STATE_THREAD_RANGE
+	  || m_state == STATE_STAR_RANGE))
     {
-      *thr_end = parser->range_parser.end_value;
-      tid_range_parser_skip (parser);
+      *thr_end = m_range_parser.end_value ();
+
+      skip_range ();
     }
 
   return (*inf_num != 0 && *thr_start != 0);
@@ -272,32 +274,31 @@ get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
 
 /* See tid-parse.h.  */
 
-int
-tid_range_parser_get_tid_range (struct tid_range_parser *parser, int *inf_num,
-				int *thr_start, int *thr_end)
+bool
+tid_range_parser::get_tid_range (int *inf_num,
+				 int *thr_start, int *thr_end)
 {
   gdb_assert (inf_num != NULL && thr_start != NULL && thr_end != NULL);
 
-  return get_tid_or_range (parser, inf_num, thr_start, thr_end);
+  return get_tid_or_range (inf_num, thr_start, thr_end);
 }
 
 /* See tid-parse.h.  */
 
-int
-tid_range_parser_get_tid (struct tid_range_parser *parser,
-			  int *inf_num, int *thr_num)
+bool
+tid_range_parser::get_tid (int *inf_num, int *thr_num)
 {
   gdb_assert (inf_num != NULL && thr_num != NULL);
 
-  return get_tid_or_range (parser, inf_num, thr_num, NULL);
+  return get_tid_or_range (inf_num, thr_num, NULL);
 }
 
 /* See tid-parse.h.  */
 
-int
-tid_range_parser_star_range (struct tid_range_parser *parser)
+bool
+tid_range_parser::in_star_range () const
 {
-  return parser->state == TID_RANGE_STATE_STAR_RANGE;
+  return m_state == STATE_STAR_RANGE;
 }
 
 /* See gdbthread.h.  */
@@ -306,19 +307,16 @@ int
 tid_is_in_list (const char *list, int default_inferior,
 		int inf_num, int thr_num)
 {
-  struct tid_range_parser parser;
-
   if (list == NULL || *list == '\0')
     return 1;
 
-  tid_range_parser_init (&parser, list, default_inferior);
-  while (!tid_range_parser_finished (&parser))
+  tid_range_parser parser (list, default_inferior);
+  while (!parser.finished ())
     {
       int tmp_inf, tmp_thr_start, tmp_thr_end;
 
-      if (!tid_range_parser_get_tid_range (&parser, &tmp_inf,
-					   &tmp_thr_start, &tmp_thr_end))
-	invalid_thread_id_error (parser.string);
+      if (!parser.get_tid_range (&tmp_inf, &tmp_thr_start, &tmp_thr_end))
+	invalid_thread_id_error (parser.cur_tok ());
       if (tmp_inf == inf_num
 	  && tmp_thr_start <= thr_num && thr_num <= tmp_thr_end)
 	return 1;
diff --git a/gdb/tid-parse.h b/gdb/tid-parse.h
index 830cf36..1f6ae90 100644
--- a/gdb/tid-parse.h
+++ b/gdb/tid-parse.h
@@ -36,56 +36,6 @@ extern void ATTRIBUTE_NORETURN invalid_thread_id_error (const char *string);
    thrown.  */
 struct thread_info *parse_thread_id (const char *tidstr, const char **end);
 
-/* The possible states of the tid range parser's state machine.  */
-enum tid_range_state
-{
-  /* Parsing the inferior number.  */
-  TID_RANGE_STATE_INFERIOR,
-
-  /* Parsing the thread number or thread number range.  */
-  TID_RANGE_STATE_THREAD_RANGE,
-
-  /* Parsing a star wildcard thread range.  E.g., "1.*".  */
-  TID_RANGE_STATE_STAR_RANGE,
-};
-
-/* An object of this type is passed to tid_range_parser_get_tid.  It
-   must be initialized by calling tid_range_parser_init.  This type is
-   defined here so that it can be stack-allocated, but all members
-   should be treated as opaque.  */
-struct tid_range_parser
-{
-  /* What sub-component are we expecting.  */
-  enum tid_range_state state;
-
-  /* The string being parsed.  When parsing has finished, this points
-     past the last parsed token.  */
-  const char *string;
-
-  /* The range parser state when we're parsing the thread number
-     sub-component.  */
-  struct get_number_or_range_state range_parser;
-
-  /* Last inferior number returned.  */
-  int inf_num;
-
-  /* True if the TID last parsed was explicitly inferior-qualified.
-     IOW, whether the spec specified an inferior number
-     explicitly.  */
-  int qualified;
-
-  /* The inferior number to assume if the TID is not qualified.  */
-  int default_inferior;
-};
-
-/* Initialize a tid_range_parser for use with
-   tid_range_parser_get_tid.  TIDLIST is the string to be parsed.
-   DEFAULT_INFERIOR is the inferior number to assume if a
-   non-qualified thread ID is found.  */
-extern void tid_range_parser_init (struct tid_range_parser *parser,
-				   const char *tidlist,
-				   int default_inferior);
-
 /* Parse a thread ID or a thread range list.
 
    A range will be of the form
@@ -99,74 +49,133 @@ extern void tid_range_parser_init (struct tid_range_parser *parser,
      <thread_number1>-<thread_number2>
 
    in which case GDB infers the inferior number from the default
-   passed to the tid_range_parser_init function.
+   passed to the constructor or to the last call to the init
+   function.  */
+class tid_range_parser
+{
+public:
+  /* Default construction.  Must call init before calling get_*.  */
+  tid_range_parser () {}
+
+  /* Calls init automatically.  See init for description of
+     parameters.  */
+  tid_range_parser (const char *tidlist, int default_inferior);
+
+  /* Reinitialize a tid_range_parser.  TIDLIST is the string to be
+     parsed.  DEFAULT_INFERIOR is the inferior number to assume if a
+     non-qualified thread ID is found.  */
+  void init (const char *tidlist, int default_inferior);
 
-   This function is designed to be called iteratively.  While
-   processing a thread ID range list, at each call it will return (in
-   the INF_NUM and THR_NUM output parameters) the next thread ID in
-   the range (irrespective of whether the thread actually exists).
+  /* Parse a thread ID or a thread range list.
 
-   At the beginning of parsing a thread range, the char pointer
-   PARSER->string will be advanced past <thread_number1> and left
-   pointing at the '-' token.  Subsequent calls will not advance the
-   pointer until the range is completed.  The call that completes the
-   range will advance the pointer past <thread_number2>.
+     This function is designed to be called iteratively.  While
+     processing a thread ID range list, at each call it will return
+     (in the INF_NUM and THR_NUM output parameters) the next thread ID
+     in the range (irrespective of whether the thread actually
+     exists).
 
-   This function advances through the input string for as long you
-   call it.  Once the end of the input string is reached, a call to
-   tid_range_parser_finished returns false (see below).
+     At the beginning of parsing a thread range, the char pointer
+     PARSER->m_cur_tok will be advanced past <thread_number1> and left
+     pointing at the '-' token.  Subsequent calls will not advance the
+     pointer until the range is completed.  The call that completes
+     the range will advance the pointer past <thread_number2>.
 
-   E.g., with list: "1.2 3.4-6":
+     This function advances through the input string for as long you
+     call it.  Once the end of the input string is reached, a call to
+     finished returns false (see below).
+
+     E.g., with list: "1.2 3.4-6":
 
      1st call: *INF_NUM=1; *THR_NUM=2 (finished==0)
      2nd call: *INF_NUM=3; *THR_NUM=4 (finished==0)
      3rd call: *INF_NUM=3; *THR_NUM=5 (finished==0)
      4th call: *INF_NUM=3; *THR_NUM=6 (finished==1)
 
-   Returns true if parsed a thread/range successfully, false
-   otherwise.  */
-extern int tid_range_parser_get_tid (struct tid_range_parser *parser,
-				      int *inf_num, int *thr_num);
+     Returns true if a thread/range is parsed successfully, false
+     otherwise.  */
+  bool get_tid (int *inf_num, int *thr_num);
 
-/* Like tid_range_parser_get_tid, but return a thread ID range per
-   call, rather then a single thread ID.
+  /* Like get_tid, but return a thread ID range per call, rather then
+     a single thread ID.
 
-   If the next element in the list is a single thread ID, then
-   *THR_START and *THR_END are set to the same value.
+     If the next element in the list is a single thread ID, then
+     *THR_START and *THR_END are set to the same value.
 
-   E.g.,. with list: "1.2 3.4-6"
+     E.g.,. with list: "1.2 3.4-6"
 
      1st call: *INF_NUM=1; *THR_START=2; *THR_END=2 (finished==0)
      2nd call: *INF_NUM=3; *THR_START=4; *THR_END=6 (finished==1)
 
-   Returns true if parsed a thread/range successfully, false
-   otherwise.  */
-extern int tid_range_parser_get_tid_range (struct tid_range_parser *parser,
-					   int *inf_num,
-					   int *thr_start, int *thr_end);
+     Returns true if parsed a thread/range successfully, false
+     otherwise.  */
+  bool get_tid_range (int *inf_num, int *thr_start, int *thr_end);
+
+  /* Returns true if processing a star wildcard (e.g., "1.*")
+     range.  */
+  bool in_star_range () const;
+
+  /* Returns true if parsing has completed.  */
+  bool finished () const;
+
+  /* Return the current token being parsed.  When parsing has
+     finished, this points past the last parsed token.  */
+  const char *cur_tok () const;
 
-/* Returns non-zero if processing a star wildcard (e.g., "1.*")
-   range.  */
-extern int tid_range_parser_star_range (struct tid_range_parser *parser);
+  /* When parsing a range, advance past the final token in the
+     range.  */
+  void skip_range ();
 
-/* Returns non-zero if parsing has completed.  */
-extern int tid_range_parser_finished (struct tid_range_parser *parser);
+  /* True if the TID last parsed was explicitly inferior-qualified.
+     IOW, whether the spec specified an inferior number
+     explicitly.  */
+  bool tid_is_qualified () const;
 
-/* Return the string being parsed.  When parsing has finished, this
-   points past the last parsed token.  */
-const char *tid_range_parser_string (struct tid_range_parser *parser);
+private:
+  /* No need for these.  They are intentionally not defined anywhere.  */
+  tid_range_parser (const tid_range_parser &);
+  tid_range_parser &operator= (const tid_range_parser &);
 
-/* When parsing a range, advance past the final token in the range.  */
-extern void tid_range_parser_skip (struct tid_range_parser *parser);
+  bool get_tid_or_range (int *inf_num, int *thr_start, int *thr_end);
+
+  /* The possible states of the tid range parser's state machine,
+     indicating what sub-component are we expecting.  */
+  enum
+    {
+      /* Parsing the inferior number.  */
+      STATE_INFERIOR,
+
+      /* Parsing the thread number or thread number range.  */
+      STATE_THREAD_RANGE,
+
+      /* Parsing a star wildcard thread range.  E.g., "1.*".  */
+      STATE_STAR_RANGE,
+    } m_state;
+
+  /* The string being parsed.  When parsing has finished, this points
+     past the last parsed token.  */
+  const char *m_cur_tok;
+
+  /* The range parser state when we're parsing the thread number
+     sub-component.  */
+  number_or_range_parser m_range_parser;
+
+  /* Last inferior number returned.  */
+  int m_inf_num;
+
+  /* True if the TID last parsed was explicitly inferior-qualified.
+     IOW, whether the spec specified an inferior number
+     explicitly.  */
+  bool m_qualified;
+
+  /* The inferior number to assume if the TID is not qualified.  */
+  int m_default_inferior;
+};
 
-/* True if the TID last parsed was explicitly inferior-qualified.
-   IOW, whether the spec specified an inferior number explicitly.  */
-extern int tid_range_parser_qualified (struct tid_range_parser *parser);
 
 /* Accept a string-form list of thread IDs such as is accepted by
-   tid_range_parser_get_tid.  Return true if the INF_NUM.THR.NUM
-   thread is in the list.  DEFAULT_INFERIOR is the inferior number to
-   assume if a non-qualified thread ID is found in the list.
+   tid_range_parser.  Return true if the INF_NUM.THR.NUM thread is in
+   the list.  DEFAULT_INFERIOR is the inferior number to assume if a
+   non-qualified thread ID is found in the list.
 
    By definition, an empty list includes all threads.  This is to be
    interpreted as typing a command such as "info threads" with no
-- 
2.5.5


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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-10-02 17:11                 ` Tom Tromey
@ 2016-10-05  0:06                   ` Pedro Alves
  2016-10-12 22:36                     ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-05  0:06 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Trevor Saunders, gdb-patches

On 10/02/2016 06:11 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
>>> However, once you need a copy constructor, it doesn't seem possible
>>> without a move constructor.  The issue is that a copy constructor take a
>>> const reference, so you can't modify the fields of the original.
> 
> Pedro> You can -- make the fields mutable.
> 
> Ok, yeah, I had thought of this, but it seemed pretty ugly to me.

It's hidden in the "library", so it'd be super fine with me.
I think of it as just part of the idiom.

> 
> Instead I removed all the 2 argument forms in favor of a second explicit
> assignment.  This solves the problem as well.

OK, I thought a little bit more about my worry with the implicit
copy constructor, and I think I was originally right -- it doesn't
make a difference; things still work if the compiler doesn't elide,
because the single-argument form doesn't change the global.  Guess
you could confirm things still build and run properly
with -fno-elide-constructors.

> I can go back and do the mutable thing if you really prefer it though.

I don't have a strong preference.  Maybe client code using the 1-argument form
ends up looking cleaner, in any case, not sure.

> 
> 
> Pedro> The gist is that I think that the features supported by compilers that
> Pedro> people are using in practice to build gdb with is what matters
> Pedro> in the end, not really C++03 vs C++11.
> 
> The issue I see is that it's just too easy otherwise for C++11isms to
> slip in, especially considering that everybody doing development is
> likely to be using a compiler with all the C++11 features.  Maybe
> buildbot can do C++03 builds to check.

I still disagree to an extent.  Even if we were claiming to
require "C++11", we probably wouldn't be able to use _all_ of C++11.
E.g. if we wanted to require full C++11 support, then we're need to
require gcc 4.8, which was released in 2013.  I'd be super fine with
requiring it personally, and I look forward to the day, tbc!
I think it's present in all current versions of major distros, I
believe,  I wouldn't be surprised to find opposition, though.

As compromise, I think we could be much better at documenting the older gcc version
that we actually support compiling with.  That oldest-supported version, I think
should be decided based on what's the oldest version people really care about,
and are willing to routinely test, vs how bad we'd want the C++11 features
not supported by that old compiler.  Last this was discussed, in context of
deciding whether to move forward with the C++ conversion, we settled on gcc 4.2
at least, since that's what some BSDs were still using.  But we have nothing in
place to enforce that, and I suspect that we still build correctly with
older gcc's even.  Or not, I don't know, since no one is testing it, for all I
know (i.e., no one is sending test reports to gdb-testers@).  I think all BSDs have
llvm/clang in their base systems now, so those are probably no longer really a concern.

Because, if we could require say, gcc 4.3 at least, then we
could make use of rvalue references.  If we required gcc 4.4, then we
could use "auto" and other goodies.  Etc.  IOW, if we took an incremental
approach, we'd be bound by the level of C++11 support in the oldest
compiler we supported.  

  https://gcc.gnu.org/projects/cxx-status.html#cxx11

And _that_ version is what I think should be tested by the buildbot,
irrespective of C++98/C++03/C++0x/C++11/... instead of being artificially
blocked by -std=c++03 or some such.

Thanks,
Pedro Alves

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

* Re: [RFA 19/22] Convert tid_range_parser to class
  2016-10-04 23:09           ` Pedro Alves
@ 2016-10-05  2:16             ` Trevor Saunders
  2016-10-12  2:12             ` Tom Tromey
  1 sibling, 0 replies; 123+ messages in thread
From: Trevor Saunders @ 2016-10-05  2:16 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

On Wed, Oct 05, 2016 at 12:09:13AM +0100, Pedro Alves wrote:
> On 10/04/2016 08:24 PM, Pedro Alves wrote:
> 
> > Anyway, I have to disappear now.  Will continue later.
> 
> Here's what I ended up with, after reading your version
> in more detail.  That brought in the "deleted" copy constructor/assignment
> operators [1], and "const" in several methods, which I then propagated
> to number_or_range_parser too.
> 
> WDYT?
> 
> [1] - I'm pondering making those use =delete if compiling with
> a C++ compiler, behind some
> 
>   #define DISABLE_COPY_AND_ASSIGN(TYPE) ...
> 
> macro.
> 
> Or, maybe add a gdb::noncopyable class that non-copyable
> classes inherit from privately, just like boost:noncopyable.
> Anyone got experience on the latter, and whether that turns
> out to be a bad idea?

when Mozilla supported compilers without = delete there was a MOZ_DELETE
macro that was defined to "= delete" when available, but I've never delt
with the latter style.

Trev

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

* Re: [RFA 01/22] Change selttest.c to use use std::vector
  2016-09-27 16:44     ` Tom Tromey
  2016-09-28 14:58       ` Trevor Saunders
@ 2016-10-06  0:18       ` Pedro Alves
  2016-10-06  0:39       ` Pedro Alves
  2 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-06  0:18 UTC (permalink / raw)
  To: Tom Tromey, Trevor Saunders; +Cc: gdb-patches

On 09/27/2016 04:55 PM, Tom Tromey wrote:
> Trevor> I'd agree, hopefully we can throw VEC in the trash some day.  Relatedly
> Trevor> we should probably move gcc's hash table stuff to include/ sooner rather
> Trevor> than later so we can similarly get rid of htab.
> 
> That would be nice; though we could probably use std::set and std::map
> in gdb as well.

std::unordered_map (hash table) would be a more direct replacement.
See gold/system.h -- for C++03 compilers, gold uses unordered_map (and
unordered_set) from std::tr1 if available, otherwise falls back to
std::map (balanced binary tree, usually red/black), with even
older compilers.  The idea being that you'll be able to use gold with
older compilers, though it'll run slower.

Thanks,
Pedro Alves

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

* Re: [RFA 01/22] Change selttest.c to use use std::vector
  2016-09-27 16:44     ` Tom Tromey
  2016-09-28 14:58       ` Trevor Saunders
  2016-10-06  0:18       ` Pedro Alves
@ 2016-10-06  0:39       ` Pedro Alves
  2 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-06  0:39 UTC (permalink / raw)
  To: Tom Tromey, Trevor Saunders; +Cc: gdb-patches

On 09/27/2016 04:55 PM, Tom Tromey wrote:
> Trevor> should we use a pointer to avoid the static initializer?
> 
> I was on the fence about this one.
> On the one hand, static initializers can be very bad.
> On the other hand, this one in particular doesn't seem like it could
> cause problems.

I think it's OK for now.  The patch LGTM.  We may want to revisit later.

I guess with "can be very bad" you're thinking of order of constructors
between compilation units.  Worth keeping in mind is the not making the library
use case harder to get at in the future, considering the potential need for
controlled bring up (static ctors) and teardown (static dtors) independent
of exit() time.   Yet another aspect worth considering is the startup time
overhead impact of global constructors.  VEC has a POD base
class which allows avoiding that:

  https://gcc.gnu.org/ml/gcc-patches/2016-09/msg01651.html

See LLVM here considering/doing similar things:

  https://llvm.org/bugs/show_bug.cgi?id=11944

But that feels like premature optimization too me at this point.

Thanks,
Pedro Alves

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

* Re: [RFA 01/22] Change selttest.c to use use std::vector
  2016-09-30 21:40     ` Tom Tromey
@ 2016-10-06  0:45       ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-06  0:45 UTC (permalink / raw)
  To: Tom Tromey, Simon Marchi; +Cc: gdb-patches

On 09/30/2016 10:16 PM, Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:
>>> +  printf_filtered (_("Ran %lu unit tests, %d failed\n"),
>>> +		   tests.size (), failed);
> 
> Simon> This doesn't build on 32 bits:
> 
> Thanks for trying that.
> I will send it through buildbot before the next round.
> 
> Simon> I think the right format size specifier would be 'z'.
> 
> I will probably cast to long instead.
> I don't see other uses of %zd in gdb.

That's because the %z modifier is a C99 / C++11 feature.

Thanks,
Pedro Alves

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

* Re: [RFA 05/22] Turn wchar iterator into a class
  2016-09-27  4:47 ` [RFA 05/22] Turn wchar iterator into a class Tom Tromey
@ 2016-10-06  1:01   ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-06  1:01 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This changes wchar_iterator from charset.c into a real C++ class, then
> updates the users to use the class.  This lets us remove some cleanups
> in favor of the class' destructor.

LGTM, assuming changed to use m_.

> +
> +  /* The input string.  This is updated as convert characters.  */

While at it, looks like a typo here?  "... as we convert ..." ?

Thanks,
Pedro Alves

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

* Re: [RFA 06/22] Introduce scoped_minimal_symbol_reader
  2016-09-27  4:52 ` [RFA 06/22] Introduce scoped_minimal_symbol_reader Tom Tromey
@ 2016-10-06  1:10   ` Pedro Alves
  2016-10-06 15:37     ` Tom Tromey
  2016-10-10 23:06     ` Tom Tromey
  0 siblings, 2 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-06  1:10 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> -/* Prepare to start collecting minimal symbols.  This should be called
> -   by a symbol reader to initialize the minimal symbol module.
> -   Currently, minimal symbol table creation is not reentrant; it
> -   relies on global (static) variables in minsyms.c.  */
> +// An RAII-based object that is used to record minimal symbols while
> +// they are being read.

GCC eschews using // comments, to avoid ending up with a mixbag of
styles.  Maybe we should follow suit?

> +class scoped_minimal_symbol_reader

Seems like this is growing to be _the_ reader in following patches?
I'm wondering whether the "scoped_" prefix will make sense going
forward.

Thanks,
Pedro Alves

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

* Re: [RFA 08/22] Record minimal symbols directly in reader.
  2016-10-01  4:29   ` Simon Marchi
@ 2016-10-06  1:12     ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-06  1:12 UTC (permalink / raw)
  To: Simon Marchi, Tom Tromey; +Cc: gdb-patches

On 10/01/2016 05:29 AM, Simon Marchi wrote:
> On 2016-09-27 00:08, Tom Tromey wrote:
>> This patch changes minimal symbol creation in two ways.  First, it
>> removes global variables in favor of members of
>> scoped_minimal_symbol_reader.  Second, it changes functions like
>> prim_record_minimal_symbol to be member functions of
>> scoped_minimal_symbol_reader.
> 
> I think this patch (and the previous ones that lead to it) are great. 
> That's the kind of thing that will make the data flow easier to understand.
> 
> About the naming, it's a bit of a nit, but since it might set the
> standard for future classes, I prefer to ask anyway.  Does it help in
> any way to prefix this class' name with "scoped_"?  All C++
> class/objects are "scoped" when statically allocated in a scope, meaning
> that they get destroyed when execution goes out of that scope.  So it's
> not really the property of the class itself that it's scoped, more about
> how it's being used.  It would be a bit like naming "std::string" ->
> "std::scoped_string", since it frees its resources when being destroyed.
>  "minimal_symbol_reader" sounds like a perfect name for that class,
> doesn't it?
> 
> On the other hand, I think scoped_restore is appropriately named, since
> it conveys that its primary (and only?) reason to exist is to be used in
> conjunction with scopes to do some variable restoring.

Seconded.

Sorry, hadn't read your reply yet when I sent the previous email.

Thanks,
Pedro Alves

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-09-27  4:48 ` [RFA 09/22] Remove make_cleanup_restore_current_ui Tom Tromey
  2016-09-29 11:55   ` Trevor Saunders
  2016-10-01  4:29   ` Simon Marchi
@ 2016-10-06  1:24   ` Pedro Alves
  2016-10-06  2:52     ` Tom Tromey
  2016-10-09  4:31   ` Simon Marchi
  3 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-06  1:24 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> +class switch_thru_all_uis
>  {
> +public:
> +
> +  switch_thru_all_uis () : iter (nullptr), save_ui (&current_ui)
> +  {
> +    iter = ui_list;

This initializes "iter" twice.

Thanks,
Pedro Alves

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

* Re: [RFA 10/22] Remove some cleanups in MI
  2016-09-27  4:52 ` [RFA 10/22] Remove some cleanups in MI Tom Tromey
@ 2016-10-06  1:42   ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-06  1:42 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This patch removes a couple of cleanups from MI.
> 
> 2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> 	* mi/mi-main.c (mi_cmd_data_read_memory): Use std::vector.  Remove
> 	some cleanups.

LGTM.

Thanks,
Pedro Alves

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-06  1:24   ` Pedro Alves
@ 2016-10-06  2:52     ` Tom Tromey
  0 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-10-06  2:52 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

>> +class switch_thru_all_uis
>> {
>> +public:
>> +
>> +  switch_thru_all_uis () : iter (nullptr), save_ui (&current_ui)
>> +  {
>> +    iter = ui_list;

Pedro> This initializes "iter" twice.

Thanks.  Apparently I already found that one and fixed it on my branch,
because now I see:

+  switch_thru_all_uis () : m_iter (ui_list), m_save_ui (&current_ui)
+  {
+  }
+

Tom

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-01  4:29   ` Simon Marchi
@ 2016-10-06  2:53     ` Tom Tromey
  0 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-10-06  2:53 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

Simon> We are targetting C++98, aren't we?  Or is it C++03?  Either way,
Simon> nullptr appeared in C++11, so I guess we can't use it.

Yep.  Fixed.

>> #define SWITCH_THRU_ALL_UIS(STATE)		\

Simon> You can remove STATE here.  I am surprised the preprocessor doesn't
Simon> care about the missing argument in macro references.

Maybe that's a GNU extension.  I forget.  But anyway I've fixed it.

Tom

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

* Re: [RFA 06/22] Introduce scoped_minimal_symbol_reader
  2016-10-06  1:10   ` Pedro Alves
@ 2016-10-06 15:37     ` Tom Tromey
  2016-10-10 23:06     ` Tom Tromey
  1 sibling, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-10-06 15:37 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> GCC eschews using // comments, to avoid ending up with a mixbag of
Pedro> styles.  Maybe we should follow suit?

I think // comments are just better.
However, I don't really care.  I can adapt the patches.

Tom

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

* Re: [RFA 00/22] More C++-ification
  2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
                   ` (21 preceding siblings ...)
  2016-09-27  8:32 ` [RFA 11/22] Change command stats reporting to use class Tom Tromey
@ 2016-10-08 13:57 ` Simon Marchi
  2016-10-08 16:42   ` Pedro Alves
  2016-10-09  2:09   ` Tom Tromey
  22 siblings, 2 replies; 123+ messages in thread
From: Simon Marchi @ 2016-10-08 13:57 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 2016-09-27 00:08, Tom Tromey wrote:
> This patch series converts more random parts of gdb to C++.
> 
> Some of these patches get rid of cleanups, or convert them to RAII.
> In a couple of cases, after removing cleanups I went further and
> converted a given class more fully to C++.  There's also one random
> patch to convert an iterator to a C++ class using RAII.
> 
> I didn't touch any spot where the cleanup removal would have benefited
> from unique_ptr; Pedro has a branch with the needed bits there, and I
> wanted to avoid conflicts with his work.
> 
> This was built and regtested on x86-64 Fedora 24.
> 
> I've appended the differences between the baseline run and the run
> with this series in place.  I don't know whether these represent real
> regressions or are just intermittent test failures; particularly
> because the missing tests are either FAIL or KFAIL.
> 
> Tom

Hi Tom and others,

Is anybody working on converting the ui_out infrastructure to nice C++ 
objects yet?  I'd like to get started on it, but was wondering if 
anybody had already started, and if we could avoid duplicate work.

Simon

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

* Re: [RFA 00/22] More C++-ification
  2016-10-08 13:57 ` [RFA 00/22] More C++-ification Simon Marchi
@ 2016-10-08 16:42   ` Pedro Alves
  2016-10-09  2:09   ` Tom Tromey
  1 sibling, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-08 16:42 UTC (permalink / raw)
  To: Simon Marchi, Tom Tromey; +Cc: gdb-patches

On 10/08/2016 02:57 PM, Simon Marchi wrote:

> Hi Tom and others,
> 
> Is anybody working on converting the ui_out infrastructure to nice C++
> objects yet?  

I am not.

> I'd like to get started on it, but was wondering if
> anybody had already started, and if we could avoid duplicate work.

Thanks,
Pedro Alves

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

* Re: [RFA 00/22] More C++-ification
  2016-10-08 13:57 ` [RFA 00/22] More C++-ification Simon Marchi
  2016-10-08 16:42   ` Pedro Alves
@ 2016-10-09  2:09   ` Tom Tromey
  1 sibling, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-10-09  2:09 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

Simon> Is anybody working on converting the ui_out infrastructure to nice C++
Simon> objects yet?  I'd like to get started on it, but was wondering if
Simon> anybody had already started, and if we could avoid duplicate work.

Not me.

Tom

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-09-27  4:48 ` [RFA 09/22] Remove make_cleanup_restore_current_ui Tom Tromey
                     ` (2 preceding siblings ...)
  2016-10-06  1:24   ` Pedro Alves
@ 2016-10-09  4:31   ` Simon Marchi
  2016-10-09 15:10     ` Tom Tromey
  3 siblings, 1 reply; 123+ messages in thread
From: Simon Marchi @ 2016-10-09  4:31 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 2016-09-27 00:08, Tom Tromey wrote:
> +/* State for SWITCH_THRU_ALL_UIS.  */
> +class switch_thru_all_uis
>  {
> +public:
> +
> +  switch_thru_all_uis () : iter (nullptr), save_ui (&current_ui)
> +  {
> +    iter = ui_list;
> +  }

Hi Tom,

I just found there is a little bug here.  current_ui is not set for the 
first iteration, so it runs with whatever was in there before.  If you 
look at the previous implementation, current_ui is assigned in the _cond 
function, which is executed before the first iteration.  In your 
version, it is assigned in the next() method, which isn't.

I noticed this because it fails gdb.mi/user-selected-context-sync.exp.

Simon

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-09  4:31   ` Simon Marchi
@ 2016-10-09 15:10     ` Tom Tromey
  2016-10-09 19:20       ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-09 15:10 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

>> +  switch_thru_all_uis () : iter (nullptr), save_ui (&current_ui)
>> +  {
>> +    iter = ui_list;
>> +  }

Simon> I just found there is a little bug here.
[...]

Thanks.  I'll fix it before re-posting the series.
Not sure if I should do that before the other patches are reviewed though.

Tom

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

* Re: [RFA 11/22] Change command stats reporting to use class
  2016-09-27  8:32 ` [RFA 11/22] Change command stats reporting to use class Tom Tromey
@ 2016-10-09 17:01   ` Pedro Alves
  2016-10-11 17:31     ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 17:01 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This removes make_command_stats_cleanup in favor of an RAII class.
> The patch is reasonably straightforward, but keeping the same
> semantics required reindenting much of captured_main.

Did you try splitting the reindented code to a separate
function instead?  Like:

-captured_main ()
+captured_main_1 ()
{
   ... existing code, except the command stats business
}

captured_main ()
{
 #ifdef HAVE_SBRK
  /* Set this before constructing scoped_command_stats.  */
   lim_at_start = (char *) sbrk (0);
 #endif

 {
   scoped_command_stats stat_reporter (0);

   captured_main_1 (...);
 }

  /* NOTE: cagney/1999-11-07: There is probably no reason for not
     moving this loop and the code found in captured_command_loop()
     into the command_loop() proper.  The main thing holding back that
     change - SET_TOP_LEVEL() - has been eliminated.  */
  while (1)
    {
      catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL);
    }
}

I imagine that results in a much smaller diff, and probably
clearer code.

Once someone fixes that NOTE, then we can even remove the extra
scope around scoped_command_stats.  Or if we fixed that NOTE
before this patch, then we wouldn't need the separate function
nor the reindenting at all.

Thanks,
Pedro Alves

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

* Re: [RFA 12/22] Remove unnecessary null_cleanup
  2016-09-27  4:51 ` [RFA 12/22] Remove unnecessary null_cleanup Tom Tromey
@ 2016-10-09 17:06   ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 17:06 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This patch removes an unnecessary null_cleanup.
> 
> 2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> 	* tracepoint.c (trace_dump_command): Remove unnecessary
> 	null_cleanup.

Obviously OK.  Feel free to push immediately.

Thanks,
Pedro Alves

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

* Re: [RFA 13/22] Remove unnecessary cleanup from stabsread.c
  2016-09-27  4:51 ` [RFA 13/22] Remove unnecessary cleanup from stabsread.c Tom Tromey
  2016-09-30 16:19   ` Tom Tromey
@ 2016-10-09 17:07   ` Pedro Alves
  1 sibling, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 17:07 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This removes an unnecessary cleanup from stabsread.c.  It's
> unnecessary because nothing between the cleanup creation and use makes
> a cleanup.
> 
> 2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> 	* stabsread.c (read_struct_type): Remove unnecessary cleanup.

OK.  Go ahead and push.

Thanks,
Pedro Alves

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

* Re: [RFA 14/22] Replace two xmallocs with vector
  2016-09-27  4:51 ` [RFA 14/22] Replace two xmallocs with vector Tom Tromey
@ 2016-10-09 17:20   ` Pedro Alves
  2016-10-12 22:39     ` Tom Tromey
  2016-10-13 15:15     ` Tom Tromey
  0 siblings, 2 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 17:20 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This replaces a couple of uses of xmalloc with a std::vector, also
> removing a couple of cleanups.
> 
> 2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> 	* cli/cli-dump.c (dump_memory_to_file): Use std::vector.
> 	(restore_binary_file): Likewise.

As general guideline, for these cases where we only need to
construct a buffer once (never resize/reallocate) and we don't
care about the initial contents of the buffer, I think

  unique_ptr<char[]> buf (new char[size]);

ends up being more efficient, because std::vector
default/zero initializes its elements, which is unnecessary since
we're about to write into the buffer anyway.

WDYT?

(I'll try to post my unique_ptr shim soon.)

Thanks,
Pedro Alves

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

* Re: [RFA 15/22] Use std::string in macho_symfile_read_all_oso
  2016-09-27  4:41 ` [RFA 15/22] Use std::string in macho_symfile_read_all_oso Tom Tromey
@ 2016-10-09 17:28   ` Pedro Alves
  2016-10-10 22:40     ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 17:28 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
>  
> -	  memcpy (archive_name, oso->name, pfx_len);
> -	  archive_name[pfx_len] = '\0';
> -
> -	  make_cleanup (xfree, archive_name);
> +	  std::string archive_name (oso->name, pfx_len);
>  
>            /* Compute number of oso for this archive.  */
>            for (last_ix = ix;
>                 VEC_iterate (oso_el, vec, last_ix, oso2); last_ix++)
>              {
> -              if (strncmp (oso2->name, archive_name, pfx_len) != 0)
> +              if (strncmp (oso2->name, archive_name.c_str (), pfx_len) != 0)

> +              if (strncmp (oso2->name, archive_name.c_str (), pfx_len) != 0)

Since archive_name is now a std::string, we can use ==/!= for string
comparison:

              if (archive_name != oso2->name)

Otherwise LGTM, and can go in immediately.

Thanks,
Pedro Alves

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

* Re: [RFA 16/22] Use std::vector in elf_read_minimal_symbols
  2016-09-27  4:42 ` [RFA 16/22] Use std::vector in elf_read_minimal_symbols Tom Tromey
@ 2016-10-09 17:30   ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 17:30 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This changes elf_read_minimal_symbols to use std::vector rather than
> an explicit allocation.  This removes a cleanup.

LGTM, though same comment about unique_ptr applies.  (I'll stop
saying that in follow up patches, even it would apply).

Thanks,
Pedro Alves

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

* Re: [RFA 18/22] Some cleanup removal in dwarf2loc.c
  2016-09-27  4:51 ` [RFA 18/22] Some cleanup removal in dwarf2loc.c Tom Tromey
@ 2016-10-09 17:37   ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 17:37 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This removes some cleanups and manual allocation handling in
> dwarf2loc.c with std::vector.
> 
> 2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> 	* dwarf2loc.c: Include <vector>.
> 	(read_pieced_value, write_pieced_value)
> 	(dwarf2_compile_expr_to_ax): Use std::vector.

LGTM.

Thanks,
Pedro Alves

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

* Re: [RFA 20/22] Initial conversion of dwarf_expr_ctx
  2016-09-27  4:43 ` [RFA 20/22] Initial conversion of dwarf_expr_ctx Tom Tromey
@ 2016-10-09 17:40   ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 17:40 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This is the first step in the conversion of dwarf_expr_ctx to a C++
> class.  This conversion is done in steps to make the patches, and the
> reviews, a bit simpler.  This patch changes dwarf_expr_ctx to be
> stack-allocated and removes the assocatied cleanup.

"associated"

LGTM.

Thanks,
Pedro Alves

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

* Re: [RFA 22/22] Convert dwarf_expr_context_funcs to methods
  2016-09-27  4:47 ` [RFA 22/22] Convert dwarf_expr_context_funcs to methods Tom Tromey
@ 2016-10-09 19:11   ` Pedro Alves
  2016-10-10 18:31     ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 19:11 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This patch converts the function pointers in dwarf_expr_context_funcs
> into methods on dwarf_expr_context, and then updates the various
> implementations and callers to follow.
> 
> NB this patch uses "override" (which caught a couple of renaming bugs
> during development) -- but this is C++11, so this patch at least has
> to wait for Pedro's patch that adds the OVERRIDE macro.

We can pull that bit in now, or remove the "override".  No need to hold
this patch back.

LGTM.  I wondered if defining member functions outside the
class definition wouldn't have resulted in a bit less churn
in dwarf2loc.c.  gcc's coding conventions require doing that,
but I won't be pedantic about it.

Thanks,
Pedro Alves

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

* Re: [RFA 21/22] Convert DWARF expr functions to methods
  2016-09-27  4:45 ` [RFA 21/22] Convert DWARF expr functions to methods Tom Tromey
@ 2016-10-09 19:18   ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 19:18 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 09/27/2016 05:08 AM, Tom Tromey wrote:
> This converts various DWARF expr functions to be members on
> dwarf_expr_context, then fixes up the various users.  This results in
> somewhat less wordy code and sets the stage for the next patch.
> 
> 2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> 	* dwarf2loc.c (per_cu_dwarf_call)
> 	(dwarf_expr_push_dwarf_reg_entry_value)
> 	(dwarf2_evaluate_loc_desc_full, dwarf2_locexpr_baton_eval)
> 	(needs_dwarf_reg_entry_value)
> 	(dwarf2_loc_desc_get_symbol_read_needs): Update.
> 	* dwarf2expr.h (dwarf_expr_context) <push_address, eval, fetch,
> 	fetch_address, fetch_in_stack_memory, address_type, grow_stack,
> 	push, stack_empty_p, add_piece, get_base_type, execute_stack_op,
> 	pop>: New method declarations.
> 	(dwarf_expr_push_address, dwarf_expr_eval, dwarf_expr_fetch)
> 	(dwarf_expr_fetch_address, dwarf_expr_fetch_in_stack_memory):
> 	Don't declare.
> 	* dwarf2expr.c (address_type, grow_stack, push, push_address)
> 	(pop, fetch, fetch_address, fetch_in_stack_memory)
> 	(stack_empty_p, add_piece, eval, get_base_type)
> 	(execute_stack_op): Rename.  Turn into methods.
> 	* dwarf2-frame.c (execute_stack_op): Update.

LGTM.

Thanks,
Pedro Alves

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-09 15:10     ` Tom Tromey
@ 2016-10-09 19:20       ` Pedro Alves
  2016-10-12 22:43         ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-09 19:20 UTC (permalink / raw)
  To: Tom Tromey, Simon Marchi; +Cc: gdb-patches

On 10/09/2016 04:10 PM, Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:
> 
>>> +  switch_thru_all_uis () : iter (nullptr), save_ui (&current_ui)
>>> +  {
>>> +    iter = ui_list;
>>> +  }
> 
> Simon> I just found there is a little bug here.
> [...]
> 
> Thanks.  I'll fix it before re-posting the series.
> Not sure if I should do that before the other patches are reviewed though.

I _think_ they've all been reviewed now.  Please push in
the ones that are independent and OK already, and repost the
others.

Thanks,
Pedro Alves

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

* Re: [RFA 22/22] Convert dwarf_expr_context_funcs to methods
  2016-10-09 19:11   ` Pedro Alves
@ 2016-10-10 18:31     ` Pedro Alves
  2016-10-10 19:33       ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-10 18:31 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/09/2016 08:11 PM, Pedro Alves wrote:
> On 09/27/2016 05:08 AM, Tom Tromey wrote:
>> This patch converts the function pointers in dwarf_expr_context_funcs
>> into methods on dwarf_expr_context, and then updates the various
>> implementations and callers to follow.
>>
>> NB this patch uses "override" (which caught a couple of renaming bugs
>> during development) -- but this is C++11, so this patch at least has
>> to wait for Pedro's patch that adds the OVERRIDE macro.
> 
> We can pull that bit in now, or remove the "override".  No need to hold
> this patch back.

I remembered that I had proposed on the gcc list a while ago to
move their OVERRIDE/FINAL macros to ansidecl.h instead, so we
could share it.  I'm testing a patch that does that.

Thanks,
Pedro Alves

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

* Re: [RFA 22/22] Convert dwarf_expr_context_funcs to methods
  2016-10-10 18:31     ` Pedro Alves
@ 2016-10-10 19:33       ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-10 19:33 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/10/2016 07:31 PM, Pedro Alves wrote:
> On 10/09/2016 08:11 PM, Pedro Alves wrote:
>> On 09/27/2016 05:08 AM, Tom Tromey wrote:
>>> This patch converts the function pointers in dwarf_expr_context_funcs
>>> into methods on dwarf_expr_context, and then updates the various
>>> implementations and callers to follow.
>>>
>>> NB this patch uses "override" (which caught a couple of renaming bugs
>>> during development) -- but this is C++11, so this patch at least has
>>> to wait for Pedro's patch that adds the OVERRIDE macro.
>>
>> We can pull that bit in now, or remove the "override".  No need to hold
>> this patch back.
> 
> I remembered that I had proposed on the gcc list a while ago to
> move their OVERRIDE/FINAL macros to ansidecl.h instead, so we
> could share it.  I'm testing a patch that does that.

Patch sent:

 https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00654.html

Thanks,
Pedro Alves

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

* Re: [RFA 15/22] Use std::string in macho_symfile_read_all_oso
  2016-10-09 17:28   ` Pedro Alves
@ 2016-10-10 22:40     ` Tom Tromey
  2016-10-10 22:46       ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-10 22:40 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

>> +              if (strncmp (oso2->name, archive_name.c_str (), pfx_len) != 0)

Pedro> Since archive_name is now a std::string, we can use ==/!= for string
Pedro> comparison:
Pedro>               if (archive_name != oso2->name)

It isn't entirely clear to me that this is valid, given that the current
comparison is using strncmp.

Tom

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

* Re: [RFA 15/22] Use std::string in macho_symfile_read_all_oso
  2016-10-10 22:40     ` Tom Tromey
@ 2016-10-10 22:46       ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-10 22:46 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/10/2016 11:39 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
>>> +              if (strncmp (oso2->name, archive_name.c_str (), pfx_len) != 0)
> 
> Pedro> Since archive_name is now a std::string, we can use ==/!= for string
> Pedro> comparison:
> Pedro>               if (archive_name != oso2->name)
> 
> It isn't entirely clear to me that this is valid, given that the current
> comparison is using strncmp.

Wow, I completely missed that, somehow.  Sorry about that.  I guess you
could use std::string::compare, but then it doesn't really make a difference.

Patch LGTM as is then.

Thanks,
Pedro Alves

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

* Re: [RFA 06/22] Introduce scoped_minimal_symbol_reader
  2016-10-06  1:10   ` Pedro Alves
  2016-10-06 15:37     ` Tom Tromey
@ 2016-10-10 23:06     ` Tom Tromey
  2016-10-10 23:26       ` Pedro Alves
  1 sibling, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-10 23:06 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> GCC eschews using // comments, to avoid ending up with a mixbag
Pedro> of styles.  Maybe we should follow suit?

I don't remember - did you want me to change this or not?
I prefer "//" comments but it's up to you.

>> +class scoped_minimal_symbol_reader

Pedro> Seems like this is growing to be _the_ reader in following patches?
Pedro> I'm wondering whether the "scoped_" prefix will make sense going
Pedro> forward.

I made this change.  Thank goodness for git filter-branch.

Tom

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

* Re: [RFA 06/22] Introduce scoped_minimal_symbol_reader
  2016-10-10 23:06     ` Tom Tromey
@ 2016-10-10 23:26       ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-10 23:26 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/11/2016 12:06 AM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> GCC eschews using // comments, to avoid ending up with a mixbag
> Pedro> of styles.  Maybe we should follow suit?
> 
> I don't remember - did you want me to change this or not?
> I prefer "//" comments but it's up to you.

I'd prefer to change it for the sake of consistency.  A single comment
in a different style in between other comments stands out as odd to me.

For tail-end single-line comments, like

  } // namespace gdb

it doesn't look that odd to me.  AFAICS, these are the cases
where gcc uses // too, for the most part.

Thanks,
Pedro Alves

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

* Re: [RFA 11/22] Change command stats reporting to use class
  2016-10-09 17:01   ` Pedro Alves
@ 2016-10-11 17:31     ` Tom Tromey
  0 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-10-11 17:31 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> Did you try splitting the reindented code to a separate
Pedro> function instead?

Thanks.  I did this and in the process noticed that the earlier patch
was incorrect -- it left a dangling cleanup.

I have a follow-on patch now to remove that last cleanup from
captured_main.

Tom

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

* Re: [RFA 19/22] Convert tid_range_parser to class
  2016-10-04 23:09           ` Pedro Alves
  2016-10-05  2:16             ` Trevor Saunders
@ 2016-10-12  2:12             ` Tom Tromey
  2016-10-13  1:06               ` Pedro Alves
  1 sibling, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-12  2:12 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> Here's what I ended up with, after reading your version in more
Pedro> detail.  That brought in the "deleted" copy
Pedro> constructor/assignment operators [1], and "const" in several
Pedro> methods, which I then propagated to number_or_range_parser too.

Pedro> WDYT?

I'm sorry I didn't reply to this sooner.
This all looks good to me.

Pedro> [1] - I'm pondering making those use =delete if compiling with
Pedro> a C++ compiler, behind some
Pedro>   #define DISABLE_COPY_AND_ASSIGN(TYPE) ...
Pedro> macro.

Pedro> Or, maybe add a gdb::noncopyable class that non-copyable
Pedro> classes inherit from privately, just like boost:noncopyable.
Pedro> Anyone got experience on the latter, and whether that turns
Pedro> out to be a bad idea?

I haven't used that.
The Moz approach that Trevor mentioned seems reasonable.
Or, just switching to C++11, per the other thread, and using =delete.

Tom

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

* Re: [RFA 02/22] Use RAII to save and restore scalars
  2016-10-05  0:06                   ` Pedro Alves
@ 2016-10-12 22:36                     ` Tom Tromey
  0 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-10-12 22:36 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, Trevor Saunders, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> You can -- make the fields mutable.

>> Ok, yeah, I had thought of this, but it seemed pretty ugly to me.

Pedro> It's hidden in the "library", so it'd be super fine with me.
Pedro> I think of it as just part of the idiom.

I did this and restored the 2-argument form.

Tom

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

* Re: [RFA 14/22] Replace two xmallocs with vector
  2016-10-09 17:20   ` Pedro Alves
@ 2016-10-12 22:39     ` Tom Tromey
  2016-10-13  1:17       ` Pedro Alves
  2016-10-13 15:15     ` Tom Tromey
  1 sibling, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-12 22:39 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

>> * cli/cli-dump.c (dump_memory_to_file): Use std::vector.
>> (restore_binary_file): Likewise.

Pedro> As general guideline, for these cases where we only need to
Pedro> construct a buffer once (never resize/reallocate) and we don't
Pedro> care about the initial contents of the buffer, I think
Pedro>   unique_ptr<char[]> buf (new char[size]);
Pedro> ends up being more efficient, because std::vector
Pedro> default/zero initializes its elements, which is unnecessary since
Pedro> we're about to write into the buffer anyway.

Pedro> WDYT?

It's fine with me.

Often the performance doesn't matter, and std::vector is safe to use.
On the other hand XNEWVEC isn't really unsafe -- maybe just mildly less
clear to gdb newbies.

Tom

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-09 19:20       ` Pedro Alves
@ 2016-10-12 22:43         ` Tom Tromey
  2016-10-13  1:28           ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-12 22:43 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, Simon Marchi, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> I _think_ they've all been reviewed now.  Please push in
Pedro> the ones that are independent and OK already, and repost the
Pedro> others.

Ok.  I think after all is said and done, there are 5 that can go in and
the rest need something -- either final review on scoped_restore or
unique_ptr.

BTW, I'm wondering if you want scoped_restore in its own header.  It
didn't occur to me while writing it, but now it seems like a good idea.

Tom

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

* Re: [RFA 19/22] Convert tid_range_parser to class
  2016-10-12  2:12             ` Tom Tromey
@ 2016-10-13  1:06               ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-13  1:06 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/12/2016 03:11 AM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> Here's what I ended up with, after reading your version in more
> Pedro> detail.  That brought in the "deleted" copy
> Pedro> constructor/assignment operators [1], and "const" in several
> Pedro> methods, which I then propagated to number_or_range_parser too.
> 
> Pedro> WDYT?
> 
> I'm sorry I didn't reply to this sooner.
> This all looks good to me.

OK, I've pushed it in now.  Thanks!

> Pedro> [1] - I'm pondering making those use =delete if compiling with
> Pedro> a C++ compiler, behind some
> Pedro>   #define DISABLE_COPY_AND_ASSIGN(TYPE) ...
> Pedro> macro.
> 
> Pedro> Or, maybe add a gdb::noncopyable class that non-copyable
> Pedro> classes inherit from privately, just like boost:noncopyable.
> Pedro> Anyone got experience on the latter, and whether that turns
> Pedro> out to be a bad idea?
> 
> I haven't used that.
> The Moz approach that Trevor mentioned seems reasonable.
> Or, just switching to C++11, per the other thread, and using =delete.

Yeah.

Thanks,
Pedro Alves

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

* Re: [RFA 14/22] Replace two xmallocs with vector
  2016-10-12 22:39     ` Tom Tromey
@ 2016-10-13  1:17       ` Pedro Alves
  2016-10-13  2:04         ` Tom Tromey
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-13  1:17 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/12/2016 11:39 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
>>> * cli/cli-dump.c (dump_memory_to_file): Use std::vector.
>>> (restore_binary_file): Likewise.
> 
> Pedro> As general guideline, for these cases where we only need to
> Pedro> construct a buffer once (never resize/reallocate) and we don't
> Pedro> care about the initial contents of the buffer, I think
> Pedro>   unique_ptr<char[]> buf (new char[size]);
> Pedro> ends up being more efficient, because std::vector
> Pedro> default/zero initializes its elements, which is unnecessary since
> Pedro> we're about to write into the buffer anyway.
> 
> Pedro> WDYT?
> 
> It's fine with me.
> 
> Often the performance doesn't matter, and std::vector is safe to use.
> On the other hand XNEWVEC isn't really unsafe -- maybe just mildly less
> clear to gdb newbies.

Hmm, the code you're touching isn't using XNEWVEC, so I'm not sure
I know exactly what you're referring to, but I assume you're thinking
of the xmallocs you're replacing.

Both vector and unique_ptr<T[]> (or unique_malloc_ptr<T> with the
to go with the existing mallocs) have the advantage of not requiring a
cleanup, of course.  Writing either I think is almost the same code.
I think unique_ptr communicates intent a little better for these
cases, with the added bonus of a little extra efficiency, but it's not
a huge issue.

Thanks,
Pedro Alves

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-12 22:43         ` Tom Tromey
@ 2016-10-13  1:28           ` Pedro Alves
  2016-10-13  6:11             ` Eli Zaretskii
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-13  1:28 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Simon Marchi, gdb-patches

On 10/12/2016 11:43 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> I _think_ they've all been reviewed now.  Please push in
> Pedro> the ones that are independent and OK already, and repost the
> Pedro> others.
> 
> Ok.  I think after all is said and done, there are 5 that can go in and
> the rest need something -- either final review on scoped_restore or
> unique_ptr.

Yeah, sounds right.  I was trying get the gdb::unique_ptr in, in order
to unblock the cases I suggested you use unique_ptr, but I'm a bit
confused on what to do about it now...  I _think_ people are generally
OK with it.  There was some opposition, but I'm not sure anymore
whether it still exists.  C++11 is now on the table, but maybe a
staged approach (enable C++11 while supporting C++03 too for a while,
to catch issues) would make sense anyway.
But I'd really like to move forward with deciding on _some_
smart pointer to use, in order to unblock further conversion.
I'll re-review tomorrow with a fresher head (and give people time to
comment on actual implementation details (or just say they mean to),
if they want...)

> BTW, I'm wondering if you want scoped_restore in its own header.  It
> didn't occur to me while writing it, but now it seems like a good idea.

It does sound like a good idea.

Thanks,
Pedro Alves

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

* Re: [RFA 14/22] Replace two xmallocs with vector
  2016-10-13  1:17       ` Pedro Alves
@ 2016-10-13  2:04         ` Tom Tromey
  0 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-10-13  2:04 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

>> Often the performance doesn't matter, and std::vector is safe to use.
>> On the other hand XNEWVEC isn't really unsafe -- maybe just mildly less
>> clear to gdb newbies.

Pedro> Hmm, the code you're touching isn't using XNEWVEC, so I'm not sure
Pedro> I know exactly what you're referring to, but I assume you're thinking
Pedro> of the xmallocs you're replacing.

Yeah.

Hmm, if it's xmalloc (I'm looking at one patch where it's XCNEWVEC, but
apparently could be XNEWVEC without any loss), then I'm less sure.
XNEWVEC is at least reasonably type-safe, but plain xmalloc less so.

Anyway once unique_ptr is in I'll update all those patches and we can
discuss it more concretely.

Tom

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13  1:28           ` Pedro Alves
@ 2016-10-13  6:11             ` Eli Zaretskii
  2016-10-13 10:16               ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Eli Zaretskii @ 2016-10-13  6:11 UTC (permalink / raw)
  To: Pedro Alves; +Cc: tom, simon.marchi, gdb-patches

> Cc: Simon Marchi <simon.marchi@polymtl.ca>, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Thu, 13 Oct 2016 02:28:44 +0100
> 
> Yeah, sounds right.  I was trying get the gdb::unique_ptr in, in order
> to unblock the cases I suggested you use unique_ptr, but I'm a bit
> confused on what to do about it now...  I _think_ people are generally
> OK with it.  There was some opposition, but I'm not sure anymore
> whether it still exists.  C++11 is now on the table, but maybe a
> staged approach (enable C++11 while supporting C++03 too for a while,
> to catch issues) would make sense anyway.

I still think we shouldn't have workarounds for versions of the
standard older than what we want to support.  IOW, if we decide to use
C++11, we should _require_ a compiler that supports it, and error out
if the configure test(s) regarding that fail.

Supporting more than one standard means we will have rarely used code
that is almost never tested, and that means maintenance burden which
threaten to undo at least some part of the benefits you aspire to
achieve by moving to C++ in general and to a new enough C++ standard
in particular.

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13  6:11             ` Eli Zaretskii
@ 2016-10-13 10:16               ` Pedro Alves
  2016-10-13 13:53                 ` Eli Zaretskii
  2016-10-13 14:26                 ` Trevor Saunders
  0 siblings, 2 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-13 10:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, simon.marchi, gdb-patches

On 10/13/2016 07:11 AM, Eli Zaretskii wrote:
>> Cc: Simon Marchi <simon.marchi@polymtl.ca>, gdb-patches@sourceware.org
>> From: Pedro Alves <palves@redhat.com>
>> Date: Thu, 13 Oct 2016 02:28:44 +0100
>>
>> Yeah, sounds right.  I was trying get the gdb::unique_ptr in, in order
>> to unblock the cases I suggested you use unique_ptr, but I'm a bit
>> confused on what to do about it now...  I _think_ people are generally
>> OK with it.  There was some opposition, but I'm not sure anymore
>> whether it still exists.  C++11 is now on the table, but maybe a
>> staged approach (enable C++11 while supporting C++03 too for a while,
>> to catch issues) would make sense anyway.
> 
> I still think we shouldn't have workarounds for versions of the
> standard older than what we want to support.

That is not what the patch does...  

#1 - Starting from the position that gdb wants to build with C++03
     compilers.

#2 - The patch adds a new smart pointer type.  In C++03, you're pretty
     much guaranteed to need to do that.  The one the standard gives you
     is too limited.

#3 - (owning) smart pointers all look the same for most client code - they're
     meant to look like raw pointers afterall - i.e., ptr->foo, and *ptr
     works as expected, transparently.

#4 - where owning smart pointer APIs tend to differ is in code around pointee
     ownership.

     I chose to model the API on std::unique_ptr (C++11).
     There are advantages.

#5 - We could stop here.  Done.

#6 - But I went a step further, and made it so that if we have C++11
     handy, then we can make use of the compiler to catch bugs at
     compile time, all while keeping the nice API.

So again:

> I still think we shouldn't have workarounds for versions of the
> standard older than what we want to support.

there's no workaround for versions older than what we want to support
at all.  There's the code for the version that we had decided earlier
that we wanted to support, plus extra API enforcement when built
with a compiler that supports a version _newer_ than what we want
to support.


I'll give you more examples of why I think forbidding C++11 completely
is short sighted.  C++11 has a nice feature where you can tell the compiler
that some class is "final" (not possible to to inherit from that class).
This allows the compiler to optimize the code better.

Another nice C++11 feature is that it's possible to mark class methods
as overriding a virtual method in the base class.  This is quite handy,
because with C++03, if you change the method's prototype in base class,
you have to remember to update all users.  And without the "override" marker,
the compiler won't help you find them at all.  The program builds, and then
fails at run time.  Maybe only after release do you notice it.
With the override marker, the compiler now errors out pointing at all
the places you need to fix.  Bug found at compiler time.  Wonderful.

So if we have a C++11 compiler handy, why not make use of these
features to help with development?  I don't see how it makes
sense to not take advantage of compiler help if available.

Here's GCC conditionally using these features if available as well:

  https://gcc.gnu.org/ml/jit/2016-q2/msg00000.html

And GCC still supports building with a C++03 compiler.  Just
like GDB.  Tons of projects out there do the same thing.

> IOW, if we decide to use
> C++11, we should _require_ a compiler that supports it, and error out
> if the configure test(s) regarding that fail.
> 

So:

#1.1 - for people with new compilers, we'd go through C++11 std::unique_ptr
       all the time.

#1.2 - people with older compilers would be out of luck.  tough.  get newer
       compiler first.

Vs:

#2.1 - for people with new compilers, we'd go through std::unique_ptr all
       the time.

#2.2 - for people with older compilers we go through the fallback
       implementation.  gdb still works.

(I wasn't planning on starting the discussion on whether 1.2 is
reasonable nowadays.  That happened because someone else brought it up.)


So for people with newer compilers, the result is the same.
(#1.1 == #1.2).  While I'm proposing a solution that gives us all the
benefits (#2.1) while keeping support for older compilers
for a little while longer (#2.2).

> Supporting more than one standard means we will have rarely used code
> that is almost never tested, and that means maintenance burden 

That same argument could be applied to gnulib.  Or the many HAVE_FOO's
in the code base.  We rely on gnulib's reimplementation of the whole
printf family of functions if the compiler doesn't support it properly
for example!

So what if the fallback code is only used on older compilers?
If you're willing to go #1.1/#2.1 above, then what do you lose?

The sane way to make sure the fallback code still works is
via autotesting with the buildbot.

> that means maintenance burden 

For whom?  _I'm_ willing to maintain this code.  It's not rocket
science code.  And then users of the smart pointer don't really
have to care.  Whether C++11 or C++03, you write the same code.
You may miss a gdb::move call with C++03.  No big deal.  The fix
is just to add a gdb::move call.

Several others have said they think this is a good idea.  I've even
ran this idea through the libstdc++ maintainer in person at the Cauldron.
Trevor said he wants to do this in gcc as well.

If redirecting to C++11 std::unique_ptr turns out to cause trouble, or
I'm hit by a bus, then it's trivial to remove that redirection.  All it
takes is remove a handful of lines of code guarded with
#if __cplusplus >= 201103 to always go through the fallback implementation.

So there's no "point of no return here".

> which
> threaten to undo at least some part of the benefits you aspire to
> achieve by moving to C++ in general and to a new enough C++ standard
> in particular.

I don't understand what this is trying to say.

I propose to move forward with my plan, and if it does cause
trouble, then we drop the gdb::unique_ptr -> std::unique_ptr mapping.

It may happen, I don't know.  We will know if it will indeed cause
trouble in practice if we try.

That will allow moving forward with cleanup elimination and more.

And _in_ parallel, as a separate discussion, we can discuss dropping
support for C++03 and going C++11 fully.  I think we could pull it
off, but I wouldn't want to do it in a rush, and without an easy
fallback plan available.  The patch I sent yesterday to make use
of C++11 with gcc >= 4.8 would be the first step.  Then if that doesn't
cause problems, we can tell the autoconf macro to require C++11
with a single line change.  If _requiring_ C++11 causes significant
trouble on people, and we want to go back to supporting older compilers,
then it's easy to revert that, and go back to the unique_ptr C++03
fallback implementation.  This is header-only template code, so we
really can't tell if this will cause trouble for people without
adding actual _uses_ of the smart pointer.

> IOW, if we decide to use
> C++11, we should _require_ a compiler that supports it, and error out
> if the configure test(s) regarding that fail.

In the patch I sent yesterday to teach gdb's configure about C++11
in gcc >= 4.8, if we change the macro invocation to make C++11
mandatory, then if configure doesn't find a C++11 compiler,
it errors out with a nice error message.

And no, I'm not planning on getting hit by a bus.  :-)

Thanks,
Pedro Alves

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13 10:16               ` Pedro Alves
@ 2016-10-13 13:53                 ` Eli Zaretskii
  2016-10-13 14:26                   ` Pedro Alves
  2016-10-13 14:26                 ` Trevor Saunders
  1 sibling, 1 reply; 123+ messages in thread
From: Eli Zaretskii @ 2016-10-13 13:53 UTC (permalink / raw)
  To: Pedro Alves; +Cc: tom, simon.marchi, gdb-patches

> Cc: tom@tromey.com, simon.marchi@polymtl.ca, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Thu, 13 Oct 2016 11:16:26 +0100
> 
> On 10/13/2016 07:11 AM, Eli Zaretskii wrote:
> >> Cc: Simon Marchi <simon.marchi@polymtl.ca>, gdb-patches@sourceware.org
> >> From: Pedro Alves <palves@redhat.com>
> >> Date: Thu, 13 Oct 2016 02:28:44 +0100
> >>
> >> Yeah, sounds right.  I was trying get the gdb::unique_ptr in, in order
> >> to unblock the cases I suggested you use unique_ptr, but I'm a bit
> >> confused on what to do about it now...  I _think_ people are generally
> >> OK with it.  There was some opposition, but I'm not sure anymore
> >> whether it still exists.  C++11 is now on the table, but maybe a
> >> staged approach (enable C++11 while supporting C++03 too for a while,
> >> to catch issues) would make sense anyway.
> > 
> > I still think we shouldn't have workarounds for versions of the
> > standard older than what we want to support.
> 
> That is not what the patch does...  

I wasn't referring to the patch, I was referring to the quoted part of
your message, specifically to this:

> >> C++11 is now on the table, but maybe a staged approach (enable
> >> C++11 while supporting C++03 too for a while, to catch issues)
> >> would make sense anyway.

> So again:
> 
> > I still think we shouldn't have workarounds for versions of the
> > standard older than what we want to support.
> 
> there's no workaround for versions older than what we want to support
> at all.

Since I'm still unclear what is the oldest C++ standard we want to
support, I cannot decide whether I agree or disagree.  Is the version
of the C++ standard we support C++03 or C++11?  My comment assumed
that it was C++11.

> I'll give you more examples of why I think forbidding C++11 completely
> is short sighted.

Thanks, but that kind of arguments completely misses the point.  You
don't need to convince me that a later standard is better than the
previous ones.  The issue at hand is whether we should write code that
targets more than a single language standard, where these standards
aren't compatible.  I think we shouldn't.

> > Supporting more than one standard means we will have rarely used code
> > that is almost never tested, and that means maintenance burden 
> 
> That same argument could be applied to gnulib.  Or the many HAVE_FOO's
> in the code base.  We rely on gnulib's reimplementation of the whole
> printf family of functions if the compiler doesn't support it properly
> for example!

I did apply it to gnulib at the time, but was voted down.

Do you seriously consider the gnulib solution a good one?  I don't.
The code obfuscation is very significant.  Of course, as long as you
don't look into the gnulib headers, you don't care, but in this case
you propose to have all those shims in our sources, in plain sight.

> > that means maintenance burden 
> 
> For whom?  _I'm_ willing to maintain this code.

Are you saying that no one else will be allowed to modify the code
which has 2 branches, one for C++03, the other for C++11?  I'm betting
you aren't saying that, and so this is a burden for all of us, not
just for you.  And that is even before we consider the "bus issue".

> It's not rocket science code.

Today it isn't.  I'm not talking about this particular patch, I'm
talking about this policy in general.  As do you, I suppose: you
aren't just asking for agreement about using C++11 features in this
single case, right?

> Several others have said they think this is a good idea.  I've even
> ran this idea through the libstdc++ maintainer in person at the Cauldron.
> Trevor said he wants to do this in gcc as well.

I just wanted to voice my opposition, that's all.  I don't have to
give up just because a few others think otherwise.  Right?

> If redirecting to C++11 std::unique_ptr turns out to cause trouble, or
> I'm hit by a bus, then it's trivial to remove that redirection.  All it
> takes is remove a handful of lines of code guarded with
> #if __cplusplus >= 201103 to always go through the fallback implementation.

Once again, it's not just this single patch that bothers me.  Once we
have enough of these #if's, removing them is not necessarily a trivial
matter, especially when most of the builds, perhaps even all of them,
have been using the C++11 code path all the time, and the other one
has simply bitrotted.

> > which
> > threaten to undo at least some part of the benefits you aspire to
> > achieve by moving to C++ in general and to a new enough C++ standard
> > in particular.
> 
> I don't understand what this is trying to say.

The move to C++ was supposed to make the maintenance easier, right?
I'm saying that targeting more than a single language standard makes
maintenance harder, so it works against the purpose of the move.

> And no, I'm not planning on getting hit by a bus.  :-)

Who is?

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13 13:53                 ` Eli Zaretskii
@ 2016-10-13 14:26                   ` Pedro Alves
  2016-10-13 14:46                     ` Eli Zaretskii
  0 siblings, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-13 14:26 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, simon.marchi, gdb-patches

On 10/13/2016 02:52 PM, Eli Zaretskii wrote:

> Since I'm still unclear what is the oldest C++ standard we want to
> support, I cannot decide whether I agree or disagree.  Is the version
> of the C++ standard we support C++03 or C++11?  My comment assumed
> that it was C++11.

It was decided in 2014 that we'd target C++03.  We have not decided
yet to _require_ C++11.

> 
>> I'll give you more examples of why I think forbidding C++11 completely
>> is short sighted.
> 
> Thanks, but that kind of arguments completely misses the point.  You
> don't need to convince me that a later standard is better than the
> previous ones.  The issue at hand is whether we should write code that
> targets more than a single language standard, where these standards
> aren't compatible.  I think we shouldn't.

They are not incompatible.  C++03 code compiles with a C++11 compiler
just fine.

> 
>>> Supporting more than one standard means we will have rarely used code
>>> that is almost never tested, and that means maintenance burden 
>>
>> That same argument could be applied to gnulib.  Or the many HAVE_FOO's
>> in the code base.  We rely on gnulib's reimplementation of the whole
>> printf family of functions if the compiler doesn't support it properly
>> for example!
> 
> I did apply it to gnulib at the time, but was voted down.
> 
> Do you seriously consider the gnulib solution a good one?  I don't.

Yes, I do.

> The code obfuscation is very significant.  Of course, as long as you
> don't look into the gnulib headers, you don't care, but in this case
> you propose to have all those shims in our sources, in plain sight.

Yes, "all those shims".  One file.  And then cleaner code in thousands
of uses of the shim throughout the codebase.  None of that
shim-using code needs to know what version of the standard is
being targeted.  Take a look at patch #3 from the gdb::unique_ptr
series, and see for yourself.

So I'll take that tradeoff, yes.

> 
>>> that means maintenance burden 
>>
>> For whom?  _I'm_ willing to maintain this code.
> 
> Are you saying that no one else will be allowed to modify the code
> which has 2 branches, one for C++03, the other for C++11?  I'm betting
> you aren't saying that, 

Of course not.

> and so this is a burden for all of us, not just for you.  

You're automatically assuming it's a burden.  I believe that's
false.

> 
>> It's not rocket science code.
> 
> Today it isn't.  I'm not talking about this particular patch, I'm
> talking about this policy in general.  As do you, I suppose: you
> aren't just asking for agreement about using C++11 features in this
> single case, right?

I'm talking about adding a small utility that is going to be used 
extensively throughout the codebase.  A smart pointer is a central widget.
That mine was modeled on a C++11 feature should be seen as
a _good_ thing.  The std::unique_ptr was so good that it made it
to the standard.  Not a small feat.  Bonus.  Once we move on to C++11
for real (I don't know when), then there's one less API to learn.

> 
>> Several others have said they think this is a good idea.  I've even
>> ran this idea through the libstdc++ maintainer in person at the Cauldron.
>> Trevor said he wants to do this in gcc as well.
> 
> I just wanted to voice my opposition, that's all.  I don't have to
> give up just because a few others think otherwise.  Right?

Of course.  The problem is that your opinion is interpreted as
a hard blocker.  The result is stalling.

>> If redirecting to C++11 std::unique_ptr turns out to cause trouble, or
>> I'm hit by a bus, then it's trivial to remove that redirection.  All it
>> takes is remove a handful of lines of code guarded with
>> #if __cplusplus >= 201103 to always go through the fallback implementation.
> 
> Once again, it's not just this single patch that bothers me.  Once we
> have enough of these #if's, removing them is not necessarily a trivial

And not "not necessarily" either...  This just looks like fear of
the unknown, I'm afraid.

> matter, especially when most of the builds, perhaps even all of them,
> have been using the C++11 code path all the time, and the other one
> has simply bitrotted.

As I've said before, we can make use of the buildbot for that.
If the fallback code breaks, you get an immediate email notification.

>>> which
>>> threaten to undo at least some part of the benefits you aspire to
>>> achieve by moving to C++ in general and to a new enough C++ standard
>>> in particular.
>>
>> I don't understand what this is trying to say.
> 
> The move to C++ was supposed to make the maintenance easier, right?
> I'm saying that targeting more than a single language standard makes
> maintenance harder, so it works against the purpose of the move.

Many, many, many, free software projects, small and large, went
through that exercise.  It's known territory, we can learn
from their experience, and we know that it's quite doable.

> 
>> And no, I'm not planning on getting hit by a bus.  :-)
> 
> Who is?

;-)

Thanks,
Pedro Alves

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13 10:16               ` Pedro Alves
  2016-10-13 13:53                 ` Eli Zaretskii
@ 2016-10-13 14:26                 ` Trevor Saunders
  1 sibling, 0 replies; 123+ messages in thread
From: Trevor Saunders @ 2016-10-13 14:26 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Eli Zaretskii, tom, simon.marchi, gdb-patches

On Thu, Oct 13, 2016 at 11:16:26AM +0100, Pedro Alves wrote:
> On 10/13/2016 07:11 AM, Eli Zaretskii wrote:
> >> Cc: Simon Marchi <simon.marchi@polymtl.ca>, gdb-patches@sourceware.org
> >> From: Pedro Alves <palves@redhat.com>
> >> Date: Thu, 13 Oct 2016 02:28:44 +0100
> >>
> >> Yeah, sounds right.  I was trying get the gdb::unique_ptr in, in order
> >> to unblock the cases I suggested you use unique_ptr, but I'm a bit
> >> confused on what to do about it now...  I _think_ people are generally
> >> OK with it.  There was some opposition, but I'm not sure anymore
> >> whether it still exists.  C++11 is now on the table, but maybe a
> >> staged approach (enable C++11 while supporting C++03 too for a while,
> >> to catch issues) would make sense anyway.
> > 
> > I still think we shouldn't have workarounds for versions of the
> > standard older than what we want to support.
> 
> That is not what the patch does...  
> 
> #1 - Starting from the position that gdb wants to build with C++03
>      compilers.
> 
> #2 - The patch adds a new smart pointer type.  In C++03, you're pretty
>      much guaranteed to need to do that.  The one the standard gives you
>      is too limited.
> 
> #3 - (owning) smart pointers all look the same for most client code - they're
>      meant to look like raw pointers afterall - i.e., ptr->foo, and *ptr
>      works as expected, transparently.
> 
> #4 - where owning smart pointer APIs tend to differ is in code around pointee
>      ownership.
> 
>      I chose to model the API on std::unique_ptr (C++11).
>      There are advantages.
> 
> #5 - We could stop here.  Done.
> 
> #6 - But I went a step further, and made it so that if we have C++11
>      handy, then we can make use of the compiler to catch bugs at
>      compile time, all while keeping the nice API.
> 
> So again:
> 
> > I still think we shouldn't have workarounds for versions of the
> > standard older than what we want to support.
> 
> there's no workaround for versions older than what we want to support
> at all.  There's the code for the version that we had decided earlier
> that we wanted to support, plus extra API enforcement when built
> with a compiler that supports a version _newer_ than what we want
> to support.
> 
> 
> I'll give you more examples of why I think forbidding C++11 completely
> is short sighted.  C++11 has a nice feature where you can tell the compiler
> that some class is "final" (not possible to to inherit from that class).
> This allows the compiler to optimize the code better.
> 
> Another nice C++11 feature is that it's possible to mark class methods
> as overriding a virtual method in the base class.  This is quite handy,
> because with C++03, if you change the method's prototype in base class,
> you have to remember to update all users.  And without the "override" marker,
> the compiler won't help you find them at all.  The program builds, and then
> fails at run time.  Maybe only after release do you notice it.
> With the override marker, the compiler now errors out pointing at all
> the places you need to fix.  Bug found at compiler time.  Wonderful.
> 
> So if we have a C++11 compiler handy, why not make use of these
> features to help with development?  I don't see how it makes
> sense to not take advantage of compiler help if available.

And infact gdb already does the same exact sort of thing in the form of
the ATTRIBUTE_PRINTF macros.

> Here's GCC conditionally using these features if available as well:
> 
>   https://gcc.gnu.org/ml/jit/2016-q2/msg00000.html
> 
> And GCC still supports building with a C++03 compiler.  Just
> like GDB.  Tons of projects out there do the same thing.

as far as conditional compilation goes this seems a lot saner than  many
of the ifdefs in gcc, and probably the rest of the toolchain.  Its also
a lot easier to test than many of them.

> > IOW, if we decide to use
> > C++11, we should _require_ a compiler that supports it, and error out
> > if the configure test(s) regarding that fail.
> > 
> 
> So:
> 
> #1.1 - for people with new compilers, we'd go through C++11 std::unique_ptr
>        all the time.
> 
> #1.2 - people with older compilers would be out of luck.  tough.  get newer
>        compiler first.
> 
> Vs:
> 
> #2.1 - for people with new compilers, we'd go through std::unique_ptr all
>        the time.
> 
> #2.2 - for people with older compilers we go through the fallback
>        implementation.  gdb still works.
> 
> (I wasn't planning on starting the discussion on whether 1.2 is
> reasonable nowadays.  That happened because someone else brought it up.)
> 
> 
> So for people with newer compilers, the result is the same.
> (#1.1 == #1.2).  While I'm proposing a solution that gives us all the
> benefits (#2.1) while keeping support for older compilers
> for a little while longer (#2.2).
> 
> > Supporting more than one standard means we will have rarely used code
> > that is almost never tested, and that means maintenance burden 
> 
> That same argument could be applied to gnulib.  Or the many HAVE_FOO's
> in the code base.  We rely on gnulib's reimplementation of the whole
> printf family of functions if the compiler doesn't support it properly
> for example!

Claiming the C++98 code will be rarely tested is only true if very few
people try to compile gdb somewhere that doesn't have a C++11 compiler,
in which case yes we might as well drop support for C++98 compilers
because supporting them doesn't help anyone.  Basically you can't have
it both ways, either there are people who benefit from support for C++98
compilers, and so they'll test C++98 only code, or those people don't
exist, and you might as well require C++11.

> The sane way to make sure the fallback code still works is
> via autotesting with the buildbot.

and doing that is a whole lot easier than say testing if gdb works
without HAVE_PERSONALITY defined since testing the latter requires some
old kernel and probably glibc.

> > that means maintenance burden 
> 
> For whom?  _I'm_ willing to maintain this code.  It's not rocket
> science code.  And then users of the smart pointer don't really
> have to care.  Whether C++11 or C++03, you write the same code.
> You may miss a gdb::move call with C++03.  No big deal.  The fix
> is just to add a gdb::move call.
> 
> Several others have said they think this is a good idea.  I've even
> ran this idea through the libstdc++ maintainer in person at the Cauldron.
> Trevor said he wants to do this in gcc as well.
> 
> If redirecting to C++11 std::unique_ptr turns out to cause trouble, or
> I'm hit by a bus, then it's trivial to remove that redirection.  All it
> takes is remove a handful of lines of code guarded with
> #if __cplusplus >= 201103 to always go through the fallback implementation.
> 
> So there's no "point of no return here".
> 
> > which
> > threaten to undo at least some part of the benefits you aspire to
> > achieve by moving to C++ in general and to a new enough C++ standard
> > in particular.
> 
> I don't understand what this is trying to say.
> 
> I propose to move forward with my plan, and if it does cause
> trouble, then we drop the gdb::unique_ptr -> std::unique_ptr mapping.
> 
> It may happen, I don't know.  We will know if it will indeed cause
> trouble in practice if we try.

having delt with very similar smart pointers in other projects that
couldn't require C++11 I'll be suprised if it causes problems.

> And _in_ parallel, as a separate discussion, we can discuss dropping
> support for C++03 and going C++11 fully.  I think we could pull it
> off, but I wouldn't want to do it in a rush, and without an easy
> fallback plan available.  The patch I sent yesterday to make use
> of C++11 with gcc >= 4.8 would be the first step.  Then if that doesn't
> cause problems, we can tell the autoconf macro to require C++11
> with a single line change.  If _requiring_ C++11 causes significant
> trouble on people, and we want to go back to supporting older compilers,
> then it's easy to revert that, and go back to the unique_ptr C++03
> fallback implementation.  This is header-only template code, so we
> really can't tell if this will cause trouble for people without
> adding actual _uses_ of the smart pointer.

Yeah, I really don't see what the down side to adding the fall back, and
then deleting it in several weeks or months or whatever it ends up
taking to require C++11 is, and I don't see what the advantage of
rushing a switch to C++11 instead is.

Trev

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13 14:26                   ` Pedro Alves
@ 2016-10-13 14:46                     ` Eli Zaretskii
  2016-10-13 15:04                       ` Pedro Alves
  2016-10-13 15:27                       ` [RFA 09/22] Remove make_cleanup_restore_current_ui Pedro Alves
  0 siblings, 2 replies; 123+ messages in thread
From: Eli Zaretskii @ 2016-10-13 14:46 UTC (permalink / raw)
  To: Pedro Alves; +Cc: tom, simon.marchi, gdb-patches

> Cc: tom@tromey.com, simon.marchi@polymtl.ca, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Thu, 13 Oct 2016 15:26:07 +0100
> 
> On 10/13/2016 02:52 PM, Eli Zaretskii wrote:
> 
> > Since I'm still unclear what is the oldest C++ standard we want to
> > support, I cannot decide whether I agree or disagree.  Is the version
> > of the C++ standard we support C++03 or C++11?  My comment assumed
> > that it was C++11.
> 
> It was decided in 2014 that we'd target C++03.  We have not decided
> yet to _require_ C++11.

Then that comment is not yet relevant.  But then I think we should not
use C++11 code in GDB.

> >> I'll give you more examples of why I think forbidding C++11 completely
> >> is short sighted.
> > 
> > Thanks, but that kind of arguments completely misses the point.  You
> > don't need to convince me that a later standard is better than the
> > previous ones.  The issue at hand is whether we should write code that
> > targets more than a single language standard, where these standards
> > aren't compatible.  I think we shouldn't.
> 
> They are not incompatible.  C++03 code compiles with a C++11 compiler
> just fine.

Granted, I meant the other way around: use code that a C++11 compiler
will compile, but not a C++03 compiler.

> > The code obfuscation is very significant.  Of course, as long as you
> > don't look into the gnulib headers, you don't care, but in this case
> > you propose to have all those shims in our sources, in plain sight.
> 
> Yes, "all those shims".  One file.  And then cleaner code in thousands
> of uses of the shim throughout the codebase.  None of that
> shim-using code needs to know what version of the standard is
> being targeted.  Take a look at patch #3 from the gdb::unique_ptr
> series, and see for yourself.
> 
> So I'll take that tradeoff, yes.

Is this a one-time tradeoff, for this single patch?  Or is this a
policy?  In the former case, I have no objections.  In the latter
case, the "one file" argument doesn't apply.

> >>> that means maintenance burden 
> >>
> >> For whom?  _I'm_ willing to maintain this code.
> > 
> > Are you saying that no one else will be allowed to modify the code
> > which has 2 branches, one for C++03, the other for C++11?  I'm betting
> > you aren't saying that, 
> 
> Of course not.
> 
> > and so this is a burden for all of us, not just for you.  
> 
> You're automatically assuming it's a burden.  I believe that's
> false.

It should be clear and agreed by all that maintaining two
implementations for a single feature is more work than maintaining
just one.

> >> It's not rocket science code.
> > 
> > Today it isn't.  I'm not talking about this particular patch, I'm
> > talking about this policy in general.  As do you, I suppose: you
> > aren't just asking for agreement about using C++11 features in this
> > single case, right?
> 
> I'm talking about adding a small utility that is going to be used 
> extensively throughout the codebase.  A smart pointer is a central widget.
> That mine was modeled on a C++11 feature should be seen as
> a _good_ thing.  The std::unique_ptr was so good that it made it
> to the standard.  Not a small feat.  Bonus.  Once we move on to C++11
> for real (I don't know when), then there's one less API to learn.

And I'm again asking whether this is about this single patch, or about
a more general policy.  I assume that it's the latter, in which case
we are not talking about a single small utility, we are talking about
all the code that will be in the future admitted to GDB with the same
premise.  It is the policy that I object to, not a single exception.

> >> Several others have said they think this is a good idea.  I've even
> >> ran this idea through the libstdc++ maintainer in person at the Cauldron.
> >> Trevor said he wants to do this in gcc as well.
> > 
> > I just wanted to voice my opposition, that's all.  I don't have to
> > give up just because a few others think otherwise.  Right?
> 
> Of course.  The problem is that your opinion is interpreted as
> a hard blocker.  The result is stalling.

If there are no more convincing arguments, then a usual way out of
stalling is to find some compromise.  Is that possible in this case?

> >> If redirecting to C++11 std::unique_ptr turns out to cause trouble, or
> >> I'm hit by a bus, then it's trivial to remove that redirection.  All it
> >> takes is remove a handful of lines of code guarded with
> >> #if __cplusplus >= 201103 to always go through the fallback implementation.
> > 
> > Once again, it's not just this single patch that bothers me.  Once we
> > have enough of these #if's, removing them is not necessarily a trivial
> 
> And not "not necessarily" either...  This just looks like fear of
> the unknown, I'm afraid.

What exactly is unknown here?  It should be clear to anyone that more
of such patches, with separate implementations for C++11 and C++03,
will come soon enough.  What reason do you have to think they won't?
After all, C++11 is so much better than C++03, right?

> > matter, especially when most of the builds, perhaps even all of them,
> > have been using the C++11 code path all the time, and the other one
> > has simply bitrotted.
> 
> As I've said before, we can make use of the buildbot for that.
> If the fallback code breaks, you get an immediate email notification.

If someone sets it up to build both with and without C++11, yes.
A.k.a. "maintenance burden".

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

* Re: [RFA 03/22] Use scoped_restore for ui_file
  2016-10-01 11:47       ` Simon Marchi
@ 2016-10-13 14:56         ` Tom Tromey
  0 siblings, 0 replies; 123+ messages in thread
From: Tom Tromey @ 2016-10-13 14:56 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

>> FWIW Mozilla uses an Option class for this kind of thing.
>> It works like:

If you happened to search Firefox looking for this, it's called Maybe,
not Option -- Option is the Rust name for this.

Also I thought it was worth pointing out that this has made it into
C++17 under the name std::optional:

http://en.cppreference.com/w/cpp/utility/optional

Tom

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13 14:46                     ` Eli Zaretskii
@ 2016-10-13 15:04                       ` Pedro Alves
  2016-10-13 15:19                         ` Eli Zaretskii
  2016-10-13 15:27                       ` [RFA 09/22] Remove make_cleanup_restore_current_ui Pedro Alves
  1 sibling, 1 reply; 123+ messages in thread
From: Pedro Alves @ 2016-10-13 15:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, simon.marchi, gdb-patches

On 10/13/2016 03:46 PM, Eli Zaretskii wrote:
> And I'm again asking whether this is about this single patch, or about
> a more general policy.  I assume that it's the latter, in which case
> we are not talking about a single small utility, we are talking about
> all the code that will be in the future admitted to GDB with the same
> premise.  It is the policy that I object to, not a single exception.

I don't have an answer simply because I don't know what we'll
need in the future.  All I know right now that we sorely need
an owning smart pointer.  And for this particular case, I think
it makes a ton of sense to go dual dialect.

Maybe for other utilities that we may find missing in C++03,
we may decide to write replacements based on what C++11 or
later does, if they exist, and always use our replacement
code, even when compiled in C++11 mode.  In the owning smart
pointer case, there's a benefit to using the C++11 version.
For other things, there probably isn't.

So I don't plan on doing anything like this in the future.
It's hard to set a policy when all you have is one
example.

If I knew the future, I'd play the lottery.

Thanks,
Pedro Alves

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

* Re: [RFA 14/22] Replace two xmallocs with vector
  2016-10-09 17:20   ` Pedro Alves
  2016-10-12 22:39     ` Tom Tromey
@ 2016-10-13 15:15     ` Tom Tromey
  2016-10-13 15:26       ` Trevor Saunders
  1 sibling, 1 reply; 123+ messages in thread
From: Tom Tromey @ 2016-10-13 15:15 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> As general guideline, for these cases where we only need to
Pedro> construct a buffer once (never resize/reallocate) and we don't
Pedro> care about the initial contents of the buffer, I think
Pedro>   unique_ptr<char[]> buf (new char[size]);
Pedro> ends up being more efficient, because std::vector
Pedro> default/zero initializes its elements, which is unnecessary since
Pedro> we're about to write into the buffer anyway.

I made this change in my patches.

While doing so I realized one reason to prefer vector: with vector you
can build gdb with the libstdc++ debug mode, and get range checking.

Tom

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13 15:04                       ` Pedro Alves
@ 2016-10-13 15:19                         ` Eli Zaretskii
  2016-10-13 15:43                           ` Pedro Alves
  0 siblings, 1 reply; 123+ messages in thread
From: Eli Zaretskii @ 2016-10-13 15:19 UTC (permalink / raw)
  To: Pedro Alves; +Cc: tom, simon.marchi, gdb-patches

> Cc: tom@tromey.com, simon.marchi@polymtl.ca, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Thu, 13 Oct 2016 16:04:05 +0100
> 
> On 10/13/2016 03:46 PM, Eli Zaretskii wrote:
> > And I'm again asking whether this is about this single patch, or about
> > a more general policy.  I assume that it's the latter, in which case
> > we are not talking about a single small utility, we are talking about
> > all the code that will be in the future admitted to GDB with the same
> > premise.  It is the policy that I object to, not a single exception.
> 
> I don't have an answer simply because I don't know what we'll
> need in the future.

If we agree on some policy, then we don't need to worry about the
future, because the policy will determine what is going to be admitted
and what not.

> All I know right now that we sorely need an owning smart pointer.
> And for this particular case, I think it makes a ton of sense to go
> dual dialect.

But if we agree to require C++11 starting from now, you can go ahead
with your patch, and don't even need the other dialect.  So this
sounds like a win-win solution to me.

The only other thing we need to agree is that we are not going to
switch to a C++ standard newer than C++11, and won't allow code that
doesn't compile with C++11 compilers, until the oldest compiler which
supports that newer standard is at least 3 years old (like GCC 4.8.1
is today).

Does this sound like a compromise everyone can live with?

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

* Re: [RFA 14/22] Replace two xmallocs with vector
  2016-10-13 15:15     ` Tom Tromey
@ 2016-10-13 15:26       ` Trevor Saunders
  0 siblings, 0 replies; 123+ messages in thread
From: Trevor Saunders @ 2016-10-13 15:26 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, gdb-patches

On Thu, Oct 13, 2016 at 08:51:13AM -0600, Tom Tromey wrote:
> >>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> As general guideline, for these cases where we only need to
> Pedro> construct a buffer once (never resize/reallocate) and we don't
> Pedro> care about the initial contents of the buffer, I think
> Pedro>   unique_ptr<char[]> buf (new char[size]);
> Pedro> ends up being more efficient, because std::vector
> Pedro> default/zero initializes its elements, which is unnecessary since
> Pedro> we're about to write into the buffer anyway.
> 
> I made this change in my patches.
> 
> While doing so I realized one reason to prefer vector: with vector you
> can build gdb with the libstdc++ debug mode, and get range checking.

On the other hand if there isn't already a debug unique_ptr with the same
checking it seems like we should add that.  It shouldn't be terribly
hard.

Trev

> 
> Tom

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13 14:46                     ` Eli Zaretskii
  2016-10-13 15:04                       ` Pedro Alves
@ 2016-10-13 15:27                       ` Pedro Alves
  1 sibling, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-13 15:27 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, simon.marchi, gdb-patches

I hadn't answered everything.  Correcting that now.

On 10/13/2016 03:46 PM, Eli Zaretskii wrote:

>> You're automatically assuming it's a burden.  I believe that's
>> false.
> 
> It should be clear and agreed by all that maintaining two
> implementations for a single feature is more work than maintaining
> just one.

Sure, as general principle.  In this particular case, I can't
imagine any amount of significant work.

>>>> Several others have said they think this is a good idea.  I've even
>>>> ran this idea through the libstdc++ maintainer in person at the Cauldron.
>>>> Trevor said he wants to do this in gcc as well.
>>>
>>> I just wanted to voice my opposition, that's all.  I don't have to
>>> give up just because a few others think otherwise.  Right?
>>
>> Of course.  The problem is that your opinion is interpreted as
>> a hard blocker.  The result is stalling.
> 
> If there are no more convincing arguments, then a usual way out of
> stalling is to find some compromise.  Is that possible in this case?

I don't think so.

>>>> If redirecting to C++11 std::unique_ptr turns out to cause trouble, or
>>>> I'm hit by a bus, then it's trivial to remove that redirection.  All it
>>>> takes is remove a handful of lines of code guarded with
>>>> #if __cplusplus >= 201103 to always go through the fallback implementation.
>>>
>>> Once again, it's not just this single patch that bothers me.  Once we
>>> have enough of these #if's, removing them is not necessarily a trivial
>>
>> And not "not necessarily" either...  This just looks like fear of
>> the unknown, I'm afraid.
> 
> What exactly is unknown here?

The amount of work it'd take to remove the #ifs.

>>> matter, especially when most of the builds, perhaps even all of them,
>>> have been using the C++11 code path all the time, and the other one
>>> has simply bitrotted.
>>
>> As I've said before, we can make use of the buildbot for that.
>> If the fallback code breaks, you get an immediate email notification.
> 
> If someone sets it up to build both with and without C++11, yes.
> A.k.a. "maintenance burden".

All you need is one of buildbots testing gdb on an older distro
that doesn't have a new enough compiler.  It may even be already
there -- e.g., mjw's debian build bot.  So probably zero work,
actually.

Thanks,
Pedro Alves

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13 15:19                         ` Eli Zaretskii
@ 2016-10-13 15:43                           ` Pedro Alves
  2016-10-13 15:48                             ` Pedro Alves
  2016-10-17 23:43                             ` Go C++11? (was: Re: [RFA 09/22] Remove make_cleanup_restore_current_ui) Pedro Alves
  0 siblings, 2 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-13 15:43 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, simon.marchi, gdb-patches

On 10/13/2016 04:19 PM, Eli Zaretskii wrote:
>> Cc: tom@tromey.com, simon.marchi@polymtl.ca, gdb-patches@sourceware.org

>> All I know right now that we sorely need an owning smart pointer.
>> And for this particular case, I think it makes a ton of sense to go
>> dual dialect.
> 
> But if we agree to require C++11 starting from now, you can go ahead
> with your patch, and don't even need the other dialect.  So this
> sounds like a win-win solution to me.

Well, that'd be perfect.

But as I mentioned elsewhere, I'd prefer to take a staged approach
to C++11.  I.e., have a fallback plan.  My shim would actually _help_
with that.  So the plan would span a few weeks, and it'd be:

#1 - get gdb::unique_ptr in

#2 - start using unique_ptr throughout (there's a ton of work
     to do here, and it go on in parallel with the remainder
     of the plan.)

#3 - install the patch that switches C++11 on if the compiler supports it.
     The one I sent yesterday.

#4 - see if that causes problems.  fix problems.  maybe revert patch
     from step #3 if problems are hard to solve quickly.

#5 - flip to consider C++11 mandatory.  Make configure error out
     if no C++11 compiler is found.

#6 - see what workflows break (e.g., see if we need to do anything
     with some buildslaves.

#6.a - if $problem, revert patch from step #5.  fix whatever workflows,
       and goto #5.

#7 - otherwise, after some period, start using C++11 in full.
     Remove the shim and do s/gdb::unique_ptr/std::unique_ptr/g
     throughout the code base.

All the while between #1 and #7, we can progressively convert
cleanups to use gdb::unique_ptr.  Ie., we'd pipeline/paralyze
the work.

> The only other thing we need to agree is that we are not going to
> switch to a C++ standard newer than C++11, and won't allow code that
> doesn't compile with C++11 compilers, until the oldest compiler which
> supports that newer standard is at least 3 years old (like GCC 4.8.1
> is today).

Agreed.

> Does this sound like a compromise everyone can live with?

Thanks,
Pedro Alves

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

* Re: [RFA 09/22] Remove make_cleanup_restore_current_ui
  2016-10-13 15:43                           ` Pedro Alves
@ 2016-10-13 15:48                             ` Pedro Alves
  2016-10-17 23:43                             ` Go C++11? (was: Re: [RFA 09/22] Remove make_cleanup_restore_current_ui) Pedro Alves
  1 sibling, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-13 15:48 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, simon.marchi, gdb-patches

On 10/13/2016 04:43 PM, Pedro Alves wrote:
> All the while between #1 and #7, we can progressively convert
> cleanups to use gdb::unique_ptr.  Ie., we'd pipeline/paralyze
> the work.

err, s/paralyze/parallelize/ of course.  :-)

Thanks,
Pedro Alves

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

* Go C++11? (was: Re: [RFA 09/22] Remove make_cleanup_restore_current_ui)
  2016-10-13 15:43                           ` Pedro Alves
  2016-10-13 15:48                             ` Pedro Alves
@ 2016-10-17 23:43                             ` Pedro Alves
  2016-10-18  6:14                               ` Eli Zaretskii
  2016-10-19 18:02                               ` Go C++11? Luis Machado
  1 sibling, 2 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-17 23:43 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: tom, simon.marchi, gdb-patches

On 10/13/2016 04:43 PM, Pedro Alves wrote:
> On 10/13/2016 04:19 PM, Eli Zaretskii wrote:
>>> Cc: tom@tromey.com, simon.marchi@polymtl.ca, gdb-patches@sourceware.org
> 
>>> All I know right now that we sorely need an owning smart pointer.
>>> And for this particular case, I think it makes a ton of sense to go
>>> dual dialect.
>>
>> But if we agree to require C++11 starting from now, you can go ahead
>> with your patch, and don't even need the other dialect.  So this
>> sounds like a win-win solution to me.
> 
> Well, that'd be perfect.
> 
> But as I mentioned elsewhere, I'd prefer to take a staged approach
> to C++11.  I.e., have a fallback plan.  My shim would actually _help_
> with that.  So the plan would span a few weeks, and it'd be:
> 
> #1 - get gdb::unique_ptr in
> 
> #2 - start using unique_ptr throughout (there's a ton of work
>      to do here, and it go on in parallel with the remainder
>      of the plan.)
> 
> #3 - install the patch that switches C++11 on if the compiler supports it.
>      The one I sent yesterday.
> 
> #4 - see if that causes problems.  fix problems.  maybe revert patch
>      from step #3 if problems are hard to solve quickly.
> 
> #5 - flip to consider C++11 mandatory.  Make configure error out
>      if no C++11 compiler is found.
> 
> #6 - see what workflows break (e.g., see if we need to do anything
>      with some buildslaves.
> 
> #6.a - if $problem, revert patch from step #5.  fix whatever workflows,
>        and goto #5.
> 
> #7 - otherwise, after some period, start using C++11 in full.
>      Remove the shim and do s/gdb::unique_ptr/std::unique_ptr/g
>      throughout the code base.
> 
> All the while between #1 and #7, we can progressively convert
> cleanups to use gdb::unique_ptr.  Ie., we'd pipeline/paralyze
> the work.

So from the analysis I did at [1] it seems like we're actually
clear from the buildslave's side on requiring C++11.  I thought
it take longer to update the buildslaves, but MarkW was quick
and there doesn't seem to be other buildslaves that need
updating.

Sooo....  Shall we proceed with the straw man proposal and
apply the patches at [2] (enable -std=gnu+11 on gcc >= 4.8)?

 [1] - https://sourceware.org/ml/gdb-patches/2016-10/msg00496.html
 [2] - https://sourceware.org/ml/gdb-patches/2016-10/msg00336.html

Do people feel this hasn't been sufficiently discussed?

If we can do this now, I'll happily drop my shim in favor of
jumping to C++11 quicker!  Maybe it'll find a home in gcc.  :-)

I'd love to hear feedback.

Thanks,
Pedro Alves

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

* Re: Go C++11? (was: Re: [RFA 09/22] Remove make_cleanup_restore_current_ui)
  2016-10-17 23:43                             ` Go C++11? (was: Re: [RFA 09/22] Remove make_cleanup_restore_current_ui) Pedro Alves
@ 2016-10-18  6:14                               ` Eli Zaretskii
  2016-10-19 18:02                               ` Go C++11? Luis Machado
  1 sibling, 0 replies; 123+ messages in thread
From: Eli Zaretskii @ 2016-10-18  6:14 UTC (permalink / raw)
  To: Pedro Alves; +Cc: tom, simon.marchi, gdb-patches

> Cc: tom@tromey.com, simon.marchi@polymtl.ca, gdb-patches@sourceware.org
> From: Pedro Alves <palves@redhat.com>
> Date: Tue, 18 Oct 2016 00:43:19 +0100
> 
> Sooo....  Shall we proceed with the straw man proposal and
> apply the patches at [2] (enable -std=gnu+11 on gcc >= 4.8)?
> 
>  [1] - https://sourceware.org/ml/gdb-patches/2016-10/msg00496.html
>  [2] - https://sourceware.org/ml/gdb-patches/2016-10/msg00336.html
> 
> Do people feel this hasn't been sufficiently discussed?
> 
> If we can do this now, I'll happily drop my shim in favor of
> jumping to C++11 quicker!  Maybe it'll find a home in gcc.  :-)
> 
> I'd love to hear feedback.

You don't really want to hear more from me on this, do you?  Because
what I can say is quite clear.  Right?

Thanks.

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

* Re: Go C++11?
  2016-10-17 23:43                             ` Go C++11? (was: Re: [RFA 09/22] Remove make_cleanup_restore_current_ui) Pedro Alves
  2016-10-18  6:14                               ` Eli Zaretskii
@ 2016-10-19 18:02                               ` Luis Machado
  2016-10-19 22:34                                 ` Pedro Alves
  1 sibling, 1 reply; 123+ messages in thread
From: Luis Machado @ 2016-10-19 18:02 UTC (permalink / raw)
  To: Pedro Alves, Eli Zaretskii; +Cc: tom, simon.marchi, gdb-patches

On 10/17/2016 06:43 PM, Pedro Alves wrote:
> On 10/13/2016 04:43 PM, Pedro Alves wrote:
>> On 10/13/2016 04:19 PM, Eli Zaretskii wrote:
>>>> Cc: tom@tromey.com, simon.marchi@polymtl.ca, gdb-patches@sourceware.org
>>
>>>> All I know right now that we sorely need an owning smart pointer.
>>>> And for this particular case, I think it makes a ton of sense to go
>>>> dual dialect.
>>>
>>> But if we agree to require C++11 starting from now, you can go ahead
>>> with your patch, and don't even need the other dialect.  So this
>>> sounds like a win-win solution to me.
>>
>> Well, that'd be perfect.
>>
>> But as I mentioned elsewhere, I'd prefer to take a staged approach
>> to C++11.  I.e., have a fallback plan.  My shim would actually _help_
>> with that.  So the plan would span a few weeks, and it'd be:
>>
>> #1 - get gdb::unique_ptr in
>>
>> #2 - start using unique_ptr throughout (there's a ton of work
>>      to do here, and it go on in parallel with the remainder
>>      of the plan.)
>>
>> #3 - install the patch that switches C++11 on if the compiler supports it.
>>      The one I sent yesterday.
>>
>> #4 - see if that causes problems.  fix problems.  maybe revert patch
>>      from step #3 if problems are hard to solve quickly.
>>
>> #5 - flip to consider C++11 mandatory.  Make configure error out
>>      if no C++11 compiler is found.
>>
>> #6 - see what workflows break (e.g., see if we need to do anything
>>      with some buildslaves.
>>
>> #6.a - if $problem, revert patch from step #5.  fix whatever workflows,
>>        and goto #5.
>>
>> #7 - otherwise, after some period, start using C++11 in full.
>>      Remove the shim and do s/gdb::unique_ptr/std::unique_ptr/g
>>      throughout the code base.
>>
>> All the while between #1 and #7, we can progressively convert
>> cleanups to use gdb::unique_ptr.  Ie., we'd pipeline/paralyze
>> the work.
>
> So from the analysis I did at [1] it seems like we're actually
> clear from the buildslave's side on requiring C++11.  I thought
> it take longer to update the buildslaves, but MarkW was quick
> and there doesn't seem to be other buildslaves that need
> updating.
>
> Sooo....  Shall we proceed with the straw man proposal and
> apply the patches at [2] (enable -std=gnu+11 on gcc >= 4.8)?
>
>  [1] - https://sourceware.org/ml/gdb-patches/2016-10/msg00496.html
>  [2] - https://sourceware.org/ml/gdb-patches/2016-10/msg00336.html
>
> Do people feel this hasn't been sufficiently discussed?
>
> If we can do this now, I'll happily drop my shim in favor of
> jumping to C++11 quicker!  Maybe it'll find a home in gcc.  :-)
>
> I'd love to hear feedback.

I personally feel this hasn't been discussed much, but honestly it 
doesn't feel like discussion is going to change anything here other than 
create clashes of ideas. :-)

I've seen this go from "You got it wrong. We're not going to move to 
C++11" to "So, shall we move now?" rather quickly. Nothing showed up in 
gdb@ either.

Since we're already moving things quickly, we should probably discuss a 
policy to accept the next standard version and follow that from now on.

My $0.02.

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

* Re: Go C++11?
  2016-10-19 18:02                               ` Go C++11? Luis Machado
@ 2016-10-19 22:34                                 ` Pedro Alves
  0 siblings, 0 replies; 123+ messages in thread
From: Pedro Alves @ 2016-10-19 22:34 UTC (permalink / raw)
  To: Luis Machado, Eli Zaretskii; +Cc: tom, simon.marchi, gdb-patches

On 10/19/2016 07:02 PM, Luis Machado wrote:
> On 10/17/2016 06:43 PM, Pedro Alves wrote:

>> Sooo....  Shall we proceed with the straw man proposal and
>> apply the patches at [2] (enable -std=gnu+11 on gcc >= 4.8)?
>>
>>  [1] - https://sourceware.org/ml/gdb-patches/2016-10/msg00496.html
>>  [2] - https://sourceware.org/ml/gdb-patches/2016-10/msg00336.html
>>
>> Do people feel this hasn't been sufficiently discussed?
>>
>> If we can do this now, I'll happily drop my shim in favor of
>> jumping to C++11 quicker!  Maybe it'll find a home in gcc.  :-)
>>
>> I'd love to hear feedback.
> 
> I personally feel this hasn't been discussed much, but honestly it
> doesn't feel like discussion is going to change anything here other than
> create clashes of ideas. :-)

:-)

Right, discussion just for the sake of it is not in anyone's interests, IMO.

AFAIK, all blockers that _I_ thought existed either don't actually
exist or have been resolved.

If there are specific, actual blockers, we should certainly discuss those.

> 
> I've seen this go from "You got it wrong. We're not going to move to
> C++11" to "So, shall we move now?" rather quickly. 

To be clear, the original message, which is still true was:

The gdb::unique_ptr patch does _not_ make us require C++11.

> Nothing showed up in gdb@ either.
> Since we're already moving things quickly, we should probably discuss a
> policy to accept the next standard version and follow that from now on.

IMO such a discussion doesn't have to block starting to require C++11,
and can happen in parallel, since for sure we're not going to start
thinking about requiring C++14 right now.

In any case, Eli has suggested a policy.

Thanks,
Pedro Alves

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

end of thread, other threads:[~2016-10-19 22:34 UTC | newest]

Thread overview: 123+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-27  4:49 [RFA 00/22] More C++-ification Tom Tromey
2016-09-27  4:41 ` [RFA 15/22] Use std::string in macho_symfile_read_all_oso Tom Tromey
2016-10-09 17:28   ` Pedro Alves
2016-10-10 22:40     ` Tom Tromey
2016-10-10 22:46       ` Pedro Alves
2016-09-27  4:41 ` [RFA 07/22] Change scoped_minimal_symbol_reader to store objfile Tom Tromey
2016-09-29  9:19   ` Trevor Saunders
2016-09-30 21:41     ` Tom Tromey
2016-09-27  4:42 ` [RFA 19/22] Convert tid_range_parser to class Tom Tromey
2016-09-30  1:41   ` Pedro Alves
2016-09-30 14:52     ` Tom Tromey
     [not found]       ` <926126cb-b3c5-340b-ac1c-5bc14ca41bf9@redhat.com>
2016-10-04 19:24         ` Pedro Alves
2016-10-04 23:09           ` Pedro Alves
2016-10-05  2:16             ` Trevor Saunders
2016-10-12  2:12             ` Tom Tromey
2016-10-13  1:06               ` Pedro Alves
2016-09-27  4:42 ` [RFA 16/22] Use std::vector in elf_read_minimal_symbols Tom Tromey
2016-10-09 17:30   ` Pedro Alves
2016-09-27  4:43 ` [RFA 20/22] Initial conversion of dwarf_expr_ctx Tom Tromey
2016-10-09 17:40   ` Pedro Alves
2016-09-27  4:45 ` [RFA 21/22] Convert DWARF expr functions to methods Tom Tromey
2016-10-09 19:18   ` Pedro Alves
2016-09-27  4:47 ` [RFA 02/22] Use RAII to save and restore scalars Tom Tromey
2016-09-27 10:24   ` Trevor Saunders
2016-09-30  1:40     ` Pedro Alves
2016-09-30  9:22       ` Pedro Alves
2016-09-30 15:00       ` Tom Tromey
2016-09-30 23:50         ` Pedro Alves
2016-09-30 15:44       ` Tom Tromey
2016-09-30 23:51         ` Pedro Alves
2016-10-01  3:55           ` Tom Tromey
2016-10-01  4:23             ` Tom Tromey
2016-10-01 10:33               ` Pedro Alves
2016-10-02 17:11                 ` Tom Tromey
2016-10-05  0:06                   ` Pedro Alves
2016-10-12 22:36                     ` Tom Tromey
2016-09-27  4:47 ` [RFA 04/22] Use scoped_restore for current_ui Tom Tromey
2016-09-27  4:47 ` [RFA 05/22] Turn wchar iterator into a class Tom Tromey
2016-10-06  1:01   ` Pedro Alves
2016-09-27  4:47 ` [RFA 22/22] Convert dwarf_expr_context_funcs to methods Tom Tromey
2016-10-09 19:11   ` Pedro Alves
2016-10-10 18:31     ` Pedro Alves
2016-10-10 19:33       ` Pedro Alves
2016-09-27  4:48 ` [RFA 09/22] Remove make_cleanup_restore_current_ui Tom Tromey
2016-09-29 11:55   ` Trevor Saunders
2016-10-01  3:47     ` Tom Tromey
2016-10-01  4:29   ` Simon Marchi
2016-10-06  2:53     ` Tom Tromey
2016-10-06  1:24   ` Pedro Alves
2016-10-06  2:52     ` Tom Tromey
2016-10-09  4:31   ` Simon Marchi
2016-10-09 15:10     ` Tom Tromey
2016-10-09 19:20       ` Pedro Alves
2016-10-12 22:43         ` Tom Tromey
2016-10-13  1:28           ` Pedro Alves
2016-10-13  6:11             ` Eli Zaretskii
2016-10-13 10:16               ` Pedro Alves
2016-10-13 13:53                 ` Eli Zaretskii
2016-10-13 14:26                   ` Pedro Alves
2016-10-13 14:46                     ` Eli Zaretskii
2016-10-13 15:04                       ` Pedro Alves
2016-10-13 15:19                         ` Eli Zaretskii
2016-10-13 15:43                           ` Pedro Alves
2016-10-13 15:48                             ` Pedro Alves
2016-10-17 23:43                             ` Go C++11? (was: Re: [RFA 09/22] Remove make_cleanup_restore_current_ui) Pedro Alves
2016-10-18  6:14                               ` Eli Zaretskii
2016-10-19 18:02                               ` Go C++11? Luis Machado
2016-10-19 22:34                                 ` Pedro Alves
2016-10-13 15:27                       ` [RFA 09/22] Remove make_cleanup_restore_current_ui Pedro Alves
2016-10-13 14:26                 ` Trevor Saunders
2016-09-27  4:48 ` [RFA 08/22] Record minimal symbols directly in reader Tom Tromey
2016-10-01  4:29   ` Simon Marchi
2016-10-06  1:12     ` Pedro Alves
2016-09-27  4:48 ` [RFA 01/22] Change selttest.c to use use std::vector Tom Tromey
2016-09-27  8:50   ` Trevor Saunders
2016-09-27 16:44     ` Tom Tromey
2016-09-28 14:58       ` Trevor Saunders
2016-09-29  8:59         ` Tom Tromey
2016-10-06  0:18       ` Pedro Alves
2016-10-06  0:39       ` Pedro Alves
2016-09-30 14:43   ` Simon Marchi
2016-09-30 21:40     ` Tom Tromey
2016-10-06  0:45       ` Pedro Alves
2016-09-27  4:48 ` [RFA 03/22] Use scoped_restore for ui_file Tom Tromey
2016-10-01  4:28   ` Simon Marchi
2016-10-01  5:22     ` Tom Tromey
2016-10-01 11:47       ` Simon Marchi
2016-10-13 14:56         ` Tom Tromey
2016-09-27  4:50 ` [RFA 17/22] Remove make_cleanup_restore_current_uiout Tom Tromey
2016-09-29 14:35   ` Trevor Saunders
2016-09-29 15:23     ` Tom Tromey
2016-09-29 17:55       ` Simon Marchi
2016-09-29 20:34         ` Tom Tromey
2016-09-30  2:45       ` Pedro Alves
2016-09-30 23:48         ` Tom Tromey
2016-09-30 23:52           ` Pedro Alves
2016-09-27  4:51 ` [RFA 13/22] Remove unnecessary cleanup from stabsread.c Tom Tromey
2016-09-30 16:19   ` Tom Tromey
2016-10-09 17:07   ` Pedro Alves
2016-09-27  4:51 ` [RFA 12/22] Remove unnecessary null_cleanup Tom Tromey
2016-10-09 17:06   ` Pedro Alves
2016-09-27  4:51 ` [RFA 18/22] Some cleanup removal in dwarf2loc.c Tom Tromey
2016-10-09 17:37   ` Pedro Alves
2016-09-27  4:51 ` [RFA 14/22] Replace two xmallocs with vector Tom Tromey
2016-10-09 17:20   ` Pedro Alves
2016-10-12 22:39     ` Tom Tromey
2016-10-13  1:17       ` Pedro Alves
2016-10-13  2:04         ` Tom Tromey
2016-10-13 15:15     ` Tom Tromey
2016-10-13 15:26       ` Trevor Saunders
2016-09-27  4:52 ` [RFA 06/22] Introduce scoped_minimal_symbol_reader Tom Tromey
2016-10-06  1:10   ` Pedro Alves
2016-10-06 15:37     ` Tom Tromey
2016-10-10 23:06     ` Tom Tromey
2016-10-10 23:26       ` Pedro Alves
2016-09-27  4:52 ` [RFA 10/22] Remove some cleanups in MI Tom Tromey
2016-10-06  1:42   ` Pedro Alves
2016-09-27  8:32 ` [RFA 11/22] Change command stats reporting to use class Tom Tromey
2016-10-09 17:01   ` Pedro Alves
2016-10-11 17:31     ` Tom Tromey
2016-10-08 13:57 ` [RFA 00/22] More C++-ification Simon Marchi
2016-10-08 16:42   ` Pedro Alves
2016-10-09  2:09   ` Tom Tromey

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