public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFA v2 07/17] Remove make_cleanup_restore_current_ui
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (11 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 01/17] Use RAII to save and restore scalars Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:37   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 11/17] Use gdb::unique_ptr in elf_read_minimal_symbols Tom Tromey
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 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-10-10  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, tui_on_user_selected_context_changed):
	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, mi_user_selected_context_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, cli_on_user_selected_context_changed):
	Update.
	* breakpoint.c (watchpoint_check): Update.
---
 gdb/ChangeLog        |  32 ++++++++++++++++
 gdb/breakpoint.c     |   8 +---
 gdb/cli/cli-interp.c |  27 ++++---------
 gdb/event-top.c      |  50 -------------------------
 gdb/infrun.c         |  15 +++-----
 gdb/mi/mi-interp.c   | 104 +++++++++++++--------------------------------------
 gdb/top.h            |  56 +++++++++++++++++----------
 gdb/tui/tui-interp.c |  27 ++++---------
 8 files changed, 117 insertions(+), 202 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a1e2f6e..04e550a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,35 @@
+2016-10-10  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, tui_on_user_selected_context_changed):
+	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, mi_user_selected_context_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, cli_on_user_selected_context_changed):
+	Update.
+	* breakpoint.c (watchpoint_check): Update.
+
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
 	* xcoffread.c (record_minimal_symbol, scan_xcoff_symtab): Add
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index b9bb797..ea4d29a 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5219,8 +5219,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
@@ -5235,7 +5233,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;
 
@@ -5416,9 +5414,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 cc556a4..dfa96d6 100644
--- a/gdb/cli/cli-interp.c
+++ b/gdb/cli/cli-interp.c
@@ -99,12 +99,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);
@@ -124,9 +122,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 ());
 
@@ -142,9 +138,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 ());
 
@@ -160,9 +154,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 ());
 
@@ -178,9 +170,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 ());
 
@@ -196,9 +186,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 ());
 
@@ -240,7 +228,6 @@ cli_on_command_error (void)
 static void
 cli_on_user_selected_context_changed (user_selected_what selection)
 {
-  struct switch_thru_all_uis state;
   struct thread_info *tp;
 
   /* This event is suppressed.  */
@@ -249,7 +236,7 @@ cli_on_user_selected_context_changed (user_selected_what selection)
 
   tp = find_thread_ptid (inferior_ptid);
 
-  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 2883717..1864019 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3855,9 +3855,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 ();
     }
@@ -3868,9 +3866,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 ();
@@ -8215,7 +8211,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);
 
@@ -8280,7 +8275,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"),
@@ -8292,7 +8287,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 ();
@@ -8309,7 +8304,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 d7db499..72d63d0 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;
@@ -777,12 +752,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;
@@ -811,9 +784,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;
@@ -839,9 +810,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;
@@ -869,9 +838,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;
@@ -909,15 +876,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;
@@ -963,15 +928,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;
@@ -996,15 +959,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;
@@ -1045,9 +1006,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 ());
 
