OSDN Git Service

(varobj_update): Remove unused local. Use gdb_assert
[pf3gnuchains/sourceware.git] / gdb / varobj.c
index 056cf58..f86082e 100644 (file)
@@ -1,6 +1,6 @@
 /* Implementation of the GDB variable objects API.
 
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
@@ -71,6 +71,10 @@ struct varobj_root
      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;
 
@@ -107,14 +111,12 @@ struct varobj
   /* The type of this variable. This may NEVER be NULL. */
   struct type *type;
 
-  /* The value of this expression or subexpression.  This may be NULL. 
+  /* 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;
 
-  /* Did an error occur evaluating the expression or getting its value? */
-  int error;
-
   /* The number of (immediate) children this variable has */
   int num_children;
 
@@ -178,7 +180,7 @@ 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 *);
 
@@ -438,7 +440,7 @@ varobj_create (char *objname,
 
       /* Allow creator to specify context of variable */
       if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME))
-       fi = deprecated_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
@@ -485,7 +487,7 @@ varobj_create (char *objname,
       if (fi != NULL)
        {
          var->root->frame = get_frame_id (fi);
-         old_fi = deprecated_selected_frame;
+         old_fi = get_selected_frame (NULL);
          select_frame (fi);
        }
 
@@ -744,8 +746,9 @@ varobj_get_type (struct varobj *var)
   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 ();
@@ -780,7 +783,7 @@ varobj_get_attributes (struct varobj *var)
 {
   int attributes = 0;
 
-  if (variable_editable (var))
+  if (var->root->is_valid && variable_editable (var))
     /* FIXME: define masks for attributes */
     attributes |= 0x00000001;  /* Editable */
 
@@ -811,7 +814,7 @@ varobj_set_value (struct varobj *var, char *expression)
   struct value *value;
   int saved_input_radix = input_radix;
 
-  if (var->value != NULL && variable_editable (var) && !var->error)
+  if (var->value != NULL && variable_editable (var))
     {
       char *s = expression;
       int i;
@@ -909,7 +912,6 @@ install_new_value (struct varobj *var, struct value *value, int initial)
   int need_to_fetch;
   int changed = 0;
 
-  var->error = 0;
   /* 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. */
@@ -946,29 +948,30 @@ install_new_value (struct varobj *var, struct value *value, int initial)
     {
       if (!gdb_value_fetch_lazy (value))
        {
-         var->error = 1;
          /* 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;
        }
-      else
-       var->error = 0;
     }
 
   /* 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)
+  if (initial && changeable)
     var->print_value = value_get_print_value (value, var->format);
   else if (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.  */      
+        -var-update. So need to the varobj as changed.  */
       if (var->updated)
-       changed = 1;
+       {
+         xfree (var->print_value);
+         var->print_value = value_get_print_value (value, var->format);
+         changed = 1;
+       }
       else 
        {
          /* Try to compare the values.  That requires that both
@@ -979,7 +982,11 @@ install_new_value (struct varobj *var, struct value *value, int initial)
            /* Equal. */
            ;
          else if (var->value == NULL || value == NULL)
-           changed = 1;
+           {
+             xfree (var->print_value);
+             var->print_value = value_get_print_value (value, var->format);
+             changed = 1;
+           }
          else
            {
              char *print_value;
@@ -987,6 +994,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
              gdb_assert (!value_lazy (value));
              print_value = value_get_print_value (value, var->format);
 
+             gdb_assert (var->print_value != NULL && print_value != NULL);
              if (strcmp (var->print_value, print_value) != 0)
                {
                  xfree (var->print_value);
@@ -1015,22 +1023,20 @@ install_new_value (struct varobj *var, struct value *value, int initial)
    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... 
 
    NOTE: This function may delete the caller's varobj. If it
-   returns -2, then it has done this and VARP will be modified
-   to point to the new varobj. */
+   returns TYPE_CHANGED, then it has done this and VARP will be modified
+   to point to the new varobj.  */
 
 int
 varobj_update (struct varobj **varp, struct varobj ***changelist)
 {
   int changed = 0;
-  int error = 0;
   int type_changed;
   int i;
   int vleft;
@@ -1043,40 +1049,34 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
   struct frame_id old_fid;
   struct frame_info *fi;
 
-  /* sanity check: have we been passed a pointer? */
-  if (changelist == NULL)
-    return -1;
+  /* sanity check: have we been passed a pointer?  */
+  gdb_assert (changelist);
 
-  /*  Only root variables can be updated... */
   if (!is_root_p (*varp))
-    /* Not a root var */
-    return -1;
+    error (_("Only root variables can be updated"));
+
+  if (!(*varp)->root->is_valid)
+    return INVALID;
 
   /* Save the selected stack frame, since we will need to change it
-     in order to evaluate expressions. */
-  old_fid = get_frame_id (deprecated_selected_frame);
+     in order to evaluate expressions.  */
+  old_fid = get_frame_id (deprecated_safe_get_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. */
+     has changed.  */
   type_changed = 1;
   new = value_of_root (varp, &type_changed);
 
-  /* Restore selected frame */
+  /* Restore selected frame */
   fi = frame_find_by_id (old_fid);
   if (fi)
     select_frame (fi);
 
-  if (new == NULL)
-    {
-      (*varp)->error = 1;
-      return -1;
-    }
-
   /* If this is a "use_selected_frame" varobj, and its type has changed,
-     them note that it's changed. */
+     them note that it's changed.  */
   if (type_changed)
     VEC_safe_push (varobj_p, result, *varp);
 
@@ -1088,9 +1088,17 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
       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;
+    }
+
   VEC_safe_push (varobj_p, stack, *varp);
 
-  /* Walk through the children, reconstructing them all. */
+  /* Walk through the children, reconstructing them all.  */
   while (!VEC_empty (varobj_p, stack))
     {
       v = VEC_pop (varobj_p, stack);
@@ -1121,7 +1129,7 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
        }
     }
 
-  /* Alloc (changed + 1) list entries */
+  /* Alloc (changed + 1) list entries */
   changed = VEC_length (varobj_p, result);
   *changelist = xmalloc ((changed + 1) * sizeof (struct varobj *));
   cv = *changelist;
@@ -1135,7 +1143,7 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
   *cv = 0;
 
   if (type_changed)
-    return -2;
+    return TYPE_CHANGED;
   else
     return changed;
 }
@@ -1361,9 +1369,6 @@ create_child (struct varobj *parent, int index, char *name)
                                                       child->index);
   install_new_value (child, value, 1);
 
-  if ((!CPLUS_FAKE_CHILD (child) && child->value == NULL) || parent->error)
-    child->error = 1;
-
   return child;
 }
 \f
@@ -1384,7 +1389,6 @@ new_variable (void)
   var->index = -1;
   var->type = NULL;
   var->value = NULL;
-  var->error = 0;
   var->num_children = -1;
   var->parent = NULL;
   var->children = NULL;
@@ -1408,6 +1412,7 @@ new_root_variable (void)
   var->root->frame = null_frame_id;
   var->root->use_selected_frame = 0;
   var->root->rootvar = NULL;
+  var->root->is_valid = 1;
 
   return var;
 }
@@ -1458,22 +1463,33 @@ get_type (struct varobj *var)
   return type;
 }
 
-/* This returns the type of the variable, dereferencing references, pointers
-   and references to 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)
-    {
-      if (TYPE_CODE (type) == TYPE_CODE_REF)
-       type = get_target_type (type);
-      if (TYPE_CODE (type) == TYPE_CODE_PTR)
-       type = get_target_type (type);
-    }
+  if (TYPE_CODE (type) == TYPE_CODE_REF)
+    type = get_target_type (type);
+
+  type = check_typedef (type);
 
   return type;
 }
@@ -1680,19 +1696,29 @@ variable_editable (struct varobj *var)
 static char *
 my_value_of_variable (struct varobj *var)
 {
-  return (*var->root->lang->value_of_variable) (var);
+  if (var->root->is_valid)
+    return (*var->root->lang->value_of_variable) (var);
+  else
+    return NULL;
 }
 
 static char *
 value_get_print_value (struct value *value, enum varobj_display_formats format)
 {
   long dummy;
-  struct ui_file *stb = mem_fileopen ();
-  struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
+  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;
 }
@@ -1715,7 +1741,7 @@ varobj_value_is_changeable_p (struct varobj *var)
   if (CPLUS_FAKE_CHILD (var))
     return 0;
 
-  type = get_type (var);
+  type = get_value_type (var);
 
   switch (TYPE_CODE (type))
     {
@@ -1732,17 +1758,61 @@ varobj_value_is_changeable_p (struct varobj *var)
   return r;
 }
 
+/* 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.  */
+static void
+adjust_value_for_child_access (struct value **value,
+                                 struct type **type)
+{
+  gdb_assert (type && *type);
+
+  *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)
+           gdb_value_ind (*value, value);        
+         *type = target_type;
+       }
+    }
+
+  /* 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);
   target = get_target_type (type);
-  children = 0;
 
   switch (TYPE_CODE (type))
     {
@@ -1762,30 +1832,19 @@ c_number_of_children (struct varobj *var)
       break;
 
     case TYPE_CODE_PTR:
-      /* This is where things get complicated. 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:
@@ -1851,7 +1910,7 @@ c_describe_child (struct varobj *parent, int index,
                  char **cname, struct value **cvalue, struct type **ctype)
 {
   struct value *value = parent->value;
-  struct type *type = get_type (parent);
+  struct type *type = get_value_type (parent);
 
   if (cname)
     *cname = NULL;
@@ -1860,19 +1919,7 @@ c_describe_child (struct varobj *parent, int index,
   if (ctype)
     *ctype = NULL;
 
-  /* Pointers to structures are treated just like
-     structures when accessing children.  */
-  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)
-           gdb_value_ind (value, &value);        
-         type = target_type;
-       }
-    }
+  adjust_value_for_child_access (&value, &type);
       
   switch (TYPE_CODE (type))
     {
@@ -1920,8 +1967,11 @@ c_describe_child (struct varobj *parent, int index,
       if (cvalue && value)
        gdb_value_ind (value, cvalue);
 
+      /* 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 = get_target_type (type);
+       *ctype = TYPE_TARGET_TYPE (type);
       
       break;
 
@@ -1956,11 +2006,10 @@ c_value_of_root (struct varobj **var_handle)
 
 
   /* Determine whether the variable is still around. */
-  if (var->root->valid_block == NULL)
+  if (var->root->valid_block == NULL || var->root->use_selected_frame)
     within_scope = 1;
   else
     {
-      reinit_frame_cache ();
       fi = frame_find_by_id (var->root->frame);
       within_scope = fi != NULL;
       /* FIXME: select_frame could fail */
@@ -1970,23 +2019,16 @@ c_value_of_root (struct varobj **var_handle)
          if (pc <  BLOCK_START (var->root->valid_block) ||
              pc >= BLOCK_END (var->root->valid_block))
            within_scope = 0;
-         select_frame (fi);
+         else
+           select_frame (fi);
        }         
     }
 
   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))
