aboutsummaryrefslogtreecommitdiff
path: root/gdb/c-varobj.c
diff options
context:
space:
mode:
authorYao Qi <yao@codesourcery.com>2013-10-17 13:28:37 +0000
committerYao Qi <yao@codesourcery.com>2013-10-17 13:28:37 +0000
commit99ad94278d293fb7f5a823caf92221ff4419e556 (patch)
tree13f05185c64b72b3b3f2809c64549463c6c4c676 /gdb/c-varobj.c
parentc8a62302a53ba460e181f0c7cf03a5facc346d57 (diff)
downloadgdb-99ad94278d293fb7f5a823caf92221ff4419e556.zip
gdb-99ad94278d293fb7f5a823caf92221ff4419e556.tar.gz
gdb-99ad94278d293fb7f5a823caf92221ff4419e556.tar.bz2
gdb/
* Makefile.in (SFILES): Add c-varobj.c and jv-varobj.c. (COMMON_OBS): Add c-varobj.o and jv-varobj.o. * ada-varobj.c: Include "varobj.h". (ada_number_of_children): New. Moved from varobj.c. (ada_name_of_variable, ada_name_of_child): Likewise. (ada_path_expr_of_child, ada_value_of_child): Likewise. (ada_type_of_child, ada_value_of_variable): Likewise. (ada_value_is_changeable_p, ada_value_has_mutated): Likewise. (ada_varobj_ops): New. * c-varobj.c, jv-varobj.c: New file. Moved from varobj.c. * gdbtypes.c (get_target_type): New. Moved from varobj.c. * gdbtypes.h (get_target_type): Declare. * varobj.c: Remove the inclusion of "ada-varobj.h" and "ada-lang.h". (ANONYMOUS_STRUCT_NAME): Move it to c-varobj.c. (ANONYMOUS_UNION_NAME): Likewise. (get_type, get_value_type, get_target_type): Remove declarations. (value_get_print_value, varobj_value_get_print_value): Likewise. (c_number_of_children, c_name_of_variable): Likewise. (c_name_of_child, c_path_expr_of_child): Likewise. (c_value_of_child, c_type_of_child): Likewise. (c_value_of_variable, cplus_number_of_children): Likewise. (cplus_class_num_children, cplus_name_of_variable): Likewise. (cplus_name_of_child, cplus_path_expr_of_child): Likewise. (cplus_value_of_child, cplus_type_of_child): Likewise. (cplus_value_of_variable, java_number_of_children): Likewise. (java_name_of_variable, java_name_of_child): Likewise. (java_path_expr_of_child, java_value_of_child): Likewise. (java_type_of_child, java_value_of_variable): Likewise. (ada_number_of_children, ada_name_of_variable): Likewise. (ada_name_of_child, ada_path_expr_of_child): Likewise. (ada_value_of_child, ada_type_of_child): Likewise. (ada_value_of_variable, ada_value_is_changeable_p): Likewise. (ada_value_has_mutated): Likewise. (struct language_specific): Move it to varobj.h. (CPLUS_FAKE_CHILD): Move it to varobj.h. (restrict_range): Rename it varobj_restrict_range. Make it extern. Callers update. (get_path_expr_parent): Rename it to varobj_get_path_expr_parent. Make it extern. (is_anonymous_child): Move it to c-varobj.c and rename to varobj_is_anonymous_child. Caller update. (get_type): Move it to c-varobj.c. (get_value_type): Rename it varobj_get_value_type. Make it extern. (get_target_type): Move it gdbtypes.c. (varobj_formatted_print_options): New function. (value_get_print_value): Rename it to varobj_value_get_print_value and make it extern. (varobj_value_is_changeable_p): Make it extern. (adjust_value_for_child_access): Move it to c-varobj.c. (default_value_is_changeable_p): Rename it to varobj_default_value_is_changeable_p. Make it extern. (c_number_of_children, c_name_of_variable): Move it to c-varobj.c (c_name_of_child, c_path_expr_of_child): Likewise. (c_value_of_child, c_type_of_child): Likewise. (c_value_of_variable, cplus_number_of_children): Likewise. (cplus_class_num_children, cplus_name_of_variable): Likewise. (cplus_name_of_child, cplus_path_expr_of_child): Likewise. (cplus_value_of_child, cplus_type_of_child): Likewise. (cplus_value_of_variable): Likewise. (java_number_of_children, java_name_of_variable): Move it to jv-varobj.c. (java_name_of_child, java_path_expr_of_child): Likewise. (java_value_of_child, java_type_of_child): Likewise. (java_value_of_variable): Likewise. (ada_number_of_children, ada_name_of_variable): Move it to ada-varobj.c. (ada_name_of_child, ada_path_expr_of_child): Likewise. (ada_value_of_child, ada_type_of_child): Likewise. (ada_value_of_variable, ada_value_is_changeable_p): Likewise. (ada_value_has_mutated): Likewise. * varobj.h (CPLUS_FAKE_CHILD): New macro, moved from varobj.c. (struct lang_varobj_ops): New. Renamed by 'struct language_specific'. (c_varobj_ops, cplus_varobj_ops): Declare. (java_varobj_ops, ada_varobj_ops): Declare. (varobj_default_value_is_changeable_p): Declare. (varobj_value_is_changeable_p): Declare. (varobj_get_value_type, varobj_is_anonymous_child): Declare. (varobj_get_path_expr_parent): Declare. (varobj_value_get_print_value): Declare. (varobj_formatted_print_options): Declare. (varobj_restrict_range): Declare.
Diffstat (limited to 'gdb/c-varobj.c')
-rw-r--r--gdb/c-varobj.c910
1 files changed, 910 insertions, 0 deletions
diff --git a/gdb/c-varobj.c b/gdb/c-varobj.c
new file mode 100644
index 0000000..73e785c
--- /dev/null
+++ b/gdb/c-varobj.c
@@ -0,0 +1,910 @@
+/* varobj support for C and C++.
+
+ Copyright (C) 1999-2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "value.h"
+#include "varobj.h"
+#include "gdbthread.h"
+#include "valprint.h"
+
+static void cplus_class_num_children (struct type *type, int children[3]);
+
+/* The names of varobjs representing anonymous structs or unions. */
+#define ANONYMOUS_STRUCT_NAME _("<anonymous struct>")
+#define ANONYMOUS_UNION_NAME _("<anonymous union>")
+
+/* Does CHILD represent a child with no name? This happens when
+ the child is an anonmous struct or union and it has no field name
+ in its parent variable.
+
+ This has already been determined by *_describe_child. The easiest
+ thing to do is to compare the child's name with ANONYMOUS_*_NAME. */
+
+int
+varobj_is_anonymous_child (struct varobj *child)
+{
+ return (strcmp (child->name, ANONYMOUS_STRUCT_NAME) == 0
+ || strcmp (child->name, ANONYMOUS_UNION_NAME) == 0);
+}
+
+/* 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.
+
+ If LOOKUP_ACTUAL_TYPE is set the enclosing type of the
+ value will be fetched and if it differs from static type
+ the value will be casted to it.
+
+ 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 dereferenced
+ in this function. */
+
+static void
+adjust_value_for_child_access (struct value **value,
+ struct type **type,
+ int *was_ptr,
+ int lookup_actual_type)
+{
+ 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)
+ {
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ *value = value_ind (*value);
+ }
+
+ if (except.reason < 0)
+ *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. */
+
+ /* Access a real type of the value (if necessary and possible). */
+ if (value && *value && lookup_actual_type)
+ {
+ struct type *enclosing_type;
+ int real_type_found = 0;
+
+ enclosing_type = value_actual_type (*value, 1, &real_type_found);
+ if (real_type_found)
+ {
+ *type = enclosing_type;
+ *value = value_cast (enclosing_type, *value);
+ }
+ }
+}
+
+/* C */
+
+static int
+c_number_of_children (struct varobj *var)
+{
+ struct type *type = varobj_get_value_type (var);
+ int children = 0;
+ struct type *target;
+
+ adjust_value_for_child_access (NULL, &type, NULL, 0);
+ target = get_target_type (type);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (target) > 0
+ && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
+ children = TYPE_LENGTH (type) / TYPE_LENGTH (target);
+ else
+ /* If we don't know how many elements there are, don't display
+ any. */
+ children = 0;
+ break;
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ children = TYPE_NFIELDS (type);
+ break;
+
+ case TYPE_CODE_PTR:
+ /* 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". */
+ if (TYPE_CODE (target) == TYPE_CODE_FUNC
+ || TYPE_CODE (target) == TYPE_CODE_VOID)
+ children = 0;
+ else
+ children = 1;
+ break;
+
+ default:
+ /* Other types have no children. */
+ break;
+ }
+
+ return children;
+}
+
+static char *
+c_name_of_variable (struct varobj *parent)
+{
+ return xstrdup (parent->name);
+}
+
+/* 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 value *result = NULL;
+ volatile struct gdb_exception e;
+ 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 (field_is_static (&TYPE_FIELD (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 = varobj_get_value_type (parent);
+ char *parent_expression = NULL;
+ int was_ptr;
+ volatile struct gdb_exception except;
+
+ if (cname)
+ *cname = NULL;
+ if (cvalue)
+ *cvalue = NULL;
+ if (ctype)
+ *ctype = NULL;
+ if (cfull_expression)
+ {
+ *cfull_expression = NULL;
+ parent_expression
+ = varobj_get_path_expr (varobj_get_path_expr_parent (parent));
+ }
+ adjust_value_for_child_access (&value, &type, &was_ptr, 0);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ if (cname)
+ *cname
+ = xstrdup (int_string (index
+ + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
+ 10, 1, 0, 0));
+
+ if (cvalue && value)
+ {
+ int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
+
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ *cvalue = value_subscript (value, real_index);
+ }
+ }
+
+ if (ctype)
+ *ctype = get_target_type (type);
+
+ if (cfull_expression)
+ *cfull_expression =
+ xstrprintf ("(%s)[%s]", parent_expression,
+ int_string (index
+ + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
+ 10, 1, 0, 0));
+
+
+ break;
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ {
+ const char *field_name;
+
+ /* If the type is anonymous and the field has no name,
+ set an appropriate name. */
+ field_name = TYPE_FIELD_NAME (type, index);
+ if (field_name == NULL || *field_name == '\0')
+ {
+ if (cname)
+ {
+ if (TYPE_CODE (TYPE_FIELD_TYPE (type, index))
+ == TYPE_CODE_STRUCT)
+ *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
+ else
+ *cname = xstrdup (ANONYMOUS_UNION_NAME);
+ }
+
+ if (cfull_expression)
+ *cfull_expression = xstrdup ("");
+ }
+ else
+ {
+ if (cname)
+ *cname = xstrdup (field_name);
+
+ if (cfull_expression)
+ {
+ char *join = was_ptr ? "->" : ".";
+
+ *cfull_expression = xstrprintf ("(%s)%s%s", parent_expression,
+ join, field_name);
+ }
+ }
+
+ 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);
+ }
+ break;
+
+ case TYPE_CODE_PTR:
+ if (cname)
+ *cname = xstrprintf ("*%s", parent->name);
+
+ if (cvalue && value)
+ {
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ *cvalue = value_ind (value);
+ }
+
+ if (except.reason < 0)
+ *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. */
+ 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 char *
+c_path_expr_of_child (struct varobj *child)
+{
+ c_describe_child (child->parent, child->index, NULL, NULL, NULL,
+ &child->path_expr);
+ return child->path_expr;
+}
+
+static struct value *
+c_value_of_child (struct varobj *parent, int index)
+{
+ struct value *value = NULL;
+
+ c_describe_child (parent, index, NULL, &value, NULL, NULL);
+ return value;
+}
+
+static struct type *
+c_type_of_child (struct varobj *parent, int index)
+{
+ struct type *type = NULL;
+
+ c_describe_child (parent, index, NULL, NULL, &type, NULL);
+ return type;
+}
+
+/* This returns the type of the variable. It also skips past typedefs
+ to return the real type of the variable. */
+
+static struct type *
+get_type (struct varobj *var)
+{
+ struct type *type;
+
+ type = var->type;
+ if (type != NULL)
+ type = check_typedef (type);
+
+ return type;
+}
+
+static char *
+c_value_of_variable (struct varobj *var, enum varobj_display_formats format)
+{
+ /* 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);
+
+ /* Strip top-level references. */
+ while (TYPE_CODE (type) == TYPE_CODE_REF)
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ return xstrdup ("{...}");
+ /* break; */
+
+ case TYPE_CODE_ARRAY:
+ {
+ char *number;
+
+ number = xstrprintf ("[%d]", var->num_children);
+ return (number);
+ }
+ /* break; */
+
+ default:
+ {
+ 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 varobj_value_get_print_value (var->value, format, var);
+ }
+ }
+ }
+}
+
+
+/* varobj operations for c. */
+
+const struct lang_varobj_ops c_varobj_ops =
+{
+ c_number_of_children,
+ c_name_of_variable,
+ c_name_of_child,
+ c_path_expr_of_child,
+ c_value_of_child,
+ c_type_of_child,
+ c_value_of_variable,
+ varobj_default_value_is_changeable_p,
+ NULL /* value_has_mutated */
+};
+
+/* A little convenience enum for dealing with C++/Java. */
+enum vsections
+{
+ v_public = 0, v_private, v_protected
+};
+
+/* C++ */
+
+static int
+cplus_number_of_children (struct varobj *var)
+{
+ struct value *value = NULL;
+ struct type *type;
+ int children, dont_know;
+ int lookup_actual_type = 0;
+ struct value_print_options opts;
+
+ dont_know = 1;
+ children = 0;
+
+ get_user_print_options (&opts);
+
+ if (!CPLUS_FAKE_CHILD (var))
+ {
+ type = varobj_get_value_type (var);
+
+ /* It is necessary to access a real type (via RTTI). */
+ if (opts.objectprint)
+ {
+ value = var->value;
+ lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
+ || TYPE_CODE (var->type) == TYPE_CODE_PTR);
+ }
+ adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
+
+ if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
+ ((TYPE_CODE (type)) == TYPE_CODE_UNION))
+ {
+ int kids[3];
+
+ cplus_class_num_children (type, kids);
+ if (kids[v_public] != 0)
+ children++;
+ if (kids[v_private] != 0)
+ children++;
+ if (kids[v_protected] != 0)
+ children++;
+
+ /* Add any baseclasses. */
+ children += TYPE_N_BASECLASSES (type);
+ dont_know = 0;
+
+ /* FIXME: save children in var. */
+ }
+ }
+ else
+ {
+ int kids[3];
+
+ type = varobj_get_value_type (var->parent);
+
+ /* It is necessary to access a real type (via RTTI). */
+ if (opts.objectprint)
+ {
+ struct varobj *parent = var->parent;
+
+ value = parent->value;
+ lookup_actual_type = (TYPE_CODE (parent->type) == TYPE_CODE_REF
+ || TYPE_CODE (parent->type) == TYPE_CODE_PTR);
+ }
+ adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
+
+ cplus_class_num_children (type, kids);
+ if (strcmp (var->name, "public") == 0)
+ children = kids[v_public];
+ else if (strcmp (var->name, "private") == 0)
+ children = kids[v_private];
+ else
+ children = kids[v_protected];
+ dont_know = 0;
+ }
+
+ if (dont_know)
+ children = c_number_of_children (var);
+
+ return children;
+}
+
+/* Compute # of public, private, and protected variables in this class.
+ That means we need to descend into all baseclasses and find out
+ how many are there, too. */
+
+static void
+cplus_class_num_children (struct type *type, int children[3])
+{
+ int i, vptr_fieldno;
+ struct type *basetype = NULL;
+
+ children[v_public] = 0;
+ children[v_private] = 0;
+ children[v_protected] = 0;
+
+ vptr_fieldno = get_vptr_fieldno (type, &basetype);
+ for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
+ {
+ /* If we have a virtual table pointer, omit it. Even if virtual
+ table pointers are not specifically marked in the debug info,
+ they should be artificial. */
+ if ((type == basetype && i == vptr_fieldno)
+ || TYPE_FIELD_ARTIFICIAL (type, i))
+ continue;
+
+ if (TYPE_FIELD_PROTECTED (type, i))
+ children[v_protected]++;
+ else if (TYPE_FIELD_PRIVATE (type, i))
+ children[v_private]++;
+ else
+ children[v_public]++;
+ }
+}
+
+static char *
+cplus_name_of_variable (struct varobj *parent)
+{
+ return c_name_of_variable (parent);
+}
+
+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)
+{
+ 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)
+{
+ struct value *value;
+ struct type *type;
+ int was_ptr;
+ int lookup_actual_type = 0;
+ char *parent_expression = NULL;
+ struct varobj *var;
+ struct value_print_options opts;
+
+ if (cname)
+ *cname = NULL;
+ if (cvalue)
+ *cvalue = NULL;
+ if (ctype)
+ *ctype = NULL;
+ if (cfull_expression)
+ *cfull_expression = NULL;
+
+ get_user_print_options (&opts);
+
+ var = (CPLUS_FAKE_CHILD (parent)) ? parent->parent : parent;
+ if (opts.objectprint)
+ lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
+ || TYPE_CODE (var->type) == TYPE_CODE_PTR);
+ value = var->value;
+ type = varobj_get_value_type (var);
+ if (cfull_expression)
+ parent_expression
+ = varobj_get_path_expr (varobj_get_path_expr_parent (var));
+
+ adjust_value_for_child_access (&value, &type, &was_ptr, lookup_actual_type);
+
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION)
+ {
+ char *join = was_ptr ? "->" : ".";
+
+ if (CPLUS_FAKE_CHILD (parent))
+ {
+ /* 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;
+ int vptr_fieldno;
+ struct type *basetype = NULL;
+ const char *field_name;
+
+ vptr_fieldno = get_vptr_fieldno (type, &basetype);
+ if (strcmp (parent->name, "private") == 0)
+ acc = private_field;
+ else if (strcmp (parent->name, "protected") == 0)
+ acc = protected_field;
+
+ while (index >= 0)
+ {
+ if ((type == basetype && type_index == vptr_fieldno)
+ || TYPE_FIELD_ARTIFICIAL (type, type_index))
+ ; /* ignore vptr */
+ else if (match_accessibility (type, type_index, acc))
+ --index;
+ ++type_index;
+ }
+ --type_index;
+
+ /* If the type is anonymous and the field has no name,
+ set an appopriate name. */
+ field_name = TYPE_FIELD_NAME (type, type_index);
+ if (field_name == NULL || *field_name == '\0')
+ {
+ if (cname)
+ {
+ if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
+ == TYPE_CODE_STRUCT)
+ *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
+ else if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
+ == TYPE_CODE_UNION)
+ *cname = xstrdup (ANONYMOUS_UNION_NAME);
+ }
+
+ if (cfull_expression)
+ *cfull_expression = xstrdup ("");
+ }
+ else
+ {
+ if (cname)
+ *cname = xstrdup (TYPE_FIELD_NAME (type, type_index));
+
+ if (cfull_expression)
+ *cfull_expression
+ = xstrprintf ("((%s)%s%s)", parent_expression, join,
+ field_name);
+ }
+
+ 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)
+ *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value);
+
+ 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.
+
+ When we are in the scope of the base class or of one
+ of its children, the type field name will be interpreted
+ as a constructor, if it exists. Therefore, we must
+ indicate that the name is a class name by using the
+ 'class' keyword. See PR mi/11912 */
+ *cfull_expression = xstrprintf ("(%s(class %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"
+
+ 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)
+ access = "public";
+ else if (children[v_private] > 0)
+ access = "private";
+ else
+ access = "protected";
+ break;
+ case 1:
+ if (children[v_public] > 0)
+ {
+ if (children[v_private] > 0)
+ access = "private";
+ else
+ access = "protected";
+ }
+ else if (children[v_private] > 0)
+ access = "protected";
+ break;
+ case 2:
+ /* Must be protected. */
+ access = "protected";
+ break;
+ default:
+ /* error! */
+ break;
+ }
+
+ gdb_assert (access);
+ if (cname)
+ *cname = xstrdup (access);
+
+ /* Value and type and full expression are null here. */
+ }
+ }
+ else
+ {
+ 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 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_child (struct varobj *parent, int 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 = NULL;
+
+ cplus_describe_child (parent, index, NULL, NULL, &type, NULL);
+ return type;
+}
+
+static char *
+cplus_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format)
+{
+
+ /* If we have one of our special types, don't print out
+ any value. */
+ if (CPLUS_FAKE_CHILD (var))
+ return xstrdup ("");
+
+ return c_value_of_variable (var, format);
+}
+
+
+/* varobj operations for c++. */
+
+const struct lang_varobj_ops cplus_varobj_ops =
+{
+ cplus_number_of_children,
+ cplus_name_of_variable,
+ cplus_name_of_child,
+ cplus_path_expr_of_child,
+ cplus_value_of_child,
+ cplus_type_of_child,
+ cplus_value_of_variable,
+ varobj_default_value_is_changeable_p,
+ NULL /* value_has_mutated */
+};
+
+