diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 29 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 46 | ||||
-rw-r--r-- | gdb/mi/mi-cmd-var.c | 21 | ||||
-rw-r--r-- | gdb/mi/mi-cmds.c | 2 | ||||
-rw-r--r-- | gdb/mi/mi-cmds.h | 1 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/testsuite/gdb.mi/mi-var-cp.cc | 86 | ||||
-rw-r--r-- | gdb/testsuite/gdb.mi/mi-var-cp.exp | 1 | ||||
-rw-r--r-- | gdb/varobj.c | 170 | ||||
-rw-r--r-- | gdb/varobj.h | 2 |
11 files changed, 346 insertions, 24 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 182df0cdf60..242822fdb5e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,34 @@ 2007-08-31 Vladimir Prus <vladimir@codesourcery.com> + Implement -var-info-path-expression. + + * mi/mi-cmds.h (mi_cmd_var_info_path_expression): + Declare. + * mi/mi-cmds.c (mi_cmds): Register var-info-path-expression. + * mi/mi-cmd-var.c (mi_cmd_var_info_path_expression): New. + * varobj.c (struct varobj): New field 'path_expr'. + (c_path_expr_of_child, cplus_path_expr_of_child) + (java_path_expr_of_child): New. + (struct language_specific): New field path_expr_of_child. + (varobj_create): Initialize the path_expr field. + (varobj_get_path_expr): New. + (new_variable): Initialize the path_expr field. + (free_variable): Free the path_expr field. + (adjust_value_for_children_access): New parameter + WAS_TYPE. + (c_number_of_children): Adjust. + (c_describe_child): New parameter CFULL_EXPRESSION. + Compute full expression. + (c_value_of_child, c_type_of_child): Adjust. + (cplus_number_of_children): Adjust. + (cplus_describe_child): New parameter CFULL_EXPRESSION. + Compute full expression. + (cplus_name_of_child, cplus_value_of_child) + (cplus_type_of_child): Adjust. + * varobj.h (varobj_get_path_expr): Declare. + +2007-08-31 Vladimir Prus <vladimir@codesourcery.com> + * mi/mi-cmd-var.c (print_varobj): If a varobj type is NULL, don't try to print it. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 0c6ebe8ccd4..1c1a2ca0171 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,9 @@ +2007-08-31 Vladimir Prus <vladimir@codesourcery.com> + + * gdb.texinfo (Variable Objects): Adjust docs + for -var-info-expression and document + -var-info-path-expression. + 2007-08-20 Jim Blandy <jimb@codesourcery.com> * gdb.texinfo (Top): Dedicate manual to the memory of Fred Fish. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index a74d10ed7f3..8d935650133 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -19312,7 +19312,9 @@ access this functionality: @item @code{-var-info-type} @tab show the type of this variable object @item @code{-var-info-expression} -@tab print what this variable object represents +@tab print parent-relative expression that this variable object represents +@item @code{-var-info-path-expression} +@tab print full expression that this variable object represents @item @code{-var-show-attributes} @tab is this variable editable? does it exist here? @item @code{-var-evaluate-expression} @@ -19513,14 +19515,50 @@ returned as a string in the same format as it is output by the -var-info-expression @var{name} @end smallexample -Returns what is represented by the variable object @var{name}: +Returns a string that is suitable for presenting this +variable object in user interface. The string is generally +not valid expression in the current language, and cannot be evaluated. + +For example, if @code{a} is an array, and variable object +@code{A} was created for @code{a}, then we'll get this output: @smallexample - lang=@var{lang-spec},exp=@var{expression} +(gdb) -var-info-expression A.1 +^done,lang="C",exp="1" @end smallexample @noindent -where @var{lang-spec} is @code{@{"C" | "C++" | "Java"@}}. +Here, the values of @code{lang} can be @code{@{"C" | "C++" | "Java"@}}. + +Note that the output of the @code{-var-list-children} command also +includes those expressions, so the @code{-var-info-expression} command +is of limited use. + +@subheading The @code{-var-info-path-expression} Command +@findex -var-info-path-expression + +@subsubheading Synopsis + +@smallexample + -var-info-path-expression @var{name} +@end smallexample + +Returns an expression that can be evaluated in the current +context and will yield the same value that a variable object has. +Compare this with the @code{-var-info-expression} command, which +result can be used only for UI presentation. Typical use of +the @code{-var-info-path-expression} command is creating a +watchpoint from a variable object. + +For example, suppose @code{C} is a C@t{++} class, derived from class +@code{Base}, and that the @code{Base} class has a member called +@code{m_size}. Assume a variable @code{c} is has the type of +@code{C} and a variable object @code{C} was created for variable +@code{c}. Then, we'll get this output: +@smallexample +(gdb) -var-info-path-expression C.Base.public.m_size +^done,path_expr=((Base)c).m_size) +@end smallexample @subheading The @code{-var-show-attributes} Command @findex -var-show-attributes diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c index 05fe7a923ba..213681e3c09 100644 --- a/gdb/mi/mi-cmd-var.c +++ b/gdb/mi/mi-cmd-var.c @@ -413,6 +413,27 @@ mi_cmd_var_info_type (char *command, char **argv, int argc) } enum mi_cmd_result +mi_cmd_var_info_path_expression (char *command, char **argv, int argc) +{ + struct varobj *var; + char *path_expr; + + if (argc != 1) + error (_("Usage: NAME.")); + + /* Get varobj handle, if a valid var obj name was specified. */ + var = varobj_get_handle (argv[0]); + if (var == NULL) + error (_("Variable object not found")); + + path_expr = varobj_get_path_expr (var); + + ui_out_field_string (uiout, "path_expr", path_expr); + + return MI_CMD_DONE; +} + +enum mi_cmd_result mi_cmd_var_info_expression (char *command, char **argv, int argc) { enum varobj_languages lang; diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index 7a05e33b3a7..48ba2087fa1 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -149,6 +149,8 @@ struct mi_cmd mi_cmds[] = { "var-create", { NULL, 0 }, 0, mi_cmd_var_create}, { "var-delete", { NULL, 0 }, 0, mi_cmd_var_delete}, { "var-evaluate-expression", { NULL, 0 }, 0, mi_cmd_var_evaluate_expression}, + { "var-info-path-expression", { NULL, 0 }, 0, + mi_cmd_var_info_path_expression}, { "var-info-expression", { NULL, 0 }, 0, mi_cmd_var_info_expression}, { "var-info-num-children", { NULL, 0 }, 0, mi_cmd_var_info_num_children}, { "var-info-type", { NULL, 0 }, 0, mi_cmd_var_info_type}, diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index e045a66c855..7b3eb0e3bae 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -107,6 +107,7 @@ extern mi_cmd_argv_ftype mi_cmd_var_create; extern mi_cmd_argv_ftype mi_cmd_var_delete; extern mi_cmd_argv_ftype mi_cmd_var_evaluate_expression; extern mi_cmd_argv_ftype mi_cmd_var_info_expression; +extern mi_cmd_argv_ftype mi_cmd_var_info_path_expression; extern mi_cmd_argv_ftype mi_cmd_var_info_num_children; extern mi_cmd_argv_ftype mi_cmd_var_info_type; extern mi_cmd_argv_ftype mi_cmd_var_list_children; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 54d47762fb5..c4d0887c989 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-08-31 Vladimir Prus <vladimir@codesourcery.com> + + * gdb.mi/mi-var-cp.cc (path_expression): New + function. + * gdb.mi/mi-var-cp.exp: Run path exression tests. + 2007-08-27 Markus Deuling <deuling@de.ibm.com> * gdb.cp/cp-relocate.exp (add-symbol-file): Change addresses diff --git a/gdb/testsuite/gdb.mi/mi-var-cp.cc b/gdb/testsuite/gdb.mi/mi-var-cp.cc index ad8e75ae289..3faadc36de7 100644 --- a/gdb/testsuite/gdb.mi/mi-var-cp.cc +++ b/gdb/testsuite/gdb.mi/mi-var-cp.cc @@ -120,11 +120,97 @@ int reference_to_struct () /*: END: reference_to_struct :*/ } +struct Base1 +{ + int i; +}; + +struct Base2 +{ + int i; +}; + +struct Derived : public Base1, public Base2 +{ + int i; +}; + +/* Test for the -var-info-path-expression command. Although + said command is not specific to C++, it's of more importance + to C++ than to C, so we test it in mi-var-cp test. */ +int path_expression () +{ + /*: BEGIN: path_expression :*/ + int i = 10; + int *ip = &i; + /*: mi_create_varobj IP ip "create varobj for ip" + mi_list_varobj_children IP {{IP.\\*ip \\*ip 0 int}} "list children of IP" + mi_gdb_test "-var-info-path-expression IP.*ip" \ + "\\^done,path_expr=\"\\*\\(ip\\)\"" \ + "-var-info-path-expression IP.*ip" + :*/ + Derived d; + Derived *dp = &d; + /*: mi_create_varobj DP dp "create varobj for dp" + mi_list_varobj_children DP \ + {{DP.Base1 Base1 1 Base1} \ + {DP.Base2 Base2 1 Base2} \ + {DP.public public 1}} "list children of DP" + mi_gdb_test "-var-info-path-expression DP.Base1" \ + "\\^done,path_expr=\"\\(\\*\\(Base1\\*\\) dp\\)\"" \ + "-var-info-path-expression DP.Base1" + mi_list_varobj_children DP.public { \ + {DP.public.i i 0 int} \ + } "list children of DP.public" + mi_gdb_test "-var-info-path-expression DP.public.i" \ + "\\^done,path_expr=\"\\(\\(dp\\)->i\\)\"" \ + "-var-info-path-expression DP.public.i" + mi_list_varobj_children DP.Base1 { \ + {DP.Base1.public public 1} \ + } "list children of DP.Base1" + mi_list_varobj_children DP.Base1.public { \ + {DP.Base1.public.i i 0 int} \ + } "list children of DP.Base1.public" + mi_gdb_test "-var-info-path-expression DP.Base1.public.i" \ + "\\^done,path_expr=\"\\(\\(\\(\\*\\(Base1\\*\\) dp\\)\\).i\\)\"" \ + "-var-info-path-expression DP.Base1.public.i" + + mi_gdb_test "-var-info-path-expression DP.public" \ + "\\^done,path_expr=\"\"" \ + "-var-info-path-expression DP.public" + + mi_create_varobj D d "create varobj for d" + mi_list_varobj_children D \ + {{D.Base1 Base1 1 Base1} \ + {D.Base2 Base2 1 Base2} \ + {D.public public 1}} "list children of D" + mi_gdb_test "-var-info-path-expression D.Base1" \ + "\\^done,path_expr=\"\\(\\(Base1\\) d\\)\"" \ + "-var-info-path-expression D.Base1" + :*/ + int array[4] = {1,2,3}; + array[3] = 10; + /*: mi_create_varobj A array "create varobj for array" + mi_list_varobj_children A { \ + {A.0 0 0 int} + {A.1 1 0 int} + {A.2 2 0 int} + {A.3 3 0 int}} "list children of A" + mi_gdb_test "-var-info-path-expression A.2" \ + "\\^done,path_expr=\"\\(array\\)\\\[2\\\]\"" \ + "-var-info-path-expression A.2" + :*/ + + return 99; + /*: END: path_expression :*/ +} + int main () { reference_update_tests (); base_in_reference_test_main (); reference_to_pointer (); reference_to_struct (); + path_expression (); return 0; } diff --git a/gdb/testsuite/gdb.mi/mi-var-cp.exp b/gdb/testsuite/gdb.mi/mi-var-cp.exp index 0933cfe18a0..1e331b9cf85 100644 --- a/gdb/testsuite/gdb.mi/mi-var-cp.exp +++ b/gdb/testsuite/gdb.mi/mi-var-cp.exp @@ -44,6 +44,7 @@ mi_run_inline_test reference_update mi_run_inline_test base_in_reference mi_run_inline_test reference_to_pointer mi_run_inline_test reference_to_struct +mi_run_inline_test path_expression mi_gdb_exit return 0 diff --git a/gdb/varobj.c b/gdb/varobj.c index 96d5610a160..7235de31f1f 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -99,6 +99,10 @@ struct varobj /* NOTE: This is the "expression" */ char *name; + /* Alloc'd expression for this child. Can be used to create a + root variable corresponding to this child. */ + char *path_expr; + /* The alloc'd name for this variable's object. This is here for convenience when constructing this object's children. */ char *obj_name; @@ -234,6 +238,8 @@ static char *c_name_of_variable (struct varobj *parent); static char *c_name_of_child (struct varobj *parent, int index); +static char *c_path_expr_of_child (struct varobj *child); + static struct value *c_value_of_root (struct varobj **var_handle); static struct value *c_value_of_child (struct varobj *parent, int index); @@ -254,6 +260,8 @@ static char *cplus_name_of_variable (struct varobj *parent); static char *cplus_name_of_child (struct varobj *parent, int index); +static char *cplus_path_expr_of_child (struct varobj *child); + static struct value *cplus_value_of_root (struct varobj **var_handle); static struct value *cplus_value_of_child (struct varobj *parent, int index); @@ -272,6 +280,8 @@ static char *java_name_of_variable (struct varobj *parent); static char *java_name_of_child (struct varobj *parent, int index); +static char *java_path_expr_of_child (struct varobj *child); + static struct value *java_value_of_root (struct varobj **var_handle); static struct value *java_value_of_child (struct varobj *parent, int index); @@ -299,6 +309,10 @@ struct language_specific /* The name of the INDEX'th child of PARENT. */ char *(*name_of_child) (struct varobj * parent, int index); + /* Returns the rooted expression of CHILD, which is a variable + obtain that has some parent. */ + char *(*path_expr_of_child) (struct varobj * child); + /* The ``struct value *'' of the root variable ROOT. */ struct value *(*value_of_root) (struct varobj ** root_handle); @@ -323,6 +337,7 @@ static struct language_specific languages[vlang_end] = { c_number_of_children, c_name_of_variable, c_name_of_child, + c_path_expr_of_child, c_value_of_root, c_value_of_child, c_type_of_child, @@ -335,6 +350,7 @@ static struct language_specific languages[vlang_end] = { c_number_of_children, c_name_of_variable, c_name_of_child, + c_path_expr_of_child, c_value_of_root, c_value_of_child, c_type_of_child, @@ -347,6 +363,7 @@ static struct language_specific languages[vlang_end] = { cplus_number_of_children, cplus_name_of_variable, cplus_name_of_child, + cplus_path_expr_of_child, cplus_value_of_root, cplus_value_of_child, cplus_type_of_child, @@ -359,6 +376,7 @@ static struct language_specific languages[vlang_end] = { java_number_of_children, java_name_of_variable, java_name_of_child, + java_path_expr_of_child, java_value_of_root, java_value_of_child, java_type_of_child, @@ -442,6 +460,7 @@ varobj_create (char *objname, char *p; enum varobj_languages lang; struct value *value = NULL; + int expr_len; /* Parse and evaluate the expression, filling in as much of the variable's data as possible */ @@ -486,7 +505,10 @@ varobj_create (char *objname, var->format = variable_default_display (var); var->root->valid_block = innermost_block; - var->name = savestring (expression, strlen (expression)); + expr_len = strlen (expression); + var->name = savestring (expression, expr_len); + /* For a root var, the name and the expr are the same. */ + var->path_expr = savestring (expression, expr_len); /* When the frame is different from the current frame, we must select the appropriate frame before parsing @@ -804,6 +826,23 @@ varobj_get_gdb_type (struct varobj *var) return var->type; } +/* Return a pointer to the full rooted expression of varobj VAR. + If it has not been computed yet, compute it. */ +char * +varobj_get_path_expr (struct varobj *var) +{ + if (var->path_expr != NULL) + return var->path_expr; + else + { + /* For root varobjs, we initialize path_expr + when creating varobj, so here it should be + child varobj. */ + gdb_assert (!is_root_p (var)); + return (*var->root->lang->path_expr_of_child) (var); + } +} + enum varobj_languages varobj_get_language (struct varobj *var) { @@ -1457,6 +1496,7 @@ new_variable (void) var = (struct varobj *) xmalloc (sizeof (struct varobj)); var->name = NULL; + var->path_expr = NULL; var->obj_name = NULL; var->index = -1; var->type = NULL; @@ -1505,6 +1545,7 @@ free_variable (struct varobj *var) xfree (var->name); xfree (var->obj_name); xfree (var->print_value); + xfree (var->path_expr); xfree (var); } @@ -1845,13 +1886,21 @@ varobj_value_is_changeable_p (struct varobj *var) Both TYPE and *TYPE should be non-null. VALUE can be null if we want to only translate type. *VALUE can be null as well -- if the parent - value is not known. */ + value is not known. + + If WAS_PTR is not NULL, set *WAS_PTR to 0 or 1 + depending on whether pointer was deferenced + in this function. */ static void adjust_value_for_child_access (struct value **value, - struct type **type) + struct type **type, + int *was_ptr) { gdb_assert (type && *type); + if (was_ptr) + *was_ptr = 0; + *type = check_typedef (*type); /* The type of value stored in varobj, that is passed @@ -1872,6 +1921,8 @@ adjust_value_for_child_access (struct value **value, if (value && *value) gdb_value_ind (*value, value); *type = target_type; + if (was_ptr) + *was_ptr = 1; } } @@ -1888,7 +1939,7 @@ c_number_of_children (struct varobj *var) int children = 0; struct type *target; - adjust_value_for_child_access (NULL, &type); + adjust_value_for_child_access (NULL, &type, NULL); target = get_target_type (type); switch (TYPE_CODE (type)) @@ -1984,10 +2035,13 @@ value_struct_element_index (struct value *value, int type_index) to NULL. */ static void c_describe_child (struct varobj *parent, int index, - char **cname, struct value **cvalue, struct type **ctype) + char **cname, struct value **cvalue, struct type **ctype, + char **cfull_expression) { struct value *value = parent->value; struct type *type = get_value_type (parent); + char *parent_expression = NULL; + int was_ptr; if (cname) *cname = NULL; @@ -1995,8 +2049,12 @@ c_describe_child (struct varobj *parent, int index, *cvalue = NULL; if (ctype) *ctype = NULL; - - adjust_value_for_child_access (&value, &type); + if (cfull_expression) + { + *cfull_expression = NULL; + parent_expression = varobj_get_path_expr (parent); + } + adjust_value_for_child_access (&value, &type, &was_ptr); switch (TYPE_CODE (type)) { @@ -2016,6 +2074,12 @@ c_describe_child (struct varobj *parent, int index, if (ctype) *ctype = get_target_type (type); + if (cfull_expression) + *cfull_expression = xstrprintf ("(%s)[%d]", parent_expression, + index + + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type))); + + break; case TYPE_CODE_STRUCT: @@ -2035,6 +2099,13 @@ c_describe_child (struct varobj *parent, int index, if (ctype) *ctype = TYPE_FIELD_TYPE (type, index); + if (cfull_expression) + { + char *join = was_ptr ? "->" : "."; + *cfull_expression = xstrprintf ("(%s)%s%s", parent_expression, join, + TYPE_FIELD_NAME (type, index)); + } + break; case TYPE_CODE_PTR: @@ -2049,6 +2120,9 @@ c_describe_child (struct varobj *parent, int index, declared type of the variable. */ if (ctype) *ctype = TYPE_TARGET_TYPE (type); + + if (cfull_expression) + *cfull_expression = xstrprintf ("*(%s)", parent_expression); break; @@ -2056,6 +2130,8 @@ c_describe_child (struct varobj *parent, int index, /* This should not happen */ if (cname) *cname = xstrdup ("???"); + if (cfull_expression) + *cfull_expression = xstrdup ("???"); /* Don't set value and type, we don't know then. */ } } @@ -2064,10 +2140,18 @@ static char * c_name_of_child (struct varobj *parent, int index) { char *name; - c_describe_child (parent, index, &name, NULL, NULL); + c_describe_child (parent, index, &name, NULL, NULL, NULL); return name; } +static char * +c_path_expr_of_child (struct varobj *child) +{ + c_describe_child (child->parent, child->index, NULL, NULL, NULL, + &child->path_expr); + return child->path_expr; +} + static struct value * c_value_of_root (struct varobj **var_handle) { @@ -2116,7 +2200,7 @@ static struct value * c_value_of_child (struct varobj *parent, int index) { struct value *value = NULL; - c_describe_child (parent, index, NULL, &value, NULL); + c_describe_child (parent, index, NULL, &value, NULL, NULL); return value; } @@ -2125,7 +2209,7 @@ static struct type * c_type_of_child (struct varobj *parent, int index) { struct type *type = NULL; - c_describe_child (parent, index, NULL, NULL, &type); + c_describe_child (parent, index, NULL, NULL, &type, NULL); return type; } @@ -2215,7 +2299,7 @@ cplus_number_of_children (struct varobj *var) if (!CPLUS_FAKE_CHILD (var)) { type = get_value_type (var); - adjust_value_for_child_access (NULL, &type); + adjust_value_for_child_access (NULL, &type, NULL); if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) || ((TYPE_CODE (type)) == TYPE_CODE_UNION)) @@ -2242,7 +2326,7 @@ cplus_number_of_children (struct varobj *var) int kids[3]; type = get_value_type (var->parent); - adjust_value_for_child_access (NULL, &type); + adjust_value_for_child_access (NULL, &type, NULL); cplus_class_num_children (type, kids); if (strcmp (var->name, "public") == 0) @@ -2313,11 +2397,14 @@ match_accessibility (struct type *type, int index, enum accessibility acc) static void cplus_describe_child (struct varobj *parent, int index, - char **cname, struct value **cvalue, struct type **ctype) + char **cname, struct value **cvalue, struct type **ctype, + char **cfull_expression) { char *name = NULL; struct value *value; struct type *type; + int was_ptr; + char *parent_expression = NULL; if (cname) *cname = NULL; @@ -2325,24 +2412,30 @@ cplus_describe_child (struct varobj *parent, int index, *cvalue = NULL; if (ctype) *ctype = NULL; - + if (cfull_expression) + *cfull_expression = NULL; if (CPLUS_FAKE_CHILD (parent)) { value = parent->parent->value; type = get_value_type (parent->parent); + if (cfull_expression) + parent_expression = varobj_get_path_expr (parent->parent); } else { value = parent->value; type = get_value_type (parent); + if (cfull_expression) + parent_expression = varobj_get_path_expr (parent); } - adjust_value_for_child_access (&value, &type); + adjust_value_for_child_access (&value, &type, &was_ptr); if (TYPE_CODE (type) == TYPE_CODE_STRUCT || TYPE_CODE (type) == TYPE_CODE_STRUCT) { + char *join = was_ptr ? "->" : "."; if (CPLUS_FAKE_CHILD (parent)) { /* The fields of the class type are ordered as they @@ -2377,6 +2470,11 @@ cplus_describe_child (struct varobj *parent, int index, if (ctype) *ctype = TYPE_FIELD_TYPE (type, type_index); + + if (cfull_expression) + *cfull_expression = xstrprintf ("((%s)%s%s)", parent_expression, + join, + TYPE_FIELD_NAME (type, type_index)); } else if (index < TYPE_N_BASECLASSES (type)) { @@ -2387,12 +2485,30 @@ cplus_describe_child (struct varobj *parent, int index, if (cvalue && value) { *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value); + release_value (*cvalue); } if (ctype) { *ctype = TYPE_FIELD_TYPE (type, index); } + + if (cfull_expression) + { + char *ptr = was_ptr ? "*" : ""; + /* Cast the parent to the base' type. Note that in gdb, + expression like + (Base1)d + will create an lvalue, for all appearences, so we don't + need to use more fancy: + *(Base1*)(&d) + construct. */ + *cfull_expression = xstrprintf ("(%s(%s%s) %s)", + ptr, + TYPE_FIELD_NAME (type, index), + ptr, + parent_expression); + } } else { @@ -2440,12 +2556,12 @@ cplus_describe_child (struct varobj *parent, int index, if (cname) *cname = xstrdup (access); - /* Value and type are null here. */ + /* Value and type and full expression are null here. */ } } else { - c_describe_child (parent, index, cname, cvalue, ctype); + c_describe_child (parent, index, cname, cvalue, ctype, cfull_expression); } } @@ -2453,10 +2569,18 @@ static char * cplus_name_of_child (struct varobj *parent, int index) { char *name = NULL; - cplus_describe_child (parent, index, &name, NULL, NULL); + cplus_describe_child (parent, index, &name, NULL, NULL, NULL); return name; } +static char * +cplus_path_expr_of_child (struct varobj *child) +{ + cplus_describe_child (child->parent, child->index, NULL, NULL, NULL, + &child->path_expr); + return child->path_expr; +} + static struct value * cplus_value_of_root (struct varobj **var_handle) { @@ -2467,7 +2591,7 @@ static struct value * cplus_value_of_child (struct varobj *parent, int index) { struct value *value = NULL; - cplus_describe_child (parent, index, NULL, &value, NULL); + cplus_describe_child (parent, index, NULL, &value, NULL, NULL); return value; } @@ -2475,7 +2599,7 @@ static struct type * cplus_type_of_child (struct varobj *parent, int index) { struct type *type = NULL; - cplus_describe_child (parent, index, NULL, NULL, &type); + cplus_describe_child (parent, index, NULL, NULL, &type, NULL); return type; } @@ -2547,6 +2671,12 @@ java_name_of_child (struct varobj *parent, int index) return name; } +static char * +java_path_expr_of_child (struct varobj *child) +{ + return NULL; +} + static struct value * java_value_of_root (struct varobj **var_handle) { diff --git a/gdb/varobj.h b/gdb/varobj.h index bff475b4380..519fb391351 100644 --- a/gdb/varobj.h +++ b/gdb/varobj.h @@ -97,6 +97,8 @@ extern char *varobj_get_type (struct varobj *var); extern struct type *varobj_get_gdb_type (struct varobj *var); +extern char *varobj_get_path_expr (struct varobj *var); + extern enum varobj_languages varobj_get_language (struct varobj *var); extern int varobj_get_attributes (struct varobj *var); |