-       {
-         var->error = 0;
-         release_value (new_val);
-       }
-      else
-       var->error = 1;
-
+         expression fails we want to just return NULL.  */
+      gdb_evaluate_expression (var->root->exp, &new_val);
       return new_val;
     }
 
@@ -1998,8 +2040,6 @@ c_value_of_child (struct varobj *parent, int index)
 {
   struct value *value = NULL;
   c_describe_child (parent, index, NULL, &value, NULL);
-  if (value != NULL)
-    release_value (value);
 
   return value;
 }
@@ -2015,7 +2055,7 @@ c_type_of_child (struct varobj *parent, int index)
 static int
 c_variable_editable (struct varobj *var)
 {
-  switch (TYPE_CODE (get_type (var)))
+  switch (TYPE_CODE (get_value_type (var)))
     {
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
@@ -2091,7 +2131,8 @@ 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);
 
       if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
          ((TYPE_CODE (type)) == TYPE_CODE_UNION))
@@ -2117,7 +2158,8 @@ 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);
 
       cplus_class_num_children (type, kids);
       if (strcmp (var->name, "public") == 0)
@@ -2168,25 +2210,56 @@ 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 *name = 0;
+  struct value *value;
   struct type *type;
 
+  if (cname)
+    *cname = NULL;
+  if (cvalue)
+    *cvalue = NULL;
+  if (ctype)
+    *ctype = 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);
     }
   else