@@ -1133,7 +1093,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 ();
@@ -1144,7 +1103,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;
@@ -1164,9 +1123,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;
@@ -1205,9 +1162,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;
@@ -1247,12 +1202,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;
@@ -1287,12 +1240,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;
@@ -1341,7 +1292,6 @@ mi_memory_changed (struct inferior *inferior, CORE_ADDR memaddr,
 static void
 mi_user_selected_context_changed (user_selected_what selection)
 {
-  struct switch_thru_all_uis state;
   struct thread_info *tp;
 
   /* Don't send an event if we're responding to an MI command.  */
@@ -1350,7 +1300,7 @@ mi_user_selected_context_changed (user_selected_what selection)
 
   tp = find_thread_ptid (inferior_ptid);
 
-  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..fcf16eb 100644
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -155,27 +155,48 @@ 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
 {
-  struct ui *iter;
-  struct cleanup *old_chain;
+public:
+
+  switch_thru_all_uis () : m_iter (ui_list), m_save_ui (&current_ui)
+  {
+    current_ui = ui_list;
+  }
+
+  // If done iterating, return true; otherwise return false.
+  bool done () const
+  {
+    return m_iter == NULL;
+  }
+
+  // Move to the next UI, setting current_ui if iteration is not yet
+  // complete.
+  void next ()
+  {
+    m_iter = m_iter->next;
+    if (m_iter != NULL)
+      current_ui = m_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 *m_iter;
+
+  // Save and restore current_ui.
+  scoped_restore_tmpl<struct ui *> m_save_ui;
 };
 
-/* 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);
-
   /* 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))
+#define SWITCH_THRU_ALL_UIS()		\
+  for (switch_thru_all_uis stau_state; !stau_state.done (); stau_state.next ())
 
 /* Traverse over all UIs.  */
 #define ALL_UIS(UI)				\
@@ -188,9 +209,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 e06d679..8d35124 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 ());
 
@@ -211,7 +199,6 @@ tui_on_command_error (void)
 static void
 tui_on_user_selected_context_changed (user_selected_what selection)
 {
-  struct switch_thru_all_uis state;
   struct thread_info *tp;
 
   /* This event is suppressed.  */
@@ -220,7 +207,7 @@ tui_on_user_selected_context_changed (user_selected_what selection)
 
   tp = find_thread_ptid (inferior_ptid);
 
-  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] 59+ messages in thread

* [RFA v2 04/17] Introduce minimal_symbol_reader
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (2 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 12/17] Remove make_cleanup_restore_current_uiout Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:20   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 05/17] Change minimal_symbol_reader to store objfile Tom Tromey
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch introduced 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
	minimal_symbol_reader.
	* mipsread.c (mipscoff_symfile_read): Use
	minimal_symbol_reader.
	* minsyms.h (minimal_symbol_reader): New class.
	(init_minimal_symbol_collection)
	(make_cleanup_discard_minimal_symbols, install_minimal_symbols):
	Don't declare.
	* minsyms.c (minimal_symbol_reader): Renamed from
	init_minimal_symbol_collection, turned into constructor.
	(~minimal_symbol_reader): Renamed from
	do_discard_minimal_symbols_cleanup, turned into destructor.
	(make_cleanup_discard_minimal_symbols): Remove.
	(minimal_symbol_reader::install): Rename form
	install_minimal_symbols.
	* mdebugread.c (elfmdebug_build_psymtabs): Use
	minimal_symbol_reader.
	* machoread.c (macho_symfile_read): Use
	minimal_symbol_reader.
	* elfread.c (elf_read_minimal_symbols): Use
	minimal_symbol_reader.
	* dbxread.c (dbx_symfile_read): Use minimal_symbol_reader.
	* coffread.c (coff_symfile_read): Use
	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 8ab0c10..840831c 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
+	minimal_symbol_reader.
+	* mipsread.c (mipscoff_symfile_read): Use
+	minimal_symbol_reader.
+	* minsyms.h (minimal_symbol_reader): New class.
+	(init_minimal_symbol_collection)
+	(make_cleanup_discard_minimal_symbols, install_minimal_symbols):
+	Don't declare.
+	* minsyms.c (minimal_symbol_reader): Renamed from
+	init_minimal_symbol_collection, turned into constructor.
+	(~minimal_symbol_reader): Renamed from
+	do_discard_minimal_symbols_cleanup, turned into destructor.
+	(make_cleanup_discard_minimal_symbols): Remove.
+	(minimal_symbol_reader::install): Rename form
+	install_minimal_symbols.
+	* mdebugread.c (elfmdebug_build_psymtabs): Use
+	minimal_symbol_reader.
+	* machoread.c (macho_symfile_read): Use
+	minimal_symbol_reader.
+	* elfread.c (elf_read_minimal_symbols): Use
+	minimal_symbol_reader.
+	* dbxread.c (dbx_symfile_read): Use minimal_symbol_reader.
+	* coffread.c (coff_symfile_read): Use
+	minimal_symbol_reader.
+
+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/coffread.c b/gdb/coffread.c
index 830deb5..67b9cb7 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 ();
+  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 cb5f54c..4f2852b 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 ();
+  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..4f55e37 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 ();
+  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 2eff534..45ae67b 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -855,8 +855,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 ();
+          minimal_symbol_reader reader;
 
 	  symcount = bfd_canonicalize_symtab (objfile->obfd, symbol_table);
 
@@ -867,7 +866,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..358ee70 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 ();
+  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 21255d6..32146dc 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -916,8 +916,7 @@ get_symbol_leading_char (bfd *abfd)
 
 /* See minsyms.h.  */
 
-void
-init_minimal_symbol_collection (void)
+minimal_symbol_reader::minimal_symbol_reader ()
 {
   msym_count = 0;
   msym_bunch = NULL;
@@ -927,6 +926,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?  */
+
+minimal_symbol_reader::~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
@@ -1082,37 +1101,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.
@@ -1239,7 +1227,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)
+minimal_symbol_reader::install (struct objfile *objfile)
 {
   int bindex;
   int mcount;
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index 8857f1a..d75bd41 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 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 minimal_symbol_reader ();
+
+  ~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.  */
+  minimal_symbol_reader &operator=
+    (const minimal_symbol_reader &);
+  minimal_symbol_reader (const 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..dff1cb1 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 ();
+  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..76d6d79 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 ();
+  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] 59+ messages in thread

* [RFA v2 01/17] Use RAII to save and restore scalars
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (10 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 14/17] Initial conversion of dwarf_expr_ctx Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:03   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 07/17] Remove make_cleanup_restore_current_ui Tom Tromey
                   ` (6 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 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.

The class is typically instantiated using make_scoped_restore.  This
allows for template argument deduction.

2016-10-13  Tom Tromey  <tom@tromey.com>

	* common/scoped_restore.h: New file.
	* utils.h: Include scoped_restore.h.
	* 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               | 23 +++++++++++
 gdb/arm-tdep.c              |  9 ++---
 gdb/cli/cli-script.c        | 18 ++-------
 gdb/common/scoped_restore.h | 99 +++++++++++++++++++++++++++++++++++++++++++++
 gdb/compile/compile.c       | 23 ++++-------
 gdb/infrun.c                | 16 +-------
 gdb/linux-fork.c            | 11 ++---
 gdb/mi/mi-cmd-var.c         |  8 +---
 gdb/mi/mi-main.c            |  3 +-
 gdb/printcmd.c              |  6 +--
 gdb/python/python.c         | 12 ++----
 gdb/top.c                   |  3 +-
 gdb/utils.h                 |  1 +
 13 files changed, 155 insertions(+), 77 deletions(-)
 create mode 100644 gdb/common/scoped_restore.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0efe9c1..775fa81 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,26 @@
+2016-10-13  Tom Tromey  <tom@tromey.com>
+
+	* common/scoped_restore.h: New file.
+	* utils.h: Include scoped_restore.h.
+	* 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-10-12  Tom Tromey  <tom@tromey.com>
 
 	* machoread.c (macho_symfile_read_all_oso): Use std::string.
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 31ebdc3..9fda74a 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -4255,15 +4255,12 @@ 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 save_override_mode
+    = make_scoped_restore (&arm_override_mode,
+			   (int) 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 0118795..b5684a4 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 save_async = make_scoped_restore (&current_ui->async, 0);
 
   command_nest_depth++;
   while (cmdlines)
@@ -651,7 +650,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);
@@ -659,13 +657,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 save_async = make_scoped_restore (&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
@@ -683,13 +678,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 save_async = make_scoped_restore (&current_ui->async, 0);
 
   execute_control_command_untraced (command);
   free_command_lines (&command);
-
-  do_cleanups (old_chain);
 }
 
 /* Cleanup */
@@ -1647,10 +1639,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 save_async = make_scoped_restore (&current_ui->async, 0);
 
     TRY
       {
diff --git a/gdb/common/scoped_restore.h b/gdb/common/scoped_restore.h
new file mode 100644
index 0000000..8c2a5b0
--- /dev/null
+++ b/gdb/common/scoped_restore.h
@@ -0,0 +1,99 @@
+/* scoped_restore, a simple class for saving and restoring a value
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef SCOPED_RESTORE_H
+#define SCOPED_RESTORE_H
+
+/* Base class for scoped_restore_tmpl.  */
+struct scoped_restore_base
+{
+};
+
+/* A convenience typedef.  Users of make_scoped_restore declare the
+   local RAII object as having this type.  */
+typedef const scoped_restore_base &scoped_restore;
+
+/* 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_tmpl : public scoped_restore_base
+{
+ public:
+
+  /* Create a new scoped_restore object that saves the current value
+     of *VAR.  *VAR will be restored when this scoped_restore object
+     is destroyed.  */
+  scoped_restore_tmpl (T *var)
+    : m_saved_var (var),
+      m_saved_value (*var)
+  {
+  }
+
+  /* Create a new scoped_restore object that saves the current value
+     of *VAR, and sets *VAR to VALUE.  *VAR will be restored when this
+     scoped_restore object is destroyed.  */
+  scoped_restore_tmpl (T *var, T value)
+    : m_saved_var (var),
+      m_saved_value (*var)
+  {
+    *var = value;
+  }
+
+  scoped_restore_tmpl (const scoped_restore_tmpl<T> &other)
+    : m_saved_var (other.m_saved_var),
+      m_saved_value (other.m_saved_value)
+  {
+    other.m_saved_var = NULL;
+  }
+
+  ~scoped_restore_tmpl ()
+  {
+    if (m_saved_var != NULL)
+      *m_saved_var = m_saved_value;
+  }
+
+ private:
+
+  /* No need for this.  It is intentionally not defined anywhere.  */
+  scoped_restore_tmpl &operator= (const scoped_restore_tmpl &);
+
+  /* The saved variable.  */
+  mutable T *m_saved_var;
+
+  /* The saved value.  */
+  const T m_saved_value;
+};
+
+/* Make a scoped_restore.  This is useful because it lets template
+   argument deduction work.  */
+template<typename T>
+scoped_restore_tmpl<T> make_scoped_restore (T *var)
+{
+  return scoped_restore_tmpl<T> (var);
+}
+
+/* Make a scoped_restore.  This is useful because it lets template
+   argument deduction work.  */
+template<typename T>
+scoped_restore_tmpl<T> make_scoped_restore (T *var, T value)
+{
+  return scoped_restore_tmpl<T> (var, value);
+}
+
+#endif /* SCOPED_RESTORE_H */
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 0db95e4..2de9de5 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 save_async = make_scoped_restore (&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 save_async = make_scoped_restore (&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 save_async = make_scoped_restore (&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 2fa6449..3e62cfe 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3877,17 +3877,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
@@ -3904,7 +3893,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;
 
@@ -3943,8 +3931,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 save_exec_dir
+    = make_scoped_restore (&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..e4be593 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 save_pid
+      = make_scoped_restore (&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 48dc602..147e026 100644
--- a/gdb/mi/mi-cmd-var.c
+++ b/gdb/mi/mi-cmd-var.c
@@ -591,7 +591,6 @@ mi_cmd_var_assign (char *command, char **argv, int argc)
 {
   struct ui_out *uiout = current_uiout;
   struct varobj *var;
-  struct cleanup *cleanup;
 
   if (argc != 2)
     error (_("-var-assign: Usage: NAME EXPRESSION."));
@@ -606,9 +605,8 @@ 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 save_suppress
+    = make_scoped_restore (&mi_suppress_notification.memory, 1);
 
   if (!varobj_set_value (var, expression))
     error (_("-var-assign: Could not assign "
@@ -616,8 +614,6 @@ mi_cmd_var_assign (char *command, char **argv, int argc)
 
   std::string val = varobj_get_value (var);
   ui_out_field_string (uiout, "value", val.c_str ());
-
-  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 98d53ca..b80b4f2 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -301,7 +301,7 @@ exec_continue (char **argv, int argc)
     }
   else
     {
-      struct cleanup *back_to = make_cleanup_restore_integer (&sched_multi);
+      scoped_restore save_multi = make_scoped_restore (&sched_multi);
 
       if (current_context->all)
 	{
@@ -316,7 +316,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 ef64d15..082f8e8 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1919,7 +1919,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)
@@ -1970,8 +1969,8 @@ 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 save_display_number
+    = make_scoped_restore (&current_display_number, d->number);
 
   annotate_display_begin ();
   printf_filtered ("%d", d->number);
@@ -2059,7 +2058,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 0ca7d9a..53f83b8 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 save_async = make_scoped_restore (&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 save_async = make_scoped_restore (&current_ui->async, 0);
 
   arg = skip_spaces (arg);
   if (arg && *arg)
@@ -652,8 +647,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 save_async = make_scoped_restore (&current_ui->async, 0);
 
       make_cleanup_restore_current_uiout ();
 
diff --git a/gdb/top.c b/gdb/top.c
index fb424b6..ce41bc9 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -700,8 +700,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 save_async = make_scoped_restore (&current_ui->async, 0);
 
   str_file = mem_fileopen ();
 
diff --git a/gdb/utils.h b/gdb/utils.h
index 8635075..c4944e1 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -22,6 +22,7 @@
 #define UTILS_H
 
 #include "exceptions.h"
+#include "common/scoped_restore.h"
 
 extern void initialize_utils (void);
 
-- 
2.7.4

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

* [RFA v2 02/17] Use scoped_restore for ui_file
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (6 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 03/17] Use scoped_restore for current_ui Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:07   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 06/17] Record minimal symbols directly in reader Tom Tromey
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 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             | 16 ++++++----------
 gdb/utils.c           | 29 -----------------------------
 gdb/utils.h           |  3 ---
 5 files changed, 19 insertions(+), 48 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 775fa81..8539d0e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,12 @@
+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-10-13  Tom Tromey  <tom@tromey.com>
 
 	* common/scoped_restore.h: New file.
diff --git a/gdb/guile/scm-ports.c b/gdb/guile/scm-ports.c
index 5559475..dea9077 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 save_file = make_scoped_restore (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 ce41bc9..f6176ae 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -705,22 +705,18 @@ 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 save_stdout = make_scoped_restore (&gdb_stdout, str_file);
+  scoped_restore save_stderr = make_scoped_restore (&gdb_stderr, str_file);
+  scoped_restore save_stdlog = make_scoped_restore (&gdb_stdlog, str_file);
+  scoped_restore save_stdtarg = make_scoped_restore (&gdb_stdtarg, str_file);
+  scoped_restore save_stdtargerr = make_scoped_restore (&gdb_stdtargerr,
+							str_file);
 
   execute_command (p, from_tty);
 
diff --git a/gdb/utils.c b/gdb/utils.c
index 6feeb4d..e50177d 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 c4944e1..36f5294 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -91,9 +91,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] 59+ messages in thread

* [RFA v2 15/17] Convert DWARF expr functions to methods
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 23:01   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 08/17] Remove some cleanups in MI Tom Tromey
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 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 bcf08f8..b58e622 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 e8487a6..72de98d 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.  */
@@ -422,14 +412,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)
@@ -437,7 +427,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;
 }
@@ -612,14 +602,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
@@ -627,15 +617,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)
     {
@@ -696,26 +686,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;
 
@@ -808,7 +798,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:
@@ -817,7 +807,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:
@@ -827,9 +817,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");
@@ -837,7 +827,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;
 
@@ -845,21 +835,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");
 	  }
@@ -899,7 +889,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);
@@ -909,7 +899,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);
 	  }
@@ -925,78 +915,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;
 	  }
 
@@ -1004,12 +994,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)
 	      {
@@ -1017,12 +1007,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.  */
@@ -1046,8 +1036,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)
 	      {
@@ -1095,11 +1085,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"));
@@ -1128,7 +1118,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);
@@ -1163,7 +1153,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);
 		  }
@@ -1180,7 +1170,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);
 		  }
@@ -1231,7 +1221,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;
@@ -1246,9 +1236,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;
 
@@ -1264,11 +1254,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;
 
@@ -1281,14 +1271,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;
 
@@ -1299,14 +1289,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;
 
@@ -1315,7 +1305,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:
@@ -1324,7 +1314,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;
 
@@ -1334,7 +1324,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;
 	
@@ -1352,7 +1342,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 */);
@@ -1365,9 +1355,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;
@@ -1385,7 +1375,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 */);
@@ -1405,7 +1395,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;
@@ -1419,8 +1409,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;
 
@@ -1436,10 +1426,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);
@@ -1459,7 +1449,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;
 
@@ -1469,7 +1459,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:
       ;
     }
@@ -1477,12 +1467,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 4914c16..1f946df 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] 59+ messages in thread

* [RFA v2 11/17] Use gdb::unique_ptr in elf_read_minimal_symbols
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (12 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 07/17] Remove make_cleanup_restore_current_ui Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:44   ` Pedro Alves
  2016-10-13 21:13 ` [RFA v2 13/17] Some cleanup removal in dwarf2loc.c Tom Tromey
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes elf_read_minimal_symbols to use gdb::unique_ptr rather
than an explicit allocation.  This removes a cleanup.

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

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

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0d5f425..ea777f6 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 gdb::unique_ptr.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* cli/cli-dump.c (dump_memory_to_file): Use gdb::unique_ptr.
 	(restore_binary_file): Likewise.
 
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 56fac28..485e55d 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1024,7 +1024,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 +1052,6 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
     }
 
   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 +1133,14 @@ 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);
+      gdb::unique_ptr<asymbol *[]>
+	synth_symbol_table (new asymbol *[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.get (), 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] 59+ messages in thread

* [RFA v2 14/17] Initial conversion of dwarf_expr_ctx
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (9 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:54   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 01/17] Use RAII to save and restore scalars Tom Tromey
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 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 associated 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 a06cc27..bcf08f8 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>
+
 	* dwarf2loc.c: Include <vector>.
 	(read_pieced_value, write_pieced_value)
 	(dwarf2_compile_expr_to_ax): Use std::vector.
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 90e4e25..e8487a6 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 (NULL),
+  stack_len (0),
+  stack_allocated (10),
+  gdbarch (NULL),
+  addr_size (0),
+  ref_addr_size (0),
+  offset (0),
+  recursion_depth (0),
+  max_recursion_depth (0x100),
+  location (DWARF_VALUE_MEMORY),
+  len (0),
+  data (NULL),
+  initialized (0),
+  num_pieces (0),
+  pieces (NULL)
 {
-  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 87a4fb9..4914c16 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] 59+ messages in thread

* [RFA v2 05/17] Change minimal_symbol_reader to store objfile
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (3 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 04/17] Introduce minimal_symbol_reader Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:21   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 10/17] Replace two xmallocs with unique_ptr Tom Tromey
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes 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 (minimal_symbol_reader): Add obj argument.
	Initialize member.
	(install): Remove objfile argument.  Update.
	* 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 (minimal_symbol_reader): Add m_objfile member.
	(constructor): Add objfile argument.
	(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    | 35 ++++++++++++++++++-----------------
 gdb/minsyms.h    |  6 ++++--
 gdb/mipsread.c   |  4 ++--
 gdb/xcoffread.c  |  4 ++--
 10 files changed, 52 insertions(+), 33 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 840831c..790be41 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 (minimal_symbol_reader): Add obj argument.
+	Initialize member.
+	(install): Remove objfile argument.  Update.
+	* 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 (minimal_symbol_reader): Add m_objfile member.
+	(constructor): Add objfile argument.
+	(minimal_symbol_reader::install): Remove objfile argument.
+
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
 	* xcoffread.c (xcoff_initial_scan): Use
 	minimal_symbol_reader.
 	* mipsread.c (mipscoff_symfile_read): Use
diff --git a/gdb/coffread.c b/gdb/coffread.c
index 67b9cb7..b4de08e 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);
 
-  minimal_symbol_reader reader;
+  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 4f2852b..446813b 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);
 
-  minimal_symbol_reader reader;
+  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 4f55e37..58e0cbc 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1049,7 +1049,7 @@ elf_read_minimal_symbols (struct objfile *objfile, int symfile_flags,
       return;
     }
 
-  minimal_symbol_reader reader;
+  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 45ae67b..1f82f2b 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -855,7 +855,7 @@ macho_symfile_read (struct objfile *objfile, int symfile_flags)
 	  symbol_table = (asymbol **) xmalloc (storage_needed);
 	  make_cleanup (xfree, symbol_table);
 
-          minimal_symbol_reader reader;
+          minimal_symbol_reader reader (objfile);
 
 	  symcount = bfd_canonicalize_symtab (objfile->obfd, symbol_table);
 
@@ -866,7 +866,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 358ee70..1285db4 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.  */
 
-  minimal_symbol_reader reader;
+  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 32146dc..e614ff0 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -916,7 +916,8 @@ get_symbol_leading_char (bfd *abfd)
 
 /* See minsyms.h.  */
 
-minimal_symbol_reader::minimal_symbol_reader ()
+minimal_symbol_reader::minimal_symbol_reader (struct objfile *obj)
+: m_objfile (obj)
 {
   msym_count = 0;
   msym_bunch = NULL;
@@ -1227,7 +1228,7 @@ build_minimal_symbol_hash_tables (struct objfile *objfile)
    attempts to demangle them if we later add more minimal symbols.  */
 
 void
-minimal_symbol_reader::install (struct objfile *objfile)
+minimal_symbol_reader::install ()
 {
   int bindex;
   int mcount;
@@ -1235,7 +1236,7 @@ minimal_symbol_reader::install (struct objfile *objfile)
   struct minimal_symbol *msymbols;
   int alloc_count;
 
-  if (objfile->per_bfd->minsyms_read)
+  if (m_objfile->per_bfd->minsyms_read)
     return;
 
   if (msym_count > 0)
@@ -1244,7 +1245,7 @@ minimal_symbol_reader::install (struct objfile *objfile)
 	{
 	  fprintf_unfiltered (gdb_stdlog,
 			      "Installing %d minimal symbols of objfile %s.\n",
-			      msym_count, objfile_name (objfile));
+			      msym_count, objfile_name (m_objfile));
 	}
 
       /* Allocate enough space in the obstack, into which we will gather the
@@ -1252,17 +1253,17 @@ minimal_symbol_reader::install (struct objfile *objfile)
          compact out the duplicate entries.  Once we have a final table,
          we will give back the excess space.  */
 
-      alloc_count = msym_count + objfile->per_bfd->minimal_symbol_count + 1;
-      obstack_blank (&objfile->per_bfd->storage_obstack,
+      alloc_count = msym_count + m_objfile->per_bfd->minimal_symbol_count + 1;
+      obstack_blank (&m_objfile->per_bfd->storage_obstack,
 		     alloc_count * sizeof (struct minimal_symbol));
       msymbols = (struct minimal_symbol *)
-	obstack_base (&objfile->per_bfd->storage_obstack);
+	obstack_base (&m_objfile->per_bfd->storage_obstack);
 
       /* Copy in the existing minimal symbols, if there are any.  */
 
-      if (objfile->per_bfd->minimal_symbol_count)
-	memcpy ((char *) msymbols, (char *) objfile->per_bfd->msymbols,
-	    objfile->per_bfd->minimal_symbol_count * sizeof (struct minimal_symbol));
+      if (m_objfile->per_bfd->minimal_symbol_count)
+	memcpy ((char *) msymbols, (char *) m_objfile->per_bfd->msymbols,
+	    m_objfile->per_bfd->minimal_symbol_count * sizeof (struct minimal_symbol));
 
       /* Walk through the list of minimal symbol bunches, adding each symbol
          to the new contiguous array of symbols.  Note that we start with the
@@ -1270,7 +1271,7 @@ minimal_symbol_reader::install (struct objfile *objfile)
          msym_bunch_index for the first bunch we copy over), and thereafter
          each bunch is full.  */
 
-      mcount = objfile->per_bfd->minimal_symbol_count;
+      mcount = m_objfile->per_bfd->minimal_symbol_count;
 
       for (bunch = msym_bunch; bunch != NULL; bunch = bunch->next)
 	{
@@ -1287,12 +1288,12 @@ minimal_symbol_reader::install (struct objfile *objfile)
       /* Compact out any duplicates, and free up whatever space we are
          no longer using.  */
 
-      mcount = compact_minimal_symbols (msymbols, mcount, objfile);
+      mcount = compact_minimal_symbols (msymbols, mcount, m_objfile);
 
-      obstack_blank_fast (&objfile->per_bfd->storage_obstack,
+      obstack_blank_fast (&m_objfile->per_bfd->storage_obstack,
 	       (mcount + 1 - alloc_count) * sizeof (struct minimal_symbol));
       msymbols = (struct minimal_symbol *)
-	obstack_finish (&objfile->per_bfd->storage_obstack);
+	obstack_finish (&m_objfile->per_bfd->storage_obstack);
 
       /* We also terminate the minimal symbol table with a "null symbol",
          which is *not* included in the size of the table.  This makes it
@@ -1308,14 +1309,14 @@ minimal_symbol_reader::install (struct objfile *objfile)
          The strings themselves are also located in the storage_obstack
          of this objfile.  */
 
-      objfile->per_bfd->minimal_symbol_count = mcount;
-      objfile->per_bfd->msymbols = msymbols;
+      m_objfile->per_bfd->minimal_symbol_count = mcount;
+      m_objfile->per_bfd->msymbols = msymbols;
 
       /* Now build the hash tables; we can't do this incrementally
          at an earlier point since we weren't finished with the obstack
 	 yet.  (And if the msymbol obstack gets moved, all the internal
 	 pointers to other msymbols need to be adjusted.)  */
-      build_minimal_symbol_hash_tables (objfile);
+      build_minimal_symbol_hash_tables (m_objfile);
     }
 }
 
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index d75bd41..b83e2d0 100644
--- a/gdb/minsyms.h
+++ b/gdb/minsyms.h
@@ -64,14 +64,14 @@ class minimal_symbol_reader
      Currently, minimal symbol table creation is not reentrant; it
      relies on global (static) variables in minsyms.c.  */
 
-  explicit minimal_symbol_reader ();
+  explicit minimal_symbol_reader (struct objfile *);
 
   ~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 minimal_symbol_reader
   minimal_symbol_reader &operator=
     (const minimal_symbol_reader &);
   minimal_symbol_reader (const minimal_symbol_reader &);
+
+  struct objfile *m_objfile;
 };
 
 /* Record a new minimal symbol.  This is the "full" entry point;
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
index dff1cb1..256b262 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;
 
-  minimal_symbol_reader reader;
+  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 76d6d79..2656d4c 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);
 
-  minimal_symbol_reader reader;
+  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] 59+ messages in thread

* [RFA v2 06/17] Record minimal symbols directly in reader.
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (7 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 02/17] Use scoped_restore for ui_file Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:34   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods Tom Tromey
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 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 minimal_symbol_reader.
Second, it changes functions like prim_record_minimal_symbol to be
member functions of 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 (minimal_symbol_reader) <record, record_full>:
	Declare.
	<m_msym_bunch, m_msym_bunch_index, m_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.
	(minimal_symbol_reader): Initialize new members.
	(minimal_symbol_reader::record): Renamed from
	prim_record_minimal_symbol.
	(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      | 106 +++++++++++++++++-----------------------------
 gdb/minsyms.h      | 120 +++++++++++++++++++++++++++++------------------------
 gdb/mipsread.c     |  12 +++---
 gdb/symfile.h      |   3 +-
 gdb/xcoffread.c    |  35 ++++++++--------
 13 files changed, 271 insertions(+), 232 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 790be41..a1e2f6e 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 (minimal_symbol_reader) <record, record_full>:
+	Declare.
+	<m_msym_bunch, m_msym_bunch_index, m_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.
+	(minimal_symbol_reader): Initialize new members.
+	(minimal_symbol_reader::record): Renamed from
+	prim_record_minimal_symbol.
+	(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 (minimal_symbol_reader): Add obj argument.
diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c
index 8836361..b0201d1 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 (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 (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 (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..6a82e4c 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 (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 b4de08e..3125fb1 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 (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 (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 (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 446813b..8cc6429 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 (minimal_symbol_reader &reader,
+				     struct objfile *objfile);
 
-static void read_dbx_symtab (struct objfile *);
+static void read_dbx_symtab (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 (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 (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 (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 (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 58e0cbc..56fac28 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 (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 (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 (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 1f82f2b..7889b00 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -97,7 +97,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 (minimal_symbol_reader &reader,
+			 struct objfile *objfile, const asymbol *sym)
 {
   if (sym->name == NULL || *sym->name == '\0')
     {
@@ -147,10 +148,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));
     }
 }
 
@@ -158,7 +158,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 (minimal_symbol_reader &reader,
+		   struct objfile *objfile,
 		   long number_of_symbols, asymbol **symbol_table,
 		   VEC (oso_el) **oso_vector_ptr)
 {
@@ -227,7 +228,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;
 
@@ -864,7 +865,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 1285db4..a149ee9 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 (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 (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 (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 (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 e614ff0..a649ea7 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
@@ -917,14 +904,14 @@ get_symbol_leading_char (bfd *abfd)
 /* See minsyms.h.  */
 
 minimal_symbol_reader::minimal_symbol_reader (struct objfile *obj)
-: m_objfile (obj)
-{
-  msym_count = 0;
-  msym_bunch = NULL;
-  /* Note that presetting msym_bunch_index to BUNCH_SIZE causes the
+: m_objfile (obj),
+  m_msym_bunch (NULL),
+  /* Note that presetting m_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;
+  m_msym_bunch_index (BUNCH_SIZE),
+  m_msym_count (0)
+{
 }
 
 /* Discard the currently collected minimal symbols, if any.  If we wish
@@ -939,20 +926,19 @@ minimal_symbol_reader::~minimal_symbol_reader ()
 {
   struct msym_bunch *next;
 
-  while (msym_bunch != NULL)
+  while (m_msym_bunch != NULL)
     {
-      next = msym_bunch->next;
-      xfree (msym_bunch);
-      msym_bunch = next;
+      next = m_msym_bunch->next;
+      xfree (m_msym_bunch);
+      m_msym_bunch = next;
     }
 }
 
 /* See minsyms.h.  */
 
 void
-prim_record_minimal_symbol (const char *name, CORE_ADDR address,
-			    enum minimal_symbol_type ms_type,
-			    struct objfile *objfile)
+minimal_symbol_reader::record (const char *name, CORE_ADDR address,
+				      enum minimal_symbol_type ms_type)
 {
   int section;
 
@@ -962,32 +948,31 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address,
     case mst_text_gnu_ifunc:
     case mst_file_text:
     case mst_solib_trampoline:
-      section = SECT_OFF_TEXT (objfile);
+      section = SECT_OFF_TEXT (m_objfile);
       break;
     case mst_data:
     case mst_file_data:
-      section = SECT_OFF_DATA (objfile);
+      section = SECT_OFF_DATA (m_objfile);
       break;
     case mst_bss:
     case mst_file_bss:
-      section = SECT_OFF_BSS (objfile);
+      section = SECT_OFF_BSS (m_objfile);
       break;
     default:
       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)
+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;
@@ -1004,7 +989,7 @@ prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
 
   /* It's safe to strip the leading char here once, since the name
      is also stored stripped in the minimal symbol table.  */
-  if (name[0] == get_symbol_leading_char (objfile->obfd))
+  if (name[0] == get_symbol_leading_char (m_objfile->obfd))
     {
       ++name;
       --name_len;
@@ -1013,17 +998,17 @@ prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
   if (ms_type == mst_file_text && startswith (name, "__gnu_compiled"))
     return (NULL);
 
-  if (msym_bunch_index == BUNCH_SIZE)
+  if (m_msym_bunch_index == BUNCH_SIZE)
     {
       newobj = XCNEW (struct msym_bunch);
-      msym_bunch_index = 0;
-      newobj->next = msym_bunch;
-      msym_bunch = newobj;
+      m_msym_bunch_index = 0;
+      newobj->next = m_msym_bunch;
+      m_msym_bunch = newobj;
     }
-  msymbol = &msym_bunch->contents[msym_bunch_index];
+  msymbol = &m_msym_bunch->contents[m_msym_bunch_index];
   MSYMBOL_SET_LANGUAGE (msymbol, language_auto,
-			&objfile->per_bfd->storage_obstack);
-  MSYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, objfile);
+			&m_objfile->per_bfd->storage_obstack);
+  MSYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, m_objfile);
 
   SET_MSYMBOL_VALUE_ADDRESS (msymbol, address);
   MSYMBOL_SECTION (msymbol) = section;
@@ -1042,28 +1027,15 @@ prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
 
   /* If we already read minimal symbols for this objfile, then don't
      ever allocate a new one.  */
-  if (!objfile->per_bfd->minsyms_read)
+  if (!m_objfile->per_bfd->minsyms_read)
     {
-      msym_bunch_index++;
-      objfile->per_bfd->n_minsyms++;
+      m_msym_bunch_index++;
+      m_objfile->per_bfd->n_minsyms++;
     }
-  msym_count++;
+  m_msym_count++;
   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.  */
@@ -1239,13 +1211,13 @@ minimal_symbol_reader::install ()
   if (m_objfile->per_bfd->minsyms_read)
     return;
 
-  if (msym_count > 0)
+  if (m_msym_count > 0)
     {
       if (symtab_create_debug)
 	{
 	  fprintf_unfiltered (gdb_stdlog,
 			      "Installing %d minimal symbols of objfile %s.\n",
-			      msym_count, objfile_name (m_objfile));
+			      m_msym_count, objfile_name (m_objfile));
 	}
 
       /* Allocate enough space in the obstack, into which we will gather the
@@ -1253,7 +1225,7 @@ minimal_symbol_reader::install ()
          compact out the duplicate entries.  Once we have a final table,
          we will give back the excess space.  */
 
-      alloc_count = msym_count + m_objfile->per_bfd->minimal_symbol_count + 1;
+      alloc_count = m_msym_count + m_objfile->per_bfd->minimal_symbol_count + 1;
       obstack_blank (&m_objfile->per_bfd->storage_obstack,
 		     alloc_count * sizeof (struct minimal_symbol));
       msymbols = (struct minimal_symbol *)
@@ -1273,11 +1245,11 @@ minimal_symbol_reader::install ()
 
       mcount = m_objfile->per_bfd->minimal_symbol_count;
 
-      for (bunch = msym_bunch; bunch != NULL; bunch = bunch->next)
+      for (bunch = m_msym_bunch; bunch != NULL; bunch = bunch->next)
 	{
-	  for (bindex = 0; bindex < msym_bunch_index; bindex++, mcount++)
+	  for (bindex = 0; bindex < m_msym_bunch_index; bindex++, mcount++)
 	    msymbols[mcount] = bunch->contents[bindex];
-	  msym_bunch_index = BUNCH_SIZE;
+	  m_msym_bunch_index = BUNCH_SIZE;
 	}
 
       /* Sort the minimal symbols by address.  */
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index b83e2d0..b22920b 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 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 minimal_symbol_reader (struct objfile *);
 
@@ -73,6 +74,56 @@ class 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 minimal_symbol_reader
   minimal_symbol_reader (const minimal_symbol_reader &);
 
   struct objfile *m_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 *m_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 m_msym_bunch_index;
+
+  /* Total number of minimal symbols recorded so far for the
+     objfile.  */
+
+  int m_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 256b262..39af0d3 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 (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 (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..32902cb 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 (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 2656d4c..32f9a1b 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 (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 (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 (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] 59+ messages in thread

* [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (8 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 06/17] Record minimal symbols directly in reader Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 23:05   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 14/17] Initial conversion of dwarf_expr_ctx Tom Tromey
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 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    | 647 +++++++++++++++++++++++------------------------------
 5 files changed, 466 insertions(+), 607 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b58e622..849adbb 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 72de98d..bbccdab 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -415,20 +415,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;
 }
 
@@ -699,13 +690,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;
 
@@ -889,8 +880,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);
 	  }
@@ -899,7 +889,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);
 	  }
@@ -919,14 +909,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"));
@@ -1012,7 +1000,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.  */
@@ -1221,7 +1209,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;
@@ -1238,7 +1226,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;
 
@@ -1314,7 +1302,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;
 
@@ -1324,7 +1312,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;
 	
@@ -1342,10 +1330,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;
 	      }
 
@@ -1357,9 +1344,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;
 	      }
 
@@ -1375,10 +1361,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;
 
@@ -1410,7 +1395,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;
 
@@ -1449,7 +1434,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;
 
@@ -1475,75 +1460,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 1f946df..9b6b28d 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,174 @@ 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 save_arch = make_scoped_restore (&this->gdbarch);
+    this->gdbarch
+      = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu));
+    scoped_restore save_addr_size = make_scoped_restore (&this->addr_size);
+    this->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu);
+    scoped_restore save_offset = make_scoped_restore (&this->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 +1307,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 +2235,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 +2247,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 +2256,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 +2488,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 +2506,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 +2516,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 +2661,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 +2761,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 +2795,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] 59+ messages in thread

* [RFA v2 00/17] more C++
@ 2016-10-13 21:11 Tom Tromey
  2016-10-13 21:11 ` [RFA v2 15/17] Convert DWARF expr functions to methods Tom Tromey
                   ` (18 more replies)
  0 siblings, 19 replies; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 UTC (permalink / raw)
  To: gdb-patches

This is an updated version of my C++-ification series.  It has been
rebased on Pedro's unique_ptr patch, so it can't go in until that
does.

I think I've addressed all review comments.  (Though now that I am
writing this I remember I haven't yet dealt with the "override"
issue.)

I've added one more patch to remove some cleanups from captured_main.

Built and regtested on x86-64 Fedora 24.

Tom

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

* [RFA v2 08/17] Remove some cleanups in MI
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
  2016-10-13 21:11 ` [RFA v2 15/17] Convert DWARF expr functions to methods Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:38   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 12/17] Remove make_cleanup_restore_current_uiout Tom Tromey
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch removes a couple of cleanups from MI by using
gdb::unique_ptr.

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

	* mi/mi-main.c (mi_cmd_data_read_memory): Use gdb::unique_ptr.
	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 04e550a..7c072b5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2016-09-26  Tom Tromey  <tom@tromey.com>
