/* Ada language support routines for GDB, the GNU debugger.
- Copyright (C) 1992-2017 Free Software Foundation, Inc.
+ Copyright (C) 1992-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "annotate.h"
#include "valprint.h"
#include "source.h"
-#include "observer.h"
-#include "vec.h"
+#include "observable.h"
+#include "common/vec.h"
#include "stack.h"
-#include "gdb_vecs.h"
+#include "common/gdb_vecs.h"
#include "typeprint.h"
#include "namespace.h"
static struct block_symbol *defns_collected (struct obstack *, int);
-static struct value *resolve_subexp (struct expression **, int *, int,
- struct type *);
+static struct value *resolve_subexp (expression_up *, int *, int,
+ struct type *, int,
+ innermost_block_tracker *);
-static void replace_operator_with_call (struct expression **, int, int, int,
+static void replace_operator_with_call (expression_up *, int, int, int,
struct symbol *, const struct block *);
static int possible_user_operator_p (enum exp_opcode, struct value **);
static struct value *value_subscript_packed (struct value *, int,
struct value **);
-static void move_bits (gdb_byte *, int, const gdb_byte *, int, int, int);
-
static struct value *coerce_unspec_val_to_type (struct value *,
struct type *);
static int find_struct_field (const char *, struct type *, int,
struct type **, int *, int *, int *, int *);
-static struct value *ada_to_fixed_value_create (struct type *, CORE_ADDR,
- struct value *);
-
static int ada_resolve_function (struct block_symbol *, int,
struct value **, int, const char *,
- struct type *);
+ struct type *, int);
static int ada_is_direct_array_type (struct type *);
ADA_KNOWN_AUXILIARY_FUNCTION_NAME_PATTERNS NULL
};
-/* Space for allocating results of ada_lookup_symbol_list. */
-static struct obstack symbol_list_obstack;
-
/* Maintenance-related settings for this module. */
static struct cmd_list_element *maint_set_ada_cmdlist;
return result;
}
-/* Return a string starting with '<', followed by STR, and '>'.
- The result is good until the next call. */
+/* Return a string starting with '<', followed by STR, and '>'. */
-static char *
+static std::string
add_angle_brackets (const char *str)
{
- static char *result = NULL;
-
- xfree (result);
- result = xstrprintf ("<%s>", str);
- return result;
+ return string_printf ("<%s>", str);
}
static const char *
fprintf_filtered (stream, " => ");
}
+/* la_watch_location_expression for Ada. */
+
+gdb::unique_xmalloc_ptr<char>
+ada_watch_location_expression (struct type *type, CORE_ADDR addr)
+{
+ type = check_typedef (TYPE_TARGET_TYPE (check_typedef (type)));
+ std::string name = type_to_string (type);
+ return gdb::unique_xmalloc_ptr<char>
+ (xstrprintf ("{%s} %s", name.c_str (), core_addr_to_string (addr)));
+}
+
/* Assuming VECT points to an array of *SIZE objects of size
ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
updating *SIZE as necessary and returning the (new) array. */
ada_main_name (void)
{
struct bound_minimal_symbol msym;
- static char *main_program_name = NULL;
+ static gdb::unique_xmalloc_ptr<char> main_program_name;
/* For Ada, the name of the main procedure is stored in a specific
string constant, generated by the binder. Look for that symbol,
if (main_program_name_addr == 0)
error (_("Invalid address for Ada main program name."));
- xfree (main_program_name);
target_read_string (main_program_name_addr, &main_program_name,
1024, &err_code);
if (err_code != 0)
return NULL;
- return main_program_name;
+ return main_program_name.get ();
}
/* The main procedure doesn't seem to be in Ada. */
static char *decoding_buffer = NULL;
static size_t decoding_buffer_size = 0;
+ /* With function descriptors on PPC64, the value of a symbol named
+ ".FN", if it exists, is the entry point of the function "FN". */
+ if (encoded[0] == '.')
+ encoded += 1;
+
/* The name of the Ada main procedure starts with "_ada_".
This prefix is not part of the decoded name, so skip this part
if we see this prefix. */
return v;
}
-/* Move N bits from SOURCE, starting at bit offset SRC_OFFSET to
- TARGET, starting at bit offset TARG_OFFSET. SOURCE and TARGET must
- not overlap. */
-static void
-move_bits (gdb_byte *target, int targ_offset, const gdb_byte *source,
- int src_offset, int n, int bits_big_endian_p)
-{
- unsigned int accum, mask;
- int accum_bits, chunk_size;
-
- target += targ_offset / HOST_CHAR_BIT;
- targ_offset %= HOST_CHAR_BIT;
- source += src_offset / HOST_CHAR_BIT;
- src_offset %= HOST_CHAR_BIT;
- if (bits_big_endian_p)
- {
- accum = (unsigned char) *source;
- source += 1;
- accum_bits = HOST_CHAR_BIT - src_offset;
-
- while (n > 0)
- {
- int unused_right;
-
- accum = (accum << HOST_CHAR_BIT) + (unsigned char) *source;
- accum_bits += HOST_CHAR_BIT;
- source += 1;
- chunk_size = HOST_CHAR_BIT - targ_offset;
- if (chunk_size > n)
- chunk_size = n;
- unused_right = HOST_CHAR_BIT - (chunk_size + targ_offset);
- mask = ((1 << chunk_size) - 1) << unused_right;
- *target =
- (*target & ~mask)
- | ((accum >> (accum_bits - chunk_size - unused_right)) & mask);
- n -= chunk_size;
- accum_bits -= chunk_size;
- target += 1;
- targ_offset = 0;
- }
- }
- else
- {
- accum = (unsigned char) *source >> src_offset;
- source += 1;
- accum_bits = HOST_CHAR_BIT - src_offset;
-
- while (n > 0)
- {
- accum = accum + ((unsigned char) *source << accum_bits);
- accum_bits += HOST_CHAR_BIT;
- source += 1;
- chunk_size = HOST_CHAR_BIT - targ_offset;
- if (chunk_size > n)
- chunk_size = n;
- mask = ((1 << chunk_size) - 1) << targ_offset;
- *target = (*target & ~mask) | ((accum << targ_offset) & mask);
- n -= chunk_size;
- accum_bits -= chunk_size;
- accum >>= chunk_size;
- target += 1;
- targ_offset = 0;
- }
- }
-}
-
/* Store the contents of FROMVAL into the location of TOVAL.
Return a new value with the location of TOVAL and contents of
FROMVAL. Handles assignment into packed fields that have
if (from_size == 0)
from_size = TYPE_LENGTH (value_type (fromval)) * TARGET_CHAR_BIT;
if (gdbarch_bits_big_endian (get_type_arch (type)))
- move_bits (buffer, value_bitpos (toval),
- value_contents (fromval), from_size - bits, bits, 1);
+ copy_bitwise (buffer, value_bitpos (toval),
+ value_contents (fromval), from_size - bits, bits, 1);
else
- move_bits (buffer, value_bitpos (toval),
- value_contents (fromval), 0, bits, 0);
+ copy_bitwise (buffer, value_bitpos (toval),
+ value_contents (fromval), 0, bits, 0);
write_memory_with_notification (to_addr, buffer, len);
val = value_copy (toval);
bits = value_bitsize (component);
if (gdbarch_bits_big_endian (get_type_arch (value_type (container))))
- move_bits (value_contents_writeable (container) + offset_in_container,
- value_bitpos (container) + bit_offset_in_container,
- value_contents (val),
- TYPE_LENGTH (value_type (component)) * TARGET_CHAR_BIT - bits,
- bits, 1);
+ {
+ int src_offset;
+
+ if (is_scalar_type (check_typedef (value_type (component))))
+ src_offset
+ = TYPE_LENGTH (value_type (component)) * TARGET_CHAR_BIT - bits;
+ else
+ src_offset = 0;
+ copy_bitwise (value_contents_writeable (container) + offset_in_container,
+ value_bitpos (container) + bit_offset_in_container,
+ value_contents (val), src_offset, bits, 1);
+ }
else
- move_bits (value_contents_writeable (container) + offset_in_container,
- value_bitpos (container) + bit_offset_in_container,
- value_contents (val), 0, bits, 0);
+ copy_bitwise (value_contents_writeable (container) + offset_in_container,
+ value_bitpos (container) + bit_offset_in_container,
+ value_contents (val), 0, bits, 0);
+}
+
+/* Determine if TYPE is an access to an unconstrained array. */
+
+bool
+ada_is_access_to_unconstrained_array (struct type *type)
+{
+ return (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
+ && is_thick_pntr (ada_typedef_target_type (type)));
}
/* The value of the element of array ARR at the ARITY indices given in IND.
for (k = 0; k < arity; k += 1)
{
+ struct type *saved_elt_type = TYPE_TARGET_TYPE (elt_type);
+
if (TYPE_CODE (elt_type) != TYPE_CODE_ARRAY)
error (_("too many subscripts (%d expected)"), k);
+
elt = value_subscript (elt, pos_atr (ind[k]));
+
+ if (ada_is_access_to_unconstrained_array (saved_elt_type)
+ && TYPE_CODE (value_type (elt)) != TYPE_CODE_TYPEDEF)
+ {
+ /* The element is a typedef to an unconstrained array,
+ except that the value_subscript call stripped the
+ typedef layer. The typedef layer is GNAT's way to
+ specify that the element is, at the source level, an
+ access to the unconstrained array, rather than the
+ unconstrained array. So, we need to restore that
+ typedef layer, which we can do by forcing the element's
+ type back to its original type. Otherwise, the returned
+ value is going to be printed as the array, rather
+ than as an access. Another symptom of the same issue
+ would be that an expression trying to dereference the
+ element would also be improperly rejected. */
+ deprecated_set_value_type (elt, saved_elt_type);
+ }
+
+ elt_type = ada_check_typedef (value_type (elt));
}
+
return elt;
}
struct type *base_index_type = TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0));
struct type *index_type
= create_static_range_type (NULL, base_index_type, low, high);
- struct type *slice_type =
- create_array_type (NULL, TYPE_TARGET_TYPE (type0), index_type);
+ struct type *slice_type = create_array_type_with_stride
+ (NULL, TYPE_TARGET_TYPE (type0), index_type,
+ get_dyn_prop (DYN_PROP_BYTE_STRIDE, type0),
+ TYPE_FIELD_BITSIZE (type0, 0));
int base_low = ada_discrete_type_low_bound (TYPE_INDEX_TYPE (type0));
LONGEST base_low_pos, low_pos;
CORE_ADDR base;
struct type *base_index_type = TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type));
struct type *index_type
= create_static_range_type (NULL, TYPE_INDEX_TYPE (type), low, high);
- struct type *slice_type =
- create_array_type (NULL, TYPE_TARGET_TYPE (type), index_type);
+ struct type *slice_type = create_array_type_with_stride
+ (NULL, TYPE_TARGET_TYPE (type), index_type,
+ get_dyn_prop (DYN_PROP_BYTE_STRIDE, type),
+ TYPE_FIELD_BITSIZE (type, 0));
LONGEST low_pos, high_pos;
if (!discrete_position (base_index_type, low, &low_pos)
}
arr_type = check_typedef (arr_type);
- index_type = TYPE_INDEX_TYPE (arr_type);
+ index_type = ada_index_type (arr_type, n, "length");
if (index_type != NULL)
{
struct type *base_type;
return high - low + 1;
}
-/* An empty array whose type is that of ARR_TYPE (an array type),
- with bounds LOW to LOW-1. */
+/* An array whose type is that of ARR_TYPE (an array type), with
+ bounds LOW to HIGH, but whose contents are unimportant. If HIGH is
+ less than LOW, then LOW-1 is used. */
static struct value *
-empty_array (struct type *arr_type, int low)
+empty_array (struct type *arr_type, int low, int high)
{
struct type *arr_type0 = ada_check_typedef (arr_type);
struct type *index_type
= create_static_range_type
- (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)), low, low - 1);
+ (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)), low,
+ high < low ? low - 1 : high);
struct type *elt_type = ada_array_element_type (arr_type0, 1);
return allocate_value (create_array_type (NULL, elt_type, index_type));
return type is preferred. May change (expand) *EXP. */
static void
-resolve (struct expression **expp, int void_context_p)
+resolve (expression_up *expp, int void_context_p, int parse_completion,
+ innermost_block_tracker *tracker)
{
struct type *context_type = NULL;
int pc = 0;
if (void_context_p)
context_type = builtin_type ((*expp)->gdbarch)->builtin_void;
- resolve_subexp (expp, &pc, 1, context_type);
+ resolve_subexp (expp, &pc, 1, context_type, parse_completion, tracker);
}
/* Resolve the operator of the subexpression beginning at
are as in ada_resolve, above. */
static struct value *
-resolve_subexp (struct expression **expp, int *pos, int deprocedure_p,
- struct type *context_type)
+resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
+ struct type *context_type, int parse_completion,
+ innermost_block_tracker *tracker)
{
int pc = *pos;
int i;
argvec = NULL;
nargs = 0;
- exp = *expp;
+ exp = expp->get ();
/* Pass one: resolve operands, saving their types and updating *pos,
if needed. */
else
{
*pos += 3;
- resolve_subexp (expp, pos, 0, NULL);
+ resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
}
nargs = longest_to_int (exp->elts[pc + 1].longconst);
break;
case UNOP_ADDR:
*pos += 1;
- resolve_subexp (expp, pos, 0, NULL);
+ resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
break;
case UNOP_QUAL:
*pos += 3;
- resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type));
+ resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type),
+ parse_completion, tracker);
break;
case OP_ATR_MODULUS:
struct value *arg1;
*pos += 1;
- arg1 = resolve_subexp (expp, pos, 0, NULL);
+ arg1 = resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
if (arg1 == NULL)
- resolve_subexp (expp, pos, 1, NULL);
+ resolve_subexp (expp, pos, 1, NULL, parse_completion, tracker);
else
- resolve_subexp (expp, pos, 1, value_type (arg1));
+ resolve_subexp (expp, pos, 1, value_type (arg1), parse_completion,
+ tracker);
break;
}
argvec = XALLOCAVEC (struct value *, nargs + 1);
for (i = 0; i < nargs; i += 1)
- argvec[i] = resolve_subexp (expp, pos, 1, NULL);
+ argvec[i] = resolve_subexp (expp, pos, 1, NULL, parse_completion,
+ tracker);
argvec[i] = NULL;
- exp = *expp;
+ exp = expp->get ();
/* Pass two: perform any resolution on principal operator. */
switch (op)
case OP_VAR_VALUE:
if (SYMBOL_DOMAIN (exp->elts[pc + 2].symbol) == UNDEF_DOMAIN)
{
- struct block_symbol *candidates;
+ std::vector<struct block_symbol> candidates;
int n_candidates;
n_candidates =
else if (n_candidates == 1)
i = 0;
else if (deprocedure_p
- && !is_nonfunction (candidates, n_candidates))
+ && !is_nonfunction (candidates.data (), n_candidates))
{
i = ada_resolve_function
- (candidates, n_candidates, NULL, 0,
+ (candidates.data (), n_candidates, NULL, 0,
SYMBOL_LINKAGE_NAME (exp->elts[pc + 2].symbol),
- context_type);
+ context_type, parse_completion);
if (i < 0)
error (_("Could not find a match for %s"),
SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol));
{
printf_filtered (_("Multiple matches for %s\n"),
SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol));
- user_select_syms (candidates, n_candidates, 1);
+ user_select_syms (candidates.data (), n_candidates, 1);
i = 0;
}
exp->elts[pc + 1].block = candidates[i].block;
exp->elts[pc + 2].symbol = candidates[i].symbol;
- if (innermost_block == NULL
- || contained_in (candidates[i].block, innermost_block))
- innermost_block = candidates[i].block;
+ tracker->update (candidates[i]);
}
if (deprocedure_p
&& (TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 2].symbol))
== TYPE_CODE_FUNC))
{
- replace_operator_with_call (expp, pc, 0, 0,
+ replace_operator_with_call (expp, pc, 0, 4,
exp->elts[pc + 2].symbol,
exp->elts[pc + 1].block);
- exp = *expp;
+ exp = expp->get ();
}
break;
if (exp->elts[pc + 3].opcode == OP_VAR_VALUE
&& SYMBOL_DOMAIN (exp->elts[pc + 5].symbol) == UNDEF_DOMAIN)
{
- struct block_symbol *candidates;
+ std::vector<struct block_symbol> candidates;
int n_candidates;
n_candidates =
(exp->elts[pc + 5].symbol),
exp->elts[pc + 4].block, VAR_DOMAIN,
&candidates);
+
if (n_candidates == 1)
i = 0;
else
{
i = ada_resolve_function
- (candidates, n_candidates,
+ (candidates.data (), n_candidates,
argvec, nargs,
SYMBOL_LINKAGE_NAME (exp->elts[pc + 5].symbol),
- context_type);
+ context_type, parse_completion);
if (i < 0)
error (_("Could not find a match for %s"),
SYMBOL_PRINT_NAME (exp->elts[pc + 5].symbol));
exp->elts[pc + 4].block = candidates[i].block;
exp->elts[pc + 5].symbol = candidates[i].symbol;
- if (innermost_block == NULL
- || contained_in (candidates[i].block, innermost_block))
- innermost_block = candidates[i].block;
+ tracker->update (candidates[i]);
}
}
break;
case UNOP_ABS:
if (possible_user_operator_p (op, argvec))
{
- struct block_symbol *candidates;
+ std::vector<struct block_symbol> candidates;
int n_candidates;
n_candidates =
ada_lookup_symbol_list (ada_decoded_op_name (op),
- (struct block *) NULL, VAR_DOMAIN,
+ NULL, VAR_DOMAIN,
&candidates);
- i = ada_resolve_function (candidates, n_candidates, argvec, nargs,
- ada_decoded_op_name (op), NULL);
+
+ i = ada_resolve_function (candidates.data (), n_candidates, argvec,
+ nargs, ada_decoded_op_name (op), NULL,
+ parse_completion);
if (i < 0)
break;
replace_operator_with_call (expp, pc, nargs, 1,
candidates[i].symbol,
candidates[i].block);
- exp = *expp;
+ exp = expp->get ();
}
break;
static int
ada_resolve_function (struct block_symbol syms[],
int nsyms, struct value **args, int nargs,
- const char *name, struct type *context_type)
+ const char *name, struct type *context_type,
+ int parse_completion)
{
int fallback;
int k;
error (_("\
canceled because the command is ambiguous\n\
See set/show multiple-symbol."));
-
+
/* If select_mode is "all", then return all possible symbols.
Only do that if more than one symbol can be selected, of course.
Otherwise, display the menu as usual. */
if (select_mode == multiple_symbols_all && max_results > 1)
return nsyms;
- printf_unfiltered (_("[0] cancel\n"));
+ printf_filtered (_("[0] cancel\n"));
if (max_results > 1)
- printf_unfiltered (_("[1] all\n"));
+ printf_filtered (_("[1] all\n"));
sort_choices (syms, nsyms);
struct symtab_and_line sal =
find_function_start_sal (syms[i].symbol, 1);
- printf_unfiltered ("[%d] ", i + first_choice);
+ printf_filtered ("[%d] ", i + first_choice);
ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
&type_print_raw_options);
if (sal.symtab == NULL)
- printf_unfiltered (_(" at <no source file available>:%d\n"),
- sal.line);
+ printf_filtered (_(" at <no source file available>:%d\n"),
+ sal.line);
else
- printf_unfiltered (_(" at %s:%d\n"),
- symtab_to_filename_for_display (sal.symtab),
- sal.line);
+ printf_filtered (_(" at %s:%d\n"),
+ symtab_to_filename_for_display (sal.symtab),
+ sal.line);
continue;
}
else
if (SYMBOL_LINE (syms[i].symbol) != 0 && symtab != NULL)
{
- printf_unfiltered ("[%d] ", i + first_choice);
+ printf_filtered ("[%d] ", i + first_choice);
ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
&type_print_raw_options);
- printf_unfiltered (_(" at %s:%d\n"),
- symtab_to_filename_for_display (symtab),
- SYMBOL_LINE (syms[i].symbol));
+ printf_filtered (_(" at %s:%d\n"),
+ symtab_to_filename_for_display (symtab),
+ SYMBOL_LINE (syms[i].symbol));
}
else if (is_enumeral
&& TYPE_NAME (SYMBOL_TYPE (syms[i].symbol)) != NULL)
{
- printf_unfiltered (("[%d] "), i + first_choice);
+ printf_filtered (("[%d] "), i + first_choice);
ada_print_type (SYMBOL_TYPE (syms[i].symbol), NULL,
gdb_stdout, -1, 0, &type_print_raw_options);
- printf_unfiltered (_("'(%s) (enumeral)\n"),
- SYMBOL_PRINT_NAME (syms[i].symbol));
+ printf_filtered (_("'(%s) (enumeral)\n"),
+ SYMBOL_PRINT_NAME (syms[i].symbol));
}
else
{
- printf_unfiltered ("[%d] ", i + first_choice);
+ printf_filtered ("[%d] ", i + first_choice);
ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
&type_print_raw_options);
if (symtab != NULL)
- printf_unfiltered (is_enumeral
- ? _(" in %s (enumeral)\n")
- : _(" at %s:?\n"),
- symtab_to_filename_for_display (symtab));
+ printf_filtered (is_enumeral
+ ? _(" in %s (enumeral)\n")
+ : _(" at %s:?\n"),
+ symtab_to_filename_for_display (symtab));
else
- printf_unfiltered (is_enumeral
- ? _(" (enumeral)\n")
- : _(" at ?\n"));
+ printf_filtered (is_enumeral
+ ? _(" (enumeral)\n")
+ : _(" at ?\n"));
}
}
}
if (prompt == NULL)
prompt = "> ";
- args = command_line_input (prompt, 0, annotation_suffix);
+ args = command_line_input (prompt, annotation_suffix);
if (args == NULL)
error_no_arg (_("one or more choice numbers"));
arguments. Update *EXPP as needed to hold more space. */
static void
-replace_operator_with_call (struct expression **expp, int pc, int nargs,
+replace_operator_with_call (expression_up *expp, int pc, int nargs,
int oplen, struct symbol *sym,
const struct block *block)
{
struct expression *newexp = (struct expression *)
xzalloc (sizeof (struct expression)
+ EXP_ELEM_TO_BYTES ((*expp)->nelts + 7 - oplen));
- struct expression *exp = *expp;
+ struct expression *exp = expp->get ();
newexp->nelts = exp->nelts + 7 - oplen;
newexp->language_defn = exp->language_defn;
newexp->elts[pc + 4].block = block;
newexp->elts[pc + 5].symbol = sym;
- *expp = newexp;
- xfree (exp);
+ expp->reset (newexp);
}
/* Type-class predicates */
|| TYPE_NFIELDS (type) != 1)
return ADA_NOT_RENAMING;
- name = type_name_no_tag (type);
+ name = TYPE_NAME (type);
if (name == NULL)
return ADA_NOT_RENAMING;
if (TYPE_CODE (formal_target) == TYPE_CODE_ARRAY
&& ada_is_array_descriptor_type (actual_target))
result = desc_data (actual);
- else if (TYPE_CODE (actual_type) != TYPE_CODE_PTR)
+ else if (TYPE_CODE (formal_type) != TYPE_CODE_PTR)
{
if (VALUE_LVAL (actual) != lval_memory)
{
return;
h = msymbol_hash (name) % HASH_SIZE;
- e = (struct cache_entry *) obstack_alloc (&sym_cache->cache_space,
- sizeof (*e));
+ e = XOBNEW (&sym_cache->cache_space, cache_entry);
e->next = sym_cache->root[h];
sym_cache->root[h] = e;
e->name = copy
searching for all symbols matching LOOKUP_NAME.
LOOKUP_NAME is expected to be a symbol name after transformation
- for Ada lookups (see ada_name_for_lookup). */
+ for Ada lookups. */
static symbol_name_match_type
name_match_type_from_name (const char *lookup_name)
domain_enum domain)
{
/* Initialize it just to avoid a GCC false warning. */
- struct block_symbol sym = {NULL, NULL};
+ struct block_symbol sym = {};
if (lookup_cached_symbol (name, domain, &sym.symbol, NULL))
return sym.symbol;
- sym = lookup_symbol_in_language (name, block, domain, language_c, 0);
+ ada_lookup_encoded_symbol (name, block, domain, &sym);
cache_symbol (name, domain, sym.symbol, sym.block);
return sym.symbol;
}
ada_lookup_simple_minsym (const char *name)
{
struct bound_minimal_symbol result;
- struct objfile *objfile;
- struct minimal_symbol *msymbol;
memset (&result, 0, sizeof (result));
symbol_name_matcher_ftype *match_name
= ada_get_symbol_name_matcher (lookup_name);
- ALL_MSYMBOLS (objfile, msymbol)
- {
- if (match_name (MSYMBOL_LINKAGE_NAME (msymbol), lookup_name, NULL)
- && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
- {
- result.minsym = msymbol;
- result.objfile = objfile;
- break;
- }
- }
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ for (minimal_symbol *msymbol : objfile->msymbols ())
+ {
+ if (match_name (MSYMBOL_LINKAGE_NAME (msymbol), lookup_name, NULL)
+ && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
+ {
+ result.minsym = msymbol;
+ result.objfile = objfile;
+ break;
+ }
+ }
+ }
return result;
}
So, for practical purposes, we consider them as the same. */
static int
-symbols_are_identical_enums (struct block_symbol *syms, int nsyms)
+symbols_are_identical_enums (const std::vector<struct block_symbol> &syms)
{
int i;
(see ada_identical_enum_types_p). */
/* Quick check: All symbols should have an enum type. */
- for (i = 0; i < nsyms; i++)
+ for (i = 0; i < syms.size (); i++)
if (TYPE_CODE (SYMBOL_TYPE (syms[i].symbol)) != TYPE_CODE_ENUM)
return 0;
/* Quick check: They should all have the same value. */
- for (i = 1; i < nsyms; i++)
+ for (i = 1; i < syms.size (); i++)
if (SYMBOL_VALUE (syms[i].symbol) != SYMBOL_VALUE (syms[0].symbol))
return 0;
/* Quick check: They should all have the same number of enumerals. */
- for (i = 1; i < nsyms; i++)
+ for (i = 1; i < syms.size (); i++)
if (TYPE_NFIELDS (SYMBOL_TYPE (syms[i].symbol))
!= TYPE_NFIELDS (SYMBOL_TYPE (syms[0].symbol)))
return 0;
/* All the sanity checks passed, so we might have a set of
identical enumeration types. Perform a more complete
comparison of the type of each symbol. */
- for (i = 1; i < nsyms; i++)
+ for (i = 1; i < syms.size (); i++)
if (!ada_identical_enum_types_p (SYMBOL_TYPE (syms[i].symbol),
SYMBOL_TYPE (syms[0].symbol)))
return 0;
return 1;
}
-/* Remove any non-debugging symbols in SYMS[0 .. NSYMS-1] that definitely
+/* Remove any non-debugging symbols in SYMS that definitely
duplicate other symbols in the list (The only case I know of where
this happens is when object files containing stabs-in-ecoff are
linked with files containing ordinary ecoff debugging symbols (or no
Returns the number of items in the modified list. */
static int
-remove_extra_symbols (struct block_symbol *syms, int nsyms)
+remove_extra_symbols (std::vector<struct block_symbol> *syms)
{
int i, j;
/* We should never be called with less than 2 symbols, as there
cannot be any extra symbol in that case. But it's easy to
handle, since we have nothing to do in that case. */
- if (nsyms < 2)
- return nsyms;
+ if (syms->size () < 2)
+ return syms->size ();
i = 0;
- while (i < nsyms)
+ while (i < syms->size ())
{
int remove_p = 0;
/* If two symbols have the same name and one of them is a stub type,
the get rid of the stub. */
- if (TYPE_STUB (SYMBOL_TYPE (syms[i].symbol))
- && SYMBOL_LINKAGE_NAME (syms[i].symbol) != NULL)
+ if (TYPE_STUB (SYMBOL_TYPE ((*syms)[i].symbol))
+ && SYMBOL_LINKAGE_NAME ((*syms)[i].symbol) != NULL)
{
- for (j = 0; j < nsyms; j++)
+ for (j = 0; j < syms->size (); j++)
{
if (j != i
- && !TYPE_STUB (SYMBOL_TYPE (syms[j].symbol))
- && SYMBOL_LINKAGE_NAME (syms[j].symbol) != NULL
- && strcmp (SYMBOL_LINKAGE_NAME (syms[i].symbol),
- SYMBOL_LINKAGE_NAME (syms[j].symbol)) == 0)
+ && !TYPE_STUB (SYMBOL_TYPE ((*syms)[j].symbol))
+ && SYMBOL_LINKAGE_NAME ((*syms)[j].symbol) != NULL
+ && strcmp (SYMBOL_LINKAGE_NAME ((*syms)[i].symbol),
+ SYMBOL_LINKAGE_NAME ((*syms)[j].symbol)) == 0)
remove_p = 1;
}
}
/* Two symbols with the same name, same class and same address
should be identical. */
- else if (SYMBOL_LINKAGE_NAME (syms[i].symbol) != NULL
- && SYMBOL_CLASS (syms[i].symbol) == LOC_STATIC
- && is_nondebugging_type (SYMBOL_TYPE (syms[i].symbol)))
+ else if (SYMBOL_LINKAGE_NAME ((*syms)[i].symbol) != NULL
+ && SYMBOL_CLASS ((*syms)[i].symbol) == LOC_STATIC
+ && is_nondebugging_type (SYMBOL_TYPE ((*syms)[i].symbol)))
{
- for (j = 0; j < nsyms; j += 1)
+ for (j = 0; j < syms->size (); j += 1)
{
if (i != j
- && SYMBOL_LINKAGE_NAME (syms[j].symbol) != NULL
- && strcmp (SYMBOL_LINKAGE_NAME (syms[i].symbol),
- SYMBOL_LINKAGE_NAME (syms[j].symbol)) == 0
- && SYMBOL_CLASS (syms[i].symbol)
- == SYMBOL_CLASS (syms[j].symbol)
- && SYMBOL_VALUE_ADDRESS (syms[i].symbol)
- == SYMBOL_VALUE_ADDRESS (syms[j].symbol))
+ && SYMBOL_LINKAGE_NAME ((*syms)[j].symbol) != NULL
+ && strcmp (SYMBOL_LINKAGE_NAME ((*syms)[i].symbol),
+ SYMBOL_LINKAGE_NAME ((*syms)[j].symbol)) == 0
+ && SYMBOL_CLASS ((*syms)[i].symbol)
+ == SYMBOL_CLASS ((*syms)[j].symbol)
+ && SYMBOL_VALUE_ADDRESS ((*syms)[i].symbol)
+ == SYMBOL_VALUE_ADDRESS ((*syms)[j].symbol))
remove_p = 1;
}
}
if (remove_p)
- {
- for (j = i + 1; j < nsyms; j += 1)
- syms[j - 1] = syms[j];
- nsyms -= 1;
- }
+ syms->erase (syms->begin () + i);
i += 1;
}
to ask the user to disambiguate anyways. And if we have to
present a multiple-choice menu, it's less confusing if the list
isn't missing some choices that were identical and yet distinct. */
- if (symbols_are_identical_enums (syms, nsyms))
- nsyms = 1;
+ if (symbols_are_identical_enums (*syms))
+ syms->resize (1);
- return nsyms;
+ return syms->size ();
}
/* Given a type that corresponds to a renaming entity, use the type name
to extract the scope (package name or function name, fully qualified,
and following the GNAT encoding convention) where this renaming has been
- defined. The string returned needs to be deallocated after use. */
+ defined. */
-static char *
+static std::string
xget_renaming_scope (struct type *renaming_type)
{
/* The renaming types adhere to the following convention:
So, to extract the scope, we search for the "___XR" extension,
and then backtrack until we find the first "__". */
- const char *name = type_name_no_tag (renaming_type);
+ const char *name = TYPE_NAME (renaming_type);
const char *suffix = strstr (name, "___XR");
const char *last;
- int scope_len;
- char *scope;
/* Now, backtrack a bit until we find the first "__". Start looking
at suffix - 3, as the <rename> part is at least one character long. */
break;
/* Make a copy of scope and return it. */
-
- scope_len = last - name;
- scope = (char *) xmalloc ((scope_len + 1) * sizeof (char));
-
- strncpy (scope, name, scope_len);
- scope[scope_len] = '\0';
-
- return scope;
+ return std::string (name, last);
}
/* Return nonzero if NAME corresponds to a package name. */
to NAME not existing in our list of symbols. There is only one
small complication with library-level functions (see below). */
- char *fun_name;
-
/* If it is a function that has not been defined at library level,
then we should be able to look it up in the symbols. */
if (standard_lookup (name, NULL, VAR_DOMAIN) != NULL)
if (strstr (name, "__") != NULL)
return 0;
- fun_name = xstrprintf ("_ada_%s", name);
+ std::string fun_name = string_printf ("_ada_%s", name);
- return (standard_lookup (fun_name, NULL, VAR_DOMAIN) == NULL);
+ return (standard_lookup (fun_name.c_str (), NULL, VAR_DOMAIN) == NULL);
}
/* Return nonzero if SYM corresponds to a renaming entity that is
static int
old_renaming_is_invisible (const struct symbol *sym, const char *function_name)
{
- char *scope;
- struct cleanup *old_chain;
-
if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
return 0;
- scope = xget_renaming_scope (SYMBOL_TYPE (sym));
- old_chain = make_cleanup (xfree, scope);
+ std::string scope = xget_renaming_scope (SYMBOL_TYPE (sym));
/* If the rename has been defined in a package, then it is visible. */
- if (is_package_name (scope))
- {
- do_cleanups (old_chain);
- return 0;
- }
+ if (is_package_name (scope.c_str ()))
+ return 0;
/* Check that the rename is in the current function scope by checking
that its name starts with SCOPE. */
if (startswith (function_name, "_ada_"))
function_name += 5;
- {
- int is_invisible = !startswith (function_name, scope);
-
- do_cleanups (old_chain);
- return is_invisible;
- }
+ return !startswith (function_name, scope.c_str ());
}
/* Remove entries from SYMS that corresponds to a renaming entity that
the user will be unable to print such rename entities. */
static int
-remove_irrelevant_renamings (struct block_symbol *syms,
- int nsyms, const struct block *current_block)
+remove_irrelevant_renamings (std::vector<struct block_symbol> *syms,
+ const struct block *current_block)
{
struct symbol *current_function;
const char *current_function_name;
a simple variable foo in the same block, discard the latter.
First, zero out such symbols, then compress. */
is_new_style_renaming = 0;
- for (i = 0; i < nsyms; i += 1)
+ for (i = 0; i < syms->size (); i += 1)
{
- struct symbol *sym = syms[i].symbol;
- const struct block *block = syms[i].block;
+ struct symbol *sym = (*syms)[i].symbol;
+ const struct block *block = (*syms)[i].block;
const char *name;
const char *suffix;
int j;
is_new_style_renaming = 1;
- for (j = 0; j < nsyms; j += 1)
- if (i != j && syms[j].symbol != NULL
- && strncmp (name, SYMBOL_LINKAGE_NAME (syms[j].symbol),
+ for (j = 0; j < syms->size (); j += 1)
+ if (i != j && (*syms)[j].symbol != NULL
+ && strncmp (name, SYMBOL_LINKAGE_NAME ((*syms)[j].symbol),
name_len) == 0
- && block == syms[j].block)
- syms[j].symbol = NULL;
+ && block == (*syms)[j].block)
+ (*syms)[j].symbol = NULL;
}
}
if (is_new_style_renaming)
{
int j, k;
- for (j = k = 0; j < nsyms; j += 1)
- if (syms[j].symbol != NULL)
+ for (j = k = 0; j < syms->size (); j += 1)
+ if ((*syms)[j].symbol != NULL)
{
- syms[k] = syms[j];
+ (*syms)[k] = (*syms)[j];
k += 1;
}
return k;
Abort if unable to do so. */
if (current_block == NULL)
- return nsyms;
+ return syms->size ();
current_function = block_linkage_function (current_block);
if (current_function == NULL)
- return nsyms;
+ return syms->size ();
current_function_name = SYMBOL_LINKAGE_NAME (current_function);
if (current_function_name == NULL)
- return nsyms;
+ return syms->size ();
/* Check each of the symbols, and remove it from the list if it is
a type corresponding to a renaming that is out of the scope of
the current block. */
i = 0;
- while (i < nsyms)
+ while (i < syms->size ())
{
- if (ada_parse_renaming (syms[i].symbol, NULL, NULL, NULL)
+ if (ada_parse_renaming ((*syms)[i].symbol, NULL, NULL, NULL)
== ADA_OBJECT_RENAMING
- && old_renaming_is_invisible (syms[i].symbol, current_function_name))
- {
- int j;
-
- for (j = i + 1; j < nsyms; j += 1)
- syms[j - 1] = syms[j];
- nsyms -= 1;
- }
+ && old_renaming_is_invisible ((*syms)[i].symbol,
+ current_function_name))
+ syms->erase (syms->begin () + i);
else
i += 1;
}
- return nsyms;
+ return syms->size ();
}
/* Add to OBSTACKP all symbols from BLOCK (and its super-blocks)
other has been found. */
static int
-aux_add_nonlocal_symbols (struct block *block, struct symbol *sym, void *data0)
+aux_add_nonlocal_symbols (const struct block *block, struct symbol *sym,
+ void *data0)
{
struct match_data *data = (struct match_data *) data0;
const lookup_name_info &lookup_name,
domain_enum domain, int global)
{
- struct objfile *objfile;
- struct compunit_symtab *cu;
struct match_data data;
memset (&data, 0, sizeof data);
bool is_wild_match = lookup_name.ada ().wild_match_p ();
- ALL_OBJFILES (objfile)
+ for (objfile *objfile : current_program_space->objfiles ())
{
data.objfile = objfile;
symbol_name_match_type::FULL,
compare_names);
- ALL_OBJFILE_COMPUNITS (objfile, cu)
+ for (compunit_symtab *cu : objfile->compunits ())
{
const struct block *global_block
= BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cu), GLOBAL_BLOCK);
const char *name = ada_lookup_name (lookup_name);
std::string name1 = std::string ("<_ada_") + name + '>';
- ALL_OBJFILES (objfile)
+ for (objfile *objfile : current_program_space->objfiles ())
{
data.objfile = objfile;
objfile->sf->qf->map_matching_symbols (objfile, name1.c_str (),
/* Find symbols in DOMAIN matching LOOKUP_NAME, in BLOCK and, if FULL_SEARCH
is non-zero, enclosing scope and in global scopes, returning the number of
matches.
- Sets *RESULTS to point to a vector of (SYM,BLOCK) tuples,
- indicating the symbols found and the blocks and symbol tables (if
- any) in which they were found. This vector is transient---good only to
- the next call of ada_lookup_symbol_list.
+ Fills *RESULTS with (SYM,BLOCK) tuples, indicating the symbols
+ found and the blocks and symbol tables (if any) in which they were
+ found.
When full_search is non-zero, any non-function/non-enumeral
symbol match within the nest of blocks whose innermost member is BLOCK,
ada_lookup_symbol_list_worker (const lookup_name_info &lookup_name,
const struct block *block,
domain_enum domain,
- struct block_symbol **results,
+ std::vector<struct block_symbol> *results,
int full_search)
{
int syms_from_global_search;
int ndefns;
+ auto_obstack obstack;
- obstack_free (&symbol_list_obstack, NULL);
- obstack_init (&symbol_list_obstack);
- ada_add_all_symbols (&symbol_list_obstack, block, lookup_name,
+ ada_add_all_symbols (&obstack, block, lookup_name,
domain, full_search, &syms_from_global_search);
- ndefns = num_defns_collected (&symbol_list_obstack);
- *results = defns_collected (&symbol_list_obstack, 1);
+ ndefns = num_defns_collected (&obstack);
+
+ struct block_symbol *base = defns_collected (&obstack, 1);
+ for (int i = 0; i < ndefns; ++i)
+ results->push_back (base[i]);
- ndefns = remove_extra_symbols (*results, ndefns);
+ ndefns = remove_extra_symbols (results);
if (ndefns == 0 && full_search && syms_from_global_search)
cache_symbol (ada_lookup_name (lookup_name), domain, NULL, NULL);
cache_symbol (ada_lookup_name (lookup_name), domain,
(*results)[0].symbol, (*results)[0].block);
- ndefns = remove_irrelevant_renamings (*results, ndefns, block);
+ ndefns = remove_irrelevant_renamings (results, block);
+
return ndefns;
}
/* Find symbols in DOMAIN matching NAME, in BLOCK and enclosing scope and
- in global scopes, returning the number of matches, and setting *RESULTS
- to a vector of (SYM,BLOCK) tuples.
+ in global scopes, returning the number of matches, and filling *RESULTS
+ with (SYM,BLOCK) tuples.
+
See ada_lookup_symbol_list_worker for further details. */
int
ada_lookup_symbol_list (const char *name, const struct block *block,
- domain_enum domain, struct block_symbol **results)
+ domain_enum domain,
+ std::vector<struct block_symbol> *results)
{
symbol_name_match_type name_match_type = name_match_type_from_name (name);
lookup_name_info lookup_name (name, name_match_type);
gdb::function_view<symbol_found_callback_ftype> callback)
{
int ndefs, i;
- struct block_symbol *results;
+ std::vector<struct block_symbol> results;
ndefs = ada_lookup_symbol_list_worker (name, block, domain, &results, 0);
+
for (i = 0; i < ndefs; ++i)
{
- if (!callback (results[i].symbol))
+ if (!callback (&results[i]))
break;
}
}
domain_enum domain,
struct block_symbol *info)
{
- struct block_symbol *candidates;
- int n_candidates;
-
/* Since we already have an encoded name, wrap it in '<>' to force a
verbatim match. Otherwise, if the name happens to not look like
an encoded name (because it doesn't include a "__"),
std::string verbatim = std::string ("<") + name + '>';
gdb_assert (info != NULL);
- memset (info, 0, sizeof (struct block_symbol));
-
- n_candidates = ada_lookup_symbol_list (verbatim.c_str (), block,
- domain, &candidates);
- if (n_candidates == 0)
- return;
-
- *info = candidates[0];
- info->symbol = fixup_symbol_section (info->symbol, NULL);
+ *info = ada_lookup_symbol (verbatim.c_str (), block, domain, NULL);
}
/* Return a symbol in DOMAIN matching NAME, in BLOCK0 and enclosing
ada_lookup_symbol (const char *name, const struct block *block0,
domain_enum domain, int *is_a_field_of_this)
{
- struct block_symbol info;
-
if (is_a_field_of_this != NULL)
*is_a_field_of_this = 0;
- ada_lookup_encoded_symbol (ada_encode (ada_fold_name (name)),
- block0, domain, &info);
+ std::vector<struct block_symbol> candidates;
+ int n_candidates;
+
+ n_candidates = ada_lookup_symbol_list (name, block0, domain, &candidates);
+
+ if (n_candidates == 0)
+ return {};
+
+ block_symbol info = candidates[0];
+ info.symbol = fixup_symbol_section (info.symbol, NULL);
return info;
}
return sym;
}
- return (struct block_symbol) {NULL, NULL};
+ return {};
}
enum type_code code)
{
struct symbol *sym;
- struct compunit_symtab *s;
- struct minimal_symbol *msymbol;
- struct objfile *objfile;
const struct block *b, *surrounding_static_block = 0;
- int i;
struct block_iterator iter;
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
gdb_assert (code == TYPE_CODE_UNDEF);
anything that isn't a text symbol (everything else will be
handled by the psymtab code above). */
- ALL_MSYMBOLS (objfile, msymbol)
- {
- QUIT;
-
- if (completion_skip_symbol (mode, msymbol))
- continue;
-
- completion_list_add_name (tracker,
- MSYMBOL_LANGUAGE (msymbol),
- MSYMBOL_LINKAGE_NAME (msymbol),
- lookup_name, text, word);
- }
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ for (minimal_symbol *msymbol : objfile->msymbols ())
+ {
+ QUIT;
+
+ if (completion_skip_symbol (mode, msymbol))
+ continue;
+
+ language symbol_language = MSYMBOL_LANGUAGE (msymbol);
+
+ /* Ada minimal symbols won't have their language set to Ada. If
+ we let completion_list_add_name compare using the
+ default/C-like matcher, then when completing e.g., symbols in a
+ package named "pck", we'd match internal Ada symbols like
+ "pckS", which are invalid in an Ada expression, unless you wrap
+ them in '<' '>' to request a verbatim match.
+
+ Unfortunately, some Ada encoded names successfully demangle as
+ C++ symbols (using an old mangling scheme), such as "name__2Xn"
+ -> "Xn::name(void)" and thus some Ada minimal symbols end up
+ with the wrong language set. Paper over that issue here. */
+ if (symbol_language == language_auto
+ || symbol_language == language_cplus)
+ symbol_language = language_ada;
+
+ completion_list_add_name (tracker,
+ symbol_language,
+ MSYMBOL_LINKAGE_NAME (msymbol),
+ lookup_name, text, word);
+ }
+ }
/* Search upwards from currently selected frame (so that we can
complete on local vars. */
/* Go through the symtabs and check the externs and statics for
symbols which match. */
- ALL_COMPUNITS (objfile, s)
- {
- QUIT;
- b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), GLOBAL_BLOCK);
- ALL_BLOCK_SYMBOLS (b, iter, sym)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- if (completion_skip_symbol (mode, sym))
- continue;
+ for (compunit_symtab *s : objfile->compunits ())
+ {
+ QUIT;
+ b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), GLOBAL_BLOCK);
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ {
+ if (completion_skip_symbol (mode, sym))
+ continue;
- completion_list_add_name (tracker,
- SYMBOL_LANGUAGE (sym),
- SYMBOL_LINKAGE_NAME (sym),
- lookup_name, text, word);
+ completion_list_add_name (tracker,
+ SYMBOL_LANGUAGE (sym),
+ SYMBOL_LINKAGE_NAME (sym),
+ lookup_name, text, word);
+ }
+ }
}
- }
- ALL_COMPUNITS (objfile, s)
- {
- QUIT;
- b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), STATIC_BLOCK);
- /* Don't do this block twice. */
- if (b == surrounding_static_block)
- continue;
- ALL_BLOCK_SYMBOLS (b, iter, sym)
- {
- if (completion_skip_symbol (mode, sym))
- continue;
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ for (compunit_symtab *s : objfile->compunits ())
+ {
+ QUIT;
+ b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), STATIC_BLOCK);
+ /* Don't do this block twice. */
+ if (b == surrounding_static_block)
+ continue;
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ {
+ if (completion_skip_symbol (mode, sym))
+ continue;
- completion_list_add_name (tracker,
- SYMBOL_LANGUAGE (sym),
- SYMBOL_LINKAGE_NAME (sym),
- lookup_name, text, word);
+ completion_list_add_name (tracker,
+ SYMBOL_LANGUAGE (sym),
+ SYMBOL_LINKAGE_NAME (sym),
+ lookup_name, text, word);
+ }
+ }
}
- }
-
- do_cleanups (old_chain);
}
/* Field Access */
if (is_ada95_tag (tag))
return obj;
- ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
+ ptr_type = language_lookup_primitive_type
+ (language_def (language_ada), target_gdbarch(), "storage_offset");
ptr_type = lookup_pointer_type (ptr_type);
val = value_cast (ptr_type, tag);
if (!val)
if (offset_to_top == -1)
return obj;
- base_address = value_address (obj) - offset_to_top;
+ /* OFFSET_TO_TOP used to be a positive value to be subtracted
+ from the base address. This was however incompatible with
+ C++ dispatch table: C++ uses a *negative* value to *add*
+ to the base address. Ada's convention has therefore been
+ changed in GNAT 19.0w 20171023: since then, C++ and Ada
+ use the same convention. Here, we support both cases by
+ checking the sign of OFFSET_TO_TOP. */
+
+ if (offset_to_top > 0)
+ offset_to_top = -offset_to_top;
+
+ base_address = value_address (obj) + offset_to_top;
tag = value_tag_from_contents_and_address (obj_type, NULL, base_address);
/* Make sure that we have a proper tag at the new address.
number of fields if not found. A NULL value of NAME never
matches; the function just counts visible fields in this case.
+ Notice that we need to handle when a tagged record hierarchy
+ has some components with the same name, like in this scenario:
+
+ type Top_T is tagged record
+ N : Integer := 1;
+ U : Integer := 974;
+ A : Integer := 48;
+ end record;
+
+ type Middle_T is new Top.Top_T with record
+ N : Character := 'a';
+ C : Integer := 3;
+ end record;
+
+ type Bottom_T is new Middle.Middle_T with record
+ N : Float := 4.0;
+ C : Character := '5';
+ X : Integer := 6;
+ A : Character := 'J';
+ end record;
+
+ Let's say we now have a variable declared and initialized as follow:
+
+ TC : Top_A := new Bottom_T;
+
+ And then we use this variable to call this function
+
+ procedure Assign (Obj: in out Top_T; TV : Integer);
+
+ as follow:
+
+ Assign (Top_T (B), 12);
+
+ Now, we're in the debugger, and we're inside that procedure
+ then and we want to print the value of obj.c:
+
+ Usually, the tagged record or one of the parent type owns the
+ component to print and there's no issue but in this particular
+ case, what does it mean to ask for Obj.C? Since the actual
+ type for object is type Bottom_T, it could mean two things: type
+ component C from the Middle_T view, but also component C from
+ Bottom_T. So in that "undefined" case, when the component is
+ not found in the non-resolved type (which includes all the
+ components of the parent type), then resolve it and see if we
+ get better luck once expanded.
+
+ In the case of homonyms in the derived tagged type, we don't
+ guaranty anything, and pick the one that's easiest for us
+ to program.
+
Returns 1 if found, 0 otherwise. */
static int
int *index_p)
{
int i;
+ int parent_offset = -1;
type = ada_check_typedef (type);
if (t_field_name == NULL)
continue;
+ else if (ada_is_parent_field (type, i))
+ {
+ /* This is a field pointing us to the parent type of a tagged
+ type. As hinted in this function's documentation, we give
+ preference to fields in the current record first, so what
+ we do here is just record the index of this field before
+ we skip it. If it turns out we couldn't find our field
+ in the current record, then we'll get back to it and search
+ inside it whether the field might exist in the parent. */
+
+ parent_offset = i;
+ continue;
+ }
+
else if (name != NULL && field_name_match (t_field_name, name))
{
int bit_size = TYPE_FIELD_BITSIZE (type, i);
else if (index_p != NULL)
*index_p += 1;
}
+
+ /* Field not found so far. If this is a tagged type which
+ has a parent, try finding that field in the parent now. */
+
+ if (parent_offset != -1)
+ {
+ int bit_pos = TYPE_FIELD_BITPOS (type, parent_offset);
+ int fld_offset = offset + bit_pos / 8;
+
+ if (find_struct_field (name, TYPE_FIELD_TYPE (type, parent_offset),
+ fld_offset, field_type_p, byte_offset_p,
+ bit_offset_p, bit_size_p, index_p))
+ return 1;
+ }
+
return 0;
}
and search in it assuming it has (class) type TYPE.
If found, return value, else return NULL.
- Searches recursively through wrapper fields (e.g., '_parent'). */
+ Searches recursively through wrapper fields (e.g., '_parent').
+
+ In the case of homonyms in the tagged types, please refer to the
+ long explanation in find_struct_field's function documentation. */
static struct value *
ada_search_struct_field (const char *name, struct value *arg, int offset,
struct type *type)
{
int i;
+ int parent_offset = -1;
type = ada_check_typedef (type);
for (i = 0; i < TYPE_NFIELDS (type); i += 1)
if (t_field_name == NULL)
continue;
+ else if (ada_is_parent_field (type, i))
+ {
+ /* This is a field pointing us to the parent type of a tagged
+ type. As hinted in this function's documentation, we give
+ preference to fields in the current record first, so what
+ we do here is just record the index of this field before
+ we skip it. If it turns out we couldn't find our field
+ in the current record, then we'll get back to it and search
+ inside it whether the field might exist in the parent. */
+
+ parent_offset = i;
+ continue;
+ }
+
else if (field_name_match (t_field_name, name))
return ada_value_primitive_field (arg, offset, i, type);
}
}
}
+
+ /* Field not found so far. If this is a tagged type which
+ has a parent, try finding that field in the parent now. */
+
+ if (parent_offset != -1)
+ {
+ struct value *v = ada_search_struct_field (
+ name, arg, offset + TYPE_FIELD_BITPOS (type, parent_offset) / 8,
+ TYPE_FIELD_TYPE (type, parent_offset));
+
+ if (v != NULL)
+ return v;
+ }
+
return NULL;
}
{
struct type *t, *t1;
struct value *v;
+ int check_tag;
v = NULL;
t1 = t = ada_check_typedef (value_type (arg));
else
address = value_address (ada_coerce_ref (arg));
- t1 = ada_to_fixed_type (ada_get_base_type (t1), NULL, address, NULL, 1);
+ /* Check to see if this is a tagged type. We also need to handle
+ the case where the type is a reference to a tagged type, but
+ we have to be careful to exclude pointers to tagged types.
+ The latter should be shown as usual (as a pointer), whereas
+ a reference should mostly be transparent to the user. */
+
+ if (ada_is_tagged_type (t1, 0)
+ || (TYPE_CODE (t1) == TYPE_CODE_REF
+ && ada_is_tagged_type (TYPE_TARGET_TYPE (t1), 0)))
+ {
+ /* We first try to find the searched field in the current type.
+ If not found then let's look in the fixed type. */
+
+ if (!find_struct_field (name, t1, 0,
+ &field_type, &byte_offset, &bit_offset,
+ &bit_size, NULL))
+ check_tag = 1;
+ else
+ check_tag = 0;
+ }
+ else
+ check_tag = 0;
+
+ /* Convert to fixed type in all cases, so that we have proper
+ offsets to each field in unconstrained record types. */
+ t1 = ada_to_fixed_type (ada_get_base_type (t1), NULL,
+ address, NULL, check_tag);
+
if (find_struct_field (name, t1, 0,
&field_type, &byte_offset, &bit_offset,
&bit_size, NULL))
Looks recursively into variant clauses and parent types.
+ In the case of homonyms in the tagged types, please refer to the
+ long explanation in find_struct_field's function documentation.
+
If NOERR is nonzero, return NULL if NAME is not suitably defined or
TYPE is not a type of the right kind. */
int noerr)
{
int i;
+ int parent_offset = -1;
if (name == NULL)
goto BadName;
if (t_field_name == NULL)
continue;
+ else if (ada_is_parent_field (type, i))
+ {
+ /* This is a field pointing us to the parent type of a tagged
+ type. As hinted in this function's documentation, we give
+ preference to fields in the current record first, so what
+ we do here is just record the index of this field before
+ we skip it. If it turns out we couldn't find our field
+ in the current record, then we'll get back to it and search
+ inside it whether the field might exist in the parent. */
+
+ parent_offset = i;
+ continue;
+ }
+
else if (field_name_match (t_field_name, name))
return TYPE_FIELD_TYPE (type, i);
}
+ /* Field not found so far. If this is a tagged type which
+ has a parent, try finding that field in the parent now. */
+
+ if (parent_offset != -1)
+ {
+ struct type *t;
+
+ t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (type, parent_offset),
+ name, 0, 1);
+ if (t != NULL)
+ return t;
+ }
+
BadName:
if (!noerr)
{
return 1;
else
{
- const char *type0_name = type_name_no_tag (type0);
- const char *type1_name = type_name_no_tag (type1);
+ const char *type0_name = TYPE_NAME (type0);
+ const char *type1_name = TYPE_NAME (type1);
if (type0_name != NULL && strstr (type0_name, "___XR") != NULL
&& (type1_name == NULL || strstr (type1_name, "___XR") == NULL))
return 0;
}
-/* The name of TYPE, which is either its TYPE_NAME, or, if that is
- null, its TYPE_TAG_NAME. Null if TYPE is null. */
+/* The name of TYPE, which is its TYPE_NAME. Null if TYPE is
+ null. */
const char *
ada_type_name (struct type *type)
{
if (type == NULL)
return NULL;
- else if (TYPE_NAME (type) != NULL)
- return TYPE_NAME (type);
- else
- return TYPE_TAG_NAME (type);
+ return TYPE_NAME (type);
}
/* Search the list of "descriptive" types associated to TYPE for a type
TYPE_FIELDS (type) = NULL;
INIT_CPLUS_SPECIFIC (type);
TYPE_NAME (type) = "<empty>";
- TYPE_TAG_NAME (type) = NULL;
TYPE_LENGTH (type) = 0;
return type;
}
TYPE_ALLOC (rtype, nfields * sizeof (struct field));
memset (TYPE_FIELDS (rtype), 0, sizeof (struct field) * nfields);
TYPE_NAME (rtype) = ada_type_name (type);
- TYPE_TAG_NAME (rtype) = NULL;
TYPE_FIXED_INSTANCE (rtype) = 1;
off = 0;
if (TYPE_LENGTH (type) <= 0)
{
if (TYPE_NAME (rtype))
- warning (_("Invalid type size for `%s' detected: %d."),
- TYPE_NAME (rtype), TYPE_LENGTH (type));
+ warning (_("Invalid type size for `%s' detected: %s."),
+ TYPE_NAME (rtype), pulongest (TYPE_LENGTH (type)));
else
- warning (_("Invalid type size for <unnamed> detected: %d."),
- TYPE_LENGTH (type));
+ warning (_("Invalid type size for <unnamed> detected: %s."),
+ pulongest (TYPE_LENGTH (type)));
}
else
{
memcpy (TYPE_FIELDS (type), TYPE_FIELDS (type0),
sizeof (struct field) * nfields);
TYPE_NAME (type) = ada_type_name (type0);
- TYPE_TAG_NAME (type) = NULL;
TYPE_FIXED_INSTANCE (type) = 1;
TYPE_LENGTH (type) = 0;
}
memcpy (TYPE_FIELDS (rtype), TYPE_FIELDS (type),
sizeof (struct field) * nfields);
TYPE_NAME (rtype) = ada_type_name (type);
- TYPE_TAG_NAME (rtype) = NULL;
TYPE_FIXED_INSTANCE (rtype) = 1;
TYPE_LENGTH (rtype) = TYPE_LENGTH (type);
ada_is_redundant_range_encoding (struct type *range_type,
struct type *encoding_type)
{
- struct type *fixed_range_type;
const char *bounds_str;
int n;
LONGEST lo, hi;
const char *name = ada_type_name (fixed_record_type);
char *xvz_name
= (char *) alloca (strlen (name) + 7 /* "___XVZ\0" */);
+ bool xvz_found = false;
LONGEST size;
xsnprintf (xvz_name, strlen (name) + 7, "%s___XVZ", name);
- if (get_int_var_value (xvz_name, size)
- && TYPE_LENGTH (fixed_record_type) != size)
+ TRY
+ {
+ xvz_found = get_int_var_value (xvz_name, size);
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ /* We found the variable, but somehow failed to read
+ its value. Rethrow the same error, but with a little
+ bit more information, to help the user understand
+ what went wrong (Eg: the variable might have been
+ optimized out). */
+ throw_error (except.error,
+ _("unable to read value of %s (%s)"),
+ xvz_name, except.message);
+ }
+ END_CATCH
+
+ if (xvz_found && TYPE_LENGTH (fixed_record_type) != size)
{
fixed_record_type = copy_type (fixed_record_type);
TYPE_LENGTH (fixed_record_type) = size;
if (type == NULL)
return NULL;
- /* If our type is a typedef type of a fat pointer, then we're done.
+ /* If our type is an access to an unconstrained array, which is encoded
+ as a TYPE_CODE_TYPEDEF of a fat pointer, then we're done.
We don't want to strip the TYPE_CODE_TYPDEF layer, because this is
what allows us to distinguish between fat pointers that represent
array types, and fat pointers that represent array access types
(in both cases, the compiler implements them as fat pointers). */
- if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
- && is_thick_pntr (ada_typedef_target_type (type)))
+ if (ada_is_access_to_unconstrained_array (type))
return type;
type = check_typedef (type);
if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM
|| !TYPE_STUB (type)
- || TYPE_TAG_NAME (type) == NULL)
+ || TYPE_NAME (type) == NULL)
return type;
else
{
- const char *name = TYPE_TAG_NAME (type);
+ const char *name = TYPE_NAME (type);
struct type *type1 = ada_find_any_type (name);
if (type1 == NULL)
if (type == type0 && val0 != NULL)
return val0;
- else
- return value_from_contents_and_address (type, 0, address);
+
+ if (VALUE_LVAL (val0) != lval_memory)
+ {
+ /* Our value does not live in memory; it could be a convenience
+ variable, for instance. Create a not_lval value using val0's
+ contents. */
+ return value_from_contents (type, value_contents (val0));
+ }
+
+ return value_from_contents_and_address (type, 0, address);
}
/* A value representing VAL, but with a standard (static-sized) type
ada_to_fixed_value (struct value *val)
{
val = unwrap_value (val);
- val = ada_to_fixed_value_create (value_type (val),
- value_address (val),
- val);
+ val = ada_to_fixed_value_create (value_type (val), value_address (val), val);
return val;
}
\f
if (ada_is_direct_array_type (value_type (arg1))
|| ada_is_direct_array_type (value_type (arg2)))
{
+ struct type *arg1_type, *arg2_type;
+
/* Automatically dereference any array reference before
we attempt to perform the comparison. */
arg1 = ada_coerce_ref (arg1);
arg2 = ada_coerce_ref (arg2);
-
+
arg1 = ada_coerce_to_simple_array (arg1);
arg2 = ada_coerce_to_simple_array (arg2);
- if (TYPE_CODE (value_type (arg1)) != TYPE_CODE_ARRAY
- || TYPE_CODE (value_type (arg2)) != TYPE_CODE_ARRAY)
+
+ arg1_type = ada_check_typedef (value_type (arg1));
+ arg2_type = ada_check_typedef (value_type (arg2));
+
+ if (TYPE_CODE (arg1_type) != TYPE_CODE_ARRAY
+ || TYPE_CODE (arg2_type) != TYPE_CODE_ARRAY)
error (_("Attempt to compare array with non-array"));
/* FIXME: The following works only for types whose
representations use all bits (no padding or undefined bits)
and do not have user-defined equality. */
- return
- TYPE_LENGTH (value_type (arg1)) == TYPE_LENGTH (value_type (arg2))
- && memcmp (value_contents (arg1), value_contents (arg2),
- TYPE_LENGTH (value_type (arg1))) == 0;
+ return (TYPE_LENGTH (arg1_type) == TYPE_LENGTH (arg2_type)
+ && memcmp (value_contents (arg1), value_contents (arg2),
+ TYPE_LENGTH (arg1_type)) == 0);
}
return value_equal (arg1, arg2);
}
{
struct value *mark = value_mark ();
struct value *elt;
+ struct type *lhs_type = check_typedef (value_type (lhs));
- if (TYPE_CODE (value_type (lhs)) == TYPE_CODE_ARRAY)
+ if (TYPE_CODE (lhs_type) == TYPE_CODE_ARRAY)
{
struct type *index_type = builtin_type (exp->gdbarch)->builtin_int;
struct value *index_val = value_from_longest (index_type, index);
if (!deprecated_value_modifiable (lhs))
error (_("Left operand of assignment is not a modifiable lvalue."));
- lhs_type = value_type (lhs);
+ lhs_type = check_typedef (value_type (lhs));
if (ada_is_direct_array_type (lhs_type))
{
lhs = ada_coerce_to_simple_array (lhs);
- lhs_type = value_type (lhs);
+ lhs_type = check_typedef (value_type (lhs));
low_index = TYPE_ARRAY_LOWER_BOUND_VALUE (lhs_type);
high_index = TYPE_ARRAY_UPPER_BOUND_VALUE (lhs_type);
}
return arg2;
if (ada_is_fixed_point_type (type))
- return (cast_to_fixed (type, arg2));
+ return cast_to_fixed (type, arg2);
if (ada_is_fixed_point_type (value_type (arg2)))
return cast_from_fixed (type, arg2);
error_call_unknown_return_type (NULL);
return allocate_value (TYPE_TARGET_TYPE (type));
}
- return call_function_by_hand (argvec[0], NULL, nargs, argvec + 1);
+ return call_function_by_hand (argvec[0], NULL,
+ gdb::make_array_view (argvec + 1,
+ nargs));
case TYPE_CODE_INTERNAL_FUNCTION:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
/* We don't know anything about what the internal
if (noside == EVAL_AVOID_SIDE_EFFECTS
&& ada_is_array_descriptor_type (ada_check_typedef
(value_type (array))))
- return empty_array (ada_type_of_array (array, 0), low_bound);
+ return empty_array (ada_type_of_array (array, 0), low_bound,
+ high_bound);
array = ada_coerce_to_simple_array_ptr (array);
struct type *type0 = ada_check_typedef (value_type (array));
if (high_bound < low_bound || noside == EVAL_AVOID_SIDE_EFFECTS)
- return empty_array (TYPE_TARGET_TYPE (type0), low_bound);
+ return empty_array (TYPE_TARGET_TYPE (type0), low_bound, high_bound);
else
{
struct type *arr_type0 =
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
return array;
else if (high_bound < low_bound)
- return empty_array (value_type (array), low_bound);
+ return empty_array (value_type (array), low_bound, high_bound);
else
return ada_value_slice (array, longest_to_int (low_bound),
longest_to_int (high_bound));
{
lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
- struct block_symbol *syms;
+ std::vector<struct block_symbol> syms;
int nsyms = ada_lookup_symbol_list_worker (lookup_name,
get_selected_block (0),
VAR_DOMAIN, &syms, 1);
type = create_static_range_type (alloc_type_copy (raw_type),
base_type, L, U);
+ /* create_static_range_type alters the resulting type's length
+ to match the size of the base_type, which is not what we want.
+ Set it back to the original range type's length. */
+ TYPE_LENGTH (type) = TYPE_LENGTH (raw_type);
TYPE_NAME (type) = name;
return type;
}
a catchpoint on failed assertions. */
const char *catch_assert_sym;
+ /* The name of the symbol to break on in order to insert
+ a catchpoint on exception handling. */
+ const char *catch_handlers_sym;
+
/* Assuming that the inferior just triggered an unhandled exception
catchpoint, this function is responsible for returning the address
in inferior memory where the name of that exception is stored.
"__gnat_debug_raise_exception", /* catch_exception_sym */
"__gnat_unhandled_exception", /* catch_exception_unhandled_sym */
"__gnat_debug_raise_assert_failure", /* catch_assert_sym */
+ "__gnat_begin_handler", /* catch_handlers_sym */
ada_unhandled_exception_name_addr
};
"__gnat_raise_nodefer_with_msg", /* catch_exception_sym */
"__gnat_unhandled_exception", /* catch_exception_unhandled_sym */
"system__assertions__raise_assert_failure", /* catch_assert_sym */
+ "__gnat_begin_handler", /* catch_handlers_sym */
ada_unhandled_exception_name_addr_from_raise
};
loaded. If it is not started, this may mean that the symbol is
in a shared library. */
- if (ptid_get_pid (inferior_ptid) == 0)
+ if (inferior_ptid.pid () == 0)
error (_("Unable to insert catchpoint. Try to start the program first."));
/* At this point, we know that we are debugging an Ada program and
if (strcmp (func_name.get (),
data->exception_info->catch_exception_sym) == 0)
break; /* We found the frame we were looking for... */
- fi = get_prev_frame (fi);
}
+ fi = get_prev_frame (fi);
}
if (fi == NULL)
case ada_catch_exception_unhandled:
return data->exception_info->unhandled_exception_name_addr ();
break;
-
+
+ case ada_catch_handlers:
+ return 0; /* The runtimes does not provide access to the exception
+ name. */
+ break;
+
case ada_catch_assert:
return 0; /* Exception name is not relevant in this case. */
break;
return the message which was associated to the exception, if
available. Return NULL if the message could not be retrieved.
- The caller must xfree the string after use.
-
Note: The exception message can be associated to an exception
either through the use of the Raise_Exception function, or
more simply (Ada 2005 and later), via:
*/
-static char *
+static gdb::unique_xmalloc_ptr<char>
ada_exception_message_1 (void)
{
struct value *e_msg_val;
- char *e_msg = NULL;
int e_msg_len;
- struct cleanup *cleanups;
/* For runtimes that support this feature, the exception message
is passed as an unbounded string argument called "message". */
if (e_msg_len <= 0)
return NULL;
- e_msg = (char *) xmalloc (e_msg_len + 1);
- cleanups = make_cleanup (xfree, e_msg);
- read_memory_string (value_address (e_msg_val), e_msg, e_msg_len + 1);
- e_msg[e_msg_len] = '\0';
+ gdb::unique_xmalloc_ptr<char> e_msg ((char *) xmalloc (e_msg_len + 1));
+ read_memory_string (value_address (e_msg_val), e_msg.get (), e_msg_len + 1);
+ e_msg.get ()[e_msg_len] = '\0';
- discard_cleanups (cleanups);
return e_msg;
}
/* Same as ada_exception_message_1, except that all exceptions are
contained here (returning NULL instead). */
-static char *
+static gdb::unique_xmalloc_ptr<char>
ada_exception_message (void)
{
- char *e_msg = NULL; /* Avoid a spurious uninitialized warning. */
+ gdb::unique_xmalloc_ptr<char> e_msg;
TRY
{
}
CATCH (e, RETURN_MASK_ERROR)
{
- e_msg = NULL;
+ e_msg.reset (nullptr);
}
END_CATCH
return result;
}
-static char *ada_exception_catchpoint_cond_string (const char *excep_string);
+static std::string ada_exception_catchpoint_cond_string
+ (const char *excep_string,
+ enum ada_exception_catchpoint_kind ex);
/* Ada catchpoints.
class ada_catchpoint_location : public bp_location
{
public:
- ada_catchpoint_location (const bp_location_ops *ops, breakpoint *owner)
- : bp_location (ops, owner)
+ ada_catchpoint_location (breakpoint *owner)
+ : bp_location (owner)
{}
/* The condition that checks whether the exception that was raised
expression_up excep_cond_expr;
};
-/* Implement the DTOR method in the bp_location_ops structure for all
- Ada exception catchpoint kinds. */
-
-static void
-ada_catchpoint_location_dtor (struct bp_location *bl)
-{
- struct ada_catchpoint_location *al = (struct ada_catchpoint_location *) bl;
-
- al->excep_cond_expr.reset ();
-}
-
-/* The vtable to be used in Ada catchpoint locations. */
-
-static const struct bp_location_ops ada_catchpoint_location_ops =
-{
- ada_catchpoint_location_dtor
-};
-
/* An instance of this type is used to represent an Ada catchpoint. */
struct ada_catchpoint : public breakpoint
{
- ~ada_catchpoint () override;
-
/* The name of the specific exception the user specified. */
- char *excep_string;
+ std::string excep_string;
};
/* Parse the exception condition string in the context of each of the
catchpoint's locations, and store them for later evaluation. */
static void
-create_excep_cond_exprs (struct ada_catchpoint *c)
+create_excep_cond_exprs (struct ada_catchpoint *c,
+ enum ada_exception_catchpoint_kind ex)
{
- struct cleanup *old_chain;
struct bp_location *bl;
- char *cond_string;
/* Nothing to do if there's no specific exception to catch. */
- if (c->excep_string == NULL)
+ if (c->excep_string.empty ())
return;
/* Same if there are no locations... */
/* Compute the condition expression in text form, from the specific
expection we want to catch. */
- cond_string = ada_exception_catchpoint_cond_string (c->excep_string);
- old_chain = make_cleanup (xfree, cond_string);
+ std::string cond_string
+ = ada_exception_catchpoint_cond_string (c->excep_string.c_str (), ex);
/* Iterate over all the catchpoint's locations, and parse an
expression for each. */
{
const char *s;
- s = cond_string;
+ s = cond_string.c_str ();
TRY
{
exp = parse_exp_1 (&s, bl->address,
ada_loc->excep_cond_expr = std::move (exp);
}
-
- do_cleanups (old_chain);
-}
-
-/* ada_catchpoint destructor. */
-
-ada_catchpoint::~ada_catchpoint ()
-{
- xfree (this->excep_string);
}
/* Implement the ALLOCATE_LOCATION method in the breakpoint_ops
allocate_location_exception (enum ada_exception_catchpoint_kind ex,
struct breakpoint *self)
{
- return new ada_catchpoint_location (&ada_catchpoint_location_ops, self);
+ return new ada_catchpoint_location (self);
}
/* Implement the RE_SET method in the breakpoint_ops structure for all
/* Reparse the exception conditional expressions. One for each
location. */
- create_excep_cond_exprs (c);
+ create_excep_cond_exprs (c, ex);
}
/* Returns true if we should stop for this breakpoint hit. If the
int stop;
/* With no specific exception, should always stop. */
- if (c->excep_string == NULL)
+ if (c->excep_string.empty ())
return 1;
if (ada_loc->excep_cond_expr == NULL)
{
struct ui_out *uiout = current_uiout;
struct breakpoint *b = bs->breakpoint_at;
- char *exception_message;
annotate_catchpoint (b->number);
{
case ada_catch_exception:
case ada_catch_exception_unhandled:
+ case ada_catch_handlers:
{
const CORE_ADDR addr = ada_exception_name_addr (ex, b);
char exception_name[256];
break;
}
- exception_message = ada_exception_message ();
+ gdb::unique_xmalloc_ptr<char> exception_message = ada_exception_message ();
if (exception_message != NULL)
{
- struct cleanup *cleanups = make_cleanup (xfree, exception_message);
-
uiout->text (" (");
- uiout->field_string ("exception-message", exception_message);
+ uiout->field_string ("exception-message", exception_message.get ());
uiout->text (")");
-
- do_cleanups (cleanups);
}
uiout->text (" at ");
switch (ex)
{
case ada_catch_exception:
- if (c->excep_string != NULL)
+ if (!c->excep_string.empty ())
{
- char *msg = xstrprintf (_("`%s' Ada exception"), c->excep_string);
+ std::string msg = string_printf (_("`%s' Ada exception"),
+ c->excep_string.c_str ());
uiout->field_string ("what", msg);
- xfree (msg);
}
else
uiout->field_string ("what", "all Ada exceptions");
uiout->field_string ("what", "unhandled Ada exceptions");
break;
+ case ada_catch_handlers:
+ if (!c->excep_string.empty ())
+ {
+ uiout->field_fmt ("what",
+ _("`%s' Ada exception handlers"),
+ c->excep_string.c_str ());
+ }
+ else
+ uiout->field_string ("what", "all Ada exceptions handlers");
+ break;
+
case ada_catch_assert:
uiout->field_string ("what", "failed Ada assertions");
break;
switch (ex)
{
case ada_catch_exception:
- if (c->excep_string != NULL)
+ if (!c->excep_string.empty ())
{
- char *info = xstrprintf (_("`%s' Ada exception"), c->excep_string);
- struct cleanup *old_chain = make_cleanup (xfree, info);
-
- uiout->text (info);
- do_cleanups (old_chain);
+ std::string info = string_printf (_("`%s' Ada exception"),
+ c->excep_string.c_str ());
+ uiout->text (info.c_str ());
}
else
uiout->text (_("all Ada exceptions"));
case ada_catch_exception_unhandled:
uiout->text (_("unhandled Ada exceptions"));
break;
-
+
+ case ada_catch_handlers:
+ if (!c->excep_string.empty ())
+ {
+ std::string info
+ = string_printf (_("`%s' Ada exception handlers"),
+ c->excep_string.c_str ());
+ uiout->text (info.c_str ());
+ }
+ else
+ uiout->text (_("all Ada exceptions handlers"));
+ break;
+
case ada_catch_assert:
uiout->text (_("failed Ada assertions"));
break;
{
case ada_catch_exception:
fprintf_filtered (fp, "catch exception");
- if (c->excep_string != NULL)
- fprintf_filtered (fp, " %s", c->excep_string);
+ if (!c->excep_string.empty ())
+ fprintf_filtered (fp, " %s", c->excep_string.c_str ());
break;
case ada_catch_exception_unhandled:
fprintf_filtered (fp, "catch exception unhandled");
break;
+ case ada_catch_handlers:
+ fprintf_filtered (fp, "catch handlers");
+ break;
+
case ada_catch_assert:
fprintf_filtered (fp, "catch assert");
break;
static struct breakpoint_ops catch_assert_breakpoint_ops;
-/* Return a newly allocated copy of the first space-separated token
- in ARGSP, and then adjust ARGSP to point immediately after that
- token.
+/* Virtual table for "catch handlers" breakpoints. */
- Return NULL if ARGPS does not contain any more tokens. */
-
-static char *
-ada_get_next_arg (const char **argsp)
+static struct bp_location *
+allocate_location_catch_handlers (struct breakpoint *self)
{
- const char *args = *argsp;
- const char *end;
- char *result;
+ return allocate_location_exception (ada_catch_handlers, self);
+}
- args = skip_spaces (args);
- if (args[0] == '\0')
- return NULL; /* No more arguments. */
-
- /* Find the end of the current argument. */
+static void
+re_set_catch_handlers (struct breakpoint *b)
+{
+ re_set_exception (ada_catch_handlers, b);
+}
- end = skip_to_space (args);
+static void
+check_status_catch_handlers (bpstat bs)
+{
+ check_status_exception (ada_catch_handlers, bs);
+}
- /* Adjust ARGSP to point to the start of the next argument. */
+static enum print_stop_action
+print_it_catch_handlers (bpstat bs)
+{
+ return print_it_exception (ada_catch_handlers, bs);
+}
- *argsp = end;
+static void
+print_one_catch_handlers (struct breakpoint *b,
+ struct bp_location **last_loc)
+{
+ print_one_exception (ada_catch_handlers, b, last_loc);
+}
- /* Make a copy of the current argument and return it. */
+static void
+print_mention_catch_handlers (struct breakpoint *b)
+{
+ print_mention_exception (ada_catch_handlers, b);
+}
- result = (char *) xmalloc (end - args + 1);
- strncpy (result, args, end - args);
- result[end - args] = '\0';
-
- return result;
+static void
+print_recreate_catch_handlers (struct breakpoint *b,
+ struct ui_file *fp)
+{
+ print_recreate_exception (ada_catch_handlers, b, fp);
}
+static struct breakpoint_ops catch_handlers_breakpoint_ops;
+
/* Split the arguments specified in a "catch exception" command.
Set EX to the appropriate catchpoint type.
Set EXCEP_STRING to the name of the specific exception if
specified by the user.
+ IS_CATCH_HANDLERS_CMD: True if the arguments are for a
+ "catch handlers" command. False otherwise.
If a condition is found at the end of the arguments, the condition
expression is stored in COND_STRING (memory must be deallocated
after use). Otherwise COND_STRING is set to NULL. */
static void
catch_ada_exception_command_split (const char *args,
+ bool is_catch_handlers_cmd,
enum ada_exception_catchpoint_kind *ex,
- char **excep_string,
- char **cond_string)
+ std::string *excep_string,
+ std::string *cond_string)
{
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
- char *exception_name;
- char *cond = NULL;
+ std::string exception_name;
- exception_name = ada_get_next_arg (&args);
- if (exception_name != NULL && strcmp (exception_name, "if") == 0)
+ exception_name = extract_arg (&args);
+ if (exception_name == "if")
{
/* This is not an exception name; this is the start of a condition
expression for a catchpoint on all exceptions. So, "un-get"
this token, and set exception_name to NULL. */
- xfree (exception_name);
- exception_name = NULL;
+ exception_name.clear ();
args -= 2;
}
- make_cleanup (xfree, exception_name);
/* Check to see if we have a condition. */
if (args[0] == '\0')
error (_("Condition missing after `if' keyword"));
- cond = xstrdup (args);
- make_cleanup (xfree, cond);
+ *cond_string = args;
args += strlen (args);
}
if (args[0] != '\0')
error (_("Junk at end of expression"));
- discard_cleanups (old_chain);
-
- if (exception_name == NULL)
+ if (is_catch_handlers_cmd)
+ {
+ /* Catch handling of exceptions. */
+ *ex = ada_catch_handlers;
+ *excep_string = exception_name;
+ }
+ else if (exception_name.empty ())
{
/* Catch all exceptions. */
*ex = ada_catch_exception;
- *excep_string = NULL;
+ excep_string->clear ();
}
- else if (strcmp (exception_name, "unhandled") == 0)
+ else if (exception_name == "unhandled")
{
/* Catch unhandled exceptions. */
*ex = ada_catch_exception_unhandled;
- *excep_string = NULL;
+ excep_string->clear ();
}
else
{
*ex = ada_catch_exception;
*excep_string = exception_name;
}
- *cond_string = cond;
}
/* Return the name of the symbol on which we should break in order to
case ada_catch_assert:
return (data->exception_info->catch_assert_sym);
break;
+ case ada_catch_handlers:
+ return (data->exception_info->catch_handlers_sym);
+ break;
default:
internal_error (__FILE__, __LINE__,
_("unexpected catchpoint kind (%d)"), ex);
case ada_catch_assert:
return (&catch_assert_breakpoint_ops);
break;
+ case ada_catch_handlers:
+ return (&catch_handlers_breakpoint_ops);
+ break;
default:
internal_error (__FILE__, __LINE__,
_("unexpected catchpoint kind (%d)"), ex);
being raised with the exception that the user wants to catch. This
assumes that this condition is used when the inferior just triggered
an exception catchpoint.
-
- The string returned is a newly allocated string that needs to be
- deallocated later. */
+ EX: the type of catchpoints used for catching Ada exceptions. */
-static char *
-ada_exception_catchpoint_cond_string (const char *excep_string)
+static std::string
+ada_exception_catchpoint_cond_string (const char *excep_string,
+ enum ada_exception_catchpoint_kind ex)
{
int i;
+ bool is_standard_exc = false;
+ std::string result;
+
+ if (ex == ada_catch_handlers)
+ {
+ /* For exception handlers catchpoints, the condition string does
+ not use the same parameter as for the other exceptions. */
+ result = ("long_integer (GNAT_GCC_exception_Access"
+ "(gcc_exception).all.occurrence.id)");
+ }
+ else
+ result = "long_integer (e)";
/* The standard exceptions are a special case. They are defined in
runtime units that have been compiled without debugging info; if
{
if (strcmp (standard_exc [i], excep_string) == 0)
{
- return xstrprintf ("long_integer (e) = long_integer (&standard.%s)",
- excep_string);
+ is_standard_exc = true;
+ break;
}
}
- return xstrprintf ("long_integer (e) = long_integer (&%s)", excep_string);
+
+ result += " = ";
+
+ if (is_standard_exc)
+ string_appendf (result, "long_integer (&standard.%s)", excep_string);
+ else
+ string_appendf (result, "long_integer (&%s)", excep_string);
+
+ return result;
}
/* Return the symtab_and_line that should be used to insert an exception
catchpoint of the TYPE kind.
- EXCEP_STRING should contain the name of a specific exception that
- the catchpoint should catch, or NULL otherwise.
-
ADDR_STRING returns the name of the function where the real
breakpoint that implements the catchpoints is set, depending on the
type of catchpoint we need to create. */
static struct symtab_and_line
-ada_exception_sal (enum ada_exception_catchpoint_kind ex, char *excep_string,
- const char **addr_string, const struct breakpoint_ops **ops)
+ada_exception_sal (enum ada_exception_catchpoint_kind ex,
+ std::string *addr_string, const struct breakpoint_ops **ops)
{
const char *sym_name;
struct symbol *sym;
sym_name = ada_exception_sym_name (ex);
sym = standard_lookup (sym_name, NULL, VAR_DOMAIN);
- /* We can assume that SYM is not NULL at this stage. If the symbol
- did not exist, ada_exception_support_info_sniffer would have
- raised an exception.
+ if (sym == NULL)
+ error (_("Catchpoint symbol not found: %s"), sym_name);
- Also, ada_exception_support_info_sniffer should have already
- verified that SYM is a function symbol. */
- gdb_assert (sym != NULL);
- gdb_assert (SYMBOL_CLASS (sym) == LOC_BLOCK);
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ error (_("Unable to insert catchpoint. %s is not a function."), sym_name);
/* Set ADDR_STRING. */
- *addr_string = xstrdup (sym_name);
+ *addr_string = sym_name;
/* Set OPS. */
*ops = ada_exception_breakpoint_ops (ex);
EX_KIND is the kind of exception catchpoint to be created.
- If EXCEPT_STRING is NULL, this catchpoint is expected to trigger
+ If EXCEPT_STRING is empty, this catchpoint is expected to trigger
for all exceptions. Otherwise, EXCEPT_STRING indicates the name
- of the exception to which this catchpoint applies. When not NULL,
- the string must be allocated on the heap, and its deallocation
- is no longer the responsibility of the caller.
+ of the exception to which this catchpoint applies.
- COND_STRING, if not NULL, is the catchpoint condition. This string
- must be allocated on the heap, and its deallocation is no longer
- the responsibility of the caller.
+ COND_STRING, if not empty, is the catchpoint condition.
TEMPFLAG, if nonzero, means that the underlying breakpoint
should be temporary.
void
create_ada_exception_catchpoint (struct gdbarch *gdbarch,
enum ada_exception_catchpoint_kind ex_kind,
- char *excep_string,
- char *cond_string,
+ const std::string &excep_string,
+ const std::string &cond_string,
int tempflag,
int disabled,
int from_tty)
{
- const char *addr_string = NULL;
+ std::string addr_string;
const struct breakpoint_ops *ops = NULL;
- struct symtab_and_line sal
- = ada_exception_sal (ex_kind, excep_string, &addr_string, &ops);
+ struct symtab_and_line sal = ada_exception_sal (ex_kind, &addr_string, &ops);
std::unique_ptr<ada_catchpoint> c (new ada_catchpoint ());
- init_ada_exception_breakpoint (c.get (), gdbarch, sal, addr_string,
+ init_ada_exception_breakpoint (c.get (), gdbarch, sal, addr_string.c_str (),
ops, tempflag, disabled, from_tty);
c->excep_string = excep_string;
- create_excep_cond_exprs (c.get ());
- if (cond_string != NULL)
- set_breakpoint_condition (c.get (), cond_string, from_tty);
+ create_excep_cond_exprs (c.get (), ex_kind);
+ if (!cond_string.empty ())
+ set_breakpoint_condition (c.get (), cond_string.c_str (), from_tty);
install_breakpoint (0, std::move (c), 1);
}
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
enum ada_exception_catchpoint_kind ex_kind;
- char *excep_string = NULL;
- char *cond_string = NULL;
+ std::string excep_string;
+ std::string cond_string;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
if (!arg)
arg = "";
- catch_ada_exception_command_split (arg, &ex_kind, &excep_string,
+ catch_ada_exception_command_split (arg, false, &ex_kind, &excep_string,
+ &cond_string);
+ create_ada_exception_catchpoint (gdbarch, ex_kind,
+ excep_string, cond_string,
+ tempflag, 1 /* enabled */,
+ from_tty);
+}
+
+/* Implement the "catch handlers" command. */
+
+static void
+catch_ada_handlers_command (const char *arg_entry, int from_tty,
+ struct cmd_list_element *command)
+{
+ const char *arg = arg_entry;
+ struct gdbarch *gdbarch = get_current_arch ();
+ int tempflag;
+ enum ada_exception_catchpoint_kind ex_kind;
+ std::string excep_string;
+ std::string cond_string;
+
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
+ catch_ada_exception_command_split (arg, true, &ex_kind, &excep_string,
&cond_string);
create_ada_exception_catchpoint (gdbarch, ex_kind,
excep_string, cond_string,
(the memory needs to be deallocated after use). */
static void
-catch_ada_assert_command_split (const char *args, char **cond_string)
+catch_ada_assert_command_split (const char *args, std::string &cond_string)
{
args = skip_spaces (args);
args = skip_spaces (args);
if (args[0] == '\0')
error (_("condition missing after `if' keyword"));
- *cond_string = xstrdup (args);
+ cond_string.assign (args);
}
/* Otherwise, there should be no other argument at the end of
const char *arg = arg_entry;
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
- char *cond_string = NULL;
+ std::string cond_string;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
if (!arg)
arg = "";
- catch_ada_assert_command_split (arg, &cond_string);
+ catch_ada_assert_command_split (arg, cond_string);
create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
- NULL, cond_string,
+ "", cond_string,
tempflag, 1 /* enabled */,
from_tty);
}
static int
ada_is_exception_sym (struct symbol *sym)
{
- const char *type_name = type_name_no_tag (SYMBOL_TYPE (sym));
+ const char *type_name = TYPE_NAME (SYMBOL_TYPE (sym));
return (SYMBOL_CLASS (sym) != LOC_TYPEDEF
&& SYMBOL_CLASS (sym) != LOC_BLOCK
ada_add_global_exceptions (compiled_regex *preg,
std::vector<ada_exc_info> *exceptions)
{
- struct objfile *objfile;
- struct compunit_symtab *s;
-
/* In Ada, the symbol "search name" is a linkage name, whereas the
regular expression used to do the matching refers to the natural
name. So match against the decoded name. */
NULL,
VARIABLES_DOMAIN);
- ALL_COMPUNITS (objfile, s)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (s);
- int i;
-
- for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+ for (compunit_symtab *s : objfile->compunits ())
{
- struct block *b = BLOCKVECTOR_BLOCK (bv, i);
- struct block_iterator iter;
- struct symbol *sym;
+ const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (s);
+ int i;
- ALL_BLOCK_SYMBOLS (b, iter, sym)
- if (ada_is_non_standard_exception_sym (sym)
- && name_matches_regex (SYMBOL_NATURAL_NAME (sym), preg))
- {
- struct ada_exc_info info
- = {SYMBOL_PRINT_NAME (sym), SYMBOL_VALUE_ADDRESS (sym)};
+ for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+ {
+ const struct block *b = BLOCKVECTOR_BLOCK (bv, i);
+ struct block_iterator iter;
+ struct symbol *sym;
- exceptions->push_back (info);
- }
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ if (ada_is_non_standard_exception_sym (sym)
+ && name_matches_regex (SYMBOL_NATURAL_NAME (sym), preg))
+ {
+ struct ada_exc_info info
+ = {SYMBOL_PRINT_NAME (sym), SYMBOL_VALUE_ADDRESS (sym)};
+
+ exceptions->push_back (info);
+ }
+ }
}
}
}
ada_primitive_type_natural,
ada_primitive_type_positive,
ada_primitive_type_system_address,
+ ada_primitive_type_storage_offset,
nr_ada_primitive_types
};
TYPE_NAME (lai->primitive_type_vector [ada_primitive_type_system_address])
= "system__address";
+ /* Create the equivalent of the System.Storage_Elements.Storage_Offset
+ type. This is a signed integral type whose size is the same as
+ the size of addresses. */
+ {
+ unsigned int addr_length = TYPE_LENGTH
+ (lai->primitive_type_vector [ada_primitive_type_system_address]);
+
+ lai->primitive_type_vector [ada_primitive_type_storage_offset]
+ = arch_integer_type (gdbarch, addr_length * HOST_CHAR_BIT, 0,
+ "storage_offset");
+ }
+
lai->bool_type_symbol = NULL;
lai->bool_type_default = builtin->builtin_bool;
}
return full_match (symbol_search_name, ada_lookup_name (lookup_name));
}
+/* symbol_name_matcher_ftype for exact (verbatim) matches. */
+
+static bool
+do_exact_match (const char *symbol_search_name,
+ const lookup_name_info &lookup_name,
+ completion_match_result *comp_match_res)
+{
+ return strcmp (symbol_search_name, ada_lookup_name (lookup_name)) == 0;
+}
+
/* Build the Ada lookup name for LOOKUP_NAME. */
ada_lookup_name_info::ada_lookup_name_info (const lookup_name_info &lookup_name)
comp_match_res);
}
+/* A name matcher that matches the symbol name exactly, with
+ strcmp. */
+
+static bool
+literal_symbol_name_matcher (const char *symbol_search_name,
+ const lookup_name_info &lookup_name,
+ completion_match_result *comp_match_res)
+{
+ const std::string &name = lookup_name.name ();
+
+ int cmp = (lookup_name.completion_mode ()
+ ? strncmp (symbol_search_name, name.c_str (), name.size ())
+ : strcmp (symbol_search_name, name.c_str ()));
+ if (cmp == 0)
+ {
+ if (comp_match_res != NULL)
+ comp_match_res->set_match (symbol_search_name);
+ return true;
+ }
+ else
+ return false;
+}
+
/* Implement the "la_get_symbol_name_matcher" language_defn method for
Ada. */
static symbol_name_matcher_ftype *
ada_get_symbol_name_matcher (const lookup_name_info &lookup_name)
{
+ if (lookup_name.match_type () == symbol_name_match_type::SEARCH_NAME)
+ return literal_symbol_name_matcher;
+
if (lookup_name.completion_mode ())
return ada_symbol_name_matches;
else
{
if (lookup_name.ada ().wild_match_p ())
return do_wild_match;
+ else if (lookup_name.ada ().verbatim_p ())
+ return do_exact_match;
else
return do_full_match;
}
ada_extensions,
&ada_exp_descriptor,
parse,
- ada_yyerror,
resolve,
ada_printchar, /* Print a character constant */
ada_printstr, /* Function to print string constant */
ada_read_var_value, /* la_read_var_value */
NULL, /* Language specific skip_trampoline */
NULL, /* name_of_this */
+ true, /* la_store_sym_names_in_linkage_form_p */
ada_lookup_symbol_nonlocal, /* Looking up non-local symbols. */
basic_lookup_transparent_type, /* lookup_transparent_type */
ada_la_decode, /* Language specific symbol demangler */
ada_print_array_index,
default_pass_by_reference,
c_get_string,
- c_watch_location_expression,
+ ada_watch_location_expression,
ada_get_symbol_name_matcher, /* la_get_symbol_name_matcher */
ada_iterate_over_symbols,
default_search_name_hash,
ops->print_one = print_one_catch_assert;
ops->print_mention = print_mention_catch_assert;
ops->print_recreate = print_recreate_catch_assert;
+
+ ops = &catch_handlers_breakpoint_ops;
+ *ops = bkpt_breakpoint_ops;
+ ops->allocate_location = allocate_location_catch_handlers;
+ ops->re_set = re_set_catch_handlers;
+ ops->check_status = check_status_catch_handlers;
+ ops->print_it = print_it_catch_handlers;
+ ops->print_one = print_one_catch_handlers;
+ ops->print_mention = print_mention_catch_handlers;
+ ops->print_recreate = print_recreate_catch_handlers;
}
/* This module's 'new_objfile' observer. */
initialize_ada_catchpoint_ops ();
add_prefix_cmd ("ada", no_class, set_ada_command,
- _("Prefix command for changing Ada-specfic settings"),
+ _("Prefix command for changing Ada-specific settings"),
&set_ada_list, "set ada ", 0, &setlist);
add_prefix_cmd ("ada", no_class, show_ada_command,
add_catch_command ("exception", _("\
Catch Ada exceptions, when raised.\n\
-With an argument, catch only exceptions with the given name."),
+Usage: catch exception [ ARG ]\n\
+\n\
+Without any argument, stop when any Ada exception is raised.\n\
+If ARG is \"unhandled\" (without the quotes), only stop when the exception\n\
+being raised does not have a handler (and will therefore lead to the task's\n\
+termination).\n\
+Otherwise, the catchpoint only stops when the name of the exception being\n\
+raised is the same as ARG."),
catch_ada_exception_command,
NULL,
CATCH_PERMANENT,
CATCH_TEMPORARY);
+
+ add_catch_command ("handlers", _("\
+Catch Ada exceptions, when handled.\n\
+With an argument, catch only exceptions with the given name."),
+ catch_ada_handlers_command,
+ NULL,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
add_catch_command ("assert", _("\
Catch failed Ada assertions, when raised.\n\
With an argument, catch only exceptions with the given name."),
CATCH_TEMPORARY);
varsize_limit = 65536;
+ add_setshow_uinteger_cmd ("varsize-limit", class_support,
+ &varsize_limit, _("\
+Set the maximum number of bytes allowed in a variable-size object."), _("\
+Show the maximum number of bytes allowed in a variable-size object."), _("\
+Attempts to access an object whose size is not a compile-time constant\n\
+and exceeds this limit will cause an error."),
+ NULL, NULL, &setlist, &showlist);
add_info ("exceptions", info_exceptions_command,
_("\
DWARF attribute."),
NULL, NULL, &maint_set_ada_cmdlist, &maint_show_ada_cmdlist);
- obstack_init (&symbol_list_obstack);
-
- decoded_names_store = htab_create_alloc
- (256, htab_hash_string, (int (*)(const void *, const void *)) streq,
- NULL, xcalloc, xfree);
+ decoded_names_store = htab_create_alloc (256, htab_hash_string, streq_hash,
+ NULL, xcalloc, xfree);
/* The ada-lang observers. */
- observer_attach_new_objfile (ada_new_objfile_observer);
- observer_attach_free_objfile (ada_free_objfile_observer);
- observer_attach_inferior_exit (ada_inferior_exit);
+ gdb::observers::new_objfile.attach (ada_new_objfile_observer);
+ gdb::observers::free_objfile.attach (ada_free_objfile_observer);
+ gdb::observers::inferior_exit.attach (ada_inferior_exit);
/* Setup various context-specific data. */
ada_inferior_data