forked from Imagelibrary/binutils-gdb
MI: Allow non-raw varobj evaluation
Make the MI variable object expression evaluation, with the
-var-evaluate-expression command, recursively call pretty printers, to
match the output of normal expression printing.
Consider the following code:
struct Foo { int val; };
struct Wrapper { Foo foo; };
int main() {
Wrapper w;
w.foo.val = 23;
}
and this pretty printer file:
import gdb.printing
class FooPrinter:
def __init__(self, val):
self.val = val
def to_string(self):
return "Foo" + str(self.val["val"])
class WrapperPrinter:
def __init__(self, val):
self.val = val
def to_string(self):
return self.val["foo"]
test_printer = gdb.printing.RegexpCollectionPrettyPrinter("test")
test_printer.add_printer('Foo', '^Foo$', FooPrinter)
test_printer.add_printer('Wrapper', '^Wrapper$', WrapperPrinter)
gdb.printing.register_pretty_printer(None, test_printer)
Setting a breakpoint at the end of the function, we call the following commands:
-enable-pretty-printing
^done
-var-create var_w @ w
^done,name="var_w",numchild="0",value="{val = 23}",type="Wrapper",dynamic="1",has_more="0"
-var-create var_w_foo @ w.foo
^done,name="var_w_foo",numchild="0",value="Foo23",type="Foo",dynamic="1",has_more="0"
-var-evaluate-expression var_w
^done,value="{val = 23}"
-var-evaluate-expression var_w_foo
^done,value="Foo23"
-data-evaluate-expression w
^done,value="Foo23"
-data-evaluate-expression w.foo
^done,value="Foo23"
So, in the -var-evaluate-expression var_w case, we print the "raw" value
of w.foo, while in the -data-evaluate-expression w case, we print the
pretty printed w.foo value. After this patch, all of the above print
"Foo23".
gdb/ChangeLog:
* varobj.c (varobj_formatted_print_options): Allow recursive
pretty printing if pretty printing is enabled.
gdb/testsuite/ChangeLog:
* gdb.python/py-prettyprint.c
(struct to_string_returns_value_inner,
struct to_string_returns_value_wrapper): New.
(main): Add tsrvw variable.
* gdb.python/py-prettyprint.py (ToStringReturnsValueInner,
ToStringReturnsValueWrapper): New classes.
(register_pretty_printers): Register new pretty-printers.
* gdb.python/py-prettyprint.exp (run_lang_tests): Test printing
recursive pretty printer.
* gdb.python/py-mi.exp: Likewise.
This commit is contained in:
committed by
Simon Marchi
parent
5bb0830d10
commit
0625771b9e
@@ -1,3 +1,8 @@
|
|||||||
|
2018-02-01 Leszek Swirski <leszeks@google.com>
|
||||||
|
|
||||||
|
* varobj.c (varobj_formatted_print_options): Allow recursive
|
||||||
|
pretty printing if pretty printing is enabled.
|
||||||
|
|
||||||
2018-02-01 Leszek Swirski <leszeks@google.com>
|
2018-02-01 Leszek Swirski <leszeks@google.com>
|
||||||
|
|
||||||
* c-exp.y (lex_one_token, classify_name, yylex): Don't classify
|
* c-exp.y (lex_one_token, classify_name, yylex): Don't classify
|
||||||
|
|||||||
@@ -1,3 +1,17 @@
|
|||||||
|
2018-02-01 Simon Marchi <simon.marchi@polymtl.ca>
|
||||||
|
Leszek Swirski <leszeks@google.com>
|
||||||
|
|
||||||
|
* gdb.python/py-prettyprint.c
|
||||||
|
(struct to_string_returns_value_inner,
|
||||||
|
struct to_string_returns_value_wrapper): New.
|
||||||
|
(main): Add tsrvw variable.
|
||||||
|
* gdb.python/py-prettyprint.py (ToStringReturnsValueInner,
|
||||||
|
ToStringReturnsValueWrapper): New classes.
|
||||||
|
(register_pretty_printers): Register new pretty-printers.
|
||||||
|
* gdb.python/py-prettyprint.exp (run_lang_tests): Test printing
|
||||||
|
recursive pretty printer.
|
||||||
|
* gdb.python/py-mi.exp: Likewise.
|
||||||
|
|
||||||
2018-02-01 Leszek Swirski <leszeks@google.com>
|
2018-02-01 Leszek Swirski <leszeks@google.com>
|
||||||
|
|
||||||
* gdb.cp/filename.cc, gdb.cp/filename.exp: Test that member
|
* gdb.cp/filename.cc, gdb.cp/filename.exp: Test that member
|
||||||
|
|||||||
@@ -295,6 +295,16 @@ mi_gdb_test "-var-evaluate-expression me" \
|
|||||||
mi_create_dynamic_varobj children_as_list children_as_list 1 \
|
mi_create_dynamic_varobj children_as_list children_as_list 1 \
|
||||||
"printer whose children are returned as a list"
|
"printer whose children are returned as a list"
|
||||||
|
|
||||||
|
# Test that when a pretty-printer returns a gdb.Value in its to_string, we call
|
||||||
|
# the pretty-printer of that value too.
|
||||||
|
mi_create_varobj_checked tsrvw tsrvw \
|
||||||
|
"struct to_string_returns_value_wrapper" \
|
||||||
|
"create tsrvw varobj"
|
||||||
|
mi_check_varobj_value tsrvw "Inner to_string 1989" "check tsrvw varobj value"
|
||||||
|
mi_gdb_test "-data-evaluate-expression tsrvw" \
|
||||||
|
"\\^done,value=\"Inner to_string 1989\"" \
|
||||||
|
"check tsrvw expression value"
|
||||||
|
|
||||||
# Regression test for bug 14741.
|
# Regression test for bug 14741.
|
||||||
mi_continue_to_line \
|
mi_continue_to_line \
|
||||||
[gdb_get_line_number {breakpoint bug 14741} ${srcfile}] \
|
[gdb_get_line_number {breakpoint bug 14741} ${srcfile}] \
|
||||||
|
|||||||
@@ -112,6 +112,16 @@ class Fake
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct to_string_returns_value_inner
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct to_string_returns_value_wrapper
|
||||||
|
{
|
||||||
|
struct to_string_returns_value_inner inner;
|
||||||
|
};
|
||||||
|
|
||||||
struct substruct {
|
struct substruct {
|
||||||
int a;
|
int a;
|
||||||
int b;
|
int b;
|
||||||
@@ -284,6 +294,7 @@ main ()
|
|||||||
struct lazystring estring, estring2, estring3;
|
struct lazystring estring, estring2, estring3;
|
||||||
struct hint_error hint_error;
|
struct hint_error hint_error;
|
||||||
struct children_as_list children_as_list;
|
struct children_as_list children_as_list;
|
||||||
|
struct to_string_returns_value_wrapper tsrvw = { { 1989 } };
|
||||||
|
|
||||||
nstype.elements = narray;
|
nstype.elements = narray;
|
||||||
nstype.len = 0;
|
nstype.len = 0;
|
||||||
|
|||||||
@@ -64,6 +64,10 @@ proc run_lang_tests {exefile lang} {
|
|||||||
|
|
||||||
gdb_test "print arraystruct" " = {$nl *y = 7, *$nl *x = { a=<23> b=<$hex>, a=<24> b=<$hex>} *$nl *}"
|
gdb_test "print arraystruct" " = {$nl *y = 7, *$nl *x = { a=<23> b=<$hex>, a=<24> b=<$hex>} *$nl *}"
|
||||||
|
|
||||||
|
# Test that when a pretty-printer returns a gdb.Value in its to_string, we
|
||||||
|
# call the pretty-printer of that value too.
|
||||||
|
gdb_test "print tsrvw" " = Inner to_string 1989"
|
||||||
|
|
||||||
if {$lang == "c++"} {
|
if {$lang == "c++"} {
|
||||||
gdb_test "print cps" "= a=<8> b=<$hex>"
|
gdb_test "print cps" "= a=<8> b=<$hex>"
|
||||||
gdb_test "print cpss" " = {$nl *zss = 9, *$nl *s = a=<10> b=<$hex>$nl}"
|
gdb_test "print cpss" " = {$nl *zss = 9, *$nl *s = a=<10> b=<$hex>$nl}"
|
||||||
|
|||||||
@@ -84,6 +84,25 @@ class NoStringContainerPrinter (object):
|
|||||||
def children(self):
|
def children(self):
|
||||||
return _iterator_except (self.val['elements'], self.val['len'])
|
return _iterator_except (self.val['elements'], self.val['len'])
|
||||||
|
|
||||||
|
# See ToStringReturnsValueWrapper.
|
||||||
|
class ToStringReturnsValueInner:
|
||||||
|
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
return 'Inner to_string {}'.format(int(self.val['val']))
|
||||||
|
|
||||||
|
# Test a printer that returns a gdb.Value in its to_string. That gdb.Value
|
||||||
|
# also has its own pretty-printer.
|
||||||
|
class ToStringReturnsValueWrapper:
|
||||||
|
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
return self.val['inner']
|
||||||
|
|
||||||
class pp_s (object):
|
class pp_s (object):
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.val = val
|
self.val = val
|
||||||
@@ -317,6 +336,11 @@ def register_pretty_printers ():
|
|||||||
pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
|
pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
|
||||||
pretty_printers_dict[re.compile ('^justchildren$')] = NoStringContainerPrinter
|
pretty_printers_dict[re.compile ('^justchildren$')] = NoStringContainerPrinter
|
||||||
|
|
||||||
|
pretty_printers_dict[re.compile ('^struct to_string_returns_value_inner$')] = ToStringReturnsValueInner
|
||||||
|
pretty_printers_dict[re.compile ('^to_string_returns_value_inner$')] = ToStringReturnsValueInner
|
||||||
|
pretty_printers_dict[re.compile ('^struct to_string_returns_value_wrapper$')] = ToStringReturnsValueWrapper
|
||||||
|
pretty_printers_dict[re.compile ('^to_string_returns_value_wrapper$')] = ToStringReturnsValueWrapper
|
||||||
|
|
||||||
pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns
|
pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns
|
||||||
pretty_printers_dict[re.compile ('^ns$')] = pp_ns
|
pretty_printers_dict[re.compile ('^ns$')] = pp_ns
|
||||||
|
|
||||||
|
|||||||
@@ -2274,7 +2274,7 @@ varobj_formatted_print_options (struct value_print_options *opts,
|
|||||||
{
|
{
|
||||||
get_formatted_print_options (opts, format_code[(int) format]);
|
get_formatted_print_options (opts, format_code[(int) format]);
|
||||||
opts->deref_ref = 0;
|
opts->deref_ref = 0;
|
||||||
opts->raw = 1;
|
opts->raw = !pretty_printing;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
|
|||||||
Reference in New Issue
Block a user