+
+	* mi/mi-main.c (mi_cmd_data_read_memory): Use gdb::unique_ptr.
+	Remove some cleanups.
+
 2016-10-10  Tom Tromey  <tom@tromey.com>
 
 	* tui/tui-interp.c (tui_on_normal_stop, tui_on_signal_received)
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index b80b4f2..067c9e3 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -1413,7 +1413,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;
@@ -1421,7 +1420,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;
@@ -1506,13 +1504,13 @@ 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);
+
+  gdb::unique_ptr<gdb_byte[]> mbuf (new gdb_byte[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.get (),
 			  addr, total_bytes);
   if (nr_bytes <= 0)
     error (_("Unable to read memory."));
@@ -1566,7 +1564,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);
 	      }
@@ -1593,7 +1591,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] 59+ messages in thread

* [RFA v2 10/17] Replace two xmallocs with unique_ptr
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (4 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 05/17] Change minimal_symbol_reader to store objfile Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:44   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 03/17] Use scoped_restore for current_ui Tom Tromey
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This replaces a couple of uses of xmalloc with gdb::unique_ptr, also
removing a couple of cleanups.

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

	* cli/cli-dump.c (dump_memory_to_file): Use gdb::unique_ptr.
	(restore_binary_file): Likewise.
---
 gdb/ChangeLog      |  5 +++++
 gdb/cli/cli-dump.c | 19 ++++++++-----------
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f476299..0d5f425 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 gdb::unique_ptr.
+	(restore_binary_file): Likewise.
+
+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/cli/cli-dump.c b/gdb/cli/cli-dump.c
index 611b0c3..eb7f69d 100644
--- a/gdb/cli/cli-dump.c
+++ b/gdb/cli/cli-dump.c
@@ -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);
+  gdb::unique_ptr<gdb_byte[]> buf (new gdb_byte[count]);
+  read_memory (lo, buf.get (), 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.get (), count);
     }
   else
     {
-      dump_bfd_file (filename, mode, file_format, lo, buf, count);
+      dump_bfd_file (filename, mode, file_format, lo, buf.get (), 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)
+  gdb::unique_ptr<gdb_byte[]> buf (new gdb_byte[len]);
+  if (fread (buf.get (), 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.get (), len);
   if (len != 0)
     warning (_("restore: memory write failed (%s)."), safe_strerror (len));
   do_cleanups (cleanup);
-- 
2.7.4

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

* [RFA v2 12/17] Remove make_cleanup_restore_current_uiout
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
  2016-10-13 21:11 ` [RFA v2 15/17] Convert DWARF expr functions to methods Tom Tromey
  2016-10-13 21:11 ` [RFA v2 08/17] Remove some cleanups in MI Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:49   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 04/17] Introduce minimal_symbol_reader Tom Tromey
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

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

2016-10-10  Tom Tromey  <tom@tromey.com>

	* stack.c (print_stack_frame_to_uiout): Use scoped_restore.
	* ui-out.c (make_cleanup_restore_current_uiout)
	(restore_current_uiout_cleanup): Remove.
	* infrun.c (print_stop_event): Use scoped_restore.
	* ui-out.h (make_cleanup_restore_current_uiout): Don't declare.
---
 gdb/ChangeLog       |  8 ++++++++
 gdb/infrun.c        | 15 +++++++--------
 gdb/python/python.c |  2 +-
 gdb/stack.c         |  7 +------
 gdb/ui-out.c        | 18 ------------------
 gdb/ui-out.h        |  4 ----
 6 files changed, 17 insertions(+), 37 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ea777f6..d2e51f4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2016-10-10  Tom Tromey  <tom@tromey.com>
+
+	* stack.c (print_stack_frame_to_uiout): Use scoped_restore.
+	* ui-out.c (make_cleanup_restore_current_uiout)
+	(restore_current_uiout_cleanup): Remove.
+	* infrun.c (print_stop_event): Use scoped_restore.
+	* ui-out.h (make_cleanup_restore_current_uiout): Don't declare.
+
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
 	* elfread.c (elf_read_minimal_symbols): Use gdb::unique_ptr.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 1864019..493a25e 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8082,22 +8082,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 save_uiout = make_scoped_restore (&current_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 53f83b8..d9940c2 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -649,7 +649,7 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
 
       scoped_restore save_async = make_scoped_restore (&current_ui->async, 0);
 
-      make_cleanup_restore_current_uiout ();
+      scoped_restore save_uiout = make_scoped_restore (&current_uiout);
 
       /* Use the console interpreter uiout to have the same print format
 	for console or MI.  */
diff --git a/gdb/stack.c b/gdb/stack.c
index 0f8b336..44ee81d 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -149,15 +149,10 @@ print_stack_frame_to_uiout (struct ui_out *uiout, struct frame_info *frame,
 			    int print_level, enum print_what print_what,
 			    int set_current_sal)
 {
-  struct cleanup *old_chain;
-
-  old_chain = make_cleanup_restore_current_uiout ();
-
+  scoped_restore save_uiout = make_scoped_restore (&current_uiout);
   current_uiout = uiout;
 
   print_stack_frame (frame, print_level, print_what, set_current_sal);
-
-  do_cleanups (old_chain);
 }
 
 /* Show or print a stack frame FRAME briefly.  The output is formatted
diff --git a/gdb/ui-out.c b/gdb/ui-out.c
index 9b1df3c..8c39198 100644
--- a/gdb/ui-out.c
+++ b/gdb/ui-out.c
@@ -949,24 +949,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..9e1e74d 100644
--- a/gdb/ui-out.h
+++ b/gdb/ui-out.h
@@ -247,8 +247,4 @@ 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.  */
-
-extern struct cleanup *make_cleanup_restore_current_uiout (void);
-
 #endif /* UI_OUT_H */
-- 
2.7.4

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

* [RFA v2 03/17] Use scoped_restore for current_ui
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (5 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 10/17] Replace two xmallocs with unique_ptr Tom Tromey
@ 2016-10-13 21:11 ` Tom Tromey
  2016-10-13 22:16   ` Pedro Alves
  2016-10-13 21:11 ` [RFA v2 02/17] Use scoped_restore for ui_file Tom Tromey
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:11 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 is dealt with in a later patch 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 8539d0e..8ab0c10 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 ab7426d..e435cf7 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 save_ui = make_scoped_restore (&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 3e62cfe..2883717 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3901,8 +3901,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 save_ui = make_scoped_restore (&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 f6176ae..b646c4a 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 save_ui = make_scoped_restore (&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 save_ui = make_scoped_restore (&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 save_ui = make_scoped_restore (&current_ui);
 
   if (cleanup->target_is_async_orig)
     target_async (0);
-- 
2.7.4

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

* [RFA v2 13/17] Some cleanup removal in dwarf2loc.c
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (13 preceding siblings ...)
  2016-10-13 21:11 ` [RFA v2 11/17] Use gdb::unique_ptr in elf_read_minimal_symbols Tom Tromey
@ 2016-10-13 21:13 ` Tom Tromey
  2016-10-13 22:52   ` Pedro Alves
  2016-10-13 21:14 ` [RFA v2 09/17] Change command stats reporting to use class Tom Tromey
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:13 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This removes some cleanups and manual allocation handling in
dwarf2loc.c with std::vector.  Note that this patch has a case where
the vector would normally fall into the "use gdb::unique_ptr"
guidelines -- but here because the vector is immediately initialized,
I moved the initialization into the constructor call, for further
code savings.

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 | 69 +++++++++++++++++++++------------------------------------
 2 files changed, 31 insertions(+), 44 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d2e51f4..a06cc27 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+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-10-10  Tom Tromey  <tom@tromey.com>
 
 	* stack.c (print_stack_frame_to_uiout): Use scoped_restore.
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index f9f3216..87a4fb9 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,14 +3054,7 @@ 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);
-
-  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);
+  std::vector<int> offsets (op_end - op_ptr, -1);
 
   /* By default we are making an address.  */
   loc->kind = axs_lvalue_memory;
@@ -3584,8 +3567,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 +3577,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 +3687,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] 59+ messages in thread

* [RFA v2 09/17] Change command stats reporting to use class
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (14 preceding siblings ...)
  2016-10-13 21:13 ` [RFA v2 13/17] Some cleanup removal in dwarf2loc.c Tom Tromey
@ 2016-10-13 21:14 ` Tom Tromey
  2016-10-13 22:43   ` Pedro Alves
  2016-10-13 21:18 ` [RFA v2 17/17] Remove last cleanup from captured_main_1 Tom Tromey
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:14 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 without excessive reindentation required splitting
captured_main in two.

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_1): New function.  Use
	scoped_command_stats.
	(captured_main): Call captured_main_1.
	* event-top.c (command_handler): Use scoped_command_stats.
---
 gdb/ChangeLog   |  14 +++++++
 gdb/event-top.c |   5 +--
 gdb/main.c      |  25 +++++++-----
 gdb/maint.c     | 118 ++++++++++++++++++--------------------------------------
 gdb/maint.h     |  39 +++++++++++++++++--
 5 files changed, 104 insertions(+), 97 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7c072b5..f476299 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,19 @@
 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_1): New function.  Use
+	scoped_command_stats.
+	(captured_main): Call captured_main_1.
+	* 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 gdb::unique_ptr.
 	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..420b4d3 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -441,12 +441,12 @@ typedef struct cmdarg {
 /* Define type VEC (cmdarg_s).  */
 DEF_VEC_O (cmdarg_s);
 
-static int
-captured_main (void *data)
+static void
+captured_main_1 (struct captured_main_args *context)
 {
-  struct captured_main_args *context = (struct captured_main_args *) data;
   int argc = context->argc;
   char **argv = context->argv;
+
   static int quiet = 0;
   static int set_args = 0;
   static int inhibit_home_gdbinit = 0;
@@ -486,14 +486,14 @@ captured_main (void *data)
   int save_auto_load;
   struct objfile *objfile;
 
-  struct cleanup *pre_stat_chain;
+  struct cleanup *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, "");
@@ -510,7 +510,7 @@ captured_main (void *data)
   notice_open_fds ();
   save_original_signals_state ();
 
-  make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec);
+  chain = make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec);
   dirsize = 1;
   dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
   ndir = 0;
@@ -1139,8 +1139,15 @@ captured_main (void *data)
       quit_force (NULL, 0);
     }
 
-  /* Show time and/or space usage.  */
-  do_cleanups (pre_stat_chain);
+  do_cleanups (chain);
+}
+
+static void
+captured_main (void *data)
+{
+  struct captured_main_args *context = (struct captured_main_args *) data;
+
+  captured_main_1 (context);
 
   /* 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..06e6766 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,31 +802,38 @@ 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 (m_msg_type != 0
+      && !per_command_time
+      && !per_command_space
+      && !per_command_symtab)
+    return;
 
-  if (start_stats->time_enabled && per_command_time)
+  if (this->m_time_enabled && per_command_time)
     {
-      long cmd_time = get_run_time () - start_stats->start_cpu_time;
+      long cmd_time = get_run_time () - this->m_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->m_start_wall_time);
 
       /* Subtract time spend in prompt_for_continue from walltime.  */
       wait_time = get_prompt_for_continue_wait_time ();
       timeval_sub (&delta_wall_time, &delta_wall_time, &wait_time);
 
-      printf_unfiltered (msg_type == 0
+      printf_unfiltered (m_msg_type == 0
 			 ? _("Startup time: %ld.%06ld (cpu), %ld.%06ld (wall)\n")
 			 : _("Command execution time: %ld.%06ld (cpu), %ld.%06ld (wall)\n"),
 			 cmd_time / 1000000, cmd_time % 1000000,
@@ -859,15 +841,15 @@ report_command_stats (void *arg)
 			 (long) delta_wall_time.tv_usec);
     }
 
-  if (start_stats->space_enabled && per_command_space)
+  if (this->m_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->m_start_space;
 
-      printf_unfiltered (msg_type == 0
+      printf_unfiltered (m_msg_type == 0
 			 ? _("Space used: %ld (%s%ld during startup)\n")
 			 : _("Space used: %ld (%s%ld for this command)\n"),
 			 space_now,
@@ -876,7 +858,7 @@ report_command_stats (void *arg)
 #endif
     }
 
-  if (start_stats->symtab_enabled && per_command_symtab)
+  if (this->m_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->m_start_nr_symtabs,
 			 nr_compunit_symtabs,
 			 (nr_compunit_symtabs
-			  - start_stats->start_nr_compunit_symtabs),
+			  - this->m_start_nr_compunit_symtabs),
 			 nr_blocks,
-			 nr_blocks - start_stats->start_nr_blocks);
+			 nr_blocks - this->m_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)
+: m_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)
+  if (m_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->m_start_space = lim - lim_at_start;
+      this->m_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->m_start_cpu_time = get_run_time ();
+      gettimeofday (&this->m_start_wall_time, NULL);
+      this->m_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->m_start_nr_symtabs = nr_symtabs;
+      this->m_start_nr_compunit_symtabs = nr_compunit_symtabs;
+      this->m_start_nr_blocks = nr_blocks;
+      this->m_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..ffbf0cb 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 m_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 m_time_enabled : 1;
+  int m_space_enabled : 1;
+  int m_symtab_enabled : 1;
+  long m_start_cpu_time;
+  struct timeval m_start_wall_time;
+  long m_start_space;
+  /* Total number of symtabs (over all objfiles).  */
+  int m_start_nr_symtabs;
+  /* A count of the compunits.  */
+  int m_start_nr_compunit_symtabs;
+  /* Total number of blocks.  */
+  int m_start_nr_blocks;
+};
 
 #endif /* MAINT_H */
-- 
2.7.4

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

* [RFA v2 17/17] Remove last cleanup from captured_main_1
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (15 preceding siblings ...)
  2016-10-13 21:14 ` [RFA v2 09/17] Change command stats reporting to use class Tom Tromey
@ 2016-10-13 21:18 ` Tom Tromey
  2016-10-13 23:13   ` Pedro Alves
  2016-10-13 21:39 ` [RFA v2 00/17] more C++ Pedro Alves
  2016-10-20 21:49 ` Tom Tromey
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-13 21:18 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

An earlier patch split captured_main into two parts.  This patch
removes the last remaining cleanup from captured_main_1, and also
replaces a second hand-rolled VEC-like array with a std::vector.

2016-10-11  Tom Tromey  <tom@tromey.com>

	* main.c: Include <vector>.
	(cmdarg_s): Remove typedef.  Don't define VEC.
	(captured_main_1): Use vector, not VEC.  Remove cleanups.
---
 gdb/ChangeLog |  6 ++++
 gdb/main.c    | 93 +++++++++++++++++++++++++----------------------------------
 2 files changed, 46 insertions(+), 53 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 849adbb..5e23f32 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2016-10-11  Tom Tromey  <tom@tromey.com>
+
+	* main.c: Include <vector>.
+	(cmdarg_s): Remove typedef.  Don't define VEC.
+	(captured_main_1): Use vector, not VEC.  Remove cleanups.
+
 2016-09-26  Tom Tromey  <tom@tromey.com>
 
 	* dwarf2loc.c (struct dwarf_expr_context_funcs): Don't declare.
diff --git a/gdb/main.c b/gdb/main.c
index 420b4d3..280b7c5 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -45,6 +45,7 @@
 #include "event-top.h"
 #include "infrun.h"
 #include "signals-state-save-restore.h"
+#include <vector>
 
 /* The selected interpreter.  This will be used as a set command
    variable, so it should always be malloc'ed - since
@@ -429,17 +430,14 @@ enum cmdarg_kind
 };
 
 /* Arguments of --command option and its counterpart.  */
-typedef struct cmdarg {
+struct cmdarg {
   /* Type of this option.  */
   enum cmdarg_kind type;
 
   /* Value of this option - filename or the GDB command itself.  String memory
      is not owned by this structure despite it is 'const'.  */
   char *string;
-} cmdarg_s;
-
-/* Define type VEC (cmdarg_s).  */
-DEF_VEC_O (cmdarg_s);
+};
 
 static void
 captured_main_1 (struct captured_main_args *context)
@@ -467,15 +465,10 @@ captured_main_1 (struct captured_main_args *context)
   static int print_configuration;
 
   /* Pointers to all arguments of --command option.  */
-  VEC (cmdarg_s) *cmdarg_vec = NULL;
-  struct cmdarg *cmdarg_p;
+  std::vector<struct cmdarg> cmdarg_vec;
 
-  /* Indices of all arguments of --directory option.  */
-  char **dirarg;
-  /* Allocated size.  */
-  int dirsize;
-  /* Number of elements used.  */
-  int ndir;
+  /* All arguments of --directory option.  */
+  std::vector<char *> dirarg;
 
   /* gdb init files.  */
   const char *system_gdbinit;
@@ -510,11 +503,6 @@ captured_main_1 (struct captured_main_args *context)
   notice_open_fds ();
   save_original_signals_state ();
 
-  chain = make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec);
-  dirsize = 1;
-  dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
-  ndir = 0;
-
   saved_command_line = (char *) xstrdup ("");
 
 #ifdef __MINGW32__
@@ -746,28 +734,28 @@ captured_main_1 (struct captured_main_args *context)
 	    {
 	      struct cmdarg cmdarg = { CMDARG_FILE, optarg };
 
-	      VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
+	      cmdarg_vec.push_back (cmdarg);
 	    }
 	    break;
 	  case 'X':
 	    {
 	      struct cmdarg cmdarg = { CMDARG_COMMAND, optarg };
 
-	      VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
+	      cmdarg_vec.push_back (cmdarg);
 	    }
 	    break;
 	  case OPT_IX:
 	    {
 	      struct cmdarg cmdarg = { CMDARG_INIT_FILE, optarg };
 
-	      VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
+	      cmdarg_vec.push_back (cmdarg);
 	    }
 	    break;
 	  case OPT_IEX:
 	    {
 	      struct cmdarg cmdarg = { CMDARG_INIT_COMMAND, optarg };
 
-	      VEC_safe_push (cmdarg_s, cmdarg_vec, &cmdarg);
+	      cmdarg_vec.push_back (cmdarg);
 	    }
 	    break;
 	  case 'B':
@@ -809,13 +797,7 @@ captured_main_1 (struct captured_main_args *context)
 	    interpreter_p = xstrdup (optarg);
 	    break;
 	  case 'd':
-	    dirarg[ndir++] = optarg;
-	    if (ndir >= dirsize)
-	      {
-		dirsize *= 2;
-		dirarg = (char **) xrealloc ((char *) dirarg,
-					     dirsize * sizeof (*dirarg));
-	      }
+	    dirarg.push_back (optarg);
 	    break;
 	  case 't':
 	    ttyarg = optarg;
@@ -1006,17 +988,21 @@ captured_main_1 (struct captured_main_args *context)
     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)