-    type = get_type_deref (parent);
+    {
+      value = parent->value;
+      type = get_value_type (parent);
+    }
 
-  name = NULL;
-  switch (TYPE_CODE (type))
+  adjust_value_for_child_access (&value, &type);
+
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+      || TYPE_CODE (type) == TYPE_CODE_STRUCT)
     {
-    case TYPE_CODE_STRUCT:
-    case TYPE_CODE_UNION:
       if (CPLUS_FAKE_CHILD (parent))
        {
          /* The fields of the class type are ordered as they
@@ -2196,56 +2269,53 @@ cplus_name_of_child (struct varobj *parent, int index)
             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)
-           {
-             while (index >= 0)
-               {
-                 if (TYPE_VPTR_BASETYPE (type) == type
-                     && type_index == TYPE_VPTR_FIELDNO (type))
-                   ; /* ignore vptr */
-                 else if (TYPE_FIELD_PRIVATE (type, type_index))
-                   --index;
-                 ++type_index;
-               }
-             --type_index;
-           }
+           acc = private_field;
          else if (strcmp (parent->name, "protected") == 0)
+           acc = protected_field;
+
+         while (index >= 0)
            {
-             while (index >= 0)
-               {
-                 if (TYPE_VPTR_BASETYPE (type) == type
-                     && type_index == TYPE_VPTR_FIELDNO (type))
-                   ; /* ignore vptr */
-                 else if (TYPE_FIELD_PROTECTED (type, type_index))
+             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;
            }
-         else
+         --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);
+       }
+      else if (index < TYPE_N_BASECLASSES (type))
+       {
+         /* This is a baseclass.  */
+         if (cname)
+           *cname = xstrdup (TYPE_FIELD_NAME (type, index));
+
+         if (cvalue && value)
            {
-             while (index >= 0)
-               {
-                 if (TYPE_VPTR_BASETYPE (type) == type
-                     && type_index == TYPE_VPTR_FIELDNO (type))
-                   ; /* ignore vptr */
-                 else if (!TYPE_FIELD_PRIVATE (type, type_index) &&
-                     !TYPE_FIELD_PROTECTED (type, type_index))
-                   --index;
-                 ++type_index;
-               }
-             --type_index;
+             *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value);
            }
 
