mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-28 20:43:45 +08:00
a121b7c1ac
This is the remainder boring constification that all looks more of less borderline obvious IMO. gdb/ChangeLog: 2017-04-05 Pedro Alves <palves@redhat.com> * ada-exp.y (yyerror): Constify. * ada-lang.c (bound_name, get_selections) (ada_variant_discrim_type) (ada_variant_discrim_name, ada_value_struct_elt) (ada_lookup_struct_elt_type, is_unchecked_variant) (ada_which_variant_applies, standard_exc, ada_get_next_arg) (catch_ada_exception_command_split) (catch_ada_assert_command_split, catch_assert_command) (ada_op_name): Constify. * ada-lang.h (ada_yyerror, get_selections) (ada_variant_discrim_name, ada_value_struct_elt): Constify. * arc-tdep.c (arc_print_frame_cache): Constify. * arm-tdep.c (arm_skip_stub): Constify. * ax-gdb.c (gen_binop, gen_struct_ref_recursive, gen_struct_ref) (gen_aggregate_elt_ref): Constify. * bcache.c (print_bcache_statistics): Constify. * bcache.h (print_bcache_statistics): Constify. * break-catch-throw.c (catch_exception_command_1): * breakpoint.c (struct ep_type_description::description): Constify. (add_solib_catchpoint): Constify. (catch_fork_command_1): Add cast. (add_catch_command): Constify. * breakpoint.h (add_catch_command, add_solib_catchpoint): Constify. * bsd-uthread.c (bsd_uthread_state): Constify. * buildsym.c (patch_subfile_names): Constify. * buildsym.h (next_symbol_text_func, patch_subfile_names): Constify. * c-exp.y (yyerror): Constify. (token::oper): Constify. * c-lang.h (c_yyerror, cp_print_class_member): Constify. * c-varobj.c (cplus_describe_child): Constify. * charset.c (find_charset_names): Add cast. (find_charset_names): Constify array and add const_cast. * cli/cli-cmds.c (complete_command, cd_command): Constify. (edit_command): Constify. * cli/cli-decode.c (lookup_cmd): Constify. * cli/cli-dump.c (dump_memory_command, dump_value_command): Constify. (struct dump_context): Constify. (add_dump_command, restore_command): Constify. * cli/cli-script.c (get_command_line): Constify. * cli/cli-script.h (get_command_line): Constify. * cli/cli-utils.c (check_for_argument): Constify. * cli/cli-utils.h (check_for_argument): Constify. * coff-pe-read.c (struct read_pe_section_data): Constify. * command.h (lookup_cmd): Constify. * common/print-utils.c (decimal2str): Constify. * completer.c (gdb_print_filename): Constify. * corefile.c (set_gnutarget): Constify. * cp-name-parser.y (yyerror): Constify. * cp-valprint.c (cp_print_class_member): Constify. * cris-tdep.c (cris_register_name, crisv32_register_name): Constify. * d-exp.y (yyerror): Constify. (struct token::oper): Constify. * d-lang.h (d_yyerror): Constify. * dbxread.c (struct header_file_location::name): Constify. (add_old_header_file, add_new_header_file, last_function_name) (dbx_next_symbol_text, add_bincl_to_list) (find_corresponding_bincl_psymtab, set_namestring) (find_stab_function_addr, read_dbx_symtab, start_psymtab) (dbx_end_psymtab, read_ofile_symtab, process_one_symbol): * defs.h (command_line_input, print_address_symbolic) (deprecated_readline_begin_hook): Constify. * dwarf2read.c (anonymous_struct_prefix, dwarf_bool_name): Constify. * event-top.c (handle_line_of_input): Constify and add cast. * exceptions.c (catch_errors): Constify. * exceptions.h (catch_errors): Constify. * expprint.c (print_subexp_standard, op_string, op_name) (op_name_standard, dump_raw_expression, dump_raw_expression): * expression.h (op_name, op_string, dump_raw_expression): Constify. * f-exp.y (yyerror): Constify. (struct token::oper): Constify. (struct f77_boolean_val::name): Constify. * f-lang.c (f_word_break_characters): Constify. * f-lang.h (f_yyerror): Constify. * fork-child.c (fork_inferior): Add cast. * frv-tdep.c (struct gdbarch_tdep::register_names): Constify. (new_variant): Constify. * gdbarch.sh (pstring_ptr, pstring_list): Constify. * gdbarch.c: Regenerate. * gdbcore.h (set_gnutarget): Constify. * go-exp.y (yyerror): Constify. (token::oper): Constify. * go-lang.h (go_yyerror): Constify. * go32-nat.c (go32_sysinfo): Constify. * guile/scm-breakpoint.c (gdbscm_breakpoint_expression): Constify. * guile/scm-cmd.c (cmdscm_function): Constify. * guile/scm-param.c (pascm_param_value): Constify. * h8300-tdep.c (h8300_register_name, h8300s_register_name) (h8300sx_register_name): Constify. * hppa-tdep.c (hppa32_register_name, hppa64_register_name): Constify. * ia64-tdep.c (ia64_register_names): Constify. * infcmd.c (construct_inferior_arguments): Constify. (path_command, attach_post_wait): Constify. * language.c (show_range_command, show_case_command) (unk_lang_error): Constify. * language.h (language_defn::la_error) (language_defn::la_name_of_this): Constify. * linespec.c (decode_line_2): Constify. * linux-thread-db.c (thread_db_err_str): Constify. * lm32-tdep.c (lm32_register_name): Constify. * m2-exp.y (yyerror): Constify. * m2-lang.h (m2_yyerror): Constify. * m32r-tdep.c (m32r_register_names): Constify and make static. * m68hc11-tdep.c (m68hc11_register_names): Constify. * m88k-tdep.c (m88k_register_name): Constify. * macroexp.c (appendmem): Constify. * mdebugread.c (fdr_name, add_data_symbol, parse_type) (upgrade_type, parse_external, parse_partial_symbols) (mdebug_next_symbol_text, cross_ref, mylookup_symbol, new_psymtab) (new_symbol): Constify. * memattr.c (mem_info_command): Constify. * mep-tdep.c (register_name_from_keyword): Constify. * mi/mi-cmd-env.c (mi_cmd_env_path, _initialize_mi_cmd_env): Constify. * mi/mi-cmd-stack.c (list_args_or_locals): Constify. * mi/mi-cmd-var.c (mi_cmd_var_show_attributes): Constify. * mi/mi-main.c (captured_mi_execute_command): Constify and add cast. (mi_execute_async_cli_command): Constify. * mips-tdep.c (mips_register_name): Constify. * mn10300-tdep.c (register_name, mn10300_generic_register_name) (am33_register_name, am33_2_register_name) * moxie-tdep.c (moxie_register_names): Constify. * nat/linux-osdata.c (osdata_type): Constify fields. * nto-tdep.c (nto_parse_redirection): Constify. * objc-lang.c (lookup_struct_typedef, lookup_objc_class) (lookup_child_selector): Constify. (objc_methcall::name): Constify. * objc-lang.h (lookup_objc_class, lookup_child_selector) (lookup_struct_typedef): Constify. * objfiles.c (pc_in_section): Constify. * objfiles.h (pc_in_section): Constify. * p-exp.y (struct token::oper): Constify. (yyerror): Constify. * p-lang.h (pascal_yyerror): Constify. * parser-defs.h (op_name_standard): Constify. (op_print::string): Constify. (exp_descriptor::op_name): Constify. * printcmd.c (print_address_symbolic): Constify. * psymtab.c (print_partial_symbols): Constify. * python/py-breakpoint.c (stop_func): Constify. (bppy_get_expression): Constify. * python/py-cmd.c (cmdpy_completer::name): Constify. (cmdpy_function): Constify. * python/py-event.c (evpy_add_attribute) (gdbpy_initialize_event_generic): Constify. * python/py-event.h (evpy_add_attribute) (gdbpy_initialize_event_generic): Constify. * python/py-evts.c (add_new_registry): Constify. * python/py-finishbreakpoint.c (outofscope_func): Constify. * python/py-framefilter.c (get_py_iter_from_func): Constify. * python/py-inferior.c (get_buffer): Add cast. * python/py-param.c (parm_constant::name): Constify. * python/py-unwind.c (fprint_frame_id): Constify. * python/python.c (gdbpy_parameter_value): Constify. * remote-fileio.c (remote_fio_func_map): Make 'name' const. * remote.c (memory_packet_config::name): Constify. (show_packet_config_cmd, remote_write_bytes) (remote_buffer_add_string): * reverse.c (exec_reverse_once): Constify. * rs6000-tdep.c (variant::name, variant::description): Constify. * rust-exp.y (rustyyerror): Constify. * rust-lang.c (rust_op_name): Constify. * rust-lang.h (rustyyerror): Constify. * serial.h (serial_ops::name): Constify. * sh-tdep.c (sh_sh_register_name, sh_sh3_register_name) (sh_sh3e_register_name, sh_sh2e_register_name) (sh_sh2a_register_name, sh_sh2a_nofpu_register_name) (sh_sh_dsp_register_name, sh_sh3_dsp_register_name) (sh_sh4_register_name, sh_sh4_nofpu_register_name) (sh_sh4al_dsp_register_name): Constify. * sh64-tdep.c (sh64_register_name): Constify. * solib-darwin.c (lookup_symbol_from_bfd): Constify. * spu-tdep.c (spu_register_name, info_spu_dma_cmdlist): Constify. * stabsread.c (patch_block_stabs, read_type_number) (ref_map::stabs, ref_add, process_reference) (symbol_reference_defined, define_symbol, define_symbol) (error_type, read_type, read_member_functions, read_cpp_abbrev) (read_one_struct_field, read_struct_fields, read_baseclasses) (read_tilde_fields, read_struct_type, read_array_type) (read_enum_type, read_sun_builtin_type, read_sun_floating_type) (read_huge_number, read_range_type, read_args, common_block_start) (find_name_end): Constify. * stabsread.h (common_block_start, define_symbol) (process_one_symbol, symbol_reference_defined, ref_add): * symfile.c (get_section_index, add_symbol_file_command): * symfile.h (get_section_index): Constify. * target-descriptions.c (tdesc_type::name): Constify. (tdesc_free_type): Add cast. * target.c (find_default_run_target): (add_deprecated_target_alias, find_default_run_target) (target_announce_detach): Constify. (do_option): Constify. * target.h (add_deprecated_target_alias): Constify. * thread.c (print_thread_info_1): Constify. * top.c (deprecated_readline_begin_hook, command_line_input): Constify. (init_main): Add casts. * top.h (handle_line_of_input): Constify. * tracefile-tfile.c (tfile_write_uploaded_tsv): Constify. * tracepoint.c (tvariables_info_1, trace_status_mi): Constify. (tfind_command): Rename to ... (tfind_command_1): ... this and constify. (tfind_command): New function. (tfind_end_command, tfind_start_command): Adjust. (encode_source_string): Constify. * tracepoint.h (encode_source_string): Constify. * tui/tui-data.c (tui_partial_win_by_name): Constify. * tui/tui-data.h (tui_partial_win_by_name): Constify. * tui/tui-source.c (tui_set_source_content_nil): Constify. * tui/tui-source.h (tui_set_source_content_nil): Constify. * tui/tui-win.c (parse_scrolling_args): Constify. * tui/tui-windata.c (tui_erase_data_content): Constify. * tui/tui-windata.h (tui_erase_data_content): Constify. * tui/tui-winsource.c (tui_erase_source_content): Constify. * tui/tui.c (tui_enable): Add cast. * utils.c (defaulted_query): Constify. (init_page_info): Add cast. (puts_debug, subset_compare): Constify. * utils.h (subset_compare): Constify. * varobj.c (varobj_format_string): Constify. * varobj.h (varobj_format_string): Constify. * vax-tdep.c (vax_register_name): Constify. * windows-nat.c (windows_detach): Constify. * xcoffread.c (process_linenos, xcoff_next_symbol_text): Constify. * xml-support.c (gdb_xml_end_element): Constify. * xml-tdesc.c (tdesc_start_reg): Constify. * xstormy16-tdep.c (xstormy16_register_name): Constify. * xtensa-tdep.c (xtensa_find_register_by_name): Constify. * xtensa-tdep.h (xtensa_register_t::name): Constify. gdb/gdbserver/ChangeLog: 2017-04-05 Pedro Alves <palves@redhat.com> * gdbreplay.c (sync_error): Constify. * linux-x86-low.c (push_opcode): Constify.
968 lines
24 KiB
C
968 lines
24 KiB
C
/* varobj support for C and C++.
|
||
|
||
Copyright (C) 1999-2017 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 (const struct varobj *child)
|
||
{
|
||
return (child->name == ANONYMOUS_STRUCT_NAME
|
||
|| child->name == ANONYMOUS_UNION_NAME);
|
||
}
|
||
|
||
/* 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_IS_REFERENCE (*type));
|
||
|
||
/* 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)
|
||
{
|
||
|
||
TRY
|
||
{
|
||
*value = value_ind (*value);
|
||
}
|
||
|
||
CATCH (except, RETURN_MASK_ERROR)
|
||
{
|
||
*value = NULL;
|
||
}
|
||
END_CATCH
|
||
}
|
||
*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);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Is VAR a path expression parent, i.e., can it be used to construct
|
||
a valid path expression? */
|
||
|
||
static int
|
||
c_is_path_expr_parent (const struct varobj *var)
|
||
{
|
||
struct type *type;
|
||
|
||
/* "Fake" children are not path_expr parents. */
|
||
if (CPLUS_FAKE_CHILD (var))
|
||
return 0;
|
||
|
||
type = varobj_get_gdb_type (var);
|
||
|
||
/* Anonymous unions and structs are also not path_expr parents. */
|
||
if ((TYPE_CODE (type) == TYPE_CODE_STRUCT
|
||
|| TYPE_CODE (type) == TYPE_CODE_UNION)
|
||
&& TYPE_NAME (type) == NULL
|
||
&& TYPE_TAG_NAME (type) == NULL)
|
||
{
|
||
const struct varobj *parent = var->parent;
|
||
|
||
while (parent != NULL && CPLUS_FAKE_CHILD (parent))
|
||
parent = parent->parent;
|
||
|
||
if (parent != NULL)
|
||
{
|
||
struct type *parent_type;
|
||
int was_ptr;
|
||
|
||
parent_type = varobj_get_value_type (parent);
|
||
adjust_value_for_child_access (NULL, &parent_type, &was_ptr, 0);
|
||
|
||
if (TYPE_CODE (parent_type) == TYPE_CODE_STRUCT
|
||
|| TYPE_CODE (parent_type) == TYPE_CODE_UNION)
|
||
{
|
||
const char *field_name;
|
||
|
||
gdb_assert (var->index < TYPE_NFIELDS (parent_type));
|
||
field_name = TYPE_FIELD_NAME (parent_type, var->index);
|
||
return !(field_name == NULL || *field_name == '\0');
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
/* C */
|
||
|
||
static int
|
||
c_number_of_children (const 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 std::string
|
||
c_name_of_variable (const struct varobj *parent)
|
||
{
|
||
return 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;
|
||
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
|
||
{
|
||
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);
|
||
}
|
||
CATCH (e, RETURN_MASK_ERROR)
|
||
{
|
||
return NULL;
|
||
}
|
||
END_CATCH
|
||
|
||
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 empty. */
|
||
|
||
static void
|
||
c_describe_child (const struct varobj *parent, int index,
|
||
std::string *cname, struct value **cvalue,
|
||
struct type **ctype, std::string *cfull_expression)
|
||
{
|
||
struct value *value = parent->value;
|
||
struct type *type = varobj_get_value_type (parent);
|
||
std::string parent_expression;
|
||
int was_ptr;
|
||
|
||
if (cname)
|
||
*cname = std::string ();
|
||
if (cvalue)
|
||
*cvalue = NULL;
|
||
if (ctype)
|
||
*ctype = NULL;
|
||
if (cfull_expression)
|
||
{
|
||
*cfull_expression = std::string ();
|
||
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 = 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
|
||
{
|
||
*cvalue = value_subscript (value, real_index);
|
||
}
|
||
CATCH (except, RETURN_MASK_ERROR)
|
||
{
|
||
}
|
||
END_CATCH
|
||
}
|
||
|
||
if (ctype)
|
||
*ctype = get_target_type (type);
|
||
|
||
if (cfull_expression)
|
||
*cfull_expression =
|
||
string_printf ("(%s)[%s]", parent_expression.c_str (),
|
||
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 = ANONYMOUS_STRUCT_NAME;
|
||
else
|
||
*cname = ANONYMOUS_UNION_NAME;
|
||
}
|
||
|
||
if (cfull_expression)
|
||
*cfull_expression = "";
|
||
}
|
||
else
|
||
{
|
||
if (cname)
|
||
*cname = field_name;
|
||
|
||
if (cfull_expression)
|
||
{
|
||
const char *join = was_ptr ? "->" : ".";
|
||
|
||
*cfull_expression = string_printf ("(%s)%s%s",
|
||
parent_expression.c_str (),
|
||
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 = string_printf ("*%s", parent->name.c_str ());
|
||
|
||
if (cvalue && value)
|
||
{
|
||
TRY
|
||
{
|
||
*cvalue = value_ind (value);
|
||
}
|
||
|
||
CATCH (except, RETURN_MASK_ERROR)
|
||
{
|
||
*cvalue = NULL;
|
||
}
|
||
END_CATCH
|
||
}
|
||
|
||
/* 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 = string_printf ("*(%s)", parent_expression.c_str ());
|
||
break;
|
||
|
||
default:
|
||
/* This should not happen. */
|
||
if (cname)
|
||
*cname = "???";
|
||
if (cfull_expression)
|
||
*cfull_expression = "???";
|
||
/* Don't set value and type, we don't know then. */
|
||
}
|
||
}
|
||
|
||
static std::string
|
||
c_name_of_child (const struct varobj *parent, int index)
|
||
{
|
||
std::string name;
|
||
|
||
c_describe_child (parent, index, &name, NULL, NULL, NULL);
|
||
return name;
|
||
}
|
||
|
||
static std::string
|
||
c_path_expr_of_child (const struct varobj *child)
|
||
{
|
||
std::string path_expr;
|
||
|
||
c_describe_child (child->parent, child->index, NULL, NULL, NULL,
|
||
&path_expr);
|
||
return path_expr;
|
||
}
|
||
|
||
static struct value *
|
||
c_value_of_child (const 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 (const 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 (const struct varobj *var)
|
||
{
|
||
struct type *type;
|
||
|
||
type = var->type;
|
||
if (type != NULL)
|
||
type = check_typedef (type);
|
||
|
||
return type;
|
||
}
|
||
|
||
static std::string
|
||
c_value_of_variable (const 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_IS_REFERENCE (type))
|
||
type = check_typedef (TYPE_TARGET_TYPE (type));
|
||
|
||
switch (TYPE_CODE (type))
|
||
{
|
||
case TYPE_CODE_STRUCT:
|
||
case TYPE_CODE_UNION:
|
||
return "{...}";
|
||
/* break; */
|
||
|
||
case TYPE_CODE_ARRAY:
|
||
return string_printf ("[%d]", var->num_children);
|
||
/* 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 std::string ();
|
||
}
|
||
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 std::string ();
|
||
|
||
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 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 */
|
||
c_is_path_expr_parent /* is_path_expr_parent */
|
||
};
|
||
|
||
/* A little convenience enum for dealing with C++. */
|
||
enum vsections
|
||
{
|
||
v_public = 0, v_private, v_protected
|
||
};
|
||
|
||
/* C++ */
|
||
|
||
static int
|
||
cplus_number_of_children (const 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_IS_REFERENCE (var->type)
|
||
|| 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)
|
||
{
|
||
const struct varobj *parent = var->parent;
|
||
|
||
value = parent->value;
|
||
lookup_actual_type = (TYPE_IS_REFERENCE (parent->type)
|
||
|| 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 (var->name == "public")
|
||
children = kids[v_public];
|
||
else if (var->name == "private")
|
||
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 std::string
|
||
cplus_name_of_variable (const 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 (const struct varobj *parent, int index,
|
||
std::string *cname, struct value **cvalue, struct type **ctype,
|
||
std::string *cfull_expression)
|
||
{
|
||
struct value *value;
|
||
struct type *type;
|
||
int was_ptr;
|
||
int lookup_actual_type = 0;
|
||
const char *parent_expression = NULL;
|
||
const struct varobj *var;
|
||
struct value_print_options opts;
|
||
|
||
if (cname)
|
||
*cname = std::string ();
|
||
if (cvalue)
|
||
*cvalue = NULL;
|
||
if (ctype)
|
||
*ctype = NULL;
|
||
if (cfull_expression)
|
||
*cfull_expression = std::string ();
|
||
|
||
get_user_print_options (&opts);
|
||
|
||
var = (CPLUS_FAKE_CHILD (parent)) ? parent->parent : parent;
|
||
if (opts.objectprint)
|
||
lookup_actual_type = (TYPE_IS_REFERENCE (var->type)
|
||
|| 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)
|
||
{
|
||
const 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 (parent->name == "private")
|
||
acc = private_field;
|
||
else if (parent->name == "protected")
|
||
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 = ANONYMOUS_STRUCT_NAME;
|
||
else if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
|
||
== TYPE_CODE_UNION)
|
||
*cname = ANONYMOUS_UNION_NAME;
|
||
}
|
||
|
||
if (cfull_expression)
|
||
*cfull_expression = std::string ();
|
||
}
|
||
else
|
||
{
|
||
if (cname)
|
||
*cname = TYPE_FIELD_NAME (type, type_index);
|
||
|
||
if (cfull_expression)
|
||
*cfull_expression
|
||
= string_printf ("((%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 = 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)
|
||
{
|
||
const 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 = string_printf ("(%s(class %s%s) %s)",
|
||
ptr,
|
||
TYPE_FIELD_NAME (type, index),
|
||
ptr,
|
||
parent_expression);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
const 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 = access;
|
||
|
||
/* Value and type and full expression are null here. */
|
||
}
|
||
}
|
||
else
|
||
{
|
||
c_describe_child (parent, index, cname, cvalue, ctype, cfull_expression);
|
||
}
|
||
}
|
||
|
||
static std::string
|
||
cplus_name_of_child (const struct varobj *parent, int index)
|
||
{
|
||
std::string name;
|
||
|
||
cplus_describe_child (parent, index, &name, NULL, NULL, NULL);
|
||
return name;
|
||
}
|
||
|
||
static std::string
|
||
cplus_path_expr_of_child (const struct varobj *child)
|
||
{
|
||
std::string path_expr;
|
||
|
||
cplus_describe_child (child->parent, child->index, NULL, NULL, NULL,
|
||
&path_expr);
|
||
return path_expr;
|
||
}
|
||
|
||
static struct value *
|
||
cplus_value_of_child (const 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 (const struct varobj *parent, int index)
|
||
{
|
||
struct type *type = NULL;
|
||
|
||
cplus_describe_child (parent, index, NULL, NULL, &type, NULL);
|
||
return type;
|
||
}
|
||
|
||
static std::string
|
||
cplus_value_of_variable (const 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 std::string ();
|
||
|
||
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 */
|
||
c_is_path_expr_parent /* is_path_expr_parent */
|
||
};
|
||
|
||
|