+  for (i = 0; i < cmdarg_vec.size (); i++)
     {
-      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;
+      const struct cmdarg &cmdarg_p = cmdarg_vec[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;
+	}
     }
 
   /* Now perform all the actions indicated by the arguments.  */
@@ -1025,9 +1011,8 @@ captured_main_1 (struct captured_main_args *context)
       catch_command_errors (cd_command, cdarg, 0);
     }
 
-  for (i = 0; i < ndir; i++)
+  for (i = 0; i < dirarg.size (); i++)
     catch_command_errors (directory_switch, dirarg[i], 0);
-  xfree (dirarg);
 
   /* Skip auto-loading section-specified scripts until we've sourced
      local_gdbinit (which is often used to augment the source search
@@ -1116,17 +1101,21 @@ captured_main_1 (struct captured_main_args *context)
     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)
+  for (i = 0; i < cmdarg_vec.size (); i++)
     {
-      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;
+      const struct cmdarg &cmdarg_p = cmdarg_vec[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;
+	}
     }
 
   /* Read in the old history after all the command files have been
@@ -1138,8 +1127,6 @@ captured_main_1 (struct captured_main_args *context)
       /* We have hit the end of the batch file.  */
       quit_force (NULL, 0);
     }
-
-  do_cleanups (chain);
 }
 
 static void
-- 
2.7.4

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

* Re: [RFA v2 00/17] more C++
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (16 preceding siblings ...)
  2016-10-13 21:18 ` [RFA v2 17/17] Remove last cleanup from captured_main_1 Tom Tromey
@ 2016-10-13 21:39 ` Pedro Alves
  2016-10-14 16:26   ` Pedro Alves
  2016-10-20 21:49 ` Tom Tromey
  18 siblings, 1 reply; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 21:39 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:09 PM, Tom Tromey wrote:
> 
> I think I've addressed all review comments.  (Though now that I am
> writing this I remember I haven't yet dealt with the "override"
> issue.)

My FINAL/OVERRIDE patch on the GCC side has approved barring
no objections by the end of the week:

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

So I'll probably pull that in to our tree soon.

Thanks,
Pedro Alves

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

* Re: [RFA v2 01/17] Use RAII to save and restore scalars
  2016-10-13 21:11 ` [RFA v2 01/17] Use RAII to save and restore scalars Tom Tromey
@ 2016-10-13 22:03   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:03 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:09 PM, 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.
> 
> The class is typically instantiated using make_scoped_restore.  This
> allows for template argument deduction.
> 
> 2016-10-13  Tom Tromey  <tom@tromey.com>
> 
> 	* common/scoped_restore.h: New file.
> 	* utils.h: Include scoped_restore.h.
> 	* 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.

Great.  This is OK and can go in immediately.

Thanks,
Pedro Alves

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

* Re: [RFA v2 02/17] Use scoped_restore for ui_file
  2016-10-13 21:11 ` [RFA v2 02/17] Use scoped_restore for ui_file Tom Tromey
@ 2016-10-13 22:07   ` Pedro Alves
  2016-10-14 21:33     ` Tom Tromey
  0 siblings, 1 reply; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:07 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

This is OK.  Please push.

On 10/13/2016 10:09 PM, Tom Tromey wrote:
> +  scoped_restore save_stdout = make_scoped_restore (&gdb_stdout, str_file);
> +  scoped_restore save_stderr = make_scoped_restore (&gdb_stderr, str_file);
> +  scoped_restore save_stdlog = make_scoped_restore (&gdb_stdlog, str_file);
> +  scoped_restore save_stdtarg = make_scoped_restore (&gdb_stdtarg, str_file);
> +  scoped_restore save_stdtargerr = make_scoped_restore (&gdb_stdtargerr,
> +							str_file);
>  

I wonder if aligning like:

     scoped_restore save_stdout
       = make_scoped_restore (&gdb_stdout, str_file);
     scoped_restore save_stderr
       = make_scoped_restore (&gdb_stderr, str_file);
     scoped_restore save_stdlog
       = make_scoped_restore (&gdb_stdlog, str_file);
     scoped_restore save_stdtarg
       = make_scoped_restore (&gdb_stdtarg, str_file);
     scoped_restore save_stdtargerr
       = make_scoped_restore (&gdb_stdtargerr, str_file);

