X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fvarobj.c;h=f3d3b5abef637cb1fe7f2673aea4a6546770c035;hb=ebd3bcc1327e6a7de6daf6536134cb20be9c2cfd;hp=c62aecffd65fd0aacf1f95e93a91c4fcf83f8fcd;hpb=f7635dd9207587ecb51370172ac20016fa30c1dc;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/varobj.c b/gdb/varobj.c index c62aecffd6..f3d3b5abef 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -1,9 +1,11 @@ /* Implementation of the GDB variable objects API. - Copyright 1999, 2000, 2001 Free Software Foundation, Inc. + + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 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 2 of the License, or + 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, @@ -12,143 +14,165 @@ 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, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" +#include "exceptions.h" #include "value.h" #include "expression.h" #include "frame.h" #include "language.h" #include "wrapper.h" #include "gdbcmd.h" -#include +#include "block.h" + +#include "gdb_assert.h" +#include "gdb_string.h" #include "varobj.h" +#include "vec.h" +#include "gdbthread.h" +#include "inferior.h" /* Non-zero if we want to see trace of varobj level stuff. */ int varobjdebug = 0; +static void +show_varobjdebug (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Varobj debugging is %s.\n"), value); +} /* String representations of gdb's format codes */ char *varobj_format_string[] = -{"natural", "binary", "decimal", "hexadecimal", "octal"}; + { "natural", "binary", "decimal", "hexadecimal", "octal" }; /* String representations of gdb's known languages */ -char *varobj_language_string[] = -{"unknown", "C", "C++", "Java"}; +char *varobj_language_string[] = { "unknown", "C", "C++", "Java" }; /* Data structures */ /* Every root variable has one of these structures saved in its varobj. Members which must be free'd are noted. */ struct varobj_root - { +{ + + /* Alloc'd expression for this parent. */ + struct expression *exp; + + /* Block for which this expression is valid */ + struct block *valid_block; - /* Alloc'd expression for this parent. */ - struct expression *exp; + /* The frame for this expression. This field is set iff valid_block is + not NULL. */ + struct frame_id frame; - /* Block for which this expression is valid */ - struct block *valid_block; + /* The thread ID that this varobj_root belong to. This field + is only valid if valid_block is not NULL. + When not 0, indicates which thread 'frame' belongs to. + When 0, indicates that the thread list was empty when the varobj_root + was created. */ + int thread_id; - /* The frame for this expression */ - CORE_ADDR frame; + /* If 1, the -var-update always recomputes the value in the + current thread and frame. Otherwise, variable object is + always updated in the specific scope/thread/frame */ + int floating; - /* If 1, "update" always recomputes the frame & valid block - using the currently selected frame. */ - int use_selected_frame; + /* Flag that indicates validity: set to 0 when this varobj_root refers + to symbols that do not exist anymore. */ + int is_valid; - /* Language info for this variable and its children */ - struct language_specific *lang; + /* Language info for this variable and its children */ + struct language_specific *lang; - /* The varobj for this root node. */ - struct varobj *rootvar; + /* The varobj for this root node. */ + struct varobj *rootvar; - /* Next root variable */ - struct varobj_root *next; - }; + /* Next root variable */ + struct varobj_root *next; +}; /* Every variable in the system has a structure of this type defined for it. This structure holds all information necessary to manipulate a particular object variable. Members which must be freed are noted. */ struct varobj - { - - /* Alloc'd name of the variable for this object.. If this variable is a - child, then this name will be the child's source name. - (bar, not foo.bar) */ - /* NOTE: This is the "expression" */ - char *name; - - /* The alloc'd name for this variable's object. This is here for - convenience when constructing this object's children. */ - char *obj_name; +{ - /* Index of this variable in its parent or -1 */ - int index; + /* Alloc'd name of the variable for this object.. If this variable is a + child, then this name will be the child's source name. + (bar, not foo.bar) */ + /* NOTE: This is the "expression" */ + char *name; - /* The type of this variable. This may NEVER be NULL. */ - struct type *type; + /* Alloc'd expression for this child. Can be used to create a + root variable corresponding to this child. */ + char *path_expr; - /* The value of this expression or subexpression. This may be NULL. */ - value_ptr value; + /* The alloc'd name for this variable's object. This is here for + convenience when constructing this object's children. */ + char *obj_name; - /* Did an error occur evaluating the expression or getting its value? */ - int error; + /* Index of this variable in its parent or -1 */ + int index; - /* The number of (immediate) children this variable has */ - int num_children; + /* The type of this variable. This can be NULL + for artifial variable objects -- currently, the "accessibility" + variable objects in C++. */ + struct type *type; - /* If this object is a child, this points to its immediate parent. */ - struct varobj *parent; + /* The value of this expression or subexpression. A NULL value + indicates there was an error getting this value. + Invariant: if varobj_value_is_changeable_p (this) is non-zero, + the value is either NULL, or not lazy. */ + struct value *value; - /* A list of this object's children */ - struct varobj_child *children; + /* The number of (immediate) children this variable has */ + int num_children; - /* Description of the root variable. Points to root variable for children. */ - struct varobj_root *root; + /* If this object is a child, this points to its immediate parent. */ + struct varobj *parent; - /* The format of the output for this object */ - enum varobj_display_formats format; - }; + /* Children of this object. */ + VEC (varobj_p) *children; -/* Every variable keeps a linked list of its children, described - by the following structure. */ -/* FIXME: Deprecated. All should use vlist instead */ + /* Description of the root variable. Points to root variable for children. */ + struct varobj_root *root; -struct varobj_child - { + /* The format of the output for this object */ + enum varobj_display_formats format; - /* Pointer to the child's data */ - struct varobj *child; + /* Was this variable updated via a varobj_set_value operation */ + int updated; - /* Pointer to the next child */ - struct varobj_child *next; - }; + /* Last print value. */ + char *print_value; -/* A stack of varobjs */ -/* FIXME: Deprecated. All should use vlist instead */ + /* Is this variable frozen. Frozen variables are never implicitly + updated by -var-update * + or -var-update . */ + int frozen; -struct vstack - { - struct varobj *var; - struct vstack *next; - }; + /* Is the value of this variable intentionally not fetched? It is + not fetched if either the variable is frozen, or any parents is + frozen. */ + int not_fetched; +}; struct cpstack - { - char *name; - struct cpstack *next; - }; +{ + char *name; + struct cpstack *next; +}; /* A list of varobjs */ struct vlist - { - struct varobj *var; - struct vlist *next; - }; +{ + struct varobj *var; + struct vlist *next; +}; /* Private function prototypes */ @@ -163,14 +187,8 @@ static int install_variable (struct varobj *); static void uninstall_variable (struct varobj *); -static struct varobj *child_exists (struct varobj *, char *); - static struct varobj *create_child (struct varobj *, int, char *); -static void save_child_in_parent (struct varobj *, struct varobj *); - -static void remove_child_from_parent (struct varobj *, struct varobj *); - /* Utility routines */ static struct varobj *new_variable (void); @@ -183,22 +201,19 @@ static struct cleanup *make_cleanup_free_variable (struct varobj *var); static struct type *get_type (struct varobj *var); -static struct type *get_type_deref (struct varobj *var); +static struct type *get_value_type (struct varobj *var); static struct type *get_target_type (struct type *); static enum varobj_display_formats variable_default_display (struct varobj *); -static int my_value_equal (value_ptr, value_ptr, int *); - -static void vpush (struct vstack **pstack, struct varobj *var); - -static struct varobj *vpop (struct vstack **pstack); - static void cppush (struct cpstack **pstack, char *name); static char *cppop (struct cpstack **pstack); +static int install_new_value (struct varobj *var, struct value *value, + int initial); + /* Language-specific routines. */ static enum varobj_languages variable_language (struct varobj *var); @@ -209,17 +224,19 @@ static char *name_of_variable (struct varobj *); static char *name_of_child (struct varobj *, int); -static value_ptr value_of_root (struct varobj **var_handle, int *); +static struct value *value_of_root (struct varobj **var_handle, int *); -static value_ptr value_of_child (struct varobj *parent, int index); +static struct value *value_of_child (struct varobj *parent, int index); -static struct type *type_of_child (struct varobj *var); +static char *my_value_of_variable (struct varobj *var, + enum varobj_display_formats format); -static int variable_editable (struct varobj *var); +static char *value_get_print_value (struct value *value, + enum varobj_display_formats format); -static char *my_value_of_variable (struct varobj *var); +static int varobj_value_is_changeable_p (struct varobj *var); -static int type_changeable (struct varobj *var); +static int is_root_p (struct varobj *var); /* C implementation */ @@ -229,15 +246,16 @@ static char *c_name_of_variable (struct varobj *parent); static char *c_name_of_child (struct varobj *parent, int index); -static value_ptr c_value_of_root (struct varobj **var_handle); +static char *c_path_expr_of_child (struct varobj *child); -static value_ptr c_value_of_child (struct varobj *parent, int index); +static struct value *c_value_of_root (struct varobj **var_handle); -static struct type *c_type_of_child (struct varobj *parent, int index); +static struct value *c_value_of_child (struct varobj *parent, int index); -static int c_variable_editable (struct varobj *var); +static struct type *c_type_of_child (struct varobj *parent, int index); -static char *c_value_of_variable (struct varobj *var); +static char *c_value_of_variable (struct varobj *var, + enum varobj_display_formats format); /* C++ implementation */ @@ -249,15 +267,16 @@ static char *cplus_name_of_variable (struct varobj *parent); static char *cplus_name_of_child (struct varobj *parent, int index); -static value_ptr cplus_value_of_root (struct varobj **var_handle); +static char *cplus_path_expr_of_child (struct varobj *child); -static value_ptr cplus_value_of_child (struct varobj *parent, int index); +static struct value *cplus_value_of_root (struct varobj **var_handle); -static struct type *cplus_type_of_child (struct varobj *parent, int index); +static struct value *cplus_value_of_child (struct varobj *parent, int index); -static int cplus_variable_editable (struct varobj *var); +static struct type *cplus_type_of_child (struct varobj *parent, int index); -static char *cplus_value_of_variable (struct varobj *var); +static char *cplus_value_of_variable (struct varobj *var, + enum varobj_display_formats format); /* Java implementation */ @@ -267,117 +286,113 @@ static char *java_name_of_variable (struct varobj *parent); static char *java_name_of_child (struct varobj *parent, int index); -static value_ptr java_value_of_root (struct varobj **var_handle); +static char *java_path_expr_of_child (struct varobj *child); -static value_ptr java_value_of_child (struct varobj *parent, int index); +static struct value *java_value_of_root (struct varobj **var_handle); -static struct type *java_type_of_child (struct varobj *parent, int index); +static struct value *java_value_of_child (struct varobj *parent, int index); -static int java_variable_editable (struct varobj *var); +static struct type *java_type_of_child (struct varobj *parent, int index); -static char *java_value_of_variable (struct varobj *var); +static char *java_value_of_variable (struct varobj *var, + enum varobj_display_formats format); /* The language specific vector */ struct language_specific - { +{ - /* The language of this variable */ - enum varobj_languages language; + /* The language of this variable */ + enum varobj_languages language; - /* The number of children of PARENT. */ - int (*number_of_children) (struct varobj * parent); + /* The number of children of PARENT. */ + int (*number_of_children) (struct varobj * parent); - /* The name (expression) of a root varobj. */ - char *(*name_of_variable) (struct varobj * parent); + /* The name (expression) of a root varobj. */ + char *(*name_of_variable) (struct varobj * parent); - /* The name of the INDEX'th child of PARENT. */ - char *(*name_of_child) (struct varobj * parent, int index); + /* The name of the INDEX'th child of PARENT. */ + char *(*name_of_child) (struct varobj * parent, int index); - /* The value_ptr of the root variable ROOT. */ - value_ptr (*value_of_root) (struct varobj ** root_handle); + /* Returns the rooted expression of CHILD, which is a variable + obtain that has some parent. */ + char *(*path_expr_of_child) (struct varobj * child); - /* The value_ptr of the INDEX'th child of PARENT. */ - value_ptr (*value_of_child) (struct varobj * parent, int index); + /* The ``struct value *'' of the root variable ROOT. */ + struct value *(*value_of_root) (struct varobj ** root_handle); - /* The type of the INDEX'th child of PARENT. */ - struct type *(*type_of_child) (struct varobj * parent, int index); + /* The ``struct value *'' of the INDEX'th child of PARENT. */ + struct value *(*value_of_child) (struct varobj * parent, int index); - /* Is VAR editable? */ - int (*variable_editable) (struct varobj * var); + /* The type of the INDEX'th child of PARENT. */ + struct type *(*type_of_child) (struct varobj * parent, int index); - /* The current value of VAR. */ - char *(*value_of_variable) (struct varobj * var); - }; + /* The current value of VAR. */ + char *(*value_of_variable) (struct varobj * var, + enum varobj_display_formats format); +}; /* Array of known source language routines. */ -static struct language_specific - languages[vlang_end][sizeof (struct language_specific)] = -{ +static struct language_specific languages[vlang_end] = { /* Unknown (try treating as C */ { - vlang_unknown, - c_number_of_children, - c_name_of_variable, - c_name_of_child, - c_value_of_root, - c_value_of_child, - c_type_of_child, - c_variable_editable, - c_value_of_variable - } + vlang_unknown, + 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, + c_value_of_variable} , /* C */ { - vlang_c, - c_number_of_children, - c_name_of_variable, - c_name_of_child, - c_value_of_root, - c_value_of_child, - c_type_of_child, - c_variable_editable, - c_value_of_variable - } + vlang_c, + 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, + c_value_of_variable} , /* C++ */ { - vlang_cplus, - cplus_number_of_children, - cplus_name_of_variable, - cplus_name_of_child, - cplus_value_of_root, - cplus_value_of_child, - cplus_type_of_child, - cplus_variable_editable, - cplus_value_of_variable - } + vlang_cplus, + 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, + cplus_value_of_variable} , /* Java */ { - vlang_java, - java_number_of_children, - java_name_of_variable, - java_name_of_child, - java_value_of_root, - java_value_of_child, - java_type_of_child, - java_variable_editable, - java_value_of_variable - } + vlang_java, + 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, + java_value_of_variable} }; /* A little convenience enum for dealing with C++/Java */ enum vsections - { - v_public = 0, v_private, v_protected - }; +{ + v_public = 0, v_private, v_protected +}; /* Private data */ /* Mappings of varobj_display_formats enums to gdb's format codes */ -static int format_code[] = -{0, 't', 'd', 'x', 'o'}; +static int format_code[] = { 0, 't', 'd', 'x', 'o' }; /* Header of the list of root variable objects */ static struct varobj_root *rootlist; @@ -396,13 +411,38 @@ static struct vlist **varobj_table; /* API Implementation */ +static int +is_root_p (struct varobj *var) +{ + return (var->root->rootvar == var); +} /* Creates a varobj (not its children) */ +/* Return the full FRAME which corresponds to the given CORE_ADDR + or NULL if no FRAME on the chain corresponds to CORE_ADDR. */ + +static struct frame_info * +find_frame_addr_in_frame_chain (CORE_ADDR frame_addr) +{ + struct frame_info *frame = NULL; + + if (frame_addr == (CORE_ADDR) 0) + return NULL; + + while (1) + { + frame = get_prev_frame (frame); + if (frame == NULL) + return NULL; + if (get_frame_base_address (frame) == frame_addr) + return frame; + } +} + struct varobj * varobj_create (char *objname, - char *expression, CORE_ADDR frame, - enum varobj_type type) + char *expression, CORE_ADDR frame, enum varobj_type type) { struct varobj *var; struct frame_info *fi; @@ -418,24 +458,31 @@ 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 */ /* Allow creator to specify context of variable */ - if ((type == USE_CURRENT_FRAME) - || (type == USE_SELECTED_FRAME)) - fi = selected_frame; + if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME)) + fi = deprecated_safe_get_selected_frame (); else + /* FIXME: cagney/2002-11-23: This code should be doing a + lookup using the frame ID and not just the frame's + ``address''. This, of course, means an interface change. + However, with out that interface change ISAs, such as the + ia64 with its two stacks, won't work. Similar goes for the + case where there is a frameless function. */ fi = find_frame_addr_in_frame_chain (frame); /* frame = -2 means always use selected frame */ if (type == USE_SELECTED_FRAME) - var->root->use_selected_frame = 1; + var->root->floating = 1; block = NULL; if (fi != NULL) - block = get_frame_block (fi); + block = get_frame_block (fi, 0); p = expression; innermost_block = NULL; @@ -450,51 +497,55 @@ varobj_create (char *objname, if (var->root->exp->elts[0].opcode == OP_TYPE) { do_cleanups (old_chain); - fprintf_unfiltered (gdb_stderr, - "Attempt to use a type name as an expression."); + fprintf_unfiltered (gdb_stderr, "Attempt to use a type name" + " as an expression.\n"); return NULL; } 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 the expression, otherwise the value will not be current. Since select_frame is so benign, just call it for all cases. */ - if (fi != NULL) + if (innermost_block && fi != NULL) { - var->root->frame = FRAME_FP (fi); - old_fi = selected_frame; - select_frame (fi, -1); + var->root->frame = get_frame_id (fi); + var->root->thread_id = pid_to_thread_id (inferior_ptid); + old_fi = get_selected_frame (NULL); + select_frame (fi); } - /* We definitively need to catch errors here. + /* We definitely need to catch errors here. If evaluate_expression succeeds we got the value we wanted. But if it fails, we still go on with a call to evaluate_type() */ - if (gdb_evaluate_expression (var->root->exp, &var->value)) + if (!gdb_evaluate_expression (var->root->exp, &value)) { - /* no error */ - release_value (var->value); - if (VALUE_LAZY (var->value)) - gdb_value_fetch_lazy (var->value); + /* Error getting the value. Try to at least get the + right type. */ + struct value *type_only_value = evaluate_type (var->root->exp); + var->type = value_type (type_only_value); } - else - var->value = evaluate_type (var->root->exp); + else + var->type = value_type (value); - var->type = VALUE_TYPE (var->value); + install_new_value (var, value, 1 /* Initial assignment */); /* Set language info */ lang = variable_language (var); - var->root->lang = languages[lang]; + var->root->lang = &languages[lang]; /* Set ourselves as our root */ var->root->rootvar = var; /* Reset the selected frame */ if (fi != NULL) - select_frame (old_fi, -1); + select_frame (old_fi); } /* If the variable object name is null, that means this @@ -523,13 +574,13 @@ char * varobj_gen_name (void) { static int id = 0; - char obj_name[31]; + char *obj_name; /* generate a name for this object */ id++; - sprintf (obj_name, "var%d", id); + obj_name = xstrprintf ("var%d", id); - return xstrdup (obj_name); + return obj_name; } /* Given an "objname", returns the pointer to the corresponding varobj @@ -553,7 +604,7 @@ varobj_get_handle (char *objname) cv = cv->next; if (cv == NULL) - error ("Variable object not found"); + error (_("Variable object not found")); return cv->var; } @@ -612,7 +663,8 @@ varobj_delete (struct varobj *var, char ***dellist, int only_children) } if (mycount || (*cp != NULL)) - warning ("varobj_delete: assertion failed - mycount(=%d) <> 0", mycount); + warning (_("varobj_delete: assertion failed - mycount(=%d) <> 0"), + mycount); } return delcount; @@ -638,6 +690,13 @@ varobj_set_display_format (struct varobj *var, var->format = variable_default_display (var); } + if (varobj_value_is_changeable_p (var) + && var->value && !value_lazy (var->value)) + { + free (var->print_value); + var->print_value = value_get_print_value (var->value, var->format); + } + return var->format; } @@ -647,6 +706,39 @@ varobj_get_display_format (struct varobj *var) return var->format; } +/* If the variable object is bound to a specific thread, that + is its evaluation can always be done in context of a frame + inside that thread, returns GDB id of the thread -- which + is always positive. Otherwise, returns -1. */ +int +varobj_get_thread_id (struct varobj *var) +{ + if (var->root->valid_block && var->root->thread_id > 0) + return var->root->thread_id; + else + return -1; +} + +void +varobj_set_frozen (struct varobj *var, int frozen) +{ + /* When a variable is unfrozen, we don't fetch its value. + The 'not_fetched' flag remains set, so next -var-update + won't complain. + + We don't fetch the value, because for structures the client + should do -var-update anyway. It would be bad to have different + client-size logic for structure and other types. */ + var->frozen = frozen; +} + +int +varobj_get_frozen (struct varobj *var) +{ + return var->frozen; +} + + int varobj_get_num_children (struct varobj *var) { @@ -659,43 +751,41 @@ varobj_get_num_children (struct varobj *var) /* Creates a list of the immediate children of a variable object; the return code is the number of such children or -1 on error */ -int -varobj_list_children (struct varobj *var, struct varobj ***childlist) +VEC (varobj_p)* +varobj_list_children (struct varobj *var) { struct varobj *child; char *name; int i; - /* sanity check: have we been passed a pointer? */ - if (childlist == NULL) - return -1; - - *childlist = NULL; - if (var->num_children == -1) var->num_children = number_of_children (var); - /* List of children */ - *childlist = xmalloc ((var->num_children + 1) * sizeof (struct varobj *)); + /* If that failed, give up. */ + if (var->num_children == -1) + return var->children; + + /* If we're called when the list of children is not yet initialized, + allocate enough elements in it. */ + while (VEC_length (varobj_p, var->children) < var->num_children) + VEC_safe_push (varobj_p, var->children, NULL); for (i = 0; i < var->num_children; i++) { - /* Mark as the end in case we bail out */ - *((*childlist) + i) = NULL; - - /* check if child exists, if not create */ - name = name_of_child (var, i); - child = child_exists (var, name); - if (child == NULL) - child = create_child (var, i, name); + varobj_p existing = VEC_index (varobj_p, var->children, i); - *((*childlist) + i) = child; + if (existing == NULL) + { + /* Either it's the first call to varobj_list_children for + this variable object, and the child was never created, + or it was explicitly deleted by the client. */ + name = name_of_child (var, i); + existing = create_child (var, i, name); + VEC_replace (varobj_p, var->children, i, existing); + } } - /* End of list is marked by a NULL pointer */ - *((*childlist) + i) = NULL; - - return var->num_children; + return var->children; } /* Obtain the type of an object Variable as a string similar to the one gdb @@ -704,30 +794,56 @@ varobj_list_children (struct varobj *var, struct varobj ***childlist) char * varobj_get_type (struct varobj *var) { - value_ptr val; + struct value *val; struct cleanup *old_chain; struct ui_file *stb; char *thetype; long length; /* For the "fake" variables, do not return a type. (It's type is - NULL, too.) */ - if (CPLUS_FAKE_CHILD (var)) + NULL, too.) + Do not return a type for invalid variables as well. */ + if (CPLUS_FAKE_CHILD (var) || !var->root->is_valid) return NULL; stb = mem_fileopen (); old_chain = make_cleanup_ui_file_delete (stb); - /* To print the type, we simply create a zero value_ptr and + /* To print the type, we simply create a zero ``struct value *'' and cast it to our type. We then typeprint this variable. */ val = value_zero (var->type, not_lval); - type_print (VALUE_TYPE (val), "", stb, -1); + type_print (value_type (val), "", stb, -1); thetype = ui_file_xstrdup (stb, &length); do_cleanups (old_chain); return thetype; } +/* Obtain the type of an object variable. */ + +struct type * +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) { @@ -739,17 +855,24 @@ varobj_get_attributes (struct varobj *var) { int attributes = 0; - if (variable_editable (var)) + if (varobj_editable_p (var)) /* FIXME: define masks for attributes */ attributes |= 0x00000001; /* Editable */ return attributes; } +char * +varobj_get_formatted_value (struct varobj *var, + enum varobj_display_formats format) +{ + return my_value_of_variable (var, format); +} + char * varobj_get_value (struct varobj *var) { - return my_value_of_variable (var); + return my_value_of_variable (var, var->format); } /* Set the value of an object variable (if it is editable) to the @@ -759,71 +882,61 @@ varobj_get_value (struct varobj *var) int varobj_set_value (struct varobj *var, char *expression) { - value_ptr val; + struct value *val; int offset = 0; + int error = 0; /* The argument "expression" contains the variable's new value. We need to first construct a legal expression for this -- ugh! */ /* Does this cover all the bases? */ struct expression *exp; - value_ptr value; + struct value *value; int saved_input_radix = input_radix; + char *s = expression; + int i; - if (variable_editable (var) && !var->error) - { - char *s = expression; - int i; - value_ptr temp; - - input_radix = 10; /* ALWAYS reset to decimal temporarily */ - if (!gdb_parse_exp_1 (&s, 0, 0, &exp)) - /* We cannot proceed without a well-formed expression. */ - return 0; - if (!gdb_evaluate_expression (exp, &value)) - { - /* We cannot proceed without a valid expression. */ - xfree (exp); - return 0; - } - - /* If our parent is "public", "private", or "protected", we could - be asking to modify the value of a baseclass. If so, we need to - adjust our address by the offset of our baseclass in the subclass, - since VALUE_ADDRESS (var->value) points at the start of the subclass. - For some reason, value_cast doesn't take care of this properly. */ - temp = var->value; - if (var->parent != NULL && CPLUS_FAKE_CHILD (var->parent)) - { - struct varobj *super, *sub; - struct type *type; - super = var->parent->parent; - sub = super->parent; - if (sub != NULL) - { - /* Yes, it is a baseclass */ - type = get_type_deref (sub); - - if (super->index < TYPE_N_BASECLASSES (type)) - { - temp = value_copy (var->value); - for (i = 0; i < super->index; i++) - offset += TYPE_LENGTH (TYPE_FIELD_TYPE (type, i)); - } - } - } + gdb_assert (varobj_editable_p (var)); - VALUE_ADDRESS (temp) += offset; - if (!gdb_value_assign (temp, value, &val)) - return 0; - VALUE_ADDRESS (val) -= offset; - value_free (var->value); - release_value (val); - var->value = val; - input_radix = saved_input_radix; - return 1; + input_radix = 10; /* ALWAYS reset to decimal temporarily */ + exp = parse_exp_1 (&s, 0, 0); + if (!gdb_evaluate_expression (exp, &value)) + { + /* We cannot proceed without a valid expression. */ + xfree (exp); + return 0; } - return 0; + /* All types that are editable must also be changeable. */ + gdb_assert (varobj_value_is_changeable_p (var)); + + /* The value of a changeable variable object must not be lazy. */ + gdb_assert (!value_lazy (var->value)); + + /* Need to coerce the input. We want to check if the + value of the variable object will be different + after assignment, and the first thing value_assign + does is coerce the input. + For example, if we are assigning an array to a pointer variable we + should compare the pointer with the the array's address, not with the + array's content. */ + value = coerce_array (value); + + /* The new value may be lazy. gdb_value_assign, or + rather value_contents, will take care of this. + If fetching of the new value will fail, gdb_value_assign + with catch the exception. */ + if (!gdb_value_assign (var->value, value, &val)) + return 0; + + /* If the value has changed, record it, so that next -var-update can + report this change. If a variable had a value of '1', we've set it + to '333' and then set again to '1', when -var-update will report this + variable as changed -- because the first assignment has set the + 'updated' flag. There's no need to optimize that, because return value + of -var-update should be considered an approximation. */ + var->updated = install_new_value (var, val, 0 /* Compare values. */); + input_radix = saved_input_radix; + return 1; } /* Returns a malloc'ed list with all root variable objects */ @@ -850,174 +963,288 @@ varobj_list (struct varobj ***varlist) *cv = NULL; if (mycount || (croot != NULL)) - warning ("varobj_list: assertion failed - wrong tally of root vars (%d:%d)", - rootcount, mycount); + warning + ("varobj_list: assertion failed - wrong tally of root vars (%d:%d)", + rootcount, mycount); return rootcount; } +/* Assign a new value to a variable object. If INITIAL is non-zero, + this is the first assignement after the variable object was just + created, or changed type. In that case, just assign the value + and return 0. + Otherwise, assign the value and if type_changeable returns non-zero, + find if the new value is different from the current value. + Return 1 if so, and 0 if the values are equal. + + The VALUE parameter should not be released -- the function will + take care of releasing it when needed. */ +static int +install_new_value (struct varobj *var, struct value *value, int initial) +{ + int changeable; + int need_to_fetch; + int changed = 0; + int intentionally_not_fetched = 0; + char *print_value = NULL; + + /* We need to know the varobj's type to decide if the value should + be fetched or not. C++ fake children (public/protected/private) don't have + a type. */ + gdb_assert (var->type || CPLUS_FAKE_CHILD (var)); + changeable = varobj_value_is_changeable_p (var); + need_to_fetch = changeable; + + /* We are not interested in the address of references, and given + that in C++ a reference is not rebindable, it cannot + meaningfully change. So, get hold of the real value. */ + if (value) + { + value = coerce_ref (value); + release_value (value); + } + + if (var->type && TYPE_CODE (var->type) == TYPE_CODE_UNION) + /* For unions, we need to fetch the value implicitly because + of implementation of union member fetch. When gdb + creates a value for a field and the value of the enclosing + structure is not lazy, it immediately copies the necessary + bytes from the enclosing values. If the enclosing value is + lazy, the call to value_fetch_lazy on the field will read + the data from memory. For unions, that means we'll read the + same memory more than once, which is not desirable. So + fetch now. */ + need_to_fetch = 1; + + /* The new value might be lazy. If the type is changeable, + that is we'll be comparing values of this type, fetch the + value now. Otherwise, on the next update the old value + will be lazy, which means we've lost that old value. */ + if (need_to_fetch && value && value_lazy (value)) + { + struct varobj *parent = var->parent; + int frozen = var->frozen; + for (; !frozen && parent; parent = parent->parent) + frozen |= parent->frozen; + + if (frozen && initial) + { + /* For variables that are frozen, or are children of frozen + variables, we don't do fetch on initial assignment. + For non-initial assignemnt we do the fetch, since it means we're + explicitly asked to compare the new value with the old one. */ + intentionally_not_fetched = 1; + } + else if (!gdb_value_fetch_lazy (value)) + { + /* Set the value to NULL, so that for the next -var-update, + we don't try to compare the new value with this value, + that we couldn't even read. */ + value = NULL; + } + } + + /* Below, we'll be comparing string rendering of old and new + values. Don't get string rendering if the value is + lazy -- if it is, the code above has decided that the value + should not be fetched. */ + if (value && !value_lazy (value)) + print_value = value_get_print_value (value, var->format); + + /* If the type is changeable, compare the old and the new values. + If this is the initial assignment, we don't have any old value + to compare with. */ + if (!initial && changeable) + { + /* If the value of the varobj was changed by -var-set-value, then the + value in the varobj and in the target is the same. However, that value + is different from the value that the varobj had after the previous + -var-update. So need to the varobj as changed. */ + if (var->updated) + { + changed = 1; + } + else + { + /* Try to compare the values. That requires that both + values are non-lazy. */ + if (var->not_fetched && value_lazy (var->value)) + { + /* This is a frozen varobj and the value was never read. + Presumably, UI shows some "never read" indicator. + Now that we've fetched the real value, we need to report + this varobj as changed so that UI can show the real + value. */ + changed = 1; + } + else if (var->value == NULL && value == NULL) + /* Equal. */ + ; + else if (var->value == NULL || value == NULL) + { + changed = 1; + } + else + { + gdb_assert (!value_lazy (var->value)); + gdb_assert (!value_lazy (value)); + + gdb_assert (var->print_value != NULL && print_value != NULL); + if (strcmp (var->print_value, print_value) != 0) + changed = 1; + } + } + } + + /* We must always keep the new value, since children depend on it. */ + if (var->value != NULL && var->value != value) + value_free (var->value); + var->value = value; + if (var->print_value) + xfree (var->print_value); + var->print_value = print_value; + if (value && value_lazy (value) && intentionally_not_fetched) + var->not_fetched = 1; + else + var->not_fetched = 0; + var->updated = 0; + + gdb_assert (!var->value || value_type (var->value)); + + return changed; +} + /* Update the values for a variable and its children. This is a two-pronged attack. First, re-parse the value for the root's expression to see if it's changed. Then go all the way through its children, reconstructing them and noting if they've changed. - Return value: - -1 if there was an error updating the varobj - -2 if the type changed - Otherwise it is the number of children + parent changed + Return value: + < 0 for error values, see varobj.h. + Otherwise it is the number of children + parent changed. - Only root variables can be updated... */ + The EXPLICIT parameter specifies if this call is result + of MI request to update this specific variable, or + result of implicit -var-update *. For implicit request, we don't + update frozen variables. + + NOTE: This function may delete the caller's varobj. If it + returns TYPE_CHANGED, then it has done this and VARP will be modified + to point to the new varobj. */ int -varobj_update (struct varobj *var, struct varobj ***changelist) +varobj_update (struct varobj **varp, struct varobj ***changelist, + int explicit) { int changed = 0; - int type_changed; + int type_changed = 0; int i; int vleft; - int error2; struct varobj *v; struct varobj **cv; struct varobj **templist = NULL; - value_ptr new; - struct vstack *stack = NULL; - struct vstack *result = NULL; - struct frame_info *old_fi; - - /* sanity check: have we been passed a pointer? */ - if (changelist == NULL) - return -1; + struct value *new; + VEC (varobj_p) *stack = NULL; + VEC (varobj_p) *result = NULL; + struct frame_info *fi; - /* Only root variables can be updated... */ - if (var->root->rootvar != var) - /* Not a root var */ - return -1; + /* sanity check: have we been passed a pointer? */ + gdb_assert (changelist); - /* Save the selected stack frame, since we will need to change it - in order to evaluate expressions. */ - old_fi = selected_frame; - - /* Update the root variable. value_of_root can return NULL - if the variable is no longer around, i.e. we stepped out of - the frame in which a local existed. We are letting the - value_of_root variable dispose of the varobj if the type - has changed. */ - type_changed = 1; - new = value_of_root (&var, &type_changed); - if (new == NULL) - { - var->error = 1; - return -1; - } + /* Frozen means frozen -- we don't check for any change in + this varobj, including its going out of scope, or + changing type. One use case for frozen varobjs is + retaining previously evaluated expressions, and we don't + want them to be reevaluated at all. */ + if (!explicit && (*varp)->frozen) + return 0; - /* Initialize a stack for temporary results */ - vpush (&result, NULL); + if (!(*varp)->root->is_valid) + return INVALID; - /* If this is a "use_selected_frame" varobj, and its type has changed, - them note that it's changed. */ - if (type_changed) - { - vpush (&result, var); - changed++; - } - /* If values are not equal, note that it's changed. - There a couple of exceptions here, though. - We don't want some types to be reported as "changed". */ - else if (type_changeable (var) && !my_value_equal (var->value, new, &error2)) + if ((*varp)->root->rootvar == *varp) { - vpush (&result, var); - changed++; - /* error2 replaces var->error since this new value - WILL replace the old one. */ - var->error = error2; + /* Update the root variable. value_of_root can return NULL + if the variable is no longer around, i.e. we stepped out of + the frame in which a local existed. We are letting the + value_of_root variable dispose of the varobj if the type + has changed. */ + new = value_of_root (varp, &type_changed); + + /* If this is a floating varobj, and its type has changed, + them note that it's changed. */ + if (type_changed) + VEC_safe_push (varobj_p, result, *varp); + + if (install_new_value ((*varp), new, type_changed)) + { + /* If type_changed is 1, install_new_value will never return + non-zero, so we'll never report the same variable twice. */ + gdb_assert (!type_changed); + VEC_safe_push (varobj_p, result, *varp); + } + + if (new == NULL) + { + /* This means the varobj itself is out of scope. + Report it. */ + VEC_free (varobj_p, result); + return NOT_IN_SCOPE; + } } - /* We must always keep around the new value for this root - variable expression, or we lose the updated children! */ - value_free (var->value); - var->value = new; + VEC_safe_push (varobj_p, stack, *varp); - /* Initialize a stack */ - vpush (&stack, NULL); - - /* Push the root's children */ - if (var->children != NULL) + /* Walk through the children, reconstructing them all. */ + while (!VEC_empty (varobj_p, stack)) { - struct varobj_child *c; - for (c = var->children; c != NULL; c = c->next) - vpush (&stack, c->child); - } + v = VEC_pop (varobj_p, stack); - /* Walk through the children, reconstructing them all. */ - v = vpop (&stack); - while (v != NULL) - { - /* Push any children */ - if (v->children != NULL) + /* Push any children. Use reverse order so that the first + child is popped from the work stack first, and so + will be added to result first. This does not + affect correctness, just "nicer". */ + for (i = VEC_length (varobj_p, v->children)-1; i >= 0; --i) { - struct varobj_child *c; - for (c = v->children; c != NULL; c = c->next) - vpush (&stack, c->child); + varobj_p c = VEC_index (varobj_p, v->children, i); + /* Child may be NULL if explicitly deleted by -var-delete. */ + if (c != NULL && !c->frozen) + VEC_safe_push (varobj_p, stack, c); } - /* Update this variable */ - new = value_of_child (v->parent, v->index); - if (type_changeable (v) && !my_value_equal (v->value, new, &error2)) - { - /* Note that it's changed */ - vpush (&result, v); - changed++; + /* Update this variable, unless it's a root, which is already + updated. */ + if (v->root->rootvar != v) + { + new = value_of_child (v->parent, v->index); + if (install_new_value (v, new, 0 /* type not changed */)) + { + /* Note that it's changed */ + VEC_safe_push (varobj_p, result, v); + v->updated = 0; + } } - /* error2 replaces v->error since this new value - WILL replace the old one. */ - v->error = error2; - - /* We must always keep new values, since children depend on it. */ - if (v->value != NULL) - value_free (v->value); - v->value = new; - - /* Get next child */ - v = vpop (&stack); } - /* Alloc (changed + 1) list entries */ - /* FIXME: add a cleanup for the allocated list(s) - because one day the select_frame called below can longjump */ + /* Alloc (changed + 1) list entries. */ + changed = VEC_length (varobj_p, result); *changelist = xmalloc ((changed + 1) * sizeof (struct varobj *)); - if (changed > 1) - { - templist = xmalloc ((changed + 1) * sizeof (struct varobj *)); - cv = templist; - } - else - cv = *changelist; - - /* Copy from result stack to list */ - vleft = changed; - *cv = vpop (&result); - while ((*cv != NULL) && (vleft > 0)) - { - vleft--; - cv++; - *cv = vpop (&result); - } - if (vleft) - warning ("varobj_update: assertion failed - vleft <> 0"); + cv = *changelist; - if (changed > 1) + for (i = 0; i < changed; ++i) { - /* Now we revert the order. */ - for (i=0; i < changed; i++) - *(*changelist + i) = *(templist + changed -1 - i); - *(*changelist + changed) = NULL; + *cv = VEC_index (varobj_p, result, i); + gdb_assert (*cv != NULL); + ++cv; } + *cv = 0; - /* Restore selected frame */ - select_frame (old_fi, -1); + VEC_free (varobj_p, stack); + VEC_free (varobj_p, result); if (type_changed) - return -2; + return TYPE_CHANGED; else return changed; } @@ -1046,21 +1273,23 @@ delete_variable (struct cpstack **resultp, struct varobj *var, and the parent is not removed we dump core. It must be always initially called with remove_from_parent_p set */ static void -delete_variable_1 (struct cpstack **resultp, int *delcountp, struct varobj *var, - int only_children_p, int remove_from_parent_p) +delete_variable_1 (struct cpstack **resultp, int *delcountp, + struct varobj *var, int only_children_p, + int remove_from_parent_p) { - struct varobj_child *vc; - struct varobj_child *next; + int i; /* Delete any children of this variable, too. */ - for (vc = var->children; vc != NULL; vc = next) - { + for (i = 0; i < VEC_length (varobj_p, var->children); ++i) + { + varobj_p child = VEC_index (varobj_p, var->children, i); + if (!child) + continue; if (!remove_from_parent_p) - vc->child->parent = NULL; - delete_variable_1 (resultp, delcountp, vc->child, 0, only_children_p); - next = vc->next; - xfree (vc); + child->parent = NULL; + delete_variable_1 (resultp, delcountp, child, 0, only_children_p); } + VEC_free (varobj_p, var->children); /* if we were called to delete only the children we are done here */ if (only_children_p) @@ -1080,12 +1309,11 @@ delete_variable_1 (struct cpstack **resultp, int *delcountp, struct varobj *var, (as indicated by remove_from_parent_p) we don't bother doing an expensive list search to find the element to remove when we are discarding the list afterwards */ - if ((remove_from_parent_p) && - (var->parent != NULL)) + if ((remove_from_parent_p) && (var->parent != NULL)) { - remove_child_from_parent (var->parent, var); + VEC_replace (varobj_p, var->parent->children, var->index, NULL); } - + if (var->obj_name != NULL) uninstall_variable (var); @@ -1113,7 +1341,7 @@ install_variable (struct varobj *var) cv = cv->next; if (cv != NULL) - error ("Duplicate variable object name"); + error (_("Duplicate variable object name")); /* Add varobj to hash table */ newvl = xmalloc (sizeof (struct vlist)); @@ -1122,7 +1350,7 @@ install_variable (struct varobj *var) *(varobj_table + index) = newvl; /* If root, add varobj to root list */ - if (var->root->rootvar == var) + if (is_root_p (var)) { /* Add to list of root variables */ if (rootlist == NULL) @@ -1167,7 +1395,9 @@ uninstall_variable (struct varobj *var) if (cv == NULL) { - warning ("Assertion failed: Could not find variable object \"%s\" to delete", var->obj_name); + warning + ("Assertion failed: Could not find variable object \"%s\" to delete", + var->obj_name); return; } @@ -1179,7 +1409,7 @@ uninstall_variable (struct varobj *var) xfree (cv); /* If root, remove varobj from root list */ - if (var->root->rootvar == var) + if (is_root_p (var)) { /* Remove from list of root variables */ if (rootlist == var->root) @@ -1195,7 +1425,9 @@ uninstall_variable (struct varobj *var) } if (cr == NULL) { - warning ("Assertion failed: Could not find varobj \"%s\" in root list", var->obj_name); + warning + ("Assertion failed: Could not find varobj \"%s\" in root list", + var->obj_name); return; } if (prer == NULL) @@ -1208,92 +1440,39 @@ uninstall_variable (struct varobj *var) } -/* Does a child with the name NAME exist in VAR? If so, return its data. - If not, return NULL. */ -static struct varobj * -child_exists (struct varobj *var, char *name) -{ - struct varobj_child *vc; - - for (vc = var->children; vc != NULL; vc = vc->next) - { - if (STREQ (vc->child->name, name)) - return vc->child; - } - - return NULL; -} - /* Create and install a child of the parent of the given name */ static struct varobj * create_child (struct varobj *parent, int index, char *name) { struct varobj *child; char *childs_name; + struct value *value; child = new_variable (); /* name is allocated by name_of_child */ child->name = name; child->index = index; - child->value = value_of_child (parent, index); - if (child->value == NULL || parent->error) - child->error = 1; + value = value_of_child (parent, index); child->parent = parent; child->root = parent->root; - childs_name = (char *) xmalloc ((strlen (parent->obj_name) + strlen (name) + 2) - * sizeof (char)); - sprintf (childs_name, "%s.%s", parent->obj_name, name); + childs_name = xstrprintf ("%s.%s", parent->obj_name, name); child->obj_name = childs_name; install_variable (child); - /* Save a pointer to this child in the parent */ - save_child_in_parent (parent, child); - - /* Note the type of this child */ - child->type = type_of_child (child); - - return child; -} - -/* FIXME: This should be a generic add to list */ -/* Save CHILD in the PARENT's data. */ -static void -save_child_in_parent (struct varobj *parent, struct varobj *child) -{ - struct varobj_child *vc; - - /* Insert the child at the top */ - vc = parent->children; - parent->children = - (struct varobj_child *) xmalloc (sizeof (struct varobj_child)); - - parent->children->next = vc; - parent->children->child = child; -} - -/* FIXME: This should be a generic remove from list */ -/* Remove the CHILD from the PARENT's list of children. */ -static void -remove_child_from_parent (struct varobj *parent, struct varobj *child) -{ - struct varobj_child *vc, *prev; - - /* Find the child in the parent's list */ - prev = NULL; - for (vc = parent->children; vc != NULL;) - { - if (vc->child == child) - break; - prev = vc; - vc = vc->next; - } - - if (prev == NULL) - parent->children = vc->next; + /* Compute the type of the child. Must do this before + calling install_new_value. */ + if (value != NULL) + /* If the child had no evaluation errors, var->value + will be non-NULL and contain a valid type. */ + child->type = value_type (value); else - prev->next = vc->next; + /* Otherwise, we must compute the type. */ + child->type = (*child->root->lang->type_of_child) (child->parent, + child->index); + install_new_value (child, value, 1); + return child; } @@ -1309,16 +1488,20 @@ 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; var->value = NULL; - var->error = 0; var->num_children = -1; var->parent = NULL; var->children = NULL; var->format = 0; var->root = NULL; + var->updated = 0; + var->print_value = NULL; + var->frozen = 0; + var->not_fetched = 0; return var; } @@ -1332,9 +1515,10 @@ new_root_variable (void) var->root->lang = NULL; var->root->exp = NULL; var->root->valid_block = NULL; - var->root->frame = (CORE_ADDR) -1; - var->root->use_selected_frame = 0; + var->root->frame = null_frame_id; + var->root->floating = 0; var->root->rootvar = NULL; + var->root->is_valid = 1; return var; } @@ -1344,14 +1528,16 @@ static void free_variable (struct varobj *var) { /* Free the expression if this is a root variable. */ - if (var->root->rootvar == var) + if (is_root_p (var)) { - free_current_contents ((char **) &var->root->exp); + free_current_contents (&var->root->exp); xfree (var->root); } xfree (var->name); xfree (var->obj_name); + xfree (var->print_value); + xfree (var->path_expr); xfree (var); } @@ -1367,46 +1553,67 @@ make_cleanup_free_variable (struct varobj *var) return make_cleanup (do_free_variable_cleanup, var); } -/* This returns the type of the variable. This skips past typedefs - and returns the real type of the variable. It also dereferences - pointers and references. */ +/* This returns the type of the variable. It also skips past typedefs + to return the real type of the variable. + + NOTE: TYPE_TARGET_TYPE should NOT be used anywhere in this file + except within get_target_type and get_type. */ static struct type * get_type (struct varobj *var) { struct type *type; type = var->type; - while (type != NULL && TYPE_CODE (type) == TYPE_CODE_TYPEDEF) - type = TYPE_TARGET_TYPE (type); + if (type != NULL) + type = check_typedef (type); return type; } -/* This returns the type of the variable, dereferencing pointers, too. */ +/* Return the type of the value that's stored in VAR, + or that would have being stored there if the + value were accessible. + + This differs from VAR->type in that VAR->type is always + the true type of the expession in the source language. + The return value of this function is the type we're + actually storing in varobj, and using for displaying + the values and for comparing previous and new values. + + For example, top-level references are always stripped. */ static struct type * -get_type_deref (struct varobj *var) +get_value_type (struct varobj *var) { struct type *type; - type = get_type (var); + if (var->value) + type = value_type (var->value); + else + type = var->type; + + type = check_typedef (type); - if (type != NULL && (TYPE_CODE (type) == TYPE_CODE_PTR - || TYPE_CODE (type) == TYPE_CODE_REF)) + if (TYPE_CODE (type) == TYPE_CODE_REF) type = get_target_type (type); + type = check_typedef (type); + return type; } /* This returns the target type (or NULL) of TYPE, also skipping - past typedefs, just like get_type (). */ + past typedefs, just like get_type (). + + NOTE: TYPE_TARGET_TYPE should NOT be used anywhere in this file + except within get_target_type and get_type. */ static struct type * get_target_type (struct type *type) { if (type != NULL) { type = TYPE_TARGET_TYPE (type); - while (type != NULL && TYPE_CODE (type) == TYPE_CODE_TYPEDEF) - type = TYPE_TARGET_TYPE (type); + if (type != NULL) + type = check_typedef (type); } return type; @@ -1420,113 +1627,27 @@ variable_default_display (struct varobj *var) return FORMAT_NATURAL; } -/* This function is similar to gdb's value_equal, except that this - one is "safe" -- it NEVER longjmps. It determines if the VAR's - value is the same as VAL2. */ -static int -my_value_equal (value_ptr val1, value_ptr val2, int *error2) +/* FIXME: The following should be generic for any pointer */ +static void +cppush (struct cpstack **pstack, char *name) { - int r, err1, err2; - - *error2 = 0; - /* Special case: NULL values. If both are null, say - they're equal. */ - if (val1 == NULL && val2 == NULL) - return 1; - else if (val1 == NULL || val2 == NULL) - return 0; + struct cpstack *s; - /* This is bogus, but unfortunately necessary. We must know - exactly what caused an error -- reading val1 or val2 -- so - that we can really determine if we think that something has changed. */ - err1 = 0; - err2 = 0; - /* We do need to catch errors here because the whole purpose - is to test if value_equal() has errored */ - if (!gdb_value_equal (val1, val1, &r)) - err1 = 1; + s = (struct cpstack *) xmalloc (sizeof (struct cpstack)); + s->name = name; + s->next = *pstack; + *pstack = s; +} - if (!gdb_value_equal (val2, val2, &r)) - *error2 = err2 = 1; +/* FIXME: The following should be generic for any pointer */ +static char * +cppop (struct cpstack **pstack) +{ + struct cpstack *s; + char *v; - if (err1 != err2) - return 0; - - if (!gdb_value_equal (val1, val2, &r)) - { - /* An error occurred, this could have happened if - either val1 or val2 errored. ERR1 and ERR2 tell - us which of these it is. If both errored, then - we assume nothing has changed. If one of them is - valid, though, then something has changed. */ - if (err1 == err2) - { - /* both the old and new values caused errors, so - we say the value did not change */ - /* This is indeterminate, though. Perhaps we should - be safe and say, yes, it changed anyway?? */ - return 1; - } - else - { - return 0; - } - } - - return r; -} - -/* FIXME: The following should be generic for any pointer */ -static void -vpush (struct vstack **pstack, struct varobj *var) -{ - struct vstack *s; - - s = (struct vstack *) xmalloc (sizeof (struct vstack)); - s->var = var; - s->next = *pstack; - *pstack = s; -} - -/* FIXME: The following should be generic for any pointer */ -static struct varobj * -vpop (struct vstack **pstack) -{ - struct vstack *s; - struct varobj *v; - - if ((*pstack)->var == NULL && (*pstack)->next == NULL) - return NULL; - - s = *pstack; - v = s->var; - *pstack = (*pstack)->next; - xfree (s); - - return v; -} - -/* FIXME: The following should be generic for any pointer */ -static void -cppush (struct cpstack **pstack, char *name) -{ - struct cpstack *s; - - s = (struct cpstack *) xmalloc (sizeof (struct cpstack)); - s->name = name; - s->next = *pstack; - *pstack = s; -} - -/* FIXME: The following should be generic for any pointer */ -static char * -cppop (struct cpstack **pstack) -{ - struct cpstack *s; - char *v; - - if ((*pstack)->name == NULL && (*pstack)->next == NULL) - return NULL; + if ((*pstack)->name == NULL && (*pstack)->next == NULL) + return NULL; s = *pstack; v = s->name; @@ -1590,17 +1711,16 @@ name_of_child (struct varobj *var, int index) return (*var->root->lang->name_of_child) (var, index); } -/* What is the value_ptr of the root variable VAR? - TYPE_CHANGED controls what to do if the type of a - use_selected_frame = 1 variable changes. On input, - TYPE_CHANGED = 1 means discard the old varobj, and replace - it with this one. TYPE_CHANGED = 0 means leave it around. - NB: In both cases, var_handle will point to the new varobj, - so if you use TYPE_CHANGED = 0, you will have to stash the - old varobj pointer away somewhere before calling this. - On return, TYPE_CHANGED will be 1 if the type has changed, and - 0 otherwise. */ -static value_ptr +/* What is the ``struct value *'' of the root variable VAR? + For floating variable object, evaluation can get us a value + of different type from what is stored in varobj already. In + that case: + - *type_changed will be set to 1 + - old varobj will be freed, and new one will be + created, with the same name. + - *var_handle will be set to the new varobj + Otherwise, *type_changed will be set to 0. */ +static struct value * value_of_root (struct varobj **var_handle, int *type_changed) { struct varobj *var; @@ -1613,42 +1733,50 @@ value_of_root (struct varobj **var_handle, int *type_changed) /* This should really be an exception, since this should only get called with a root variable. */ - if (var->root->rootvar != var) + if (!is_root_p (var)) return NULL; - if (var->root->use_selected_frame) + if (var->root->floating) { struct varobj *tmp_var; char *old_type, *new_type; - old_type = varobj_get_type (var); + tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0, USE_SELECTED_FRAME); if (tmp_var == NULL) { return NULL; } + old_type = varobj_get_type (var); new_type = varobj_get_type (tmp_var); - if (strcmp(old_type, new_type) == 0) + if (strcmp (old_type, new_type) == 0) { + /* The expression presently stored inside var->root->exp + remembers the locations of local variables relatively to + the frame where the expression was created (in DWARF location + button, for example). Naturally, those locations are not + correct in other frames, so update the expression. */ + + struct expression *tmp_exp = var->root->exp; + var->root->exp = tmp_var->root->exp; + tmp_var->root->exp = tmp_exp; + varobj_delete (tmp_var, NULL, 0); *type_changed = 0; } else { - if (*type_changed) - { - tmp_var->obj_name = - savestring (var->obj_name, strlen (var->obj_name)); - varobj_delete (var, NULL, 0); - } - else - { - tmp_var->obj_name = varobj_gen_name (); - } + tmp_var->obj_name = + savestring (var->obj_name, strlen (var->obj_name)); + varobj_delete (var, NULL, 0); + install_variable (tmp_var); *var_handle = tmp_var; + var = *var_handle; *type_changed = 1; } + xfree (old_type); + xfree (new_type); } else { @@ -1658,55 +1786,86 @@ value_of_root (struct varobj **var_handle, int *type_changed) return (*var->root->lang->value_of_root) (var_handle); } -/* What is the value_ptr for the INDEX'th child of PARENT? */ -static value_ptr +/* What is the ``struct value *'' for the INDEX'th child of PARENT? */ +static struct value * value_of_child (struct varobj *parent, int index) { - value_ptr value; + struct value *value; value = (*parent->root->lang->value_of_child) (parent, index); - /* If we're being lazy, fetch the real value of the variable. */ - if (value != NULL && VALUE_LAZY (value)) - gdb_value_fetch_lazy (value); - return value; } -/* What is the type of VAR? */ -static struct type * -type_of_child (struct varobj *var) +/* GDB already has a command called "value_of_variable". Sigh. */ +static char * +my_value_of_variable (struct varobj *var, enum varobj_display_formats format) { - - /* If the child had no evaluation errors, var->value - will be non-NULL and contain a valid type. */ - if (var->value != NULL) - return VALUE_TYPE (var->value); - - /* Otherwise, we must compute the type. */ - return (*var->root->lang->type_of_child) (var->parent, var->index); + if (var->root->is_valid) + return (*var->root->lang->value_of_variable) (var, format); + else + return NULL; } -/* Is this variable editable? Use the variable's type to make - this determination. */ -static int -variable_editable (struct varobj *var) +static char * +value_get_print_value (struct value *value, enum varobj_display_formats format) { - return (*var->root->lang->variable_editable) (var); + long dummy; + struct ui_file *stb; + struct cleanup *old_chain; + char *thevalue; + + if (value == NULL) + return NULL; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + common_val_print (value, stb, format_code[(int) format], 1, 0, 0); + thevalue = ui_file_xstrdup (stb, &dummy); + + do_cleanups (old_chain); + return thevalue; } -/* GDB already has a command called "value_of_variable". Sigh. */ -static char * -my_value_of_variable (struct varobj *var) +int +varobj_editable_p (struct varobj *var) { - return (*var->root->lang->value_of_variable) (var); + struct type *type; + struct value *value; + + if (!(var->root->is_valid && var->value && VALUE_LVAL (var->value))) + return 0; + + type = get_value_type (var); + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + case TYPE_CODE_ARRAY: + case TYPE_CODE_FUNC: + case TYPE_CODE_METHOD: + return 0; + break; + + default: + return 1; + break; + } } -/* Is VAR something that can change? Depending on language, - some variable's values never change. For example, - struct and unions never change values. */ +/* Return non-zero if changes in value of VAR + must be detected and reported by -var-update. + Return zero is -var-update should never report + changes of such values. This makes sense for structures + (since the changes in children values will be reported separately), + or for artifical objects (like 'public' pseudo-field in C++). + + Return value of 0 means that gdb need not call value_fetch_lazy + for the value of this variable object. */ static int -type_changeable (struct varobj *var) +varobj_value_is_changeable_p (struct varobj *var) { int r; struct type *type; @@ -1714,43 +1873,112 @@ type_changeable (struct varobj *var) if (CPLUS_FAKE_CHILD (var)) return 0; - type = get_type (var); + type = get_value_type (var); switch (TYPE_CODE (type)) { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - case TYPE_CODE_ARRAY: - r = 0; - break; - - default: - r = 1; + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + case TYPE_CODE_ARRAY: + r = 0; + break; + + default: + r = 1; } return r; } +/* Return 1 if that varobj is floating, that is is always evaluated in the + selected frame, and not bound to thread/frame. Such variable objects + are created using '@' as frame specifier to -var-create. */ +int +varobj_floating_p (struct varobj *var) +{ + return var->root->floating; +} + +/* Given the value and the type of a variable object, + adjust the value and type to those necessary + for getting children of the variable object. + This includes dereferencing top-level references + to all types and dereferencing pointers to + structures. + + 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. + + 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, + 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 + to us, is already supposed to be + reference-stripped. */ + + gdb_assert (TYPE_CODE (*type) != TYPE_CODE_REF); + + /* Pointers to structures are treated just like + structures when accessing children. Don't + dererences pointers to other types. */ + if (TYPE_CODE (*type) == TYPE_CODE_PTR) + { + struct type *target_type = get_target_type (*type); + if (TYPE_CODE (target_type) == TYPE_CODE_STRUCT + || TYPE_CODE (target_type) == TYPE_CODE_UNION) + { + if (value && *value) + { + int success = gdb_value_ind (*value, value); + if (!success) + *value = NULL; + } + *type = target_type; + if (was_ptr) + *was_ptr = 1; + } + } + + /* The 'get_target_type' function calls check_typedef on + result, so we can immediately check type code. No + need to call check_typedef here. */ +} + /* C */ static int c_number_of_children (struct varobj *var) { - struct type *type; + struct type *type = get_value_type (var); + int children = 0; struct type *target; - int children; - type = get_type (var); + adjust_value_for_child_access (NULL, &type, NULL); target = get_target_type (type); - children = 0; switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (target) > 0 - && TYPE_ARRAY_UPPER_BOUND_TYPE (type) != BOUND_CANNOT_BE_DETERMINED) + && TYPE_ARRAY_UPPER_BOUND_TYPE (type) != BOUND_CANNOT_BE_DETERMINED) children = TYPE_LENGTH (type) / TYPE_LENGTH (target); else - children = -1; + /* If we don't know how many elements there are, don't display + any. */ + children = 0; break; case TYPE_CODE_STRUCT: @@ -1759,30 +1987,19 @@ c_number_of_children (struct varobj *var) break; case TYPE_CODE_PTR: - /* This is where things get compilcated. All pointers have one child. - Except, of course, for struct and union ptr, which we automagically - dereference for the user and function ptrs, which have no children. - We also don't dereference void* as we don't know what to show. + /* The type here is a pointer to non-struct. Typically, pointers + have one child, except for function ptrs, which have no children, + and except for void*, as we don't know what to show. + We can show char* so we allow it to be dereferenced. If you decide to test for it, please mind that a little magic is necessary to properly identify it: char* has TYPE_CODE == TYPE_CODE_INT and TYPE_NAME == "char" */ - - switch (TYPE_CODE (target)) - { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - children = TYPE_NFIELDS (target); - break; - - case TYPE_CODE_FUNC: - case TYPE_CODE_VOID: - children = 0; - break; - - default: - children = 1; - } + if (TYPE_CODE (target) == TYPE_CODE_FUNC + || TYPE_CODE (target) == TYPE_CODE_VOID) + children = 0; + else + children = 1; break; default: @@ -1799,176 +2016,252 @@ c_name_of_variable (struct varobj *parent) return savestring (parent->name, strlen (parent->name)); } -static char * -c_name_of_child (struct varobj *parent, int index) +/* Return the value of element TYPE_INDEX of a structure + value VALUE. VALUE's type should be a structure, + or union, or a typedef to struct/union. + + Returns NULL if getting the value fails. Never throws. */ +static struct value * +value_struct_element_index (struct value *value, int type_index) { - struct type *type; - struct type *target; - char *name; - char *string; + struct value *result = NULL; + volatile struct gdb_exception e; - type = get_type (parent); - target = get_target_type (type); + struct type *type = value_type (value); + type = check_typedef (type); + + gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION); + TRY_CATCH (e, RETURN_MASK_ERROR) + { + if (TYPE_FIELD_STATIC (type, type_index)) + result = value_static_field (type, type_index); + else + result = value_primitive_field (value, 0, type_index, type); + } + if (e.reason < 0) + { + return NULL; + } + else + { + return result; + } +} + +/* Obtain the information about child INDEX of the variable + object PARENT. + If CNAME is not null, sets *CNAME to the name of the child relative + to the parent. + If CVALUE is not null, sets *CVALUE to the value of the child. + If CTYPE is not null, sets *CTYPE to the type of the child. + + If any of CNAME, CVALUE, or CTYPE is not null, but the corresponding + information cannot be determined, set *CNAME, *CVALUE, or *CTYPE + to NULL. */ +static void +c_describe_child (struct varobj *parent, int index, + 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; + if (cvalue) + *cvalue = NULL; + if (ctype) + *ctype = NULL; + 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)) { case TYPE_CODE_ARRAY: - { - /* We never get here unless parent->num_children is greater than 0... */ - int len = 1; - while ((int) pow ((double) 10, (double) len) < index) - len++; - name = (char *) xmalloc (1 + len * sizeof (char)); - sprintf (name, "%d", index); - } + if (cname) + *cname = xstrprintf ("%d", index + + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type))); + + if (cvalue && value) + { + int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)); + struct value *indval = + value_from_longest (builtin_type_int, (LONGEST) real_index); + gdb_value_subscript (value, indval, cvalue); + } + + 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: case TYPE_CODE_UNION: - string = TYPE_FIELD_NAME (type, index); - name = savestring (string, strlen (string)); + if (cname) + { + char *string = TYPE_FIELD_NAME (type, index); + *cname = savestring (string, strlen (string)); + } + + if (cvalue && value) + { + /* For C, varobj index is the same as type index. */ + *cvalue = value_struct_element_index (value, 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: - switch (TYPE_CODE (target)) + if (cname) + *cname = xstrprintf ("*%s", parent->name); + + if (cvalue && value) { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - string = TYPE_FIELD_NAME (target, index); - name = savestring (string, strlen (string)); - break; - - default: - name = (char *) xmalloc ((strlen (parent->name) + 2) * sizeof (char)); - sprintf (name, "*%s", parent->name); - break; + int success = gdb_value_ind (value, cvalue); + if (!success) + *cvalue = NULL; } + + /* Don't use get_target_type because it calls + check_typedef and here, we want to show the true + declared type of the variable. */ + if (ctype) + *ctype = TYPE_TARGET_TYPE (type); + + if (cfull_expression) + *cfull_expression = xstrprintf ("*(%s)", parent_expression); + break; default: /* This should not happen */ - name = xstrdup ("???"); + if (cname) + *cname = xstrdup ("???"); + if (cfull_expression) + *cfull_expression = xstrdup ("???"); + /* Don't set value and type, we don't know then. */ } +} +static char * +c_name_of_child (struct varobj *parent, int index) +{ + char *name; + c_describe_child (parent, index, &name, NULL, NULL, NULL); return name; } -static value_ptr +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; +} + +/* If frame associated with VAR can be found, switch + to it and return 1. Otherwise, return 0. */ +static int +check_scope (struct varobj *var) +{ + struct frame_info *fi; + int scope; + + fi = frame_find_by_id (var->root->frame); + scope = fi != NULL; + + if (fi) + { + CORE_ADDR pc = get_frame_pc (fi); + if (pc < BLOCK_START (var->root->valid_block) || + pc >= BLOCK_END (var->root->valid_block)) + scope = 0; + else + select_frame (fi); + } + return scope; +} + +static struct value * c_value_of_root (struct varobj **var_handle) { - value_ptr new_val; + struct value *new_val = NULL; struct varobj *var = *var_handle; struct frame_info *fi; - int within_scope; - + int within_scope = 0; + struct cleanup *back_to; + /* Only root variables can be updated... */ - if (var->root->rootvar != var) + if (!is_root_p (var)) /* Not a root var */ return NULL; - + back_to = make_cleanup_restore_current_thread ( + inferior_ptid, get_frame_id (deprecated_safe_get_selected_frame ())); + /* Determine whether the variable is still around. */ - if (var->root->valid_block == NULL) + if (var->root->valid_block == NULL || var->root->floating) within_scope = 1; + else if (var->root->thread_id == 0) + { + /* The program was single-threaded when the variable object was + created. Technically, it's possible that the program became + multi-threaded since then, but we don't support such + scenario yet. */ + within_scope = check_scope (var); + } else { - reinit_frame_cache (); - - - fi = find_frame_addr_in_frame_chain (var->root->frame); - - within_scope = fi != NULL; - /* FIXME: select_frame could fail */ - if (within_scope) - select_frame (fi, -1); + ptid_t ptid = thread_id_to_pid (var->root->thread_id); + if (in_thread_list (ptid)) + { + switch_to_thread (ptid); + within_scope = check_scope (var); + } } - + if (within_scope) { /* We need to catch errors here, because if evaluate - expression fails we just want to make val->error = 1 and - go on */ - if (gdb_evaluate_expression (var->root->exp, &new_val)) - { - if (VALUE_LAZY (new_val)) - { - /* We need to catch errors because if - value_fetch_lazy fails we still want to continue - (after making val->error = 1) */ - /* FIXME: Shouldn't be using VALUE_CONTENTS? The - comment on value_fetch_lazy() says it is only - called from the macro... */ - if (!gdb_value_fetch_lazy (new_val)) - var->error = 1; - else - var->error = 0; - } - } - else - var->error = 1; - - release_value (new_val); + expression fails we want to just return NULL. */ + gdb_evaluate_expression (var->root->exp, &new_val); return new_val; } + do_cleanups (back_to); + return NULL; } -static value_ptr +static struct value * c_value_of_child (struct varobj *parent, int index) { - value_ptr value, temp, indval; - struct type *type, *target; - char *name; - - type = get_type (parent); - target = get_target_type (type); - name = name_of_child (parent, index); - temp = parent->value; - value = NULL; - - if (temp != NULL) - { - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: -#if 0 - /* This breaks if the array lives in a (vector) register. */ - value = value_slice (temp, index, 1); - temp = value_coerce_array (value); - gdb_value_ind (temp, &value); -#else - indval = value_from_longest (builtin_type_int, (LONGEST) index); - gdb_value_subscript (temp, indval, &value); -#endif - break; - - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - value = value_struct_elt (&temp, NULL, name, NULL, "vstructure"); - break; - - case TYPE_CODE_PTR: - switch (TYPE_CODE (target)) - { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - value = value_struct_elt (&temp, NULL, name, NULL, "vstructure"); - break; - - default: - gdb_value_ind (temp, &value); - break; - } - break; - - default: - break; - } - } - - if (value != NULL) - release_value (value); + struct value *value = NULL; + c_describe_child (parent, index, NULL, &value, NULL, NULL); return value; } @@ -1976,83 +2269,23 @@ c_value_of_child (struct varobj *parent, int index) static struct type * c_type_of_child (struct varobj *parent, int index) { - struct type *type; - char *name = name_of_child (parent, index); - - switch (TYPE_CODE (parent->type)) - { - case TYPE_CODE_ARRAY: - type = TYPE_TARGET_TYPE (parent->type); - break; - - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - type = lookup_struct_elt_type (parent->type, name, 0); - break; - - case TYPE_CODE_PTR: - switch (TYPE_CODE (TYPE_TARGET_TYPE (parent->type))) - { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - type = lookup_struct_elt_type (parent->type, name, 0); - break; - - default: - type = TYPE_TARGET_TYPE (parent->type); - break; - } - break; - - default: - /* This should not happen as only the above types have children */ - warning ("Child of parent whose type does not allow children"); - /* FIXME: Can we still go on? */ - type = NULL; - break; - } - + struct type *type = NULL; + c_describe_child (parent, index, NULL, NULL, &type, NULL); return type; } -static int -c_variable_editable (struct varobj *var) -{ - switch (TYPE_CODE (get_type (var))) - { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - case TYPE_CODE_ARRAY: - case TYPE_CODE_FUNC: - case TYPE_CODE_MEMBER: - case TYPE_CODE_METHOD: - return 0; - break; - - default: - return 1; - break; - } -} - static char * -c_value_of_variable (struct varobj *var) +c_value_of_variable (struct varobj *var, enum varobj_display_formats format) { - struct type *type; - value_ptr val; + /* BOGUS: if val_print sees a struct/class, or a reference to one, + it will print out its children instead of "{...}". So we need to + catch that case explicitly. */ + struct type *type = get_type (var); - if (var->value != NULL) - val = var->value; - else - { - /* This can happen if we attempt to get the value of a struct - member when the parent is an invalid pointer. */ - return xstrdup ("???"); - } + /* Strip top-level references. */ + while (TYPE_CODE (type) == TYPE_CODE_REF) + type = check_typedef (TYPE_TARGET_TYPE (type)); - /* BOGUS: if val_print sees a struct/class, it will print out its - children instead of "{...}" */ - type = get_type (var); switch (TYPE_CODE (type)) { case TYPE_CODE_STRUCT: @@ -2062,29 +2295,40 @@ c_value_of_variable (struct varobj *var) case TYPE_CODE_ARRAY: { - char number[18]; - sprintf (number, "[%d]", var->num_children); - return xstrdup (number); + char *number; + number = xstrprintf ("[%d]", var->num_children); + return (number); } /* break; */ default: { - long dummy; - struct ui_file *stb = mem_fileopen (); - struct cleanup *old_chain = make_cleanup_ui_file_delete (stb); - char *thevalue; - - if (VALUE_LAZY (val)) - gdb_value_fetch_lazy (val); - val_print (VALUE_TYPE (val), VALUE_CONTENTS_RAW (val), 0, - VALUE_ADDRESS (val), - stb, format_code[(int) var->format], 1, 0, 0); - thevalue = ui_file_xstrdup (stb, &dummy); - do_cleanups (old_chain); - return thevalue; + if (var->value == NULL) + { + /* This can happen if we attempt to get the value of a struct + member when the parent is an invalid pointer. This is an + error condition, so we should tell the caller. */ + return NULL; + } + else + { + if (var->not_fetched && value_lazy (var->value)) + /* Frozen variable and no value yet. We don't + implicitly fetch the value. MI response will + use empty string for the value, which is OK. */ + return NULL; + + gdb_assert (varobj_value_is_changeable_p (var)); + gdb_assert (!value_lazy (var->value)); + + /* If the specified format is the current one, + we can reuse print_value */ + if (format == var->format) + return xstrdup (var->print_value); + else + return value_get_print_value (var->value, format); + } } - /* break; */ } } @@ -2102,10 +2346,11 @@ cplus_number_of_children (struct varobj *var) if (!CPLUS_FAKE_CHILD (var)) { - type = get_type_deref (var); + type = get_value_type (var); + adjust_value_for_child_access (NULL, &type, NULL); if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) || - ((TYPE_CODE (type)) == TYPE_CODE_UNION)) + ((TYPE_CODE (type)) == TYPE_CODE_UNION)) { int kids[3]; @@ -2128,12 +2373,13 @@ cplus_number_of_children (struct varobj *var) { int kids[3]; - type = get_type_deref (var->parent); + type = get_value_type (var->parent); + adjust_value_for_child_access (NULL, &type, NULL); cplus_class_num_children (type, kids); - if (STREQ (var->name, "public")) + if (strcmp (var->name, "public") == 0) children = kids[v_public]; - else if (STREQ (var->name, "private")) + else if (strcmp (var->name, "private") == 0) children = kids[v_private]; else children = kids[v_protected]; @@ -2161,8 +2407,7 @@ cplus_class_num_children (struct type *type, int children[3]) for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++) { /* If we have a virtual table pointer, omit it. */ - if (TYPE_VPTR_BASETYPE (type) == type - && TYPE_VPTR_FIELDNO (type) == i) + if (TYPE_VPTR_BASETYPE (type) == type && TYPE_VPTR_FIELDNO (type) == i) continue; if (TYPE_FIELD_PROTECTED (type, i)) @@ -2180,194 +2425,234 @@ cplus_name_of_variable (struct varobj *parent) return c_name_of_variable (parent); } -static char * -cplus_name_of_child (struct varobj *parent, int index) +enum accessibility { private_field, protected_field, public_field }; + +/* Check if field INDEX of TYPE has the specified accessibility. + Return 0 if so and 1 otherwise. */ +static int +match_accessibility (struct type *type, int index, enum accessibility acc) { - char *name; + if (acc == private_field && TYPE_FIELD_PRIVATE (type, index)) + return 1; + else if (acc == protected_field && TYPE_FIELD_PROTECTED (type, index)) + return 1; + else if (acc == public_field && !TYPE_FIELD_PRIVATE (type, index) + && !TYPE_FIELD_PROTECTED (type, index)) + return 1; + else + return 0; +} + +static void +cplus_describe_child (struct varobj *parent, int index, + char **cname, struct value **cvalue, struct type **ctype, + char **cfull_expression) +{ + char *name = NULL; + struct value *value; struct type *type; - int children[3]; + int was_ptr; + char *parent_expression = NULL; + + if (cname) + *cname = NULL; + if (cvalue) + *cvalue = NULL; + if (ctype) + *ctype = NULL; + if (cfull_expression) + *cfull_expression = NULL; if (CPLUS_FAKE_CHILD (parent)) { - /* Looking for children of public, private, or protected. */ - type = get_type_deref (parent->parent); + value = parent->parent->value; + type = get_value_type (parent->parent); + if (cfull_expression) + parent_expression = varobj_get_path_expr (parent->parent); } else - type = get_type_deref (parent); - - name = NULL; - switch (TYPE_CODE (type)) { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - cplus_class_num_children (type, children); + 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, &was_ptr); + if (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION) + { + char *join = was_ptr ? "->" : "."; if (CPLUS_FAKE_CHILD (parent)) { - /* FIXME: This assumes that type orders - inherited, public, private, protected */ - int i = index + TYPE_N_BASECLASSES (type); - if (STREQ (parent->name, "private") || STREQ (parent->name, "protected")) - i += children[v_public]; - if (STREQ (parent->name, "protected")) - i += children[v_private]; - - name = TYPE_FIELD_NAME (type, i); + /* The fields of the class type are ordered as they + appear in the class. We are given an index for a + particular access control type ("public","protected", + or "private"). We must skip over fields that don't + have the access control we are looking for to properly + find the indexed field. */ + int type_index = TYPE_N_BASECLASSES (type); + enum accessibility acc = public_field; + if (strcmp (parent->name, "private") == 0) + acc = private_field; + else if (strcmp (parent->name, "protected") == 0) + acc = protected_field; + + while (index >= 0) + { + if (TYPE_VPTR_BASETYPE (type) == type + && type_index == TYPE_VPTR_FIELDNO (type)) + ; /* ignore vptr */ + else if (match_accessibility (type, type_index, acc)) + --index; + ++type_index; + } + --type_index; + + if (cname) + *cname = xstrdup (TYPE_FIELD_NAME (type, type_index)); + + if (cvalue && value) + *cvalue = value_struct_element_index (value, type_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)) - name = TYPE_FIELD_NAME (type, index); + { + /* This is a baseclass. */ + if (cname) + *cname = xstrdup (TYPE_FIELD_NAME (type, 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 { + char *access = NULL; + int children[3]; + cplus_class_num_children (type, children); + /* Everything beyond the baseclasses can - only be "public", "private", or "protected" */ + only be "public", "private", or "protected" + + The special "fake" children are always output by varobj in + this order. So if INDEX == 2, it MUST be "protected". */ index -= TYPE_N_BASECLASSES (type); switch (index) { case 0: - if (children[v_public] != 0) - { - name = "public"; - break; - } + if (children[v_public] > 0) + access = "public"; + else if (children[v_private] > 0) + access = "private"; + else + access = "protected"; + break; case 1: - if (children[v_private] != 0) + if (children[v_public] > 0) { - name = "private"; - break; + if (children[v_private] > 0) + access = "private"; + else + access = "protected"; } + else if (children[v_private] > 0) + access = "protected"; + break; case 2: - if (children[v_protected] != 0) - { - name = "protected"; - break; - } + /* Must be protected */ + access = "protected"; + break; default: /* error! */ break; } - } - break; - default: - break; - } + gdb_assert (access); + if (cname) + *cname = xstrdup (access); - if (name == NULL) - return c_name_of_child (parent, index); + /* Value and type and full expression are null here. */ + } + } else { - if (name != NULL) - name = savestring (name, strlen (name)); - } + c_describe_child (parent, index, cname, cvalue, ctype, cfull_expression); + } +} +static char * +cplus_name_of_child (struct varobj *parent, int index) +{ + char *name = NULL; + cplus_describe_child (parent, index, &name, NULL, NULL, NULL); return name; } -static value_ptr +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) { return c_value_of_root (var_handle); } -static value_ptr +static struct value * cplus_value_of_child (struct varobj *parent, int index) { - struct type *type; - value_ptr value; - char *name; - - if (CPLUS_FAKE_CHILD (parent)) - type = get_type_deref (parent->parent); - else - type = get_type_deref (parent); - - value = NULL; - name = name_of_child (parent, index); - - if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) || - ((TYPE_CODE (type)) == TYPE_CODE_UNION)) - { - if (CPLUS_FAKE_CHILD (parent)) - { - value_ptr temp = parent->parent->value; - value = value_struct_elt (&temp, NULL, name, - NULL, "cplus_structure"); - release_value (value); - } - else if (index >= TYPE_N_BASECLASSES (type)) - { - /* public, private, or protected */ - return NULL; - } - else - { - /* Baseclass */ - if (parent->value != NULL) - { - value_ptr temp; - - if (TYPE_CODE (VALUE_TYPE (parent->value)) == TYPE_CODE_PTR - || TYPE_CODE (VALUE_TYPE (parent->value)) == TYPE_CODE_REF) - gdb_value_ind (parent->value, &temp); - else - temp = parent->value; - - value = value_cast (TYPE_FIELD_TYPE (type, index), temp); - release_value (value); - } - } - } - - if (value == NULL) - return c_value_of_child (parent, index); - + struct value *value = NULL; + cplus_describe_child (parent, index, NULL, &value, NULL, NULL); return value; } static struct type * cplus_type_of_child (struct varobj *parent, int index) { - struct type *type, *t; - - t = get_type_deref (parent); - type = NULL; - switch (TYPE_CODE (t)) - { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - if (index >= TYPE_N_BASECLASSES (t)) - { - /* special */ - return NULL; - } - else - { - /* Baseclass */ - type = TYPE_FIELD_TYPE (t, index); - } - break; - - default: - break; - } - - if (type == NULL) - return c_type_of_child (parent, index); - + struct type *type = NULL; + cplus_describe_child (parent, index, NULL, NULL, &type, NULL); return type; } -static int -cplus_variable_editable (struct varobj *var) -{ - if (CPLUS_FAKE_CHILD (var)) - return 0; - - return c_variable_editable (var); -} - static char * -cplus_value_of_variable (struct varobj *var) +cplus_value_of_variable (struct varobj *var, enum varobj_display_formats format) { /* If we have one of our special types, don't print out @@ -2375,7 +2660,7 @@ cplus_value_of_variable (struct varobj *var) if (CPLUS_FAKE_CHILD (var)) return xstrdup (""); - return c_value_of_variable (var); + return c_value_of_variable (var, format); } /* Java */ @@ -2425,13 +2710,19 @@ java_name_of_child (struct varobj *parent, int index) return name; } -static value_ptr +static char * +java_path_expr_of_child (struct varobj *child) +{ + return NULL; +} + +static struct value * java_value_of_root (struct varobj **var_handle) { return cplus_value_of_root (var_handle); } -static value_ptr +static struct value * java_value_of_child (struct varobj *parent, int index) { return cplus_value_of_child (parent, index); @@ -2443,16 +2734,10 @@ java_type_of_child (struct varobj *parent, int index) return cplus_type_of_child (parent, index); } -static int -java_variable_editable (struct varobj *var) -{ - return cplus_variable_editable (var); -} - static char * -java_value_of_variable (struct varobj *var) +java_value_of_variable (struct varobj *var, enum varobj_display_formats format) { - return cplus_value_of_variable (var); + return cplus_value_of_variable (var, format); } extern void _initialize_varobj (void); @@ -2464,10 +2749,58 @@ _initialize_varobj (void) varobj_table = xmalloc (sizeof_table); memset (varobj_table, 0, sizeof_table); - add_show_from_set ( - add_set_cmd ("debugvarobj", class_maintenance, var_zinteger, - (char *) &varobjdebug, - "Set varobj debugging.\n\ -When non-zero, varobj debugging is enabled.", &setlist), - &showlist); + add_setshow_zinteger_cmd ("debugvarobj", class_maintenance, + &varobjdebug, _("\ +Set varobj debugging."), _("\ +Show varobj debugging."), _("\ +When non-zero, varobj debugging is enabled."), + NULL, + show_varobjdebug, + &setlist, &showlist); +} + +/* Invalidate the varobjs that are tied to locals and re-create the ones that + are defined on globals. + Invalidated varobjs will be always printed in_scope="invalid". */ +void +varobj_invalidate (void) +{ + struct varobj **all_rootvarobj; + struct varobj **varp; + + if (varobj_list (&all_rootvarobj) > 0) + { + varp = all_rootvarobj; + while (*varp != NULL) + { + /* Floating varobjs are reparsed on each stop, so we don't care if + the presently parsed expression refers to something that's gone. */ + if ((*varp)->root->floating) + continue; + + /* global var must be re-evaluated. */ + if ((*varp)->root->valid_block == NULL) + { + struct varobj *tmp_var; + + /* Try to create a varobj with same expression. If we succeed replace + the old varobj, otherwise invalidate it. */ + tmp_var = varobj_create (NULL, (*varp)->name, (CORE_ADDR) 0, USE_CURRENT_FRAME); + if (tmp_var != NULL) + { + tmp_var->obj_name = xstrdup ((*varp)->obj_name); + varobj_delete (*varp, NULL, 0); + install_variable (tmp_var); + } + else + (*varp)->root->is_valid = 0; + } + else /* locals must be invalidated. */ + (*varp)->root->is_valid = 0; + + varp++; + } + xfree (all_rootvarobj); + } + return; }