Index: gdb/varobj.c |
diff --git a/gdb/varobj.c b/gdb/varobj.c |
index 195d8214167e74f22ca35d2b61e50f177059ef50..6b7ec52c983d1e63fb3b4897f152abba06119409 100644 |
--- a/gdb/varobj.c |
+++ b/gdb/varobj.c |
@@ -21,7 +21,6 @@ |
#include "expression.h" |
#include "frame.h" |
#include "language.h" |
-#include "wrapper.h" |
#include "gdbcmd.h" |
#include "block.h" |
#include "valprint.h" |
@@ -34,6 +33,8 @@ |
#include "vec.h" |
#include "gdbthread.h" |
#include "inferior.h" |
+#include "ada-varobj.h" |
+#include "ada-lang.h" |
#if HAVE_PYTHON |
#include "python/python.h" |
@@ -42,6 +43,10 @@ |
typedef int PyObject; |
#endif |
+/* The names of varobjs representing anonymous structs or unions. */ |
+#define ANONYMOUS_STRUCT_NAME _("<anonymous struct>") |
+#define ANONYMOUS_UNION_NAME _("<anonymous union>") |
+ |
/* Non-zero if we want to see trace of varobj level stuff. */ |
int varobjdebug = 0; |
@@ -265,6 +270,9 @@ static void cppush (struct cpstack **pstack, char *name); |
static char *cppop (struct cpstack **pstack); |
+static int update_type_if_necessary (struct varobj *var, |
+ struct value *new_value); |
+ |
static int install_new_value (struct varobj *var, struct value *value, |
int initial); |
@@ -301,6 +309,8 @@ static struct varobj *varobj_add_child (struct varobj *var, |
#endif /* HAVE_PYTHON */ |
+static int default_value_is_changeable_p (struct varobj *var); |
+ |
/* C implementation */ |
static int c_number_of_children (struct varobj *var); |
@@ -379,6 +389,11 @@ static struct type *ada_type_of_child (struct varobj *parent, int index); |
static char *ada_value_of_variable (struct varobj *var, |
enum varobj_display_formats format); |
+static int ada_value_is_changeable_p (struct varobj *var); |
+ |
+static int ada_value_has_mutated (struct varobj *var, struct value *new_val, |
+ struct type *new_type); |
+ |
/* The language specific vector */ |
struct language_specific |
@@ -412,6 +427,31 @@ struct language_specific |
/* The current value of VAR. */ |
char *(*value_of_variable) (struct varobj * var, |
enum varobj_display_formats format); |
+ |
+ /* Return non-zero if changes in value of VAR must be detected and |
+ reported by -var-update. Return zero if -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. */ |
+ int (*value_is_changeable_p) (struct varobj *var); |
+ |
+ /* Return nonzero if the type of VAR has mutated. |
+ |
+ VAR's value is still the varobj's previous value, while NEW_VALUE |
+ is VAR's new value and NEW_TYPE is the var's new type. NEW_VALUE |
+ may be NULL indicating that there is no value available (the varobj |
+ may be out of scope, of may be the child of a null pointer, for |
+ instance). NEW_TYPE, on the other hand, must never be NULL. |
+ |
+ This function should also be able to assume that var's number of |
+ children is set (not < 0). |
+ |
+ Languages where types do not mutate can set this to NULL. */ |
+ int (*value_has_mutated) (struct varobj *var, struct value *new_value, |
+ struct type *new_type); |
}; |
/* Array of known source language routines. */ |
@@ -426,7 +466,9 @@ static struct language_specific languages[vlang_end] = { |
c_value_of_root, |
c_value_of_child, |
c_type_of_child, |
- c_value_of_variable} |
+ c_value_of_variable, |
+ default_value_is_changeable_p, |
+ NULL /* value_has_mutated */} |
, |
/* C */ |
{ |
@@ -438,7 +480,9 @@ static struct language_specific languages[vlang_end] = { |
c_value_of_root, |
c_value_of_child, |
c_type_of_child, |
- c_value_of_variable} |
+ c_value_of_variable, |
+ default_value_is_changeable_p, |
+ NULL /* value_has_mutated */} |
, |
/* C++ */ |
{ |
@@ -450,7 +494,9 @@ static struct language_specific languages[vlang_end] = { |
cplus_value_of_root, |
cplus_value_of_child, |
cplus_type_of_child, |
- cplus_value_of_variable} |
+ cplus_value_of_variable, |
+ default_value_is_changeable_p, |
+ NULL /* value_has_mutated */} |
, |
/* Java */ |
{ |
@@ -462,7 +508,9 @@ static struct language_specific languages[vlang_end] = { |
java_value_of_root, |
java_value_of_child, |
java_type_of_child, |
- java_value_of_variable}, |
+ java_value_of_variable, |
+ default_value_is_changeable_p, |
+ NULL /* value_has_mutated */}, |
/* Ada */ |
{ |
vlang_ada, |
@@ -473,7 +521,9 @@ static struct language_specific languages[vlang_end] = { |
ada_value_of_root, |
ada_value_of_child, |
ada_type_of_child, |
- ada_value_of_variable} |
+ ada_value_of_variable, |
+ ada_value_is_changeable_p, |
+ ada_value_has_mutated} |
}; |
/* A little convenience enum for dealing with C++/Java. */ |
@@ -512,7 +562,7 @@ is_root_p (struct varobj *var) |
#ifdef HAVE_PYTHON |
/* Helper function to install a Python environment suitable for |
use during operations on VAR. */ |
-struct cleanup * |
+static struct cleanup * |
varobj_ensure_python_env (struct varobj *var) |
{ |
return ensure_python_env (var->root->exp->gdbarch, |
@@ -573,6 +623,8 @@ varobj_create (char *objname, |
char *p; |
enum varobj_languages lang; |
struct value *value = NULL; |
+ volatile struct gdb_exception except; |
+ CORE_ADDR pc; |
/* Parse and evaluate the expression, filling in as much of the |
variable's data as possible. */ |
@@ -599,15 +651,24 @@ varobj_create (char *objname, |
if (type == USE_SELECTED_FRAME) |
var->root->floating = 1; |
+ pc = 0; |
block = NULL; |
if (fi != NULL) |
- block = get_frame_block (fi, 0); |
+ { |
+ block = get_frame_block (fi, 0); |
+ pc = get_frame_pc (fi); |
+ } |
p = expression; |
innermost_block = NULL; |
/* Wrap the call to parse expression, so we can |
return a sensible error. */ |
- if (!gdb_parse_exp_1 (&p, block, 0, &var->root->exp)) |
+ TRY_CATCH (except, RETURN_MASK_ERROR) |
+ { |
+ var->root->exp = parse_exp_1 (&p, pc, block, 0); |
+ } |
+ |
+ if (except.reason < 0) |
{ |
do_cleanups (old_chain); |
return NULL; |
@@ -650,7 +711,12 @@ varobj_create (char *objname, |
/* 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, &value)) |
+ TRY_CATCH (except, RETURN_MASK_ERROR) |
+ { |
+ value = evaluate_expression (var->root->exp); |
+ } |
+ |
+ if (except.reason < 0) |
{ |
/* Error getting the value. Try to at least get the |
right type. */ |
@@ -658,15 +724,21 @@ varobj_create (char *objname, |
var->type = value_type (type_only_value); |
} |
- else |
- var->type = value_type (value); |
+ else |
+ { |
+ int real_type_found = 0; |
- install_new_value (var, value, 1 /* Initial assignment */); |
+ var->type = value_actual_type (value, 0, &real_type_found); |
+ if (real_type_found) |
+ value = value_cast (var->type, value); |
+ } |
/* Set language info */ |
lang = variable_language (var); |
var->root->lang = &languages[lang]; |
+ install_new_value (var, value, 1 /* Initial assignment */); |
+ |
/* Set ourselves as our root. */ |
var->root->rootvar = var; |
@@ -947,6 +1019,7 @@ restrict_range (VEC (varobj_p) *children, int *from, int *to) |
static void |
install_dynamic_child (struct varobj *var, |
VEC (varobj_p) **changed, |
+ VEC (varobj_p) **type_changed, |
VEC (varobj_p) **new, |
VEC (varobj_p) **unchanged, |
int *cchanged, |
@@ -969,12 +1042,18 @@ install_dynamic_child (struct varobj *var, |
{ |
varobj_p existing = VEC_index (varobj_p, var->children, index); |
+ int type_updated = update_type_if_necessary (existing, value); |
+ if (type_updated) |
+ { |
+ if (type_changed) |
+ VEC_safe_push (varobj_p, *type_changed, existing); |
+ } |
if (install_new_value (existing, value, 0)) |
{ |
- if (changed) |
+ if (!type_updated && changed) |
VEC_safe_push (varobj_p, *changed, existing); |
} |
- else if (unchanged) |
+ else if (!type_updated && unchanged) |
VEC_safe_push (varobj_p, *unchanged, existing); |
} |
} |
@@ -997,6 +1076,7 @@ dynamic_varobj_has_child_method (struct varobj *var) |
static int |
update_dynamic_varobj_children (struct varobj *var, |
VEC (varobj_p) **changed, |
+ VEC (varobj_p) **type_changed, |
VEC (varobj_p) **new, |
VEC (varobj_p) **unchanged, |
int *cchanged, |
@@ -1032,9 +1112,6 @@ update_dynamic_varobj_children (struct varobj *var, |
make_cleanup_py_decref (children); |
- if (!PyIter_Check (children)) |
- error (_("Returned value is not iterable")); |
- |
Py_XDECREF (var->child_iter); |
var->child_iter = PyObject_GetIter (children); |
if (!var->child_iter) |
@@ -1132,6 +1209,7 @@ update_dynamic_varobj_children (struct varobj *var, |
if (v == NULL) |
gdbpy_print_stack (); |
install_dynamic_child (var, can_mention ? changed : NULL, |
+ can_mention ? type_changed : NULL, |
can_mention ? new : NULL, |
can_mention ? unchanged : NULL, |
can_mention ? cchanged : NULL, i, name, v); |
@@ -1187,7 +1265,7 @@ varobj_get_num_children (struct varobj *var) |
/* If we have a dynamic varobj, don't report -1 children. |
So, try to fetch some children first. */ |
- update_dynamic_varobj_children (var, NULL, NULL, NULL, &dummy, |
+ update_dynamic_varobj_children (var, NULL, NULL, NULL, NULL, &dummy, |
0, 0, 0); |
} |
else |
@@ -1213,8 +1291,8 @@ varobj_list_children (struct varobj *var, int *from, int *to) |
/* This, in theory, can result in the number of children changing without |
frontend noticing. But well, calling -var-list-children on the same |
varobj twice is not something a sane frontend would do. */ |
- update_dynamic_varobj_children (var, NULL, NULL, NULL, &children_changed, |
- 0, 0, *to); |
+ update_dynamic_varobj_children (var, NULL, NULL, NULL, NULL, |
+ &children_changed, 0, 0, *to); |
restrict_range (var->children, from, to); |
return var->children; |
} |
@@ -1288,6 +1366,39 @@ varobj_get_gdb_type (struct varobj *var) |
return var->type; |
} |
+/* Is VAR a path expression parent, i.e., can it be used to construct |
+ a valid path expression? */ |
+ |
+static int |
+is_path_expr_parent (struct varobj *var) |
+{ |
+ struct type *type; |
+ |
+ /* "Fake" children are not path_expr parents. */ |
+ if (CPLUS_FAKE_CHILD (var)) |
+ return 0; |
+ |
+ type = get_value_type (var); |
+ |
+ /* Anonymous unions and structs are also not path_expr parents. */ |
+ return !((TYPE_CODE (type) == TYPE_CODE_STRUCT |
+ || TYPE_CODE (type) == TYPE_CODE_UNION) |
+ && TYPE_NAME (type) == NULL); |
+} |
+ |
+/* Return the path expression parent for VAR. */ |
+ |
+static struct varobj * |
+get_path_expr_parent (struct varobj *var) |
+{ |
+ struct varobj *parent = var; |
+ |
+ while (!is_root_p (parent) && !is_path_expr_parent (parent)) |
+ parent = parent->parent; |
+ |
+ return parent; |
+} |
+ |
/* Return a pointer to the full rooted expression of varobj VAR. |
If it has not been computed yet, compute it. */ |
char * |
@@ -1349,21 +1460,26 @@ varobj_get_value (struct varobj *var) |
int |
varobj_set_value (struct varobj *var, char *expression) |
{ |
- struct value *val; |
- |
+ struct value *val = NULL; /* Initialize to keep gcc happy. */ |
/* 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; |
- struct value *value; |
+ struct value *value = NULL; /* Initialize to keep gcc happy. */ |
int saved_input_radix = input_radix; |
char *s = expression; |
+ volatile struct gdb_exception except; |
gdb_assert (varobj_editable_p (var)); |
input_radix = 10; /* ALWAYS reset to decimal temporarily. */ |
- exp = parse_exp_1 (&s, 0, 0); |
- if (!gdb_evaluate_expression (exp, &value)) |
+ exp = parse_exp_1 (&s, 0, 0, 0); |
+ TRY_CATCH (except, RETURN_MASK_ERROR) |
+ { |
+ value = evaluate_expression (exp); |
+ } |
+ |
+ if (except.reason < 0) |
{ |
/* We cannot proceed without a valid expression. */ |
xfree (exp); |
@@ -1385,13 +1501,16 @@ varobj_set_value (struct varobj *var, char *expression) |
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)) |
+ /* The new value may be lazy. value_assign, or |
+ rather value_contents, will take care of this. */ |
+ TRY_CATCH (except, RETURN_MASK_ERROR) |
+ { |
+ val = value_assign (var->value, value); |
+ } |
+ |
+ if (except.reason < 0) |
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 |
@@ -1520,6 +1639,43 @@ install_new_value_visualizer (struct varobj *var) |
#endif |
} |
+/* When using RTTI to determine variable type it may be changed in runtime when |
+ the variable value is changed. This function checks whether type of varobj |
+ VAR will change when a new value NEW_VALUE is assigned and if it is so |
+ updates the type of VAR. */ |
+ |
+static int |
+update_type_if_necessary (struct varobj *var, struct value *new_value) |
+{ |
+ if (new_value) |
+ { |
+ struct value_print_options opts; |
+ |
+ get_user_print_options (&opts); |
+ if (opts.objectprint) |
+ { |
+ struct type *new_type; |
+ char *curr_type_str, *new_type_str; |
+ |
+ new_type = value_actual_type (new_value, 0, 0); |
+ new_type_str = type_to_string (new_type); |
+ curr_type_str = varobj_get_type (var); |
+ if (strcmp (curr_type_str, new_type_str) != 0) |
+ { |
+ var->type = new_type; |
+ |
+ /* This information may be not valid for a new type. */ |
+ varobj_delete (var, NULL, 1); |
+ VEC_free (varobj_p, var->children); |
+ var->num_children = -1; |
+ return 1; |
+ } |
+ } |
+ } |
+ |
+ return 0; |
+} |
+ |
/* 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 |
@@ -1594,15 +1750,29 @@ install_new_value (struct varobj *var, struct value *value, int initial) |
explicitly asked to compare the new value with the old one. */ |
intentionally_not_fetched = 1; |
} |
- else if (!gdb_value_fetch_lazy (value)) |
+ else |
{ |
- /* 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; |
+ volatile struct gdb_exception except; |
+ |
+ TRY_CATCH (except, RETURN_MASK_ERROR) |
+ { |
+ value_fetch_lazy (value); |
+ } |
+ |
+ if (except.reason < 0) |
+ { |
+ /* 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; |
+ } |
} |
} |
+ /* Get a reference now, before possibly passing it to any Python |
+ code that might release it. */ |
+ if (value != NULL) |
+ value_incref (value); |
/* Below, we'll be comparing string rendering of old and new |
values. Don't get string rendering if the value is |
@@ -1670,8 +1840,6 @@ install_new_value (struct varobj *var, struct value *value, int initial) |
if (var->value != NULL && var->value != value) |
value_free (var->value); |
var->value = value; |
- if (value != NULL) |
- value_incref (value); |
if (value && value_lazy (value) && intentionally_not_fetched) |
var->not_fetched = 1; |
else |
@@ -1757,6 +1925,30 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer) |
#endif |
} |
+/* If NEW_VALUE is the new value of the given varobj (var), return |
+ non-zero if var has mutated. In other words, if the type of |
+ the new value is different from the type of the varobj's old |
+ value. |
+ |
+ NEW_VALUE may be NULL, if the varobj is now out of scope. */ |
+ |
+static int |
+varobj_value_has_mutated (struct varobj *var, struct value *new_value, |
+ struct type *new_type) |
+{ |
+ /* If we haven't previously computed the number of children in var, |
+ it does not matter from the front-end's perspective whether |
+ the type has mutated or not. For all intents and purposes, |
+ it has not mutated. */ |
+ if (var->num_children < 0) |
+ return 0; |
+ |
+ if (var->root->lang->value_has_mutated) |
+ return var->root->lang->value_has_mutated (var, new_value, new_type); |
+ else |
+ return 0; |
+} |
+ |
/* 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 |
@@ -1772,7 +1964,8 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer) |
returns TYPE_CHANGED, then it has done this and VARP will be modified |
to point to the new varobj. */ |
-VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) |
+VEC(varobj_update_result) * |
+varobj_update (struct varobj **varp, int explicit) |
{ |
int changed = 0; |
int type_changed = 0; |
@@ -1812,8 +2005,9 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) |
value_of_root variable dispose of the varobj if the type |
has changed. */ |
new = value_of_root (varp, &type_changed); |
+ if (update_type_if_necessary(*varp, new)) |
+ type_changed = 1; |
r.varobj = *varp; |
- |
r.type_changed = type_changed; |
if (install_new_value ((*varp), new, type_changed)) |
r.changed = 1; |
@@ -1850,9 +2044,30 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) |
/* Update this variable, unless it's a root, which is already |
updated. */ |
if (!r.value_installed) |
- { |
+ { |
+ struct type *new_type; |
+ |
new = value_of_child (v->parent, v->index); |
- if (install_new_value (v, new, 0 /* type not changed */)) |
+ if (update_type_if_necessary(v, new)) |
+ r.type_changed = 1; |
+ if (new) |
+ new_type = value_type (new); |
+ else |
+ new_type = v->root->lang->type_of_child (v->parent, v->index); |
+ |
+ if (varobj_value_has_mutated (v, new, new_type)) |
+ { |
+ /* The children are no longer valid; delete them now. |
+ Report the fact that its type changed as well. */ |
+ varobj_delete (v, NULL, 1 /* only_children */); |
+ v->num_children = -1; |
+ v->to = -1; |
+ v->from = -1; |
+ v->type = new_type; |
+ r.type_changed = 1; |
+ } |
+ |
+ if (install_new_value (v, new, r.type_changed)) |
{ |
r.changed = 1; |
v->updated = 0; |
@@ -1864,7 +2079,8 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) |
invoked. */ |
if (v->pretty_printer) |
{ |
- VEC (varobj_p) *changed = 0, *new = 0, *unchanged = 0; |
+ VEC (varobj_p) *changed = 0, *type_changed = 0, *unchanged = 0; |
+ VEC (varobj_p) *new = 0; |
int i, children_changed = 0; |
if (v->frozen) |
@@ -1882,7 +2098,7 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) |
it. */ |
if (!varobj_has_more (v, 0)) |
{ |
- update_dynamic_varobj_children (v, NULL, NULL, NULL, |
+ update_dynamic_varobj_children (v, NULL, NULL, NULL, NULL, |
&dummy, 0, 0, 0); |
if (varobj_has_more (v, 0)) |
r.changed = 1; |
@@ -1896,8 +2112,8 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) |
/* If update_dynamic_varobj_children returns 0, then we have |
a non-conforming pretty-printer, so we skip it. */ |
- if (update_dynamic_varobj_children (v, &changed, &new, &unchanged, |
- &children_changed, 1, |
+ if (update_dynamic_varobj_children (v, &changed, &type_changed, &new, |
+ &unchanged, &children_changed, 1, |
v->from, v->to)) |
{ |
if (children_changed || new) |
@@ -1909,6 +2125,18 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) |
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, type_changed) - 1; i >= 0; --i) |
+ { |
+ varobj_p tmp = VEC_index (varobj_p, type_changed, i); |
+ varobj_update_result r = {0}; |
+ |
+ /* Type may change only if value was changed. */ |
+ r.varobj = tmp; |
+ r.changed = 1; |
+ r.type_changed = 1; |
+ r.value_installed = 1; |
+ VEC_safe_push (varobj_update_result, stack, &r); |
+ } |
for (i = VEC_length (varobj_p, changed) - 1; i >= 0; --i) |
{ |
varobj_p tmp = VEC_index (varobj_p, changed, i); |
@@ -1935,9 +2163,10 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) |
if (r.changed || r.children_changed) |
VEC_safe_push (varobj_update_result, result, &r); |
- /* Free CHANGED and UNCHANGED, but not NEW, because NEW |
- has been put into the result vector. */ |
+ /* Free CHANGED, TYPE_CHANGED and UNCHANGED, but not NEW, |
+ because NEW has been put into the result vector. */ |
VEC_free (varobj_p, changed); |
+ VEC_free (varobj_p, type_changed); |
VEC_free (varobj_p, unchanged); |
continue; |
@@ -2169,6 +2398,20 @@ create_child (struct varobj *parent, int index, char *name) |
value_of_child (parent, index)); |
} |
+/* 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. */ |
+ |
+static int |
+is_anonymous_child (struct varobj *child) |
+{ |
+ return (strcmp (child->name, ANONYMOUS_STRUCT_NAME) == 0 |
+ || strcmp (child->name, ANONYMOUS_UNION_NAME) == 0); |
+} |
+ |
static struct varobj * |
create_child_with_value (struct varobj *parent, int index, const char *name, |
struct value *value) |
@@ -2184,8 +2427,13 @@ create_child_with_value (struct varobj *parent, int index, const char *name, |
child->index = index; |
child->parent = parent; |
child->root = parent->root; |
- childs_name = xstrprintf ("%s.%s", parent->obj_name, name); |
+ |
+ if (is_anonymous_child (child)) |
+ childs_name = xstrprintf ("%s.%d_anonymous", parent->obj_name, index); |
+ else |
+ childs_name = xstrprintf ("%s.%s", parent->obj_name, name); |
child->obj_name = childs_name; |
+ |
install_variable (child); |
/* Compute the type of the child. Must do this before |
@@ -2193,7 +2441,7 @@ create_child_with_value (struct varobj *parent, int index, const char *name, |
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); |
+ child->type = value_actual_type (value, 0, NULL); |
else |
/* Otherwise, we must compute the type. */ |
child->type = (*child->root->lang->type_of_child) (child->parent, |
@@ -2540,7 +2788,28 @@ value_of_root (struct varobj **var_handle, int *type_changed) |
*type_changed = 0; |
} |
- return (*var->root->lang->value_of_root) (var_handle); |
+ { |
+ struct value *value; |
+ |
+ value = (*var->root->lang->value_of_root) (var_handle); |
+ if (var->value == NULL || value == NULL) |
+ { |
+ /* For root varobj-s, a NULL value indicates a scoping issue. |
+ So, nothing to do in terms of checking for mutations. */ |
+ } |
+ else if (varobj_value_has_mutated (var, value, value_type (value))) |
+ { |
+ /* The type has mutated, so the children are no longer valid. |
+ Just delete them, and tell our caller that the type has |
+ changed. */ |
+ varobj_delete (var, NULL, 1 /* only_children */); |
+ var->num_children = -1; |
+ var->to = -1; |
+ var->from = -1; |
+ *type_changed = 1; |
+ } |
+ return value; |
+ } |
} |
/* What is the ``struct value *'' for the INDEX'th child of PARENT? */ |
@@ -2729,39 +2998,12 @@ varobj_editable_p (struct varobj *var) |
} |
} |
-/* 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++). |
+/* Call VAR's value_is_changeable_p language-specific callback. */ |
- Return value of 0 means that gdb need not call value_fetch_lazy |
- for the value of this variable object. */ |
static int |
varobj_value_is_changeable_p (struct varobj *var) |
{ |
- int r; |
- struct type *type; |
- |
- if (CPLUS_FAKE_CHILD (var)) |
- return 0; |
- |
- 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; |
- } |
- |
- return r; |
+ return var->root->lang->value_is_changeable_p (var); |
} |
/* Return 1 if that varobj is floating, that is is always evaluated in the |
@@ -2780,6 +3022,10 @@ varobj_floating_p (struct varobj *var) |
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 |
@@ -2791,7 +3037,8 @@ varobj_floating_p (struct varobj *var) |
static void |
adjust_value_for_child_access (struct value **value, |
struct type **type, |
- int *was_ptr) |
+ int *was_ptr, |
+ int lookup_actual_type) |
{ |
gdb_assert (type && *type); |
@@ -2817,9 +3064,14 @@ adjust_value_for_child_access (struct value **value, |
{ |
if (value && *value) |
{ |
- int success = gdb_value_ind (*value, value); |
+ volatile struct gdb_exception except; |
- if (!success) |
+ TRY_CATCH (except, RETURN_MASK_ERROR) |
+ { |
+ *value = value_ind (*value); |
+ } |
+ |
+ if (except.reason < 0) |
*value = NULL; |
} |
*type = target_type; |
@@ -2831,9 +3083,53 @@ adjust_value_for_child_access (struct value **value, |
/* 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); |
+ } |
+ } |
+} |
+ |
+/* Implement the "value_is_changeable_p" varobj callback for most |
+ languages. */ |
+ |
+static int |
+default_value_is_changeable_p (struct varobj *var) |
+{ |
+ int r; |
+ struct type *type; |
+ |
+ if (CPLUS_FAKE_CHILD (var)) |
+ return 0; |
+ |
+ 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; |
+ } |
+ |
+ return r; |
} |
/* C */ |
+ |
static int |
c_number_of_children (struct varobj *var) |
{ |
@@ -2841,7 +3137,7 @@ c_number_of_children (struct varobj *var) |
int children = 0; |
struct type *target; |
- adjust_value_for_child_access (NULL, &type, NULL); |
+ adjust_value_for_child_access (NULL, &type, NULL, 0); |
target = get_target_type (type); |
switch (TYPE_CODE (type)) |
@@ -2944,6 +3240,7 @@ c_describe_child (struct varobj *parent, int index, |
struct type *type = get_value_type (parent); |
char *parent_expression = NULL; |
int was_ptr; |
+ volatile struct gdb_exception except; |
if (cname) |
*cname = NULL; |
@@ -2954,9 +3251,9 @@ c_describe_child (struct varobj *parent, int index, |
if (cfull_expression) |
{ |
*cfull_expression = NULL; |
- parent_expression = varobj_get_path_expr (parent); |
+ parent_expression = varobj_get_path_expr (get_path_expr_parent (parent)); |
} |
- adjust_value_for_child_access (&value, &type, &was_ptr); |
+ adjust_value_for_child_access (&value, &type, &was_ptr, 0); |
switch (TYPE_CODE (type)) |
{ |
@@ -2971,7 +3268,10 @@ c_describe_child (struct varobj *parent, int index, |
{ |
int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)); |
- gdb_value_subscript (value, real_index, cvalue); |
+ TRY_CATCH (except, RETURN_MASK_ERROR) |
+ { |
+ *cvalue = value_subscript (value, real_index); |
+ } |
} |
if (ctype) |
@@ -2989,26 +3289,49 @@ c_describe_child (struct varobj *parent, int index, |
case TYPE_CODE_STRUCT: |
case TYPE_CODE_UNION: |
- if (cname) |
- *cname = xstrdup (TYPE_FIELD_NAME (type, index)); |
+ { |
+ const char *field_name; |
- if (cvalue && value) |
- { |
- /* For C, varobj index is the same as type index. */ |
- *cvalue = value_struct_element_index (value, index); |
- } |
+ /* 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 (ctype) |
- *ctype = TYPE_FIELD_TYPE (type, index); |
+ if (cfull_expression) |
+ *cfull_expression = xstrdup (""); |
+ } |
+ else |
+ { |
+ if (cname) |
+ *cname = xstrdup (field_name); |
- if (cfull_expression) |
- { |
- char *join = was_ptr ? "->" : "."; |
+ if (cfull_expression) |
+ { |
+ char *join = was_ptr ? "->" : "."; |
- *cfull_expression = xstrprintf ("(%s)%s%s", parent_expression, join, |
- TYPE_FIELD_NAME (type, index)); |
- } |
+ *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: |
@@ -3017,9 +3340,12 @@ c_describe_child (struct varobj *parent, int index, |
if (cvalue && value) |
{ |
- int success = gdb_value_ind (value, cvalue); |
+ TRY_CATCH (except, RETURN_MASK_ERROR) |
+ { |
+ *cvalue = value_ind (value); |
+ } |
- if (!success) |
+ if (except.reason < 0) |
*cvalue = NULL; |
} |
@@ -3123,9 +3449,15 @@ c_value_of_root (struct varobj **var_handle) |
if (within_scope) |
{ |
+ volatile struct gdb_exception except; |
+ |
/* We need to catch errors here, because if evaluate |
expression fails we want to just return NULL. */ |
- gdb_evaluate_expression (var->root->exp, &new_val); |
+ TRY_CATCH (except, RETURN_MASK_ERROR) |
+ { |
+ new_val = evaluate_expression (var->root->exp); |
+ } |
+ |
return new_val; |
} |
@@ -3160,11 +3492,6 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format) |
catch that case explicitly. */ |
struct type *type = get_type (var); |
- /* If we have a custom formatter, return whatever string it has |
- produced. */ |
- if (var->pretty_printer && var->print_value) |
- return xstrdup (var->print_value); |
- |
/* Strip top-level references. */ |
while (TYPE_CODE (type) == TYPE_CODE_REF) |
type = check_typedef (TYPE_TARGET_TYPE (type)); |
@@ -3222,16 +3549,29 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format) |
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 = get_value_type (var); |
- adjust_value_for_child_access (NULL, &type, NULL); |
+ |
+ /* 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)) |
@@ -3258,7 +3598,17 @@ cplus_number_of_children (struct varobj *var) |
int kids[3]; |
type = get_value_type (var->parent); |
- adjust_value_for_child_access (NULL, &type, NULL); |
+ |
+ /* 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) |
@@ -3340,7 +3690,10 @@ cplus_describe_child (struct varobj *parent, int index, |
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; |
@@ -3351,22 +3704,18 @@ cplus_describe_child (struct varobj *parent, int index, |
if (cfull_expression) |
*cfull_expression = NULL; |
- if (CPLUS_FAKE_CHILD (parent)) |
- { |
- value = parent->parent->value; |
- type = get_value_type (parent->parent); |
- if (cfull_expression) |
- parent_expression = varobj_get_path_expr (parent->parent); |
- } |
- else |
- { |
- value = parent->value; |
- type = get_value_type (parent); |
- if (cfull_expression) |
- parent_expression = varobj_get_path_expr (parent); |
- } |
+ get_user_print_options (&opts); |
- adjust_value_for_child_access (&value, &type, &was_ptr); |
+ 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 = get_value_type (var); |
+ if (cfull_expression) |
+ parent_expression = varobj_get_path_expr (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) |
@@ -3385,6 +3734,7 @@ cplus_describe_child (struct varobj *parent, int index, |
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) |
@@ -3403,20 +3753,40 @@ cplus_describe_child (struct varobj *parent, int index, |
} |
--type_index; |
- if (cname) |
- *cname = xstrdup (TYPE_FIELD_NAME (type, 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); |
- |
- 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)) |
{ |
@@ -3648,7 +4018,7 @@ java_value_of_variable (struct varobj *var, enum varobj_display_formats format) |
static int |
ada_number_of_children (struct varobj *var) |
{ |
- return c_number_of_children (var); |
+ return ada_varobj_get_number_of_children (var->value, var->type); |
} |
static char * |
@@ -3660,13 +4030,21 @@ ada_name_of_variable (struct varobj *parent) |
static char * |
ada_name_of_child (struct varobj *parent, int index) |
{ |
- return c_name_of_child (parent, index); |
+ return ada_varobj_get_name_of_child (parent->value, parent->type, |
+ parent->name, index); |
} |
static char* |
ada_path_expr_of_child (struct varobj *child) |
{ |
- return c_path_expr_of_child (child); |
+ struct varobj *parent = child->parent; |
+ const char *parent_path_expr = varobj_get_path_expr (parent); |
+ |
+ return ada_varobj_get_path_expr_of_child (parent->value, |
+ parent->type, |
+ parent->name, |
+ parent_path_expr, |
+ child->index); |
} |
static struct value * |
@@ -3678,19 +4056,92 @@ ada_value_of_root (struct varobj **var_handle) |
static struct value * |
ada_value_of_child (struct varobj *parent, int index) |
{ |
- return c_value_of_child (parent, index); |
+ return ada_varobj_get_value_of_child (parent->value, parent->type, |
+ parent->name, index); |
} |
static struct type * |
ada_type_of_child (struct varobj *parent, int index) |
{ |
- return c_type_of_child (parent, index); |
+ return ada_varobj_get_type_of_child (parent->value, parent->type, |
+ index); |
} |
static char * |
ada_value_of_variable (struct varobj *var, enum varobj_display_formats format) |
{ |
- return c_value_of_variable (var, format); |
+ struct value_print_options opts; |
+ |
+ get_formatted_print_options (&opts, format_code[(int) format]); |
+ opts.deref_ref = 0; |
+ opts.raw = 1; |
+ |
+ return ada_varobj_get_value_of_variable (var->value, var->type, &opts); |
+} |
+ |
+/* Implement the "value_is_changeable_p" routine for Ada. */ |
+ |
+static int |
+ada_value_is_changeable_p (struct varobj *var) |
+{ |
+ struct type *type = var->value ? value_type (var->value) : var->type; |
+ |
+ if (ada_is_array_descriptor_type (type) |
+ && TYPE_CODE (type) == TYPE_CODE_TYPEDEF) |
+ { |
+ /* This is in reality a pointer to an unconstrained array. |
+ its value is changeable. */ |
+ return 1; |
+ } |
+ |
+ if (ada_is_string_type (type)) |
+ { |
+ /* We display the contents of the string in the array's |
+ "value" field. The contents can change, so consider |
+ that the array is changeable. */ |
+ return 1; |
+ } |
+ |
+ return default_value_is_changeable_p (var); |
+} |
+ |
+/* Implement the "value_has_mutated" routine for Ada. */ |
+ |
+static int |
+ada_value_has_mutated (struct varobj *var, struct value *new_val, |
+ struct type *new_type) |
+{ |
+ int i; |
+ int from = -1; |
+ int to = -1; |
+ |
+ /* If the number of fields have changed, then for sure the type |
+ has mutated. */ |
+ if (ada_varobj_get_number_of_children (new_val, new_type) |
+ != var->num_children) |
+ return 1; |
+ |
+ /* If the number of fields have remained the same, then we need |
+ to check the name of each field. If they remain the same, |
+ then chances are the type hasn't mutated. This is technically |
+ an incomplete test, as the child's type might have changed |
+ despite the fact that the name remains the same. But we'll |
+ handle this situation by saying that the child has mutated, |
+ not this value. |
+ |
+ If only part (or none!) of the children have been fetched, |
+ then only check the ones we fetched. It does not matter |
+ to the frontend whether a child that it has not fetched yet |
+ has mutated or not. So just assume it hasn't. */ |
+ |
+ restrict_range (var->children, &from, &to); |
+ for (i = from; i < to; i++) |
+ if (strcmp (ada_varobj_get_name_of_child (new_val, new_type, |
+ var->name, i), |
+ VEC_index (varobj_p, var->children, i)->name) != 0) |
+ return 1; |
+ |
+ return 0; |
} |
/* Iterate all the existing _root_ VAROBJs and call the FUNC callback for them |