would read better.  Can't tell on the mail client.
Up to you; just a thought.

Thanks,
Pedro Alves

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

* Re: [RFA v2 03/17] Use scoped_restore for current_ui
  2016-10-13 21:11 ` [RFA v2 03/17] Use scoped_restore for current_ui Tom Tromey
@ 2016-10-13 22:16   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:16 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:09 PM, Tom Tromey wrote:
> 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 is dealt with in a later patch 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.

OK.

Thanks,
Pedro Alves

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

* Re: [RFA v2 04/17] Introduce minimal_symbol_reader
  2016-10-13 21:11 ` [RFA v2 04/17] Introduce minimal_symbol_reader Tom Tromey
@ 2016-10-13 22:20   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:20 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:09 PM, Tom Tromey wrote:
> This patch introduced 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
> 	minimal_symbol_reader.
> 	* mipsread.c (mipscoff_symfile_read): Use
> 	minimal_symbol_reader.
> 	* minsyms.h (minimal_symbol_reader): New class.
> 	(init_minimal_symbol_collection)
> 	(make_cleanup_discard_minimal_symbols, install_minimal_symbols):
> 	Don't declare.
> 	* minsyms.c (minimal_symbol_reader): Renamed from
> 	init_minimal_symbol_collection, turned into constructor.
> 	(~minimal_symbol_reader): Renamed from
> 	do_discard_minimal_symbols_cleanup, turned into destructor.
> 	(make_cleanup_discard_minimal_symbols): Remove.
> 	(minimal_symbol_reader::install): Rename form
> 	install_minimal_symbols.
> 	* mdebugread.c (elfmdebug_build_psymtabs): Use
> 	minimal_symbol_reader.
> 	* machoread.c (macho_symfile_read): Use
> 	minimal_symbol_reader.
> 	* elfread.c (elf_read_minimal_symbols): Use
> 	minimal_symbol_reader.
> 	* dbxread.c (dbx_symfile_read): Use minimal_symbol_reader.
> 	* coffread.c (coff_symfile_read): Use
> 	minimal_symbol_reader.

OK.

Thanks,
Pedro Alves

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

* Re: [RFA v2 05/17] Change minimal_symbol_reader to store objfile
  2016-10-13 21:11 ` [RFA v2 05/17] Change minimal_symbol_reader to store objfile Tom Tromey
@ 2016-10-13 22:21   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:21 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, Tom Tromey wrote:
> This changes 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.
> 

OK.

Thanks,
Pedro Alves

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

* Re: [RFA v2 06/17] Record minimal symbols directly in reader.
  2016-10-13 21:11 ` [RFA v2 06/17] Record minimal symbols directly in reader Tom Tromey
@ 2016-10-13 22:34   ` Pedro Alves
  2016-10-14 21:22     ` Tom Tromey
  0 siblings, 1 reply; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:34 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, Tom Tromey wrote:
> This patch changes minimal symbol creation in two ways.  First, it
> removes global variables in favor of members of minimal_symbol_reader.
> Second, it changes functions like prim_record_minimal_symbol to be
> member functions of minimal_symbol_reader.
> 

Awesome, thanks.

>  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)
> +minimal_symbol_reader::record_full (const char *name, int name_len,
> +					   int copy_name,

Can you make this bool while at it?

> +					   CORE_ADDR address,
> +					   enum minimal_symbol_type ms_type,
> +					   int section)



>    explicit minimal_symbol_reader (struct objfile *);
>  
> @@ -73,6 +74,56 @@ class 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.

Hmm, preexisting, but, this parameter's type is actually int.
Not sure that comment makes sense as is.

> +     OBJFILE - the objfile associated with the minimal symbol.  */

ENOSUCHPARAMETER.

> +
> +  struct minimal_symbol *record_full (const char *name,
> +				      int name_len,
> +				      int copy_name,

Use "bool" for 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,

"= true".

> +     - 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);

I think it may be a good idea to give names to the parameters.

> +
> +  /* Like record_full, but:
> +     - uses strlen to compute NAME_LEN,
> +     - passes COPY_NAME = 1.  */

= true.

> +
> +  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);

s/1/true/.

LGTM with those changes.

Thanks,
Pedro Alves

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

* Re: [RFA v2 07/17] Remove make_cleanup_restore_current_ui
  2016-10-13 21:11 ` [RFA v2 07/17] Remove make_cleanup_restore_current_ui Tom Tromey
@ 2016-10-13 22:37   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:37 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, Tom Tromey wrote:

> --- a/gdb/top.h
> +++ b/gdb/top.h
> @@ -155,27 +155,48 @@ 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
>  {
> -  struct ui *iter;
> -  struct cleanup *old_chain;
> +public:
> +
> +  switch_thru_all_uis () : m_iter (ui_list), m_save_ui (&current_ui)
> +  {
> +    current_ui = ui_list;
> +  }
> +
> +  // If done iterating, return true; otherwise return false.
> +  bool done () const
> +  {
> +    return m_iter == NULL;
> +  }
> +
> +  // Move to the next UI, setting current_ui if iteration is not yet
> +  // complete.
> +  void next ()
> +  {
> +    m_iter = m_iter->next;
> +    if (m_iter != NULL)
> +      current_ui = m_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 *m_iter;
> +
> +  // Save and restore current_ui.
> +  scoped_restore_tmpl<struct ui *> m_save_ui;
>  };

// vs /**/ comments.

OK with that change.  Thanks much!

Thanks,
Pedro Alves

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

* Re: [RFA v2 08/17] Remove some cleanups in MI
  2016-10-13 21:11 ` [RFA v2 08/17] Remove some cleanups in MI Tom Tromey
@ 2016-10-13 22:38   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:38 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, Tom Tromey wrote:
> This patch removes a couple of cleanups from MI by using
> gdb::unique_ptr.
> 
> 2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> 	* mi/mi-main.c (mi_cmd_data_read_memory): Use gdb::unique_ptr.
> 	Remove some cleanups.

OK.

Thanks,
Pedro Alves

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

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

On 10/13/2016 10:10 PM, 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 without excessive reindentation required splitting
> captured_main in two.
> 
> 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_1): New function.  Use
> 	scoped_command_stats.
> 	(captured_main): Call captured_main_1.
> 	* event-top.c (command_handler): Use scoped_command_stats.
> ---
>  gdb/ChangeLog   |  14 +++++++
>  gdb/event-top.c |   5 +--
>  gdb/main.c      |  25 +++++++-----
>  gdb/maint.c     | 118 ++++++++++++++++++--------------------------------------
>  gdb/maint.h     |  39 +++++++++++++++++--
>  5 files changed, 104 insertions(+), 97 deletions(-)
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 7c072b5..f476299 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,5 +1,19 @@
>  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_1): New function.  Use
> +	scoped_command_stats.
> +	(captured_main): Call captured_main_1.
> +	* 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 gdb::unique_ptr.
>  	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..420b4d3 100644
> --- a/gdb/main.c
> +++ b/gdb/main.c
> @@ -441,12 +441,12 @@ typedef struct cmdarg {
>  /* Define type VEC (cmdarg_s).  */
>  DEF_VEC_O (cmdarg_s);
>  
> -static int
> -captured_main (void *data)
> +static void
> +captured_main_1 (struct captured_main_args *context)
>  {
> -  struct captured_main_args *context = (struct captured_main_args *) data;
>    int argc = context->argc;
>    char **argv = context->argv;
> +
>    static int quiet = 0;
>    static int set_args = 0;
>    static int inhibit_home_gdbinit = 0;
> @@ -486,14 +486,14 @@ captured_main (void *data)
>    int save_auto_load;
>    struct objfile *objfile;
>  
> -  struct cleanup *pre_stat_chain;
> +  struct cleanup *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, "");
> @@ -510,7 +510,7 @@ captured_main (void *data)
>    notice_open_fds ();
>    save_original_signals_state ();
>  
> -  make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec);
> +  chain = make_cleanup (VEC_cleanup (cmdarg_s), &cmdarg_vec);
>    dirsize = 1;
>    dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
>    ndir = 0;
> @@ -1139,8 +1139,15 @@ captured_main (void *data)
>        quit_force (NULL, 0);
>      }
>  
> -  /* Show time and/or space usage.  */
> -  do_cleanups (pre_stat_chain);
> +  do_cleanups (chain);
> +}
> +
> +static void
> +captured_main (void *data)
> +{
> +  struct captured_main_args *context = (struct captured_main_args *) data;
> +
> +  captured_main_1 (context);
>  
>    /* 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..06e6766 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,31 +802,38 @@ 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 (m_msg_type != 0
> +      && !per_command_time
> +      && !per_command_space
> +      && !per_command_symtab)
> +    return;
>  
> -  if (start_stats->time_enabled && per_command_time)
> +  if (this->m_time_enabled && per_command_time)

s/this->// ?

>      {
> -      long cmd_time = get_run_time () - start_stats->start_cpu_time;
> +      long cmd_time = get_run_time () - this->m_start_cpu_time;

Ditto.

>        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->m_start_wall_time);

Ditto.

>  
>        /* Subtract time spend in prompt_for_continue from walltime.  */
>        wait_time = get_prompt_for_continue_wait_time ();
>        timeval_sub (&delta_wall_time, &delta_wall_time, &wait_time);
>  
> -      printf_unfiltered (msg_type == 0
> +      printf_unfiltered (m_msg_type == 0
>  			 ? _("Startup time: %ld.%06ld (cpu), %ld.%06ld (wall)\n")
>  			 : _("Command execution time: %ld.%06ld (cpu), %ld.%06ld (wall)\n"),
>  			 cmd_time / 1000000, cmd_time % 1000000,
> @@ -859,15 +841,15 @@ report_command_stats (void *arg)
>  			 (long) delta_wall_time.tv_usec);
>      }
>  
> -  if (start_stats->space_enabled && per_command_space)
> +  if (this->m_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->m_start_space;
>  
> -      printf_unfiltered (msg_type == 0
> +      printf_unfiltered (m_msg_type == 0
>  			 ? _("Space used: %ld (%s%ld during startup)\n")
>  			 : _("Space used: %ld (%s%ld for this command)\n"),
>  			 space_now,
> @@ -876,7 +858,7 @@ report_command_stats (void *arg)
>  #endif
>      }
>  
> -  if (start_stats->symtab_enabled && per_command_symtab)
> +  if (this->m_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->m_start_nr_symtabs,
>  			 nr_compunit_symtabs,
>  			 (nr_compunit_symtabs
> -			  - start_stats->start_nr_compunit_symtabs),
> +			  - this->m_start_nr_compunit_symtabs),
>  			 nr_blocks,
> -			 nr_blocks - start_stats->start_nr_blocks);
> +			 nr_blocks - this->m_start_nr_blocks);

Several more.

>      }
>  }
>  
> -/* 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)
> +: m_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)
> +  if (m_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->m_start_space = lim - lim_at_start;
> +      this->m_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->m_start_cpu_time = get_run_time ();
> +      gettimeofday (&this->m_start_wall_time, NULL);
> +      this->m_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->m_start_nr_symtabs = nr_symtabs;
> +      this->m_start_nr_compunit_symtabs = nr_compunit_symtabs;
> +      this->m_start_nr_blocks = nr_blocks;
> +      this->m_symtab_enabled = 1;
>      }
>  

Many more.

>    /* 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..ffbf0cb 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);

explicit?

> +  ~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 m_msg_type;

Bool?

> +  /* 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 m_time_enabled : 1;
> +  int m_space_enabled : 1;
> +  int m_symtab_enabled : 1;
> +  long m_start_cpu_time;
> +  struct timeval m_start_wall_time;
> +  long m_start_space;
> +  /* Total number of symtabs (over all objfiles).  */
> +  int m_start_nr_symtabs;
> +  /* A count of the compunits.  */
> +  int m_start_nr_compunit_symtabs;
> +  /* Total number of blocks.  */
> +  int m_start_nr_blocks;
> +};
>  
>  #endif /* MAINT_H */
> 

OK with those changes.

Thanks,
Pedro Alves

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

* Re: [RFA v2 11/17] Use gdb::unique_ptr in elf_read_minimal_symbols
  2016-10-13 21:11 ` [RFA v2 11/17] Use gdb::unique_ptr in elf_read_minimal_symbols Tom Tromey
@ 2016-10-13 22:44   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:44 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, Tom Tromey wrote:
> This changes elf_read_minimal_symbols to use gdb::unique_ptr rather
> than an explicit allocation.  This removes a cleanup.
> 
> 2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> 	* elfread.c (elf_read_minimal_symbols): Use gdb::unique_ptr.

OK.

Thanks,
Pedro Alves

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

* Re: [RFA v2 10/17] Replace two xmallocs with unique_ptr
  2016-10-13 21:11 ` [RFA v2 10/17] Replace two xmallocs with unique_ptr Tom Tromey
@ 2016-10-13 22:44   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:44 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, Tom Tromey wrote:
> This replaces a couple of uses of xmalloc with gdb::unique_ptr, also
> removing a couple of cleanups.
> 
> 2016-09-26  Tom Tromey  <tom@tromey.com>
> 
> 	* cli/cli-dump.c (dump_memory_to_file): Use gdb::unique_ptr.
> 	(restore_binary_file): Likewise.

OK.

Thanks,
Pedro Alves

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

* Re: [RFA v2 12/17] Remove make_cleanup_restore_current_uiout
  2016-10-13 21:11 ` [RFA v2 12/17] Remove make_cleanup_restore_current_uiout Tom Tromey
@ 2016-10-13 22:49   ` Pedro Alves
  2016-10-14 21:30     ` Tom Tromey
  0 siblings, 1 reply; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:49 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, Tom Tromey wrote:

> -  print_stop_location (&last);
> +  {
> +    scoped_restore save_uiout = make_scoped_restore (&current_uiout);
> +    current_uiout = uiout;

I wonder if you had a reasoning that led to deciding when
to use two-argument form?  A couple places looked like obvious
candidates.  My reasoning would be: if the assignment is right
after the scoped_restore creation.

Anyway, this is OK.

Thanks,
Pedro Alves

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

* Re: [RFA v2 13/17] Some cleanup removal in dwarf2loc.c
  2016-10-13 21:13 ` [RFA v2 13/17] Some cleanup removal in dwarf2loc.c Tom Tromey
@ 2016-10-13 22:52   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:52 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, Tom Tromey wrote:
> This removes some cleanups and manual allocation handling in
> dwarf2loc.c with std::vector.  Note that this patch has a case where
> the vector would normally fall into the "use gdb::unique_ptr"
> guidelines -- but here because the vector is immediately initialized,
> I moved the initialization into the constructor call, for further
> code savings.

Makes sense.  LGTM.

Thanks,
Pedro Alves

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

* Re: [RFA v2 14/17] Initial conversion of dwarf_expr_ctx
  2016-10-13 21:11 ` [RFA v2 14/17] Initial conversion of dwarf_expr_ctx Tom Tromey
@ 2016-10-13 22:54   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 22:54 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, 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 associated cleanup.

OK.

Thanks,
Pedro Alves

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

* Re: [RFA v2 15/17] Convert DWARF expr functions to methods
  2016-10-13 21:11 ` [RFA v2 15/17] Convert DWARF expr functions to methods Tom Tromey
@ 2016-10-13 23:01   ` Pedro Alves
  2016-10-20 21:47     ` Tom Tromey
  0 siblings, 1 reply; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 23:01 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, 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.
> 

LGTM.

> @@ -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.  */

I notice that several of the intro comments to functions that 
are now methods still talk about CTX.  Should they be
tweaked?  Maybe to "to this context's stack".  Or maybe they're clear
as is anyway.

