This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patchv2] Fix C++ regression for bpt conditionals


On Wed, 09 Jan 2013 17:45:50 +0100, Tom Tromey wrote:
> What I meant is that if get_current_arch changes the global
> current_language, then losing this transition may cause a user-visible
> change.  So, it seems like it would be better to make the cleanup after
> calling get_current_arch.

OK, understood now.


Thanks,
Jan


gdb/
2013-01-08  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* parse.c (parse_exp_in_context): New variable inner_chain.  Call
	make_cleanup_restore_current_language.  Call set_language.  Move
	OLD_CHAIN and INNER_CHAIN cleanups.
	* utils.c (do_restore_current_language)
	(make_cleanup_restore_current_language): New functions.
	* utils.h (make_cleanup_restore_current_language): New declaration.

gdb/testsuite/
2013-01-04  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.cp/parse-lang.cc: New file.
	* gdb.cp/parse-lang.exp: New file.

diff --git a/gdb/parse.c b/gdb/parse.c
index 2d530df..09c378b 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -1143,7 +1143,7 @@ parse_exp_in_context (char **stringptr, CORE_ADDR pc, const struct block *block,
 		      int comma, int void_context_p, int *out_subexp)
 {
   volatile struct gdb_exception except;
-  struct cleanup *old_chain;
+  struct cleanup *old_chain, *inner_chain;
   const struct language_defn *lang = NULL;
   int subexp;
 
@@ -1213,7 +1213,13 @@ parse_exp_in_context (char **stringptr, CORE_ADDR pc, const struct block *block,
   else
     lang = current_language;
 
+  /* get_current_arch may reset CURRENT_LANGUAGE via select_frame.
+     While we need CURRENT_LANGUAGE to be set to LANG (for lookup_symbol
+     and others called from *.y) ensure CURRENT_LANGUAGE gets restored
+     to the value matching SELECTED_FRAME as set by get_current_arch.  */
   initialize_expout (10, lang, get_current_arch ());
+  inner_chain = make_cleanup_restore_current_language ();
+  set_language (lang->la_language);
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
@@ -1229,8 +1235,6 @@ parse_exp_in_context (char **stringptr, CORE_ADDR pc, const struct block *block,
 	}
     }
 
-  discard_cleanups (old_chain);
-
   reallocate_expout ();
 
   /* Convert expression from postfix form as generated by yacc
@@ -1249,6 +1253,9 @@ parse_exp_in_context (char **stringptr, CORE_ADDR pc, const struct block *block,
   if (expressiondebug)
     dump_prefix_expression (expout, gdb_stdlog);
 
+  do_cleanups (inner_chain);
+  discard_cleanups (old_chain);
+
   *stringptr = lexptr;
   return expout;
 }
diff --git a/gdb/utils.c b/gdb/utils.c
index e12888f..8bae4eb 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -503,6 +503,28 @@ make_cleanup_free_so (struct so_list *so)
   return make_cleanup (do_free_so, so);
 }
 
+/* Helper for make_cleanup_restore_current_language.  */
+
+static void
+do_restore_current_language (void *p)
+{
+  enum language saved_lang = (uintptr_t) p;
+
+  set_language (saved_lang);
+}
+
+/* Remember the current value of CURRENT_LANGUAGE and make it restored when
+   the cleanup is run.  */
+
+struct cleanup *
+make_cleanup_restore_current_language (void)
+{
+  enum language saved_lang = current_language->la_language;
+
+  return make_cleanup (do_restore_current_language,
+		       (void *) (uintptr_t) saved_lang);
+}
+
 /* This function is useful for cleanups.
    Do
 
diff --git a/gdb/utils.h b/gdb/utils.h
index 14235a9..6983a53 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -104,6 +104,8 @@ extern struct cleanup *make_cleanup_value_free (struct value *);
 struct so_list;
 extern struct cleanup *make_cleanup_free_so (struct so_list *so);
 
+extern struct cleanup *make_cleanup_restore_current_language (void);
+
 extern struct cleanup *make_cleanup_htab_delete (htab_t htab);
 
 extern void free_current_contents (void *);
diff --git a/gdb/testsuite/gdb.cp/parse-lang.cc b/gdb/testsuite/gdb.cp/parse-lang.cc
new file mode 100644
index 0000000..46af670
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/parse-lang.cc
@@ -0,0 +1,40 @@
+/* Copyright 2013 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+class C
+{
+public:
+  int v;
+  void m ();
+};
+
+void
+C::m ()
+{
+}
+
+void
+marker ()
+{
+}
+
+int
+main ()
+{
+  C c = { 42 };
+
+  c.m ();
+  marker ();
+}
diff --git a/gdb/testsuite/gdb.cp/parse-lang.exp b/gdb/testsuite/gdb.cp/parse-lang.exp
new file mode 100644
index 0000000..c0051e9
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/parse-lang.exp
@@ -0,0 +1,31 @@
+# Copyright 2012-2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile .cc
+
+if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} {
+    return -1
+}
+
+# Place the breakpoint before inferior gets started.  Then the breakpoint
+# condition will be re-evaluated in non-C++ startup code.
+gdb_breakpoint "C::m if v == 42"
+
+gdb_breakpoint "marker"
+
+# runto_main would delete the breakpoint.
+gdb_run_cmd
+
+gdb_test "" {Breakpoint [0-9]+, C::m .*} "breakpoint hit"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]