-         name = TYPE_FIELD_NAME (type, type_index);
+         if (ctype)
+           {
+             *ctype = TYPE_FIELD_TYPE (type, index);
+           }
        }
-      else if (index < TYPE_N_BASECLASSES (type))
-       /* We are looking up the name of a base class */
-       name = TYPE_FIELD_NAME (type, index);
       else
        {
+         char *access = 0;
          int children[3];
-         cplus_class_num_children(type, children);
+         cplus_class_num_children (type, children);
 
          /* Everything beyond the baseclasses can
             only be "public", "private", or "protected"
@@ -2257,46 +2327,49 @@ cplus_name_of_child (struct varobj *parent, int index)
            {
            case 0:
              if (children[v_public] > 0)
-               name = "public";
+               access = "public";
              else if (children[v_private] > 0)
-               name = "private";
+               access = "private";
              else 
-               name = "protected";
+               access = "protected";
              break;
            case 1:
              if (children[v_public] > 0)
                {
                  if (children[v_private] > 0)
-                   name = "private";
+                   access = "private";
                  else
-                   name = "protected";
+                   access = "protected";
                }
              else if (children[v_private] > 0)
-               name = "protected";
+               access = "protected";
              break;
            case 2:
              /* Must be protected */
-             name = "protected";
+             access = "protected";
              break;
            default:
              /* error! */
              break;
            }