>  
> -static void
> -dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need)
> +void
> +dwarf_expr_context::grow_stack (size_t need)
>  {

Thanks,
Pedro Alves

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-13 21:11 ` [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods Tom Tromey
@ 2016-10-13 23:05   ` Pedro Alves
  2016-10-18  2:50     ` Tom Tromey
  0 siblings, 1 reply; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 23:05 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, 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.
> 
> 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.


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

Should we remove the parens throughout?


> +  /* 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"));

Hmm, I think you may have missed my comments to this patch in v1.

Thanks,
Pedro Alves

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

* Re: [RFA v2 17/17] Remove last cleanup from captured_main_1
  2016-10-13 21:18 ` [RFA v2 17/17] Remove last cleanup from captured_main_1 Tom Tromey
@ 2016-10-13 23:13   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-13 23:13 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:10 PM, Tom Tromey wrote:
> An earlier patch split captured_main into two parts.  This patch
> removes the last remaining cleanup from captured_main_1, and also
> replaces a second hand-rolled VEC-like array with a std::vector.
> 
> 2016-10-11  Tom Tromey  <tom@tromey.com>
> 
> 	* main.c: Include <vector>.
> 	(cmdarg_s): Remove typedef.  Don't define VEC.
> 	(captured_main_1): Use vector, not VEC.  Remove cleanups.

Nice.  This is OK.

Thanks,
Pedro Alves

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

* Re: [RFA v2 00/17] more C++
  2016-10-13 21:39 ` [RFA v2 00/17] more C++ Pedro Alves
@ 2016-10-14 16:26   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-14 16:26 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 10/13/2016 10:39 PM, Pedro Alves wrote:
> On 10/13/2016 10:09 PM, Tom Tromey wrote:
>>
>> I think I've addressed all review comments.  (Though now that I am
>> writing this I remember I haven't yet dealt with the "override"
>> issue.)
> 
> My FINAL/OVERRIDE patch on the GCC side has approved barring
> no objections by the end of the week:
> 
>   https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00905.html
> 
> So I'll probably pull that in to our tree soon.

FYI, this is now done:
  https://sourceware.org/ml/gdb-patches/2016-10/msg00453.html

Thanks,
Pedro Alves

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

* Re: [RFA v2 06/17] Record minimal symbols directly in reader.
  2016-10-13 22:34   ` Pedro Alves
@ 2016-10-14 21:22     ` Tom Tromey
  2016-10-20 21:47       ` Tom Tromey
  0 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-14 21:22 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

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

>> +minimal_symbol_reader::record_full (const char *name, int name_len,
>> +					   int copy_name,

Pedro> Can you make this bool while at it?

I've added a follow-up patch for this.

>> +     SECTION - the symbol's section
>> +     appropriate obj_section for the minimal symbol.  This can be NULL.

Pedro> Hmm, preexisting, but, this parameter's type is actually int.
Pedro> Not sure that comment makes sense as is.

I fixed this.

>> +     OBJFILE - the objfile associated with the minimal symbol.  */

Pedro> ENOSUCHPARAMETER.

.. and this

>> +
>> +  struct minimal_symbol *record_full (const char *name,
>> +				      int name_len,
>> +				      int copy_name,

Pedro> Use "bool" for copy_name ?

.. and this and the other related things in the follow-up.
Also I've fixed the other callers of record_full.

Tom

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

* Re: [RFA v2 12/17] Remove make_cleanup_restore_current_uiout
  2016-10-13 22:49   ` Pedro Alves
@ 2016-10-14 21:30     ` Tom Tromey
  2016-10-20 21:46       ` Tom Tromey
  0 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-14 21:30 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

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

Pedro> I wonder if you had a reasoning that led to deciding when
Pedro> to use two-argument form?  A couple places looked like obvious
Pedro> candidates.  My reasoning would be: if the assignment is right
Pedro> after the scoped_restore creation.

I tried to use them everywhere, but I just forgot to restore it in this
patch when I added the two-arg form back.  I'll fix this up.

Tom

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

* Re: [RFA v2 02/17] Use scoped_restore for ui_file
  2016-10-13 22:07   ` Pedro Alves
@ 2016-10-14 21:33     ` Tom Tromey
  0 siblings, 0 replies; 59+ messages in thread
From: Tom Tromey @ 2016-10-14 21:33 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

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

Pedro> I wonder if aligning like:
Pedro>      scoped_restore save_stdout
Pedro>        = make_scoped_restore (&gdb_stdout, str_file);
Pedro>      scoped_restore save_stderr
Pedro>        = make_scoped_restore (&gdb_stderr, str_file);
Pedro>      scoped_restore save_stdlog
Pedro>        = make_scoped_restore (&gdb_stdlog, str_file);
Pedro>      scoped_restore save_stdtarg
Pedro>        = make_scoped_restore (&gdb_stdtarg, str_file);
Pedro>      scoped_restore save_stdtargerr
Pedro>        = make_scoped_restore (&gdb_stdtargerr, str_file);
Pedro> would read better.  Can't tell on the mail client.
Pedro> Up to you; just a thought.

I think so.  I went ahead and made this change.

Tom

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-13 23:05   ` Pedro Alves
@ 2016-10-18  2:50     ` Tom Tromey
  2016-10-18 10:51       ` Pedro Alves
  2016-10-20 21:48       ` Tom Tromey
  0 siblings, 2 replies; 59+ messages in thread
From: Tom Tromey @ 2016-10-18  2:50 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

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

>> -	  result = (this->funcs->get_addr_index) (this->baton, uoffset);
>> +	  result = (this->get_addr_index) (uoffset);

Pedro> Should we remove the parens throughout?

I made this change.

>> +  /* 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"));

Pedro> Hmm, I think you may have missed my comments to this patch in v1.

All I saw was the comment about possibly reducing churn:

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

... but the way that was worded, I thought it didn't need any changes.

Tom

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-18  2:50     ` Tom Tromey
@ 2016-10-18 10:51       ` Pedro Alves
  2016-10-18 14:55         ` Tom Tromey
  2016-10-20 21:48       ` Tom Tromey
  1 sibling, 1 reply; 59+ messages in thread
From: Pedro Alves @ 2016-10-18 10:51 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/18/2016 03:49 AM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
>>> -	  result = (this->funcs->get_addr_index) (this->baton, uoffset);
>>> +	  result = (this->get_addr_index) (uoffset);
> 
> Pedro> Should we remove the parens throughout?
> 
> I made this change.
> 
>>> +  /* 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"));
> 
> Pedro> Hmm, I think you may have missed my comments to this patch in v1.
> 
> All I saw was the comment about possibly reducing churn:
> 
> https://sourceware.org/ml/gdb-patches/2016-10/msg00208.html

I'm sorry, I had written comments about the parenthesis
thing and also about wondering whether these methods with
internal_error could be pure virtual ('= 0;') instead, and if not,
about adding a small comment mentioning it.

I sometimes write reviews of separate chunks in separate emails in
then merge it all before sending.  Guess I deleted that email
by mistake.

> 
> ... but the way that was worded, I thought it didn't need any changes.

Yeah, the churn thing is fine with me here.

Thanks,
Pedro Alves

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-18 10:51       ` Pedro Alves
@ 2016-10-18 14:55         ` Tom Tromey
  2016-10-18 17:38           ` Pedro Alves
  0 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-18 14:55 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

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

>> All I saw was the comment about possibly reducing churn:
>> https://sourceware.org/ml/gdb-patches/2016-10/msg00208.html

Pedro> I'm sorry, I had written comments about the parenthesis
Pedro> thing and also about wondering whether these methods with
Pedro> internal_error could be pure virtual ('= 0;') instead, and if not,
Pedro> about adding a small comment mentioning it.

I think the internal_error thing can't be a pure virtual because there
are subclasses that do not implement this method.  I could push the
internal error into the subclasses though.

Pedro> I sometimes write reviews of separate chunks in separate emails in
Pedro> then merge it all before sending.  Guess I deleted that email
Pedro> by mistake.

It's no problem.

Tom

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-18 14:55         ` Tom Tromey
@ 2016-10-18 17:38           ` Pedro Alves
  2016-10-19 22:29             ` Tom Tromey
  0 siblings, 1 reply; 59+ messages in thread
From: Pedro Alves @ 2016-10-18 17:38 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/18/2016 03:03 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
>>> All I saw was the comment about possibly reducing churn:
>>> https://sourceware.org/ml/gdb-patches/2016-10/msg00208.html
> 
> Pedro> I'm sorry, I had written comments about the parenthesis
> Pedro> thing and also about wondering whether these methods with
> Pedro> internal_error could be pure virtual ('= 0;') instead, and if not,
> Pedro> about adding a small comment mentioning it.
> 
> I think the internal_error thing can't be a pure virtual because there
> are subclasses that do not implement this method.  I could push the
> internal error into the subclasses though.

Hmm.  I guess the actual code smell is that these are internal_errors
instead of normal errors in the first place?  I.e., why are these two
cases internal_errors when the rest of the virtual methods have
defaults that call normal error instead?

Put another way, is there something in the inheritance design that
makes calling these default implementations a gdb bug?   Cases like
"virtual foo() and virtual bar() work in tandem, so if you get to
the default bar(), it means you overrode foo() but forgot bar()" would
be those which I think would be reasonable to internal_error.  I.e.,
clear implementation bugs.

So I'm wondering whether invalid dwarf (i.e., input) or something
like that could trigger these internal errors?

In any case, I see now that the old code internal_errors as well,
so in the name of keeping the patch's scope be converting function
pointer tables to virtual methods, it makes sense to keep the
internal_errors.

So patch is fine as is with the internal_error.  Thanks for the patience.

Thanks,
Pedro Alves

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

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

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

Pedro> Hmm.  I guess the actual code smell is that these are internal_errors
Pedro> instead of normal errors in the first place?  I.e., why are these two
Pedro> cases internal_errors when the rest of the virtual methods have
Pedro> defaults that call normal error instead?

Pedro> Put another way, is there something in the inheritance design that
Pedro> makes calling these default implementations a gdb bug?

Pedro> So I'm wondering whether invalid dwarf (i.e., input) or something
Pedro> like that could trigger these internal errors?

I looked at this more concretely today by changing the
internal_error-calling methods to be pure virtual, then rebuilding.

This showed that the only missing overrides were in dwarf2-frame, where
I think both push_dwarf_reg_entry_value and get_object_address don't
make sense.

So, I'll send a follow-up patch that implements these using error and
uses pure virtuals.

Tom

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

* Re: [RFA v2 12/17] Remove make_cleanup_restore_current_uiout
  2016-10-14 21:30     ` Tom Tromey
@ 2016-10-20 21:46       ` Tom Tromey
  2016-10-20 21:57         ` Pedro Alves
  0 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-20 21:46 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, gdb-patches

Pedro> I wonder if you had a reasoning that led to deciding when
Pedro> to use two-argument form?  A couple places looked like obvious
Pedro> candidates.  My reasoning would be: if the assignment is right
Pedro> after the scoped_restore creation.

Tom> I tried to use them everywhere, but I just forgot to restore it in this
Tom> patch when I added the two-arg form back.  I'll fix this up.

Here's the updated patch.

Tom

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f2743fe..d2ab393 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 2016-10-20  Tom Tromey  <tom@tromey.com>
 
+	* stack.c (print_stack_frame_to_uiout): Use scoped_restore.
+	* ui-out.c (make_cleanup_restore_current_uiout)
+	(restore_current_uiout_cleanup): Remove.
+	* infrun.c (print_stop_event): Use scoped_restore.
+	* ui-out.h (make_cleanup_restore_current_uiout): Don't declare.
+
+2016-10-20  Tom Tromey  <tom@tromey.com>
+
 	* elfread.c (elf_read_minimal_symbols): Use gdb::unique_ptr.
 
 2016-10-20  Tom Tromey  <tom@tromey.com>
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 3069b2d..00bba16 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8084,22 +8084,20 @@ 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 save_uiout = make_scoped_restore (&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 e478ec9..d6bd6bf 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -648,7 +648,7 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
 
       scoped_restore save_async = make_scoped_restore (&current_ui->async, 0);
 
-      make_cleanup_restore_current_uiout ();
+      scoped_restore save_uiout = make_scoped_restore (&current_uiout);
 
       /* Use the console interpreter uiout to have the same print format
 	for console or MI.  */
diff --git a/gdb/stack.c b/gdb/stack.c
index 706dd51..823433d 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -149,15 +149,9 @@ print_stack_frame_to_uiout (struct ui_out *uiout, struct frame_info *frame,
 			    int print_level, enum print_what print_what,
 			    int set_current_sal)
 {
-  struct cleanup *old_chain;
-
-  old_chain = make_cleanup_restore_current_uiout ();
-
-  current_uiout = uiout;
+  scoped_restore save_uiout = make_scoped_restore (&current_uiout, uiout);
 
   print_stack_frame (frame, print_level, print_what, set_current_sal);
-
-  do_cleanups (old_chain);
 }
 
 /* Show or print a stack frame FRAME briefly.  The output is formatted
diff --git a/gdb/ui-out.c b/gdb/ui-out.c
index f6d6050..932cf12 100644
--- a/gdb/ui-out.c
+++ b/gdb/ui-out.c
@@ -952,24 +952,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..9e1e74d 100644
--- a/gdb/ui-out.h
+++ b/gdb/ui-out.h
@@ -247,8 +247,4 @@ 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.  */
-
-extern struct cleanup *make_cleanup_restore_current_uiout (void);
-
 #endif /* UI_OUT_H */

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

* Re: [RFA v2 06/17] Record minimal symbols directly in reader.
  2016-10-14 21:22     ` Tom Tromey
@ 2016-10-20 21:47       ` Tom Tromey
  2016-10-20 22:13         ` Pedro Alves
  0 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-20 21:47 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, gdb-patches

Tom> I've added a follow-up patch for this.

I'll send this later.

Pedro> Hmm, preexisting, but, this parameter's type is actually int.
Pedro> Not sure that comment makes sense as is.

Tom> I fixed this.

Here's the updated version of this patch.

Tom

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2998f3d..96e1a86 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,45 @@
 2016-10-20  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 (minimal_symbol_reader) <record, record_full>:
+	Declare.
+	<m_msym_bunch, m_msym_bunch_index, m_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.
+	(minimal_symbol_reader): Initialize new members.
+	(minimal_symbol_reader::record): Renamed from
+	prim_record_minimal_symbol.
+	(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-10-20  Tom Tromey  <tom@tromey.com>
+
 	* xcoffread.c (xcoff_initial_scan): Update.
 	* mipsread.c (mipscoff_symfile_read): Update.
 	* minsyms.c (minimal_symbol_reader): Add obj argument.
diff --git a/gdb/coff-pe-read.c b/gdb/coff-pe-read.c
index 8836361..b0201d1 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 (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 (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 (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..6a82e4c 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 (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 b4de08e..3125fb1 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 (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 (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 (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 a5bb2e0..9e6df69 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 (minimal_symbol_reader &reader,
+				     struct objfile *objfile);
 
-static void read_dbx_symtab (struct objfile *);
+static void read_dbx_symtab (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 (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 (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 (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 (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 58e0cbc..56fac28 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 (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 (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 (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 1f82f2b..7889b00 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -97,7 +97,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 (minimal_symbol_reader &reader,
+			 struct objfile *objfile, const asymbol *sym)
 {
   if (sym->name == NULL || *sym->name == '\0')
     {
@@ -147,10 +148,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));
     }
 }
 
@@ -158,7 +158,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 (minimal_symbol_reader &reader,
+		   struct objfile *objfile,
 		   long number_of_symbols, asymbol **symbol_table,
 		   VEC (oso_el) **oso_vector_ptr)
 {
@@ -227,7 +228,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;
 
@@ -864,7 +865,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 1285db4..a149ee9 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 (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 (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 (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 (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 9de5722..5f6db60 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.  */
 
 minimal_symbol_reader::minimal_symbol_reader (struct objfile *obj)
-: m_objfile (obj)
-{
-  msym_count = 0;
-  msym_bunch = NULL;
-  /* Note that presetting msym_bunch_index to BUNCH_SIZE causes the
+: m_objfile (obj),
+  m_msym_bunch (NULL),
+  /* Note that presetting m_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;
+  m_msym_bunch_index (BUNCH_SIZE),
+  m_msym_count (0)
+{
 }
 
 /* Discard the currently collected minimal symbols, if any.  If we wish
@@ -944,20 +931,19 @@ minimal_symbol_reader::~minimal_symbol_reader ()
 {
   struct msym_bunch *next;
 
-  while (msym_bunch != NULL)
+  while (m_msym_bunch != NULL)
     {
-      next = msym_bunch->next;
-      xfree (msym_bunch);
-      msym_bunch = next;
+      next = m_msym_bunch->next;
+      xfree (m_msym_bunch);
+      m_msym_bunch = next;
     }
 }
 
 /* See minsyms.h.  */
 
 void
-prim_record_minimal_symbol (const char *name, CORE_ADDR address,
-			    enum minimal_symbol_type ms_type,
-			    struct objfile *objfile)
+minimal_symbol_reader::record (const char *name, CORE_ADDR address,
+				      enum minimal_symbol_type ms_type)
 {
   int section;
 
@@ -967,32 +953,31 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address,
     case mst_text_gnu_ifunc:
     case mst_file_text:
     case mst_solib_trampoline:
-      section = SECT_OFF_TEXT (objfile);
+      section = SECT_OFF_TEXT (m_objfile);
       break;
     case mst_data:
     case mst_file_data:
-      section = SECT_OFF_DATA (objfile);
+      section = SECT_OFF_DATA (m_objfile);
       break;
     case mst_bss:
     case mst_file_bss:
-      section = SECT_OFF_BSS (objfile);
+      section = SECT_OFF_BSS (m_objfile);
       break;
     default:
       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)
+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;
@@ -1009,7 +994,7 @@ prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
 
   /* It's safe to strip the leading char here once, since the name
      is also stored stripped in the minimal symbol table.  */
-  if (name[0] == get_symbol_leading_char (objfile->obfd))
+  if (name[0] == get_symbol_leading_char (m_objfile->obfd))
     {
       ++name;
       --name_len;
@@ -1018,17 +1003,17 @@ prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
   if (ms_type == mst_file_text && startswith (name, "__gnu_compiled"))
     return (NULL);
 
-  if (msym_bunch_index == BUNCH_SIZE)
+  if (m_msym_bunch_index == BUNCH_SIZE)
     {
       newobj = XCNEW (struct msym_bunch);
-      msym_bunch_index = 0;
-      newobj->next = msym_bunch;
-      msym_bunch = newobj;
+      m_msym_bunch_index = 0;
+      newobj->next = m_msym_bunch;
+      m_msym_bunch = newobj;
     }
-  msymbol = &msym_bunch->contents[msym_bunch_index];
+  msymbol = &m_msym_bunch->contents[m_msym_bunch_index];
   MSYMBOL_SET_LANGUAGE (msymbol, language_auto,
-			&objfile->per_bfd->storage_obstack);
-  MSYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, objfile);
+			&m_objfile->per_bfd->storage_obstack);
+  MSYMBOL_SET_NAMES (msymbol, name, name_len, copy_name, m_objfile);
 
   SET_MSYMBOL_VALUE_ADDRESS (msymbol, address);
   MSYMBOL_SECTION (msymbol) = section;
@@ -1047,28 +1032,15 @@ prim_record_minimal_symbol_full (const char *name, int name_len, int copy_name,
 
   /* If we already read minimal symbols for this objfile, then don't
      ever allocate a new one.  */
-  if (!objfile->per_bfd->minsyms_read)
+  if (!m_objfile->per_bfd->minsyms_read)
     {
-      msym_bunch_index++;
-      objfile->per_bfd->n_minsyms++;
+      m_msym_bunch_index++;
+      m_objfile->per_bfd->n_minsyms++;
     }
-  msym_count++;
+  m_msym_count++;
   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.  */
@@ -1244,13 +1216,13 @@ minimal_symbol_reader::install ()
   if (m_objfile->per_bfd->minsyms_read)
     return;
 
-  if (msym_count > 0)
+  if (m_msym_count > 0)
     {
       if (symtab_create_debug)
 	{
 	  fprintf_unfiltered (gdb_stdlog,
 			      "Installing %d minimal symbols of objfile %s.\n",
-			      msym_count, objfile_name (m_objfile));
+			      m_msym_count, objfile_name (m_objfile));
 	}
 
       /* Allocate enough space in the obstack, into which we will gather the
@@ -1258,7 +1230,7 @@ minimal_symbol_reader::install ()
          compact out the duplicate entries.  Once we have a final table,
          we will give back the excess space.  */
 
-      alloc_count = msym_count + m_objfile->per_bfd->minimal_symbol_count + 1;
+      alloc_count = m_msym_count + m_objfile->per_bfd->minimal_symbol_count + 1;
       obstack_blank (&m_objfile->per_bfd->storage_obstack,
 		     alloc_count * sizeof (struct minimal_symbol));
       msymbols = (struct minimal_symbol *)
@@ -1278,11 +1250,11 @@ minimal_symbol_reader::install ()
 
       mcount = m_objfile->per_bfd->minimal_symbol_count;
 
-      for (bunch = msym_bunch; bunch != NULL; bunch = bunch->next)
+      for (bunch = m_msym_bunch; bunch != NULL; bunch = bunch->next)
 	{
-	  for (bindex = 0; bindex < msym_bunch_index; bindex++, mcount++)
+	  for (bindex = 0; bindex < m_msym_bunch_index; bindex++, mcount++)
 	    msymbols[mcount] = bunch->contents[bindex];
-	  msym_bunch_index = BUNCH_SIZE;
+	  m_msym_bunch_index = BUNCH_SIZE;
 	}
 
       /* Sort the minimal symbols by address.  */
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index b83e2d0..b22920b 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 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 minimal_symbol_reader (struct objfile *);
 
@@ -73,6 +74,56 @@ class 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 minimal_symbol_reader
   minimal_symbol_reader (const minimal_symbol_reader &);
 
   struct objfile *m_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 *m_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 m_msym_bunch_index;
+
+  /* Total number of minimal symbols recorded so far for the
+     objfile.  */
+
+  int m_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 256b262..39af0d3 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 (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 (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..32902cb 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 (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 2656d4c..32f9a1b 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 (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 (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 (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.  */

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

* Re: [RFA v2 15/17] Convert DWARF expr functions to methods
  2016-10-13 23:01   ` Pedro Alves
@ 2016-10-20 21:47     ` Tom Tromey
  2016-10-20 22:01       ` Pedro Alves
  0 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-20 21:47 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

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

Pedro> I notice that several of the intro comments to functions that 
Pedro> are now methods still talk about CTX.  Should they be
Pedro> tweaked?  Maybe to "to this context's stack".  Or maybe they're clear
Pedro> as is anyway.

I've updated this patch as appended.

Tom

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c5ac1af..296c2fe 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,25 @@
 2016-10-20  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-10-20  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 e8487a6..1aa6afc 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];
@@ -119,66 +114,62 @@ dwarf_expr_context::~dwarf_expr_context ()
   xfree (this->pieces);
 }
 
-/* Expand the memory allocated to CTX's stack to contain at least
+/* Expand the memory allocated 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.  */
+/* Push VALUE onto the 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;
 }
 
-/* Push VALUE onto CTX's stack.  */
+/* Push VALUE onto the 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.  */
+/* Pop the top item off of the 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.  */
+/* Retrieve the N'th item on the 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.  */
@@ -236,13 +227,13 @@ get_signed_type (struct gdbarch *gdbarch, struct type *type)
     }
 }
 
