* [PATCH v6] Make chained function calls in expressions work
@ 2014-11-27 6:55 Siva Chandra
2014-11-28 12:10 ` Ulrich Weigand
0 siblings, 1 reply; 8+ messages in thread
From: Siva Chandra @ 2014-11-27 6:55 UTC (permalink / raw)
To: gdb-patches; +Cc: Ulrich Weigand
[-- Attachment #1: Type: text/plain, Size: 1707 bytes --]
Link to v5: https://sourceware.org/ml/gdb-patches/2014-11/msg00394.html
I have made all the changes suggested by Ulrich Weigand in his comments for v5.
gdb/ChangeLog:
2014-11-27 Siva Chandra Reddy <sivachandra@google.com>
* eval.c: Include gdbthread.h.
(evaluate_subexp): Enable thread stack temporaries before
evaluating a complete expression and clean them up after the
evaluation is complete.
* gdbthread.h: Include common/vec.h.
(value_ptr): New typedef.
(VEC (value_ptr)): New vector type.
(value_vec): New typedef.
(struct thread_info): Add new fields stack_temporaries_enabled
and stack_temporaries.
(enable_thread_stack_temporaries)
(thread_stack_temporaries_enabled_p, push_thread_stack_temporary)
(get_last_thread_stack_temporary)
(value_in_thread_stack_temporaries): Declare.
* gdbtypes.c (class_or_union_p): New function.
* gdbtypes.h (class_or_union_p): Declare.
* infcall.c (call_function_by_hand): Store return values of class
type as temporaries on stack.
* thread.c (enable_thread_stack_temporaries): New function.
(thread_stack_temporaries_enabled_p, push_thread_stack_temporary)
(get_last_thread_stack_temporary): Likewise.
(value_in_thread_stack_temporaries): Likewise.
* value.c (value_force_lval): New function.
* value.h (value_force_lval): Declare.
gdb/testsuite/ChangeLog:
2014-11-27 Siva Chandra Reddy <sivachandra@google.com>
* gdb.cp/chained-calls.cc: New file.
* gdb.cp/chained-calls.exp: New file.
* gdb.cp/smartp.exp: Remove KFAIL for "p c2->inta".
[-- Attachment #2: chained-calls-v6.txt --]
[-- Type: text/plain, Size: 17420 bytes --]
diff --git a/gdb/eval.c b/gdb/eval.c
index 655ea22..a13793c 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -24,6 +24,7 @@
#include "expression.h"
#include "target.h"
#include "frame.h"
+#include "gdbthread.h"
#include "language.h" /* For CAST_IS_CONVERSION. */
#include "f-lang.h" /* For array bound stuff. */
#include "cp-abi.h"
@@ -63,8 +64,28 @@ struct value *
evaluate_subexp (struct type *expect_type, struct expression *exp,
int *pos, enum noside noside)
{
- return (*exp->language_defn->la_exp_desc->evaluate_exp)
+ struct cleanup *cleanups;
+ struct value *retval;
+ int cleanup_temps = 0;
+
+ if (*pos == 0 && target_has_execution
+ && exp->language_defn->la_language == language_cplus)
+ {
+ cleanups = enable_thread_stack_temporaries (inferior_ptid);
+ cleanup_temps = 1;
+ }
+
+ retval = (*exp->language_defn->la_exp_desc->evaluate_exp)
(expect_type, exp, pos, noside);
+
+ if (cleanup_temps)
+ {
+ if (value_in_thread_stack_temporaries (retval, inferior_ptid))
+ retval = value_non_lval (retval);
+ do_cleanups (cleanups);
+ }
+
+ return retval;
}
\f
/* Parse the string EXP as a C expression, evaluate it,
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index 4fd5f69..c7e258f 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -28,6 +28,7 @@ struct symtab;
#include "ui-out.h"
#include "inferior.h"
#include "btrace.h"
+#include "common/vec.h"
/* Frontend view of the thread state. Possible extensions: stepping,
finishing, until(ling),... */
@@ -152,6 +153,10 @@ struct thread_suspend_state
enum gdb_signal stop_signal;
};
+typedef struct value *value_ptr;
+DEF_VEC_P (value_ptr);
+typedef VEC (value_ptr) value_vec;
+
struct thread_info
{
struct thread_info *next;
@@ -264,6 +269,14 @@ struct thread_info
/* Branch trace information for this thread. */
struct btrace_thread_info btrace;
+
+ /* Flag which indicates that the stack temporaries should be stored while
+ evaluating expressions. */
+ int stack_temporaries_enabled;
+
+ /* Values that are stored as temporaries on stack while evaluating
+ expressions. */
+ value_vec *stack_temporaries;
};
/* Create an empty thread list, or empty the existing one. */
@@ -465,6 +478,16 @@ extern void prune_threads (void);
int pc_in_thread_step_range (CORE_ADDR pc, struct thread_info *thread);
+extern struct cleanup *enable_thread_stack_temporaries (ptid_t ptid);
+
+extern int thread_stack_temporaries_enabled_p (ptid_t ptid);
+
+extern void push_thread_stack_temporary (ptid_t ptid, struct value *v);
+
+extern struct value *get_last_thread_stack_temporary (ptid_t);
+
+extern int value_in_thread_stack_temporaries (struct value *, ptid_t);
+
extern struct thread_info *thread_list;
#endif /* GDBTHREAD_H */
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 61d259d..611a0e7 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -2508,6 +2508,15 @@ is_scalar_type_recursive (struct type *t)
return 0;
}
+/* Return true is T is a class or a union. False otherwise. */
+
+int
+class_or_union_p (const struct type *t)
+{
+ return (TYPE_CODE (t) == TYPE_CODE_STRUCT
+ || TYPE_CODE (t) == TYPE_CODE_UNION);
+}
+
/* A helper function which returns true if types A and B represent the
"same" class type. This is true if the types have the same main
type, or the same name. */
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 14a1f08..a56f543 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1823,6 +1823,8 @@ extern int is_integral_type (struct type *);
extern int is_scalar_type_recursive (struct type *);
+extern int class_or_union_p (const struct type *);
+
extern void maintenance_print_type (char *, int);
extern htab_t create_copied_types_hash (struct objfile *objfile);
diff --git a/gdb/infcall.c b/gdb/infcall.c
index bbac693..718393c 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -495,6 +495,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
ptid_t call_thread_ptid;
struct gdb_exception e;
char name_buf[RAW_FUNCTION_ADDRESS_SIZE];
+ int stack_temporaries = thread_stack_temporaries_enabled_p (inferior_ptid);
if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
@@ -593,6 +594,33 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
If the ABI specifies a "Red Zone" (see the doco) the code
below will quietly trash it. */
sp = old_sp;
+
+ /* Skip over the stack temporaries that might have been generated during
+ the evaluation of an expression. */
+ if (stack_temporaries)
+ {
+ struct value *lastval;
+
+ lastval = get_last_thread_stack_temporary (inferior_ptid);
+ if (lastval != NULL)
+ {
+ CORE_ADDR lastval_addr = value_address (lastval);
+
+ if (gdbarch_inner_than (gdbarch, 1, 2))
+ {
+ gdb_assert (sp >= lastval_addr);
+ sp = lastval_addr;
+ }
+ else
+ {
+ gdb_assert (sp <= lastval_addr);
+ sp = lastval_addr + TYPE_LENGTH (value_type (lastval));
+ }
+
+ if (gdbarch_frame_align_p (gdbarch))
+ sp = gdbarch_frame_align (gdbarch, sp);
+ }
+ }
}
funaddr = find_function_addr (function, &values_type);
@@ -719,9 +747,21 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
/* Reserve space for the return structure to be written on the
stack, if necessary. Make certain that the value is correctly
- aligned. */
+ aligned.
+
+ While evaluating expressions, we reserve space on the stack for
+ return values of class type even if the language ABI and the target
+ ABI do not require that the return value be passed as a hidden first
+ argument. This is because we want to store the return value as an
+ on-stack temporary while the expression is being evaluated. This
+ enables us to have chained function calls in expressions.
- if (struct_return || hidden_first_param_p)
+ Keeping the return values as on-stack temporaries while the expression
+ is being evaluated is OK because the thread is stopped until the
+ expression is completely evaluated. */
+
+ if (struct_return || hidden_first_param_p
+ || (stack_temporaries && class_or_union_p (values_type)))
{
if (gdbarch_inner_than (gdbarch, 1, 2))
{
@@ -1059,31 +1099,40 @@ When the function is done executing, GDB will silently stop."),
At this stage, leave the RETBUF alone. */
restore_infcall_control_state (inf_status);
- /* Figure out the value returned by the function. */
- retval = allocate_value (values_type);
-
- if (hidden_first_param_p)
- read_value_memory (retval, 0, 1, struct_addr,
- value_contents_raw (retval),
- TYPE_LENGTH (values_type));
- else if (TYPE_CODE (target_values_type) != TYPE_CODE_VOID)
+ if (TYPE_CODE (values_type) == TYPE_CODE_VOID)
+ retval = allocate_value (values_type);
+ else if (struct_return || hidden_first_param_p)
{
- /* If the function returns void, don't bother fetching the
- return value. */
- switch (gdbarch_return_value (gdbarch, function, target_values_type,
- NULL, NULL, NULL))
+ if (stack_temporaries)
+ {
+ retval = value_from_contents_and_address (values_type, NULL,
+ struct_addr);
+ push_thread_stack_temporary (inferior_ptid, retval);
+ }
+ else
{
- case RETURN_VALUE_REGISTER_CONVENTION:
- case RETURN_VALUE_ABI_RETURNS_ADDRESS:
- case RETURN_VALUE_ABI_PRESERVES_ADDRESS:
- gdbarch_return_value (gdbarch, function, values_type,
- retbuf, value_contents_raw (retval), NULL);
- break;
- case RETURN_VALUE_STRUCT_CONVENTION:
+ retval = allocate_value (values_type);
read_value_memory (retval, 0, 1, struct_addr,
value_contents_raw (retval),
TYPE_LENGTH (values_type));
- break;
+ }
+ }
+ else
+ {
+ retval = allocate_value (values_type);
+ gdbarch_return_value (gdbarch, function, values_type,
+ retbuf, value_contents_raw (retval), NULL);
+ if (stack_temporaries && class_or_union_p (values_type))
+ {
+ /* Values of class type returned in registers are copied onto
+ the stack and their lval_type set to lval_memory. This is
+ required because further evaluation of the expression
+ could potentially invoke methods on the return value
+ requiring GDB to evaluate the "this" pointer. To evaluate
+ the this pointer, GDB needs the memory address of the
+ value. */
+ value_force_lval (retval, struct_addr);
+ push_thread_stack_temporary (inferior_ptid, retval);
}
}
diff --git a/gdb/testsuite/gdb.cp/chained-calls.cc b/gdb/testsuite/gdb.cp/chained-calls.cc
new file mode 100644
index 0000000..a30ec3b
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/chained-calls.cc
@@ -0,0 +1,203 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 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 S
+{
+public:
+ S () { }
+ S (S &obj);
+
+ S operator+ (const S &s);
+
+ int a;
+};
+
+S::S (S &obj)
+{
+ a = obj.a;
+}
+
+S
+S::operator+ (const S &s)
+{
+ S res;
+
+ res.a = a + s.a;
+
+ return res;
+}
+
+S
+f (int i)
+{
+ S s;
+
+ s.a = i;
+
+ return s;
+}
+
+int
+g (const S &s)
+{
+ return s.a;
+}
+
+class A
+{
+public:
+ A operator+ (const A &);
+ int a;
+};
+
+A
+A::operator+ (const A &obj)
+{
+ A n;
+
+ n.a = a + obj.a;
+
+ return n;
+}
+
+A
+p ()
+{
+ A a;
+ a.a = 12345678;
+ return a;
+}
+
+A
+r ()
+{
+ A a;
+ a.a = 10000000;
+ return a;
+}
+
+A
+q (const A &a)
+{
+ return a;
+}
+
+class B
+{
+public:
+ int b[1024];
+};
+
+B
+makeb ()
+{
+ B b;
+ int i;
+
+ for (i = 0; i < 1024; i++)
+ b.b[i] = i;
+
+ return b;
+}
+
+int
+getb (const B &b, int i)
+{
+ return b.b[i];
+}
+
+class C
+{
+public:
+ C ();
+ ~C ();
+
+ A operator* ();
+
+ A *a_ptr;
+};
+
+C::C ()
+{
+ a_ptr = new A;
+ a_ptr->a = 5678;
+}
+
+C::~C ()
+{
+ delete a_ptr;
+}
+
+A
+C::operator* ()
+{
+ return *a_ptr;
+}
+
+#define TYPE_INDEX 1
+
+enum type
+{
+ INT,
+ CHAR
+};
+
+union U
+{
+public:
+ U (type t);
+ type get_type ();
+
+ int a;
+ char c;
+ type tp[2];
+};
+
+U::U (type t)
+{
+ tp[TYPE_INDEX] = t;
+}
+
+U
+make_int ()
+{
+ return U (INT);
+}
+
+U
+make_char ()
+{
+ return U (CHAR);
+}
+
+type
+U::get_type ()
+{
+ return tp[TYPE_INDEX];
+}
+
+int
+main ()
+{
+ int i = g(f(0));
+ A a = q(p() + r());
+
+ B b = makeb ();
+ C c;
+
+ return i + getb(b, 0); /* Break here */
+}
diff --git a/gdb/testsuite/gdb.cp/chained-calls.exp b/gdb/testsuite/gdb.cp/chained-calls.exp
new file mode 100644
index 0000000..c903bea
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/chained-calls.exp
@@ -0,0 +1,44 @@
+# Copyright 2014 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/>.
+
+# This file is part of the gdb testsuite
+
+if {[skip_cplus_tests]} { continue }
+
+standard_testfile .cc
+
+if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} {
+ return -1
+}
+
+if {![runto_main]} {
+ return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "Break here"]
+gdb_continue_to_breakpoint "Break here"
+
+gdb_test "p g(f(12345))" ".* = 12345" "g(f())"
+gdb_test "p q(p())" ".* = {a = 12345678}" "q(p())"
+gdb_test "p p() + r()" ".* = {a = 22345678}" "p() + r()"
+gdb_test "p q(p() + r())" ".* = {a = 22345678}" "q(p() + r())"
+gdb_test "p g(f(6700) + f(89))" ".* = 6789" "g(f() + f())"
+gdb_test "p g(f(g(f(300) + f(40))) + f(5))" ".* = 345" \
+ "g(f(g(f() + f())) + f())"
+gdb_test "p getb(makeb(), 789)" ".* = 789" "getb(makeb(), ...)"
+gdb_test "p *c" ".* = {a = 5678}" "*c"
+gdb_test "p *c + *c" ".* = {a = 11356}" "*c + *c"
+gdb_test "P q(*c + *c)" ".* = {a = 11356}" "q(*c + *c)"
+gdb_test "p make_int().get_type ()" ".* = INT" "make_int().get_type ()"
diff --git a/gdb/testsuite/gdb.cp/smartp.exp b/gdb/testsuite/gdb.cp/smartp.exp
index 2a1028a..e3d271f 100644
--- a/gdb/testsuite/gdb.cp/smartp.exp
+++ b/gdb/testsuite/gdb.cp/smartp.exp
@@ -72,6 +72,5 @@ gdb_test "p b->foo()" "= 66"
gdb_test "p c->foo()" "= 66"
gdb_test "p c->inta" "= 77"
-setup_kfail "gdb/11606" "*-*-*"
gdb_test "p c2->inta" "= 77"
diff --git a/gdb/thread.c b/gdb/thread.c
index 5c94264..a55a47a 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -636,6 +636,109 @@ prune_threads (void)
}
}
+/* Disable storing stack temporaries for the thread whose id is
+ stored in DATA. */
+
+static void
+disable_thread_stack_temporaries (void *data)
+{
+ ptid_t *pd = data;
+ struct thread_info *tp = find_thread_ptid (*pd);
+
+ if (tp != NULL)
+ {
+ tp->stack_temporaries_enabled = 0;
+ VEC_free (value_ptr, tp->stack_temporaries);
+ }
+
+ xfree (pd);
+}
+
+/* Enable storing stack temporaries for thread with id PTID and return a
+ cleanup which can disable and clear the stack temporaries. */
+
+struct cleanup *
+enable_thread_stack_temporaries (ptid_t ptid)
+{
+ struct thread_info *tp = find_thread_ptid (ptid);
+ ptid_t *data;
+ struct cleanup *c;
+
+ gdb_assert (tp != NULL);
+
+ tp->stack_temporaries_enabled = 1;
+ tp->stack_temporaries = NULL;
+ data = (ptid_t *) xmalloc (sizeof (ptid_t));
+ *data = ptid;
+ c = make_cleanup (disable_thread_stack_temporaries, data);
+
+ return c;
+}
+
+/* Return non-zero value if stack temporaies are enabled for the thread
+ with id PTID. */
+
+int
+thread_stack_temporaries_enabled_p (ptid_t ptid)
+{
+ struct thread_info *tp = find_thread_ptid (ptid);
+
+ if (tp == NULL)
+ return 0;
+ else
+ return tp->stack_temporaries_enabled;
+}
+
+/* Push V on to the stack temporaries of the thread with id PTID. */
+
+void
+push_thread_stack_temporary (ptid_t ptid, struct value *v)
+{
+ struct thread_info *tp = find_thread_ptid (ptid);
+
+ gdb_assert (tp != NULL && tp->stack_temporaries_enabled);
+ VEC_safe_push (value_ptr, tp->stack_temporaries, v);
+}
+
+/* Return 1 if VAL is among the stack temporaries of the thread
+ with id PTID. Return 0 otherwise. */
+
+int
+value_in_thread_stack_temporaries (struct value *val, ptid_t ptid)
+{
+ struct thread_info *tp = find_thread_ptid (ptid);
+
+ gdb_assert (tp != NULL && tp->stack_temporaries_enabled);
+ if (!VEC_empty (value_ptr, tp->stack_temporaries))
+ {
+ struct value *v;
+ int i;
+
+ for (i = 0; VEC_iterate (value_ptr, tp->stack_temporaries, i, v); i++)
+ if (v == val)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Return an address after skipping over the current stack temporaries
+ of thread with id PTID. SP is the current stack frame pointer. Non-zero
+ DOWNWARD indicates that the stack grows downwards/backwards. */
+
+struct value *
+get_last_thread_stack_temporary (ptid_t ptid)
+{
+ struct value *lastval = NULL;
+ struct thread_info *tp = find_thread_ptid (ptid);
+
+ gdb_assert (tp != NULL);
+ if (!VEC_empty (value_ptr, tp->stack_temporaries))
+ lastval = VEC_last (value_ptr, tp->stack_temporaries);
+
+ return lastval;
+}
+
void
thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid)
{
diff --git a/gdb/value.c b/gdb/value.c
index ecfb154..3a9c3a9 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1724,6 +1724,18 @@ value_non_lval (struct value *arg)
return arg;
}
+/* Write contents of V at ADDR and set its lval type to be LVAL_MEMORY. */
+
+void
+value_force_lval (struct value *v, CORE_ADDR addr)
+{
+ gdb_assert (VALUE_LVAL (v) == not_lval);
+
+ write_memory (addr, value_contents_raw (v), TYPE_LENGTH (value_type (v)));
+ v->lval = lval_memory;
+ v->location.address = addr;
+}
+
void
set_value_component_location (struct value *component,
const struct value *whole)
diff --git a/gdb/value.h b/gdb/value.h
index e3603c3..a8c33fb 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -1038,6 +1038,8 @@ extern struct value *value_copy (struct value *);
extern struct value *value_non_lval (struct value *);
+extern void value_force_lval (struct value *, CORE_ADDR);
+
extern void preserve_one_value (struct value *, struct objfile *, htab_t);
/* From valops.c */
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6] Make chained function calls in expressions work
2014-11-27 6:55 [PATCH v6] Make chained function calls in expressions work Siva Chandra
@ 2014-11-28 12:10 ` Ulrich Weigand
2014-11-29 0:04 ` Siva Chandra
0 siblings, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2014-11-28 12:10 UTC (permalink / raw)
To: Siva Chandra; +Cc: gdb-patches
Siva Chandra wrote:
> gdb/ChangeLog:
>
> 2014-11-27 Siva Chandra Reddy <sivachandra@google.com>
>
> * eval.c: Include gdbthread.h.
> (evaluate_subexp): Enable thread stack temporaries before
> evaluating a complete expression and clean them up after the
> evaluation is complete.
> * gdbthread.h: Include common/vec.h.
> (value_ptr): New typedef.
> (VEC (value_ptr)): New vector type.
> (value_vec): New typedef.
> (struct thread_info): Add new fields stack_temporaries_enabled
> and stack_temporaries.
> (enable_thread_stack_temporaries)
> (thread_stack_temporaries_enabled_p, push_thread_stack_temporary)
> (get_last_thread_stack_temporary)
> (value_in_thread_stack_temporaries): Declare.
> * gdbtypes.c (class_or_union_p): New function.
> * gdbtypes.h (class_or_union_p): Declare.
> * infcall.c (call_function_by_hand): Store return values of class
> type as temporaries on stack.
> * thread.c (enable_thread_stack_temporaries): New function.
> (thread_stack_temporaries_enabled_p, push_thread_stack_temporary)
> (get_last_thread_stack_temporary): Likewise.
> (value_in_thread_stack_temporaries): Likewise.
> * value.c (value_force_lval): New function.
> * value.h (value_force_lval): Declare.
>
> gdb/testsuite/ChangeLog:
>
> 2014-11-27 Siva Chandra Reddy <sivachandra@google.com>
>
> * gdb.cp/chained-calls.cc: New file.
> * gdb.cp/chained-calls.exp: New file.
> * gdb.cp/smartp.exp: Remove KFAIL for "p c2->inta".
This is OK.
Thanks for you patience in working through the many iterations on this patch!
One final nit:
>+/* Return an address after skipping over the current stack temporaries
>+ of thread with id PTID. SP is the current stack frame pointer. Non-zero
>+ DOWNWARD indicates that the stack grows downwards/backwards. */
>+
>+struct value *
>+get_last_thread_stack_temporary (ptid_t ptid)
Comment no longer fits the new semantics of the function.
Thanks,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6] Make chained function calls in expressions work
2014-11-28 12:10 ` Ulrich Weigand
@ 2014-11-29 0:04 ` Siva Chandra
2014-11-29 8:26 ` Regression for gdb.cp/exceptprint.exp [Re: [PATCH v6] Make chained function calls in expressions work] Jan Kratochvil
0 siblings, 1 reply; 8+ messages in thread
From: Siva Chandra @ 2014-11-29 0:04 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: gdb-patches
On Fri, Nov 28, 2014 at 4:10 AM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
> Siva Chandra wrote:
>
>> gdb/ChangeLog:
>>
>> 2014-11-27 Siva Chandra Reddy <sivachandra@google.com>
>>
>> * eval.c: Include gdbthread.h.
>> (evaluate_subexp): Enable thread stack temporaries before
>> evaluating a complete expression and clean them up after the
>> evaluation is complete.
>> * gdbthread.h: Include common/vec.h.
>> (value_ptr): New typedef.
>> (VEC (value_ptr)): New vector type.
>> (value_vec): New typedef.
>> (struct thread_info): Add new fields stack_temporaries_enabled
>> and stack_temporaries.
>> (enable_thread_stack_temporaries)
>> (thread_stack_temporaries_enabled_p, push_thread_stack_temporary)
>> (get_last_thread_stack_temporary)
>> (value_in_thread_stack_temporaries): Declare.
>> * gdbtypes.c (class_or_union_p): New function.
>> * gdbtypes.h (class_or_union_p): Declare.
>> * infcall.c (call_function_by_hand): Store return values of class
>> type as temporaries on stack.
>> * thread.c (enable_thread_stack_temporaries): New function.
>> (thread_stack_temporaries_enabled_p, push_thread_stack_temporary)
>> (get_last_thread_stack_temporary): Likewise.
>> (value_in_thread_stack_temporaries): Likewise.
>> * value.c (value_force_lval): New function.
>> * value.h (value_force_lval): Declare.
>>
>> gdb/testsuite/ChangeLog:
>>
>> 2014-11-27 Siva Chandra Reddy <sivachandra@google.com>
>>
>> * gdb.cp/chained-calls.cc: New file.
>> * gdb.cp/chained-calls.exp: New file.
>> * gdb.cp/smartp.exp: Remove KFAIL for "p c2->inta".
>
> This is OK.
>
> Thanks for you patience in working through the many iterations on this patch!
Thanks for your patience with explaining things to me. I have now
pushed this patch after fixing the one comment:
6c659fc2c7cd2da6d2b9a3d7c38597ad3821832a
^ permalink raw reply [flat|nested] 8+ messages in thread
* Regression for gdb.cp/exceptprint.exp [Re: [PATCH v6] Make chained function calls in expressions work]
2014-11-29 0:04 ` Siva Chandra
@ 2014-11-29 8:26 ` Jan Kratochvil
2014-11-29 8:59 ` Siva Chandra
2014-11-29 10:16 ` Siva Chandra
0 siblings, 2 replies; 8+ messages in thread
From: Jan Kratochvil @ 2014-11-29 8:26 UTC (permalink / raw)
To: Siva Chandra; +Cc: Ulrich Weigand, gdb-patches
On Sat, 29 Nov 2014 01:03:57 +0100, Siva Chandra wrote:
> I have now pushed this patch
[bash]jkratoch@MOCK-fedora-21-x86_64:/home/jkratoch/redhat/gdb-clean/gdb/testsuite# git log
commit 6c659fc2c7cd2da6d2b9a3d7c38597ad3821832a
Author: Siva Chandra <sivachandra@chromium.org>
Date: Tue Nov 11 05:43:03 2014 -0800
Enable chained function calls in C++ expressions.
On Fedora 21 x86_64 and x86_64-m32 (i686 not tested due to some unrelated
regression).
print $_exception^M
-$1 = 0x400b10 "hi bob"^M
-(gdb) PASS: gdb.cp/exceptprint.exp: string: print exception value at throw
-continue^M
+thread.c:711: internal-error: value_in_thread_stack_temporaries: Assertion `tp != NULL && tp->stack_temporaries_enabled' failed.^M
+A problem internal to GDB has been detected,^M
+further debugging may prove unreliable.^M
Running gdb/testsuite/gdb.cp/exceptprint.exp ...
-PASS: gdb.cp/exceptprint.exp: string: print exception value at throw
+FAIL: gdb.cp/exceptprint.exp: string: print exception value at throw (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: string: print exception value at catch
+FAIL: gdb.cp/exceptprint.exp: string: print exception value at catch (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: string: print exception value at rethrow
+FAIL: gdb.cp/exceptprint.exp: string: print exception value at rethrow (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: int: print exception value at throw
+FAIL: gdb.cp/exceptprint.exp: int: print exception value at throw (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: int: print exception value at catch
+FAIL: gdb.cp/exceptprint.exp: int: print exception value at catch (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: int: print exception value at rethrow
+FAIL: gdb.cp/exceptprint.exp: int: print exception value at rethrow (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: struct: print exception value at throw
+FAIL: gdb.cp/exceptprint.exp: struct: print exception value at throw (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: struct: print exception value at catch
+FAIL: gdb.cp/exceptprint.exp: struct: print exception value at catch (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: struct: print exception value at rethrow
+FAIL: gdb.cp/exceptprint.exp: struct: print exception value at rethrow (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: reference to struct: print exception value at throw
+FAIL: gdb.cp/exceptprint.exp: reference to struct: print exception value at throw (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: reference to struct: print exception value at catch
+FAIL: gdb.cp/exceptprint.exp: reference to struct: print exception value at catch (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: reference to struct: print exception value at rethrow
+FAIL: gdb.cp/exceptprint.exp: reference to struct: print exception value at rethrow (GDB internal error)
-PASS: gdb.cp/exceptprint.exp: int: continue to throw
-PASS: gdb.cp/exceptprint.exp: int: print exception value at throw
-PASS: gdb.cp/exceptprint.exp: int: continue to catch
-PASS: gdb.cp/exceptprint.exp: int: print exception value at catch
-PASS: gdb.cp/exceptprint.exp: int: continue to rethrow
-PASS: gdb.cp/exceptprint.exp: int: print exception value at rethrow
-PASS: gdb.cp/exceptprint.exp: int: continue to final catch
+FAIL: gdb.cp/exceptprint.exp: int: continue to throw (GDB internal error)
+FAIL: gdb.cp/exceptprint.exp: int: print exception value at throw (GDB internal error)
+FAIL: gdb.cp/exceptprint.exp: int: continue to catch (GDB internal error)
+FAIL: gdb.cp/exceptprint.exp: int: print exception value at catch (GDB internal error)
+FAIL: gdb.cp/exceptprint.exp: int: continue to rethrow (GDB internal error)
+FAIL: gdb.cp/exceptprint.exp: int: print exception value at rethrow (GDB internal error)
+FAIL: gdb.cp/exceptprint.exp: int: continue to final catch (GDB internal error)
Jan
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Regression for gdb.cp/exceptprint.exp [Re: [PATCH v6] Make chained function calls in expressions work]
2014-11-29 8:26 ` Regression for gdb.cp/exceptprint.exp [Re: [PATCH v6] Make chained function calls in expressions work] Jan Kratochvil
@ 2014-11-29 8:59 ` Siva Chandra
2014-11-29 9:13 ` Jan Kratochvil
2014-11-29 10:16 ` Siva Chandra
1 sibling, 1 reply; 8+ messages in thread
From: Siva Chandra @ 2014-11-29 8:59 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: Ulrich Weigand, gdb-patches
I did not see this because this happens for me:
Running ../../../gdb_git/gdb/testsuite/gdb.cp/exceptprint.exp ...
UNTESTED: gdb.cp/exceptprint.exp: could not find libstdc++ stap probe
Any idea how to enable this test?
On Sat, Nov 29, 2014 at 12:26 AM, Jan Kratochvil
<jan.kratochvil@redhat.com> wrote:
> On Sat, 29 Nov 2014 01:03:57 +0100, Siva Chandra wrote:
>> I have now pushed this patch
>
> [bash]jkratoch@MOCK-fedora-21-x86_64:/home/jkratoch/redhat/gdb-clean/gdb/testsuite# git log
> commit 6c659fc2c7cd2da6d2b9a3d7c38597ad3821832a
> Author: Siva Chandra <sivachandra@chromium.org>
> Date: Tue Nov 11 05:43:03 2014 -0800
> Enable chained function calls in C++ expressions.
>
> On Fedora 21 x86_64 and x86_64-m32 (i686 not tested due to some unrelated
> regression).
>
> print $_exception^M
> -$1 = 0x400b10 "hi bob"^M
> -(gdb) PASS: gdb.cp/exceptprint.exp: string: print exception value at throw
> -continue^M
> +thread.c:711: internal-error: value_in_thread_stack_temporaries: Assertion `tp != NULL && tp->stack_temporaries_enabled' failed.^M
> +A problem internal to GDB has been detected,^M
> +further debugging may prove unreliable.^M
>
> Running gdb/testsuite/gdb.cp/exceptprint.exp ...
> -PASS: gdb.cp/exceptprint.exp: string: print exception value at throw
> +FAIL: gdb.cp/exceptprint.exp: string: print exception value at throw (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: string: print exception value at catch
> +FAIL: gdb.cp/exceptprint.exp: string: print exception value at catch (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: string: print exception value at rethrow
> +FAIL: gdb.cp/exceptprint.exp: string: print exception value at rethrow (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: int: print exception value at throw
> +FAIL: gdb.cp/exceptprint.exp: int: print exception value at throw (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: int: print exception value at catch
> +FAIL: gdb.cp/exceptprint.exp: int: print exception value at catch (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: int: print exception value at rethrow
> +FAIL: gdb.cp/exceptprint.exp: int: print exception value at rethrow (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: struct: print exception value at throw
> +FAIL: gdb.cp/exceptprint.exp: struct: print exception value at throw (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: struct: print exception value at catch
> +FAIL: gdb.cp/exceptprint.exp: struct: print exception value at catch (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: struct: print exception value at rethrow
> +FAIL: gdb.cp/exceptprint.exp: struct: print exception value at rethrow (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: reference to struct: print exception value at throw
> +FAIL: gdb.cp/exceptprint.exp: reference to struct: print exception value at throw (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: reference to struct: print exception value at catch
> +FAIL: gdb.cp/exceptprint.exp: reference to struct: print exception value at catch (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: reference to struct: print exception value at rethrow
> +FAIL: gdb.cp/exceptprint.exp: reference to struct: print exception value at rethrow (GDB internal error)
> -PASS: gdb.cp/exceptprint.exp: int: continue to throw
> -PASS: gdb.cp/exceptprint.exp: int: print exception value at throw
> -PASS: gdb.cp/exceptprint.exp: int: continue to catch
> -PASS: gdb.cp/exceptprint.exp: int: print exception value at catch
> -PASS: gdb.cp/exceptprint.exp: int: continue to rethrow
> -PASS: gdb.cp/exceptprint.exp: int: print exception value at rethrow
> -PASS: gdb.cp/exceptprint.exp: int: continue to final catch
> +FAIL: gdb.cp/exceptprint.exp: int: continue to throw (GDB internal error)
> +FAIL: gdb.cp/exceptprint.exp: int: print exception value at throw (GDB internal error)
> +FAIL: gdb.cp/exceptprint.exp: int: continue to catch (GDB internal error)
> +FAIL: gdb.cp/exceptprint.exp: int: print exception value at catch (GDB internal error)
> +FAIL: gdb.cp/exceptprint.exp: int: continue to rethrow (GDB internal error)
> +FAIL: gdb.cp/exceptprint.exp: int: print exception value at rethrow (GDB internal error)
> +FAIL: gdb.cp/exceptprint.exp: int: continue to final catch (GDB internal error)
>
>
>
> Jan
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Regression for gdb.cp/exceptprint.exp [Re: [PATCH v6] Make chained function calls in expressions work]
2014-11-29 8:59 ` Siva Chandra
@ 2014-11-29 9:13 ` Jan Kratochvil
0 siblings, 0 replies; 8+ messages in thread
From: Jan Kratochvil @ 2014-11-29 9:13 UTC (permalink / raw)
To: Siva Chandra; +Cc: Ulrich Weigand, gdb-patches
On Sat, 29 Nov 2014 09:58:54 +0100, Siva Chandra wrote:
> I did not see this because this happens for me:
>
> Running ../../../gdb_git/gdb/testsuite/gdb.cp/exceptprint.exp ...
> UNTESTED: gdb.cp/exceptprint.exp: could not find libstdc++ stap probe
>
> Any idea how to enable this test?
The most simple way is IMO to run Fedora 20 x86_64 in a VM; I expect you are
probably using Google/Ubuntu which I have no idea whether/when it will provide
the probes.
One needs:
readelf -n /lib64/libstdc++.so.6
Owner Data size Description
stapsdt 0x0000003b NT_STAPSDT (SystemTap probe descriptors)
Provider: libstdcxx
Name: catch
Location: 0x000000000005dd71, Base: 0x00000000000c8f10, Semaphore: 0x0000000000000000
Arguments: 8@%rax 8@-80(%rbx)
[...]
Which was checked in upstream by:
commit 88ed757eef4cad9f5f67123f948707ddfc0e7635
Author: jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Fri Mar 15 08:55:07 2013 +0000
* libsupc++/unwind-cxx.h: Include sys/sdt.h if detected.
(PROBE2): New macro.
* libsupc++/eh_throw.cc (__cxa_throw, __cxa_rethrow): Add probe.
* libsupc++/eh_catch.cc (__cxa_begin_catch): Add probe.
* configure.ac: Check for sys/sdt.h.
* configure, config.h.in: Rebuild.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@196674 138bc75d-0d04-0410-961f-82ee72b054a4
Thanks,
Jan
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Regression for gdb.cp/exceptprint.exp [Re: [PATCH v6] Make chained function calls in expressions work]
2014-11-29 8:26 ` Regression for gdb.cp/exceptprint.exp [Re: [PATCH v6] Make chained function calls in expressions work] Jan Kratochvil
2014-11-29 8:59 ` Siva Chandra
@ 2014-11-29 10:16 ` Siva Chandra
2014-11-29 12:38 ` Jan Kratochvil
1 sibling, 1 reply; 8+ messages in thread
From: Siva Chandra @ 2014-11-29 10:16 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: Ulrich Weigand, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1306 bytes --]
On Sat, Nov 29, 2014 at 12:26 AM, Jan Kratochvil
<jan.kratochvil@redhat.com> wrote:
> On Sat, 29 Nov 2014 01:03:57 +0100, Siva Chandra wrote:
>> I have now pushed this patch
>
> [bash]jkratoch@MOCK-fedora-21-x86_64:/home/jkratoch/redhat/gdb-clean/gdb/testsuite# git log
> commit 6c659fc2c7cd2da6d2b9a3d7c38597ad3821832a
> Author: Siva Chandra <sivachandra@chromium.org>
> Date: Tue Nov 11 05:43:03 2014 -0800
> Enable chained function calls in C++ expressions.
>
> On Fedora 21 x86_64 and x86_64-m32 (i686 not tested due to some unrelated
> regression).
>
> print $_exception^M
> -$1 = 0x400b10 "hi bob"^M
> -(gdb) PASS: gdb.cp/exceptprint.exp: string: print exception value at throw
> -continue^M
> +thread.c:711: internal-error: value_in_thread_stack_temporaries: Assertion `tp != NULL && tp->stack_temporaries_enabled' failed.^M
> +A problem internal to GDB has been detected,^M
> +further debugging may prove unreliable.^M
What my patch did was to make evaluate_subexp non re-entrant. As in,
if evaluate_subexp is called with *pos == 0 while a top level
expression is under evaluation, then it will crash with symptoms
similar to the above. While I setup my VM/fedora box, can I ask you to
test the attached patch which should fix this (and hopefully fix the
regression)?
Thanks,
Siva Chandra
[-- Attachment #2: quick_fix.txt --]
[-- Type: text/plain, Size: 539 bytes --]
diff --git a/gdb/eval.c b/gdb/eval.c
index a13793c..c2ab879 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -69,7 +69,8 @@ evaluate_subexp (struct type *expect_type, struct expression *exp,
int cleanup_temps = 0;
if (*pos == 0 && target_has_execution
- && exp->language_defn->la_language == language_cplus)
+ && exp->language_defn->la_language == language_cplus
+ && !thread_stack_temporaries_enabled_p (inferior_ptid))
{
cleanups = enable_thread_stack_temporaries (inferior_ptid);
cleanup_temps = 1;
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Regression for gdb.cp/exceptprint.exp [Re: [PATCH v6] Make chained function calls in expressions work]
2014-11-29 10:16 ` Siva Chandra
@ 2014-11-29 12:38 ` Jan Kratochvil
0 siblings, 0 replies; 8+ messages in thread
From: Jan Kratochvil @ 2014-11-29 12:38 UTC (permalink / raw)
To: Siva Chandra; +Cc: Ulrich Weigand, gdb-patches
On Sat, 29 Nov 2014 11:16:08 +0100, Siva Chandra wrote:
> can I ask you to test the attached patch which should fix this (and
> hopefully fix the regression)?
Confirming it fixes the regression on
{x86_64,x86_64-m32,i686}-fedora21-linux-gnu and I see no other regressions
there.
Thanks,
Jan
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2014-11-29 12:38 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-27 6:55 [PATCH v6] Make chained function calls in expressions work Siva Chandra
2014-11-28 12:10 ` Ulrich Weigand
2014-11-29 0:04 ` Siva Chandra
2014-11-29 8:26 ` Regression for gdb.cp/exceptprint.exp [Re: [PATCH v6] Make chained function calls in expressions work] Jan Kratochvil
2014-11-29 8:59 ` Siva Chandra
2014-11-29 9:13 ` Jan Kratochvil
2014-11-29 10:16 ` Siva Chandra
2014-11-29 12:38 ` Jan Kratochvil
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).