/* Ada language support routines for GDB, the GNU debugger.
- Copyright (C) 1992-2017 Free Software Foundation, Inc.
+ Copyright (C) 1992-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "annotate.h"
#include "valprint.h"
#include "source.h"
-#include "observer.h"
+#include "observable.h"
#include "vec.h"
#include "stack.h"
#include "gdb_vecs.h"
static struct block_symbol *defns_collected (struct obstack *, int);
-static struct value *resolve_subexp (struct expression **, int *, int,
+static struct value *resolve_subexp (expression_up *, int *, int,
struct type *);
-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 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 *);
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. */
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 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)
{
struct type *context_type = NULL;
int pc = 0;
are as in ada_resolve, above. */
static struct value *
-resolve_subexp (struct expression **expp, int *pos, int deprocedure_p,
+resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
struct type *context_type)
{
int pc = *pos;
struct value **argvec; /* Vector of operand types (alloca'ed). */
int nargs; /* Number of operands. */
int oplen;
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
argvec = NULL;
nargs = 0;
- exp = *expp;
+ exp = expp->get ();
/* Pass one: resolve operands, saving their types and updating *pos,
if needed. */
for (i = 0; i < nargs; i += 1)
argvec[i] = resolve_subexp (expp, pos, 1, NULL);
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 =
(exp->elts[pc + 2].symbol),
exp->elts[pc + 1].block, VAR_DOMAIN,
&candidates);
- make_cleanup (xfree, candidates);
if (n_candidates > 1)
{
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);
if (i < 0)
{
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;
+ innermost_block.update (candidates[i]);
}
if (deprocedure_p
replace_operator_with_call (expp, pc, 0, 0,
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);
- make_cleanup (xfree, 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);
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;
+ innermost_block.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,
&candidates);
- make_cleanup (xfree, 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);
if (i < 0)
break;
replace_operator_with_call (expp, pc, nargs, 1,
candidates[i].symbol,
candidates[i].block);
- exp = *expp;
+ exp = expp->get ();
}
break;
case OP_TYPE:
case OP_REGISTER:
- do_cleanups (old_chain);
return NULL;
}
*pos = pc;
- do_cleanups (old_chain);
if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE)
return evaluate_var_msym_value (EVAL_AVOID_SIDE_EFFECTS,
exp->elts[pc + 1].objfile,
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)
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. */
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)
/* 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 newly allocated vector of (SYM,BLOCK) tuples,
- indicating the symbols found and the blocks and symbol tables (if
- any) in which they were found. This vector should be freed when
- no longer useful.
+ 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;
- int results_size;
auto_obstack obstack;
ada_add_all_symbols (&obstack, block, lookup_name,
ndefns = num_defns_collected (&obstack);
- results_size = obstack_object_size (&obstack);
- *results = (struct block_symbol *) malloc (results_size);
- memcpy (*results, defns_collected (&obstack, 1), results_size);
+ 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 newly-allocated vector of (SYM,BLOCK) tuples. This newly-allocated
- vector should be freed when no longer useful.
+ 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;
- struct cleanup *old_chain;
+ std::vector<struct block_symbol> results;
ndefs = ada_lookup_symbol_list_worker (name, block, domain, &results, 0);
- old_chain = make_cleanup (xfree, results);
for (i = 0; i < ndefs; ++i)
{
if (!callback (results[i].symbol))
break;
}
-
- do_cleanups (old_chain);
}
/* The result is as for ada_lookup_symbol_list with FULL_SEARCH set
domain_enum domain,
struct block_symbol *info)
{
- struct block_symbol *candidates;
- int n_candidates;
- struct cleanup *old_chain;
-
/* 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);
- old_chain = make_cleanup (xfree, candidates);
-
- if (n_candidates == 0)
- {
- do_cleanups (old_chain);
- return;
- }
-
- *info = candidates[0];
- info->symbol = fixup_symbol_section (info->symbol, NULL);
-
- do_cleanups (old_chain);
+ *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;
}
struct objfile *objfile;
const struct block *b, *surrounding_static_block = 0;
struct block_iterator iter;
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
gdb_assert (code == TYPE_CODE_UNDEF);
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,
- MSYMBOL_LANGUAGE (msymbol),
+ symbol_language,
MSYMBOL_LINKAGE_NAME (msymbol),
lookup_name, text, word);
}
lookup_name, text, word);
}
}
-
- do_cleanups (old_chain);
}
/* Field Access */
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;
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);
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;
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
{
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);
}
{
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);
- struct cleanup *old_chain = make_cleanup (xfree, syms);
if (nsyms != 1)
{
- do_cleanups (old_chain);
if (err_msg == NULL)
return 0;
else
error (("%s"), err_msg);
}
- struct value *result = value_of_variable (syms[0].symbol, syms[0].block);
- do_cleanups (old_chain);
- return result;
+ return value_of_variable (syms[0].symbol, syms[0].block);
}
/* Value of integer variable named NAME in the current environment.
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
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.
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
/* 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,
+ada_exception_sal (enum ada_exception_catchpoint_kind ex,
const char **addr_string, const struct breakpoint_ops **ops)
{
const char *sym_name;
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;
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,
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
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
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 */
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. */
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);
- 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