-/* Retrieve the N'th item on CTX's stack, converted to an address.  */
+/* Retrieve the N'th item on the 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,101 +247,99 @@ 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;
 }
 
-/* Retrieve the in_stack_memory flag of the N'th item on CTX's stack.  */
+/* Retrieve the in_stack_memory flag of the N'th item on the 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);
     }
 }
 
-/* Evaluate the expression at ADDR (LEN bytes long) using the context
-   CTX.  */
+/* Evaluate the expression at ADDR (LEN bytes long).  */
 
 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.  */
+  /* 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.  */
@@ -417,19 +406,19 @@ base_types_equal_p (struct type *t1, struct type *t2)
   return TYPE_LENGTH (t1) == TYPE_LENGTH (t2);
 }
 
-/* A convenience function to call get_base_type on CTX and return the
-   result.  DIE is the DIE whose type we need.  SIZE is non-zero if
-   this function should verify that the resulting type has the correct
+/* A convenience function to call get_base_type and return the result.
+   DIE is the DIE whose type we need.  SIZE is non-zero if 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)
@@ -437,7 +426,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;
 }
@@ -612,14 +601,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
@@ -627,15 +616,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)
     {
@@ -696,26 +685,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;
 
@@ -808,7 +797,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:
@@ -817,7 +806,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:
@@ -827,9 +816,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");
@@ -837,7 +826,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;
 
@@ -845,21 +834,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");
 	  }
@@ -899,7 +888,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);
@@ -909,7 +898,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);
 	  }
@@ -925,78 +914,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;
 	  }
 
@@ -1004,12 +993,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)
 	      {
@@ -1017,12 +1006,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.  */
@@ -1046,8 +1035,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)
 	      {
@@ -1095,11 +1084,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"));
@@ -1128,7 +1117,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);
@@ -1163,7 +1152,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);
 		  }
@@ -1180,7 +1169,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);
 		  }
@@ -1231,7 +1220,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;
@@ -1246,9 +1235,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;
 
@@ -1264,11 +1253,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;
 
@@ -1281,14 +1270,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;
 
@@ -1299,14 +1288,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;
 
@@ -1315,7 +1304,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:
@@ -1324,7 +1313,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;
 
@@ -1334,7 +1323,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;
 	
@@ -1352,7 +1341,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 */);
@@ -1365,9 +1354,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;
@@ -1385,7 +1374,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 */);
@@ -1405,7 +1394,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;
@@ -1419,8 +1408,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;
 
@@ -1436,10 +1425,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);
@@ -1459,7 +1448,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;
 
@@ -1469,7 +1458,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:
       ;
     }
@@ -1477,12 +1466,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 4914c16..1f946df 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;
 

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-18  2:50     ` Tom Tromey
  2016-10-18 10:51       ` Pedro Alves
@ 2016-10-20 21:48       ` Tom Tromey
  2016-10-20 21:56         ` Pedro Alves
  2016-10-28 13:36         ` Pedro Alves
  1 sibling, 2 replies; 59+ messages in thread
From: Tom Tromey @ 2016-10-20 21:48 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, gdb-patches

Pedro> Should we remove the parens throughout?

Tom> I made this change.

Here's the updated version of this patch.
It also fixes some "CTX" comments.

Tom

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 296c2fe..b2a9844 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,58 @@
 2016-10-20  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-10-20  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..c9962e1 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 1aa6afc..a01d6d8 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -414,20 +414,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;
 }
 
@@ -698,13 +689,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;
 
@@ -888,8 +879,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);
 	  }
@@ -898,7 +888,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);
 	  }
@@ -918,14 +908,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"));
@@ -1011,7 +999,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.  */
@@ -1220,7 +1208,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;
@@ -1237,7 +1225,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;
 
@@ -1313,7 +1301,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;
 
@@ -1323,7 +1311,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;
 	
@@ -1341,10 +1329,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;
 	      }
 
@@ -1356,9 +1343,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;
 	      }
 
@@ -1374,10 +1360,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;
 
@@ -1409,7 +1394,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;
 
@@ -1448,7 +1433,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;
 
@@ -1474,75 +1459,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..63bdc6e 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,93 @@ 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.  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 +290,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 1f946df..6f25314 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)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
-  return dwarf2_frame_cfa (debaton->frame);
-}
-
-/* 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)
+get_frame_pc_for_per_cu_dwarf_call (void *baton)
 {
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  struct objfile *objfile = dwarf2_per_cu_objfile (debaton->per_cu);
+  dwarf_expr_context *ctx = (dwarf_expr_context *) baton;
 
-  return target_translate_tls_address (objfile, offset);
+  return ctx->get_frame_pc ();
 }
 
-/* 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,173 @@ 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);
-}
+  struct frame_info *frame;
+  struct dwarf2_per_cu_data *per_cu;
+  CORE_ADDR obj_address;
 
-/* Callback function for dwarf2_evaluate_loc_desc.  */
+  /* Helper function for dwarf2_evaluate_loc_desc.  Computes the CFA for
+     the frame in BATON.  */
 
-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;
+  CORE_ADDR get_frame_cfa () OVERRIDE
+  {
+    return dwarf2_frame_cfa (frame);
+  }
 
-  return dwarf2_get_die_type (die_offset, debaton->per_cu);
-}
+  /* 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 this objects's frame.
+
+     The 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 save_arch = make_scoped_restore (&this->gdbarch);
+    this->gdbarch
+      = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu));
+    scoped_restore save_addr_size = make_scoped_restore (&this->addr_size);
+    this->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu);
+    scoped_restore save_offset = make_scoped_restore (&this->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 +1306,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 +2234,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 +2246,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 +2255,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 +2487,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 +2505,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 +2515,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 +2660,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;
-
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
-
-  /* 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.  */
+  /* 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;
 
-static CORE_ADDR
-needs_get_addr_index (void *baton, unsigned int index)
-{
-  /* Nothing to do.  */
-  return 1;
-}
+    /* The expression may require some stub values on DWARF stack.  */
+    push_address (0, 0);
+  }
 
-/* DW_OP_push_object_address has a frame already passed through.  */
+  /* DW_OP_GNU_addr_index doesn't require a frame.  */
 
-static CORE_ADDR
-needs_get_obj_addr (void *baton)
-{
-  /* Nothing to do.  */
-  return 1;
-}
+   CORE_ADDR get_addr_index (unsigned int index) OVERRIDE
+   {
+     /* Nothing to do.  */
+     return 1;
+   }
 
-/* Virtual method table for dwarf2_loc_desc_get_symbol_read_needs
-   below.  */
+   /* DW_OP_push_object_address has a frame already passed through.  */
 
-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 +2760,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 +2794,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

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

* Re: [RFA v2 00/17] more C++
  2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
                   ` (17 preceding siblings ...)
  2016-10-13 21:39 ` [RFA v2 00/17] more C++ Pedro Alves
@ 2016-10-20 21:49 ` Tom Tromey
  2016-10-20 22:27   ` Pedro Alves
  18 siblings, 1 reply; 59+ messages in thread
From: Tom Tromey @ 2016-10-20 21:49 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

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

Tom> This is an updated version of my C++-ification series.  It has been
Tom> rebased on Pedro's unique_ptr patch, so it can't go in until that
Tom> does.

Tom> I think I've addressed all review comments.  (Though now that I am
Tom> writing this I remember I haven't yet dealt with the "override"
Tom> issue.)

I've sent the various updated patches.  I'll hold off pushing until
those are reviewed.  I did re-build and re-regtest on x86-64 Fedora 24.

I'll send my add-on patches shortly.

Tom

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-20 21:48       ` Tom Tromey
@ 2016-10-20 21:56         ` Pedro Alves
  2016-10-28 13:36         ` Pedro Alves
  1 sibling, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-20 21:56 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/20/2016 10:48 PM, Tom Tromey wrote:
> Pedro> Should we remove the parens throughout?
> 
> Tom> I made this change.
> 
> Here's the updated version of this patch.
> It also fixes some "CTX" comments.

Thanks!  This is OK.

-- 
Pedro Alves

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

* Re: [RFA v2 12/17] Remove make_cleanup_restore_current_uiout
  2016-10-20 21:46       ` Tom Tromey
@ 2016-10-20 21:57         ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-20 21:57 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/20/2016 10:46 PM, Tom Tromey wrote:
> Pedro> I wonder if you had a reasoning that led to deciding when
> Pedro> to use two-argument form?  A couple places looked like obvious
> Pedro> candidates.  My reasoning would be: if the assignment is right
> Pedro> after the scoped_restore creation.
> 
> Tom> I tried to use them everywhere, but I just forgot to restore it in this
> Tom> patch when I added the two-arg form back.  I'll fix this up.
> 
> Here's the updated patch.

OK.

Thanks,
Pedro Alves

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

* Re: [RFA v2 15/17] Convert DWARF expr functions to methods
  2016-10-20 21:47     ` Tom Tromey
@ 2016-10-20 22:01       ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-20 22:01 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/20/2016 10:46 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> I notice that several of the intro comments to functions that 
> Pedro> are now methods still talk about CTX.  Should they be
> Pedro> tweaked?  Maybe to "to this context's stack".  Or maybe they're clear
> Pedro> as is anyway.
> 
> I've updated this patch as appended.

LGTM.

Thanks,
Pedro Alves

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

* Re: [RFA v2 06/17] Record minimal symbols directly in reader.
  2016-10-20 21:47       ` Tom Tromey
@ 2016-10-20 22:13         ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-20 22:13 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

OK.

Thanks,
Pedro Alves

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

* Re: [RFA v2 00/17] more C++
  2016-10-20 21:49 ` Tom Tromey