-       }
-      break;
+         
+         if (cname)
+           *cname = xstrdup (access);
 
-    default:
-      break;
+         /* Value and type are null here.  */
+       }
     }
-
-  if (name == NULL)
-    return c_name_of_child (parent, index);
   else
     {
-      if (name != NULL)
-       name = savestring (name, strlen (name));
-    }
+      c_describe_child (parent, index, cname, cvalue, ctype);
+    }  
+}
 
+static char *
+cplus_name_of_child (struct varobj *parent, int index)
+{
+  char *name = NULL;
+  cplus_describe_child (parent, index, &name, NULL, NULL);
   return name;
 }
 
@@ -2309,118 +2382,16 @@ cplus_value_of_root (struct varobj **var_handle)
 static struct value *
 cplus_value_of_child (struct varobj *parent, int index)
 {
-  struct type *type;
-  struct value *value;
-
-  if (CPLUS_FAKE_CHILD (parent))
-    type = get_type_deref (parent->parent);
-  else
-    type = get_type_deref (parent);
-
-  value = NULL;
-
-  if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
-      ((TYPE_CODE (type)) == TYPE_CODE_UNION))
-    {
-      if (CPLUS_FAKE_CHILD (parent))
-       {
-         char *name;
-         struct value *temp = parent->parent->value;
-
-         if (temp == NULL)
-           return NULL;
-
-         name = name_of_child (parent, index);
-         gdb_value_struct_elt (NULL, &value, &temp, NULL, name, NULL,
-                               "cplus_structure");
-         if (value != NULL)
-           release_value (value);
-
-         xfree (name);
-       }
-      else if (index >= TYPE_N_BASECLASSES (type))
-       {
-         /* public, private, or protected */
-         return NULL;
-       }
-      else
-       {
-         /* Baseclass */
-         if (parent->value != NULL)
-           {
-             struct value *temp = NULL;
-
-             /* No special processing for references is needed --
-                value_cast below handles references.  */
-             if (TYPE_CODE (value_type (parent->value)) == TYPE_CODE_PTR)
-               {
-                 if (!gdb_value_ind (parent->value, &temp))
-                   return NULL;
-               }
-             else
-               temp = parent->value;
-
-             if (temp != NULL)
-               {
-                 value = value_cast (TYPE_FIELD_TYPE (type, index), temp);
-                 release_value (value);
-               }
-             else
-               {
-                 /* We failed to evaluate the parent's value, so don't even
-                    bother trying to evaluate this child. */
-                 return NULL;
-               }
-           }
-       }
-    }
-
-  if (value == NULL)
-    return c_value_of_child (parent, index);
-
+  struct value *value = NULL;
+  cplus_describe_child (parent, index, NULL, &value, NULL);
   return value;
 }
 
 static struct type *
 cplus_type_of_child (struct varobj *parent, int index)
 {
-  struct type *type, *t;
-
-  if (CPLUS_FAKE_CHILD (parent))
-    {
-      /* Looking for the type of a child of public, private, or protected. */
-      t = get_type_deref (parent->parent);
-    }
-  else
-    t = get_type_deref (parent);
-
-  type = NULL;
-  switch (TYPE_CODE (t))
-    {
-    case TYPE_CODE_STRUCT:
-    case TYPE_CODE_UNION:
-      if (CPLUS_FAKE_CHILD (parent))
-       {
-         char *name = cplus_name_of_child (parent, index);
-         type = lookup_struct_elt_type (t, name, 0);
-         xfree (name);
-       }
-      else if (index < TYPE_N_BASECLASSES (t))
-       type = TYPE_FIELD_TYPE (t, index);
-      else
-       {
-         /* special */
-         return NULL;
-       }
-      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);
   return type;
 }
 
@@ -2540,3 +2511,44 @@ When non-zero, varobj debugging is enabled."),
                            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)
+      {
+        /* 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;
+}