@ 2016-10-20 22:27   ` Pedro Alves
  0 siblings, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-10-20 22:27 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/20/2016 10:49 PM, Tom Tromey wrote:
>>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:
> 
> Tom> This is an updated version of my C++-ification series.  It has been
> Tom> rebased on Pedro's unique_ptr patch, so it can't go in until that
> Tom> does.
> 
> Tom> I think I've addressed all review comments.  (Though now that I am
> Tom> writing this I remember I haven't yet dealt with the "override"
> Tom> issue.)
> 
> I've sent the various updated patches.  I'll hold off pushing until
> those are reviewed.  I did re-build and re-regtest on x86-64 Fedora 24.
> 
> I'll send my add-on patches shortly.

I believe it's all ready now.  Let me know if I missed any.

Thanks,
Pedro Alves

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-20 21:48       ` Tom Tromey
  2016-10-20 21:56         ` Pedro Alves
@ 2016-10-28 13:36         ` Pedro Alves
  2016-10-31  2:48           ` Tom Tromey
  1 sibling, 1 reply; 59+ messages in thread
From: Pedro Alves @ 2016-10-28 13:36 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/20/2016 10:48 PM, Tom Tromey wrote:
> Pedro> Should we remove the parens throughout?
> 
> Tom> I made this change.
> 
> Here's the updated version of this patch.
> It also fixes some "CTX" comments.

Unfortunately, this caused regressions:

 https://sourceware.org/ml/gdb-testers/2016-q4/msg01382.html

*** Diff to previous build ***
============================
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: bt
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: p regparam
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: p regparam@entry
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: p &regparam@entry
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: tailcall: bt
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: tailcall: p i
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: tailcall: p i@entry
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: tailcall: p j
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: tailcall: p j@entry
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: ambiguous: bt
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: self: bt
PASS -> FAIL: gdb.arch/amd64-tailcall-noret.exp: bt
PASS -> FAIL: gdb.dwarf2/dw2-op-call.exp: p arraycallnoloc
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of w at typeddwarf.c:29
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of x at typeddwarf.c:29
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of y at typeddwarf.c:29
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of w at typeddwarf.c:53
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of x at typeddwarf.c:53
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of y at typeddwarf.c:53
============================

I've confirmed that going back to the commit before 
192ca6d8eac4 ("Convert dwarf_expr_context_funcs to methods"),
the FAILs disappear.

Comparing before/after logs, I see:

~~~
-#0  reference (regparam=@0x7fffffffd344: 21, regparam@entry=@0x7fffffffd344: 1, nodataparam=@0x60202c: 22, r3=r3@entry=3, r4=r4@entry=4, r5=r5@entry=5, r6=r6@entry=6, stackparam1=@0x7fffffffd348: 31, stackparam2=@0x7fffffffd34c: 32) at gdb.arch/amd64-entry-value.cc:155
+#0  reference (regparam=@0x7fffffffcf14: 32767, regparam@entry=@0x7fffffffcf54: 1, nodataparam=@0x60202c: 22, r3=r3@entry=3, r4=r4@entry=4, r5=r5@entry=5, r6=r6@entry=6, stackparam1=@0x7fffffffcf58: 31, stackparam2=@0x7fffffffcf5c: 32) at gdb.arch/amd64-entry-value.cc:155
 #1  0x00000000004005d0 in main () at gdb.arch/amd64-entry-value.cc:222
-(gdb) PASS: gdb.arch/amd64-entry-value.exp: entry_reference: bt
+(gdb) FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: bt

-$14 = (int &) @0x7fffffffd344: 21
-(gdb) PASS: gdb.arch/amd64-entry-value.exp: entry_reference: p regparam
+$14 = (int &) @0x7fffffffcf14: 32767
+(gdb) FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: p regparam
~~~

"32767" looks a lot like maybe some unitialized field in one of the classes.

~~~
-Breakpoint 2, d (i=71, i@entry=70, j=73.5, j@entry=72.5) at gdb.arch/amd64-entry-value.cc:34
+Breakpoint 2, d (i=<error reading variable: DWARF-2 expression error: Loop detected (257).>, j=<error reading variable: DWARF-2 expression error: Loop detected (257).>) at
~~~

Many instances of that loop error, actually.

~~~
-$26 = 1
-(gdb) PASS: gdb.dwarf2/typeddwarf.exp: check value of w at typeddwarf.c:53
+DW_OP_GNU_const_type has different sizes for type and data
+(gdb) FAIL: gdb.dwarf2/typeddwarf.exp: check value of w at typeddwarf.c:53
~~~

~~~
 p arraycallnoloc
-Asked for position 0 of stack, stack only has 0 elements on it.
-(gdb) PASS: gdb.dwarf2/dw2-op-call.exp: p arraycallnoloc
-testcase /home/pedro/gdb/mygit/cxx-convertion/src/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp completed in 1 seconds
+DW_OP_GNU_implicit_pointer is invalid in this context
+(gdb) FAIL: gdb.dwarf2/dw2-op-call.exp: p arraycallnoloc
+testcase /home/pedro/gdb/mygit/cxx-convertion/src/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp completed in 0 seconds
~~~

Could you take a look?  Maybe it'll be obvious to you what
the problem is.

Thanks,
Pedro Alves

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-28 13:36         ` Pedro Alves
@ 2016-10-31  2:48           ` Tom Tromey
  2016-11-01 22:07             ` Tom Tromey
  2016-11-02 16:12             ` Pedro Alves
  0 siblings, 2 replies; 59+ messages in thread
From: Tom Tromey @ 2016-10-31  2:48 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

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

Pedro> Unfortunately, this caused regressions:
Pedro>  https://sourceware.org/ml/gdb-testers/2016-q4/msg01382.html

Sorry about this.  Something must be wrong with regression testing here,
because I see these failures when I run the tests individually, but I
never saw them when comparing against the baseline.

I'll set up to use the try builder tomorrow and then rely on that
instead.  Meanwhile here's the patch I'll be testing.

Tom

commit 0b88198c29a9773741b8450f79e4fe1ee535efac
Author: Tom Tromey <tom@tromey.com>
Date:   Sun Oct 30 20:45:08 2016 -0600

    Fix dwarf_expr_context method regressions
    
    This fixes some regressions found in the patch to convert
    dwarf_expr_context to use methods.  Specifically:
    
    * get_base_type could erroneously throw; this was rewritten to move
      the size checks into the only spot needing them.
    * Previously the "symbol needs frame" implementation reused th
      "cfa" function for the get_frame_pc slot; this reimplements
      it under the correct name.
    * Not enough members were saved and restored in one implementation
      of push_dwarf_reg_entry_value; this patch fixes this oversight
      and also takes the opportunity to remove an extraneous structure
      definition.
    
    2016-10-30  Tom Tromey  <tom@tromey.com>
    
    	* dwarf2loc.c (dwarf_evaluate_loc_desc::get_base_type): Rename
    	from impl_get_base_type.  Rewrite.
    	(struct dwarf_expr_baton): Remove.
    	(dwarf_evaluate_loc_desc::push_dwarf_reg_entry_value): Save and
    	restore more fields.
    	(symbol_needs_eval_context::get_frame_pc): New method.
    	* dwarf2expr.h (dwarf_expr_context::get_base_type): Now public,
    	virtual.
    	(dwarf_expr_context::impl_get_base_type): Remove.
    	* dwarf2expr.c (dwarf_expr_context::get_base_type): Remove.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c38c65c..ac5b0ce 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,16 @@
+2016-10-30  Tom Tromey  <tom@tromey.com>
+
+	* dwarf2loc.c (dwarf_evaluate_loc_desc::get_base_type): Rename
+	from impl_get_base_type.  Rewrite.
+	(struct dwarf_expr_baton): Remove.
+	(dwarf_evaluate_loc_desc::push_dwarf_reg_entry_value): Save and
+	restore more fields.
+	(symbol_needs_eval_context::get_frame_pc): New method.
+	* dwarf2expr.h (dwarf_expr_context::get_base_type): Now public,
+	virtual.
+	(dwarf_expr_context::impl_get_base_type): Remove.
+	* dwarf2expr.c (dwarf_expr_context::get_base_type): Remove.
+
 2016-10-29  Pedro Alves  <palves@redhat.com>
 
 	* NEWS: Clarify C++ requirement.
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index a01d6d8..398ca0e 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -406,22 +406,6 @@ base_types_equal_p (struct type *t1, struct type *t2)
   return TYPE_LENGTH (t1) == TYPE_LENGTH (t2);
 }
 
-/* A convenience function to call get_base_type and return the result.
-   DIE is the DIE whose type we need.  SIZE is non-zero if this
-   function should verify that the resulting type has the correct
-   size.  */
-
-struct type *
-dwarf_expr_context::get_base_type (cu_offset die, int size)
-{
-  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;
-}
-
 /* If <BUF..BUF_END] contains DW_FORM_block* with single DW_OP_reg* return the
    DWARF register number.  Otherwise return -1.  */
 
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index 3d08120..883c54c 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -179,10 +179,9 @@ struct dwarf_expr_context
 
   /* 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)
+     type.  SIZE is non-zero if this function should verify that the
+     resulting type has the correct size.  */
+  virtual struct type *get_base_type (cu_offset die, int size)
   {
     /* Anything will do.  */
     return builtin_type (this->gdbarch)->builtin_int;
@@ -210,7 +209,6 @@ private:
   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 ();
 };
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 6f25314..93aec1f 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -515,10 +515,14 @@ class dwarf_evaluate_loc_desc : public dwarf_expr_context
     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
+  struct type *get_base_type (cu_offset die_offset, int size) OVERRIDE
   {
-    return dwarf2_get_die_type (die_offset, per_cu);
+    struct type *result = dwarf2_get_die_type (die_offset, per_cu);
+    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;
   }
 
   /* Callback function for dwarf2_evaluate_loc_desc.
@@ -553,7 +557,6 @@ class dwarf_evaluate_loc_desc : public dwarf_expr_context
   {
     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;
@@ -570,17 +573,20 @@ class dwarf_evaluate_loc_desc : public dwarf_expr_context
       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 save_frame = make_scoped_restore (&this->frame,
+						     caller_frame);
+    scoped_restore save_per_cu = make_scoped_restore (&this->per_cu,
+						      caller_per_cu);
+    scoped_restore save_obj_addr = make_scoped_restore (&this->obj_address,
+							(CORE_ADDR) 0);
 
     scoped_restore save_arch = make_scoped_restore (&this->gdbarch);
     this->gdbarch
-      = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu));
+      = get_objfile_arch (dwarf2_per_cu_objfile (per_cu));
     scoped_restore save_addr_size = make_scoped_restore (&this->addr_size);
-    this->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu);
+    this->addr_size = dwarf2_per_cu_addr_size (per_cu);
     scoped_restore save_offset = make_scoped_restore (&this->offset);
-    this->offset = dwarf2_per_cu_text_offset (baton_local.per_cu);
+    this->offset = dwarf2_per_cu_text_offset (per_cu);
 
     this->eval (data_src, size);
   }
@@ -2707,6 +2713,12 @@ class symbol_needs_eval_context : public dwarf_expr_context
     return 1;
   }
 
+  CORE_ADDR get_frame_pc () 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
   {

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-31  2:48           ` Tom Tromey
@ 2016-11-01 22:07             ` Tom Tromey
  2016-11-02 16:12             ` Pedro Alves
  1 sibling, 0 replies; 59+ messages in thread
From: Tom Tromey @ 2016-11-01 22:07 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, gdb-patches

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

Pedro> Unfortunately, this caused regressions:
Pedro> https://sourceware.org/ml/gdb-testers/2016-q4/msg01382.html

Tom> I'll set up to use the try builder tomorrow and then rely on that
Tom> instead.  Meanwhile here's the patch I'll be testing.

I went through all the test results and I think this went ok.
It's a little hard to tell because "Fedora-x86_64-native-gdbserver-m64"
had many failures -- but that build had many failures for another try
run of mine, so I don't believe they were caused by this patch.

Tom

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

* Re: [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods
  2016-10-31  2:48           ` Tom Tromey
  2016-11-01 22:07             ` Tom Tromey
@ 2016-11-02 16:12             ` Pedro Alves
  1 sibling, 0 replies; 59+ messages in thread
From: Pedro Alves @ 2016-11-02 16:12 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 10/31/2016 02:48 AM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> Unfortunately, this caused regressions:
> Pedro>  https://sourceware.org/ml/gdb-testers/2016-q4/msg01382.html
> 
> Sorry about this.  Something must be wrong with regression testing here,
> because I see these failures when I run the tests individually, but I
> never saw them when comparing against the baseline.
> 
> I'll set up to use the try builder tomorrow and then rely on that
> instead.  Meanwhile here's the patch I'll be testing.

This is OK.  Thanks!

-- 
Pedro Alves

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

end of thread, other threads:[~2016-11-02 16:12 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-13 21:11 [RFA v2 00/17] more C++ Tom Tromey
2016-10-13 21:11 ` [RFA v2 15/17] Convert DWARF expr functions to methods Tom Tromey
2016-10-13 23:01   ` Pedro Alves
2016-10-20 21:47     ` Tom Tromey
2016-10-20 22:01       ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 08/17] Remove some cleanups in MI Tom Tromey
2016-10-13 22:38   ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 12/17] Remove make_cleanup_restore_current_uiout Tom Tromey
2016-10-13 22:49   ` Pedro Alves
2016-10-14 21:30     ` Tom Tromey
2016-10-20 21:46       ` Tom Tromey
2016-10-20 21:57         ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 04/17] Introduce minimal_symbol_reader Tom Tromey
2016-10-13 22:20   ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 05/17] Change minimal_symbol_reader to store objfile Tom Tromey
2016-10-13 22:21   ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 10/17] Replace two xmallocs with unique_ptr Tom Tromey
2016-10-13 22:44   ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 03/17] Use scoped_restore for current_ui Tom Tromey
2016-10-13 22:16   ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 02/17] Use scoped_restore for ui_file Tom Tromey
2016-10-13 22:07   ` Pedro Alves
2016-10-14 21:33     ` Tom Tromey
2016-10-13 21:11 ` [RFA v2 06/17] Record minimal symbols directly in reader Tom Tromey
2016-10-13 22:34   ` Pedro Alves
2016-10-14 21:22     ` Tom Tromey
2016-10-20 21:47       ` Tom Tromey
2016-10-20 22:13         ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 16/17] Convert dwarf_expr_context_funcs to methods Tom Tromey
2016-10-13 23:05   ` Pedro Alves
2016-10-18  2:50     ` Tom Tromey
2016-10-18 10:51       ` Pedro Alves
2016-10-18 14:55         ` Tom Tromey
2016-10-18 17:38           ` Pedro Alves
2016-10-19 22:29             ` Tom Tromey
2016-10-20 21:48       ` Tom Tromey
2016-10-20 21:56         ` Pedro Alves
2016-10-28 13:36         ` Pedro Alves
2016-10-31  2:48           ` Tom Tromey
2016-11-01 22:07             ` Tom Tromey
2016-11-02 16:12             ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 14/17] Initial conversion of dwarf_expr_ctx Tom Tromey
2016-10-13 22:54   ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 01/17] Use RAII to save and restore scalars Tom Tromey
2016-10-13 22:03   ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 07/17] Remove make_cleanup_restore_current_ui Tom Tromey
2016-10-13 22:37   ` Pedro Alves
2016-10-13 21:11 ` [RFA v2 11/17] Use gdb::unique_ptr in elf_read_minimal_symbols Tom Tromey
2016-10-13 22:44   ` Pedro Alves
2016-10-13 21:13 ` [RFA v2 13/17] Some cleanup removal in dwarf2loc.c Tom Tromey
2016-10-13 22:52   ` Pedro Alves
2016-10-13 21:14 ` [RFA v2 09/17] Change command stats reporting to use class Tom Tromey
2016-10-13 22:43   ` Pedro Alves
2016-10-13 21:18 ` [RFA v2 17/17] Remove last cleanup from captured_main_1 Tom Tromey
2016-10-13 23:13   ` Pedro Alves
2016-10-13 21:39 ` [RFA v2 00/17] more C++ Pedro Alves
2016-10-14 16:26   ` Pedro Alves
2016-10-20 21:49 ` Tom Tromey
2016-10-20 22:27   ` Pedro Alves

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