/* Ada language support routines for GDB, the GNU debugger.
- Copyright (C) 1992-1994, 1997-2000, 2003-2005, 2007-2012 Free
- Software Foundation, Inc.
+ Copyright (C) 1992-2014 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include <stdio.h>
-#include "gdb_string.h"
+#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "demangle.h"
#include "expression.h"
#include "parser-defs.h"
#include "language.h"
+#include "varobj.h"
#include "c-lang.h"
#include "inferior.h"
#include "symfile.h"
#include "gdb_obstack.h"
#include "ada-lang.h"
#include "completer.h"
-#include "gdb_stat.h"
+#include <sys/stat.h>
#ifdef UI_OUT
#include "ui-out.h"
#endif
#include "vec.h"
#include "stack.h"
#include "gdb_vecs.h"
+#include "typeprint.h"
#include "psymtab.h"
#include "value.h"
struct type *);
static void replace_operator_with_call (struct expression **, int, int, int,
- struct symbol *, struct block *);
+ struct symbol *, const struct block *);
static int possible_user_operator_p (enum exp_opcode, struct value **);
const char **);
static struct symbol *find_old_style_renaming_symbol (const char *,
- struct block *);
+ const struct block *);
static struct type *ada_lookup_struct_elt_type (struct type *, char *,
int, int, int *);
static void ada_forward_operator_length (struct expression *, int, int *,
int *);
+
+static struct type *ada_find_any_type (const char *name);
\f
set_value_bitsize (result, value_bitsize (val));
set_value_bitpos (result, value_bitpos (val));
set_value_address (result, value_address (val));
+ set_value_optimized_out (result, value_optimized_out_const (val));
return result;
}
}
case TYPE_CODE_RANGE:
return TYPE_HIGH_BOUND (type);
case TYPE_CODE_ENUM:
- return TYPE_FIELD_BITPOS (type, TYPE_NFIELDS (type) - 1);
+ return TYPE_FIELD_ENUMVAL (type, TYPE_NFIELDS (type) - 1);
case TYPE_CODE_BOOL:
return 1;
case TYPE_CODE_CHAR:
}
}
-/* The largest value in the domain of TYPE, a discrete type, as an integer. */
+/* The smallest value in the domain of TYPE, a discrete type, as an integer. */
LONGEST
ada_discrete_type_low_bound (struct type *type)
{
case TYPE_CODE_RANGE:
return TYPE_LOW_BOUND (type);
case TYPE_CODE_ENUM:
- return TYPE_FIELD_BITPOS (type, 0);
+ return TYPE_FIELD_ENUMVAL (type, 0);
case TYPE_CODE_BOOL:
return 0;
case TYPE_CODE_CHAR:
}
return type;
}
+
+/* Return a decoded version of the given VALUE. This means returning
+ a value whose type is obtained by applying all the GNAT-specific
+ encondings, making the resulting type a static but standard description
+ of the initial type. */
+
+struct value *
+ada_get_decoded_value (struct value *value)
+{
+ struct type *type = ada_check_typedef (value_type (value));
+
+ if (ada_is_array_descriptor_type (type)
+ || (ada_is_constrained_packed_array_type (type)
+ && TYPE_CODE (type) != TYPE_CODE_PTR))
+ {
+ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) /* array access type. */
+ value = ada_coerce_to_simple_array_ptr (value);
+ else
+ value = ada_coerce_to_simple_array (value);
+ }
+ else
+ value = ada_to_fixed_value (value);
+
+ return value;
+}
+
+/* Same as ada_get_decoded_value, but with the given TYPE.
+ Because there is no associated actual value for this type,
+ the resulting type might be a best-effort approximation in
+ the case of dynamic types. */
+
+struct type *
+ada_get_decoded_type (struct type *type)
+{
+ type = to_static_fixed_type (type);
+ if (ada_is_constrained_packed_array_type (type))
+ type = ada_coerce_to_simple_array_type (type);
+ return type;
+}
+
\f
/* Language Selection */
const, but nevertheless modified to a semantically equivalent form
when a decoded name is cached in it. */
-char *
-ada_decode_symbol (const struct general_symbol_info *gsymbol)
+const char *
+ada_decode_symbol (const struct general_symbol_info *arg)
{
- char **resultp =
- (char **) &gsymbol->language_specific.mangled_lang.demangled_name;
+ struct general_symbol_info *gsymbol = (struct general_symbol_info *) arg;
+ const char **resultp =
+ &gsymbol->language_specific.mangled_lang.demangled_name;
- if (*resultp == NULL)
+ if (!gsymbol->ada_mangled)
{
const char *decoded = ada_decode (gsymbol->name);
+ struct obstack *obstack = gsymbol->language_specific.obstack;
- if (gsymbol->obj_section != NULL)
- {
- struct objfile *objf = gsymbol->obj_section->objfile;
+ gsymbol->ada_mangled = 1;
- *resultp = obsavestring (decoded, strlen (decoded),
- &objf->objfile_obstack);
- }
- /* Sometimes, we can't find a corresponding objfile, in which
- case, we put the result on the heap. Since we only decode
- when needed, we hope this usually does not cause a
- significant memory leak (FIXME). */
- if (*resultp == NULL)
+ if (obstack != NULL)
+ *resultp = obstack_copy0 (obstack, decoded, strlen (decoded));
+ else
{
+ /* Sometimes, we can't find a corresponding objfile, in
+ which case, we put the result on the heap. Since we only
+ decode when needed, we hope this usually does not cause a
+ significant memory leak (FIXME). */
+
char **slot = (char **) htab_find_slot (decoded_names_store,
decoded, INSERT);
{
struct type *new_elt_type;
struct type *new_type;
+ struct type *index_type_desc;
+ struct type *index_type;
LONGEST low_bound, high_bound;
type = ada_check_typedef (type);
if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
return type;
+ index_type_desc = ada_find_parallel_type (type, "___XA");
+ if (index_type_desc)
+ index_type = to_fixed_range_type (TYPE_FIELD_TYPE (index_type_desc, 0),
+ NULL);
+ else
+ index_type = TYPE_INDEX_TYPE (type);
+
new_type = alloc_type_copy (type);
new_elt_type =
constrained_packed_array_type (ada_check_typedef (TYPE_TARGET_TYPE (type)),
elt_bits);
- create_array_type (new_type, new_elt_type, TYPE_INDEX_TYPE (type));
+ create_array_type (new_type, new_elt_type, index_type);
TYPE_FIELD_BITSIZE (new_type, 0) = *elt_bits;
TYPE_NAME (new_type) = ada_type_name (type);
- if (get_discrete_bounds (TYPE_INDEX_TYPE (type),
- &low_bound, &high_bound) < 0)
+ if (get_discrete_bounds (index_type, &low_bound, &high_bound) < 0)
low_bound = high_bound = 0;
if (high_bound < low_bound)
*elt_bits = TYPE_LENGTH (new_type) = 0;
}
else if (VALUE_LVAL (obj) == lval_memory && value_lazy (obj))
{
- v = value_at (type,
- value_address (obj) + offset);
+ v = value_at (type, value_address (obj));
bytes = (unsigned char *) alloca (len);
- read_memory (value_address (v), bytes, len);
+ read_memory (value_address (v) + offset, bytes, len);
}
else
{
if (obj != NULL)
{
- CORE_ADDR new_addr;
+ long new_offset = offset;
set_value_component_location (v, obj);
- new_addr = value_address (obj) + offset;
set_value_bitpos (v, bit_offset + value_bitpos (obj));
set_value_bitsize (v, bit_size);
if (value_bitpos (v) >= HOST_CHAR_BIT)
{
- ++new_addr;
+ ++new_offset;
set_value_bitpos (v, value_bitpos (v) - HOST_CHAR_BIT);
}
- set_value_address (v, new_addr);
+ set_value_offset (v, new_offset);
+
+ /* Also set the parent value. This is needed when trying to
+ assign a new value (in inferior memory). */
+ set_value_parent (v, obj);
}
else
set_value_bitsize (v, bit_size);
int len = (value_bitpos (toval)
+ bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
int from_size;
- char *buffer = (char *) alloca (len);
+ gdb_byte *buffer = alloca (len);
struct value *val;
CORE_ADDR to_addr = value_address (toval);
else
move_bits (buffer, value_bitpos (toval),
value_contents (fromval), 0, bits, 0);
- write_memory (to_addr, buffer, len);
- observer_notify_memory_changed (to_addr, len, buffer);
+ write_memory_with_notification (to_addr, buffer, len);
val = value_copy (toval);
memcpy (value_contents_raw (val), value_contents (fromval),
by run-time quantities other than discriminants. */
static LONGEST
-ada_array_bound_from_type (struct type * arr_type, int n, int which)
+ada_array_bound_from_type (struct type *arr_type, int n, int which)
{
- struct type *type, *elt_type, *index_type_desc, *index_type;
+ struct type *type, *index_type_desc, *index_type;
int i;
gdb_assert (which == 0 || which == 1);
else
type = arr_type;
- elt_type = type;
- for (i = n; i > 1; i--)
- elt_type = TYPE_TARGET_TYPE (type);
-
index_type_desc = ada_find_parallel_type (type, "___XA");
ada_fixup_array_indexes_type (index_type_desc);
if (index_type_desc != NULL)
index_type = to_fixed_range_type (TYPE_FIELD_TYPE (index_type_desc, n - 1),
NULL);
else
- index_type = TYPE_INDEX_TYPE (elt_type);
+ {
+ struct type *elt_type = check_typedef (type);
+
+ for (i = 1; i < n; i++)
+ elt_type = check_typedef (TYPE_TARGET_TYPE (elt_type));
+
+ index_type = TYPE_INDEX_TYPE (elt_type);
+ }
return
(LONGEST) (which == 0
ada_lookup_symbol_list (SYMBOL_LINKAGE_NAME
(exp->elts[pc + 2].symbol),
exp->elts[pc + 1].block, VAR_DOMAIN,
- &candidates, 1);
+ &candidates);
if (n_candidates > 1)
{
ada_lookup_symbol_list (SYMBOL_LINKAGE_NAME
(exp->elts[pc + 5].symbol),
exp->elts[pc + 4].block, VAR_DOMAIN,
- &candidates, 1);
+ &candidates);
if (n_candidates == 1)
i = 0;
else
n_candidates =
ada_lookup_symbol_list (ada_encode (ada_decoded_op_name (op)),
(struct block *) NULL, VAR_DOMAIN,
- &candidates, 1);
+ &candidates);
i = ada_resolve_function (candidates, n_candidates, argvec, nargs,
ada_decoded_op_name (op), NULL);
if (i < 0)
else
printf_unfiltered (_("[%d] %s at %s:%d\n"), i + first_choice,
SYMBOL_PRINT_NAME (syms[i].sym),
- sal.symtab->filename, sal.line);
+ symtab_to_filename_for_display (sal.symtab),
+ sal.line);
continue;
}
else
(SYMBOL_CLASS (syms[i].sym) == LOC_CONST
&& SYMBOL_TYPE (syms[i].sym) != NULL
&& TYPE_CODE (SYMBOL_TYPE (syms[i].sym)) == TYPE_CODE_ENUM);
- struct symtab *symtab = syms[i].sym->symtab;
+ struct symtab *symtab = SYMBOL_SYMTAB (syms[i].sym);
if (SYMBOL_LINE (syms[i].sym) != 0 && symtab != NULL)
printf_unfiltered (_("[%d] %s at %s:%d\n"),
i + first_choice,
SYMBOL_PRINT_NAME (syms[i].sym),
- symtab->filename, SYMBOL_LINE (syms[i].sym));
+ symtab_to_filename_for_display (symtab),
+ SYMBOL_LINE (syms[i].sym));
else if (is_enumeral
&& TYPE_NAME (SYMBOL_TYPE (syms[i].sym)) != NULL)
{
printf_unfiltered (("[%d] "), i + first_choice);
ada_print_type (SYMBOL_TYPE (syms[i].sym), NULL,
- gdb_stdout, -1, 0);
+ gdb_stdout, -1, 0, &type_print_raw_options);
printf_unfiltered (_("'(%s) (enumeral)\n"),
SYMBOL_PRINT_NAME (syms[i].sym));
}
: _("[%d] %s at %s:?\n"),
i + first_choice,
SYMBOL_PRINT_NAME (syms[i].sym),
- symtab->filename);
+ symtab_to_filename_for_display (symtab));
else
printf_unfiltered (is_enumeral
? _("[%d] %s (enumeral)\n")
static void
replace_operator_with_call (struct expression **expp, int pc, int nargs,
int oplen, struct symbol *sym,
- struct block *block)
+ const struct block *block)
{
/* A new expression, with 6 more elements (3 for funcall, 4 for function
symbol, -oplen for operator being replaced). */
if (len != NULL)
*len = suffix - info;
return kind;
-}
+}
+
+/* Compute the value of the given RENAMING_SYM, which is expected to
+ be a symbol encoding a renaming expression. BLOCK is the block
+ used to evaluate the renaming. */
+
+static struct value *
+ada_read_renaming_var_value (struct symbol *renaming_sym,
+ struct block *block)
+{
+ const char *sym_name;
+ struct expression *expr;
+ struct value *value;
+ struct cleanup *old_chain = NULL;
+ sym_name = SYMBOL_LINKAGE_NAME (renaming_sym);
+ expr = parse_exp_1 (&sym_name, 0, block, 0);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ value = evaluate_expression (expr);
+
+ do_cleanups (old_chain);
+ return value;
+}
\f
/* Evaluation: Function Calls */
}
else
return actual;
- return value_cast_pointers (formal_type, result);
+ return value_cast_pointers (formal_type, result, 0);
}
else if (TYPE_CODE (actual_type) == TYPE_CODE_PTR)
return ada_value_ind (actual);
static void
cache_symbol (const char *name, domain_enum namespace, struct symbol *sym,
- struct block *block)
+ const struct block *block)
{
}
\f
standard_lookup (const char *name, const struct block *block,
domain_enum domain)
{
- struct symbol *sym;
+ /* Initialize it just to avoid a GCC false warning. */
+ struct symbol *sym = NULL;
if (lookup_cached_symbol (name, domain, &sym, NULL))
return sym;
return (struct ada_symbol_info *) obstack_base (obstackp);
}
-/* Return a minimal symbol matching NAME according to Ada decoding
- rules. Returns NULL if there is no such minimal symbol. Names
- prefixed with "standard__" are handled specially: "standard__" is
- first stripped off, and only static and global symbols are searched. */
+/* Return a bound minimal symbol matching NAME according to Ada
+ decoding rules. Returns an invalid symbol if there is no such
+ minimal symbol. Names prefixed with "standard__" are handled
+ specially: "standard__" is first stripped off, and only static and
+ global symbols are searched. */
-struct minimal_symbol *
+struct bound_minimal_symbol
ada_lookup_simple_minsym (const char *name)
{
+ struct bound_minimal_symbol result;
struct objfile *objfile;
struct minimal_symbol *msymbol;
- const int wild_match = should_use_wild_match (name);
+ const int wild_match_p = should_use_wild_match (name);
+
+ memset (&result, 0, sizeof (result));
/* Special case: If the user specifies a symbol name inside package
Standard, do a non-wild matching of the symbol name without
ALL_MSYMBOLS (objfile, msymbol)
{
- if (match_name (SYMBOL_LINKAGE_NAME (msymbol), name, wild_match)
+ if (match_name (SYMBOL_LINKAGE_NAME (msymbol), name, wild_match_p)
&& MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
- return msymbol;
+ {
+ result.minsym = msymbol;
+ result.objfile = objfile;
+ break;
+ }
}
- return NULL;
+ return result;
}
/* For all subprograms that statically enclose the subprogram of the
selected frame, add symbols matching identifier NAME in DOMAIN
and their blocks to the list of data in OBSTACKP, as for
- ada_add_block_symbols (q.v.). If WILD, treat as NAME with a
- wildcard prefix. */
+ ada_add_block_symbols (q.v.). If WILD_MATCH_P, treat as NAME
+ with a wildcard prefix. */
static void
add_symbols_from_enclosing_procs (struct obstack *obstackp,
const char *name, domain_enum namespace,
- int wild_match)
+ int wild_match_p)
{
}
/* All enums in the type should have an identical underlying value. */
for (i = 0; i < TYPE_NFIELDS (type1); i++)
- if (TYPE_FIELD_BITPOS (type1, i) != TYPE_FIELD_BITPOS (type2, i))
+ if (TYPE_FIELD_ENUMVAL (type1, i) != TYPE_FIELD_ENUMVAL (type2, i))
return 0;
/* All enumerals should also have the same name (modulo any numerical
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));
-
- make_cleanup (xfree, scope);
+ old_chain = make_cleanup (xfree, scope);
/* If the rename has been defined in a package, then it is visible. */
if (is_package_name (scope))
- return 0;
+ {
+ do_cleanups (old_chain);
+ return 0;
+ }
/* Check that the rename is in the current function scope by checking
that its name starts with SCOPE. */
if (strncmp (function_name, "_ada_", 5) == 0)
function_name += 5;
- return (strncmp (function_name, scope, strlen (scope)) != 0);
+ {
+ int is_invisible = strncmp (function_name, scope, strlen (scope)) != 0;
+
+ do_cleanups (old_chain);
+ return is_invisible;
+ }
}
/* Remove entries from SYMS that corresponds to a renaming entity that
for (i = 0; i < nsyms; i += 1)
{
struct symbol *sym = syms[i].sym;
- struct block *block = syms[i].block;
+ const struct block *block = syms[i].block;
const char *name;
const char *suffix;
If no match was found, then extend the search to "enclosing"
routines (in other words, if we're inside a nested function,
search the symbols defined inside the enclosing functions).
+ If WILD_MATCH_P is nonzero, perform the naming matching in
+ "wild" mode (see function "wild_match" for more info).
Note: This function assumes that OBSTACKP has 0 (zero) element in it. */
static void
ada_add_local_symbols (struct obstack *obstackp, const char *name,
struct block *block, domain_enum domain,
- int wild_match)
+ int wild_match_p)
{
int block_depth = 0;
while (block != NULL)
{
block_depth += 1;
- ada_add_block_symbols (obstackp, block, name, domain, NULL, wild_match);
+ ada_add_block_symbols (obstackp, block, name, domain, NULL,
+ wild_match_p);
/* If we found a non-function match, assume that's the one. */
if (is_nonfunction (defns_collected (obstackp, 0),
/* If no luck so far, try to find NAME as a local symbol in some lexically
enclosing subprogram. */
if (num_defns_collected (obstackp) == 0 && block_depth > 2)
- add_symbols_from_enclosing_procs (obstackp, name, domain, wild_match);
+ add_symbols_from_enclosing_procs (obstackp, name, domain, wild_match_p);
}
/* An object of this type is used as the user_data argument when
return 0;
}
-/* Compare STRING1 to STRING2, with results as for strcmp.
- Compatible with strcmp_iw in that strcmp_iw (STRING1, STRING2) <= 0
- implies compare_names (STRING1, STRING2) (they may differ as to
- what symbols compare equal). */
+/* Implements compare_names, but only applying the comparision using
+ the given CASING. */
static int
-compare_names (const char *string1, const char *string2)
+compare_names_with_case (const char *string1, const char *string2,
+ enum case_sensitivity casing)
{
while (*string1 != '\0' && *string2 != '\0')
{
+ char c1, c2;
+
if (isspace (*string1) || isspace (*string2))
return strcmp_iw_ordered (string1, string2);
- if (*string1 != *string2)
+
+ if (casing == case_sensitive_off)
+ {
+ c1 = tolower (*string1);
+ c2 = tolower (*string2);
+ }
+ else
+ {
+ c1 = *string1;
+ c2 = *string2;
+ }
+ if (c1 != c2)
break;
+
string1 += 1;
string2 += 1;
}
+
switch (*string1)
{
case '(':
if (*string2 == '(')
return strcmp_iw_ordered (string1, string2);
else
- return *string1 - *string2;
+ {
+ if (casing == case_sensitive_off)
+ return tolower (*string1) - tolower (*string2);
+ else
+ return *string1 - *string2;
+ }
}
}
+/* Compare STRING1 to STRING2, with results as for strcmp.
+ Compatible with strcmp_iw_ordered in that...
+
+ strcmp_iw_ordered (STRING1, STRING2) <= 0
+
+ ... implies...
+
+ compare_names (STRING1, STRING2) <= 0
+
+ (they may differ as to what symbols compare equal). */
+
+static int
+compare_names (const char *string1, const char *string2)
+{
+ int result;
+
+ /* Similar to what strcmp_iw_ordered does, we need to perform
+ a case-insensitive comparison first, and only resort to
+ a second, case-sensitive, comparison if the first one was
+ not sufficient to differentiate the two strings. */
+
+ result = compare_names_with_case (string1, string2, case_sensitive_off);
+ if (result == 0)
+ result = compare_names_with_case (string1, string2, case_sensitive_on);
+
+ return result;
+}
+
/* Add to OBSTACKP all non-local symbols whose name and domain match
NAME and DOMAIN respectively. The search is performed on GLOBAL_BLOCK
symbols if GLOBAL is non-zero, or on STATIC_BLOCK symbols otherwise. */
data.objfile = objfile;
if (is_wild_match)
- objfile->sf->qf->map_matching_symbols (name, domain, objfile, global,
+ objfile->sf->qf->map_matching_symbols (objfile, name, domain, global,
aux_add_nonlocal_symbols, &data,
wild_match, NULL);
else
- objfile->sf->qf->map_matching_symbols (name, domain, objfile, global,
+ objfile->sf->qf->map_matching_symbols (objfile, name, domain, global,
aux_add_nonlocal_symbols, &data,
full_match, compare_names);
}
strcpy (name1, "_ada_");
strcpy (name1 + sizeof ("_ada_") - 1, name);
data.objfile = objfile;
- objfile->sf->qf->map_matching_symbols (name1, domain,
- objfile, global,
+ objfile->sf->qf->map_matching_symbols (objfile, name1, domain,
+ global,
aux_add_nonlocal_symbols,
&data,
full_match, compare_names);
}
}
-/* Find symbols in DOMAIN matching NAME0, in BLOCK0 and enclosing
- scope and in global scopes, returning the number of matches. Sets
- *RESULTS to point to a vector of (SYM,BLOCK) tuples,
+/* Find symbols in DOMAIN matching NAME0, in BLOCK0 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 are transient---good only to
- the next call of ada_lookup_symbol_list. Any non-function/non-enumeral
+ any) in which they were found. This vector is transient---good only to
+ the next call of ada_lookup_symbol_list.
+
+ When full_search is non-zero, any non-function/non-enumeral
symbol match within the nest of blocks whose innermost member is BLOCK0,
is the one match returned (no other matches in that or
enclosing blocks is returned). If there are any matches in or
- surrounding BLOCK0, then these alone are returned. Otherwise, if
- FULL_SEARCH is non-zero, then the search extends to global and
- file-scope (static) symbol tables.
- Names prefixed with "standard__" are handled specially: "standard__"
+ surrounding BLOCK0, then these alone are returned.
+
+ Names prefixed with "standard__" are handled specially: "standard__"
is first stripped off, and only static and global symbols are searched. */
-int
-ada_lookup_symbol_list (const char *name0, const struct block *block0,
- domain_enum namespace,
- struct ada_symbol_info **results,
- int full_search)
+static int
+ada_lookup_symbol_list_worker (const char *name0, const struct block *block0,
+ domain_enum namespace,
+ struct ada_symbol_info **results,
+ int full_search)
{
struct symbol *sym;
struct block *block;
const char *name;
- const int wild_match = should_use_wild_match (name0);
+ const int wild_match_p = should_use_wild_match (name0);
int cacheIfUnique;
int ndefns;
/* Check the non-global symbols. If we have ANY match, then we're done. */
- ada_add_local_symbols (&symbol_list_obstack, name, block, namespace,
- wild_match);
- if (num_defns_collected (&symbol_list_obstack) > 0 || !full_search)
- goto done;
+ if (block != NULL)
+ {
+ if (full_search)
+ {
+ ada_add_local_symbols (&symbol_list_obstack, name, block,
+ namespace, wild_match_p);
+ }
+ else
+ {
+ /* In the !full_search case we're are being called by
+ ada_iterate_over_symbols, and we don't want to search
+ superblocks. */
+ ada_add_block_symbols (&symbol_list_obstack, block, name,
+ namespace, NULL, wild_match_p);
+ }
+ if (num_defns_collected (&symbol_list_obstack) > 0 || !full_search)
+ goto done;
+ }
/* No non-global symbols found. Check our cache to see if we have
already performed this search before. If we have, then return
/* Search symbols from all global blocks. */
add_nonlocal_symbols (&symbol_list_obstack, name, namespace, 1,
- wild_match);
+ wild_match_p);
/* Now add symbols from all per-file blocks if we've gotten no hits
(not strictly correct, but perhaps better than an error). */
if (num_defns_collected (&symbol_list_obstack) == 0)
add_nonlocal_symbols (&symbol_list_obstack, name, namespace, 0,
- wild_match);
+ wild_match_p);
done:
ndefns = num_defns_collected (&symbol_list_obstack);
ndefns = remove_extra_symbols (*results, ndefns);
- if (ndefns == 0)
+ if (ndefns == 0 && full_search)
cache_symbol (name0, namespace, NULL, NULL);
- if (ndefns == 1 && cacheIfUnique)
+ if (ndefns == 1 && full_search && cacheIfUnique)
cache_symbol (name0, namespace, (*results)[0].sym, (*results)[0].block);
ndefns = remove_irrelevant_renamings (*results, ndefns, block0);
return ndefns;
}
+/* Find symbols in DOMAIN matching NAME0, in BLOCK0 and enclosing scope and
+ in global scopes, returning the number of matches, and setting *RESULTS
+ to a vector of (SYM,BLOCK) tuples.
+ See ada_lookup_symbol_list_worker for further details. */
+
+int
+ada_lookup_symbol_list (const char *name0, const struct block *block0,
+ domain_enum domain, struct ada_symbol_info **results)
+{
+ return ada_lookup_symbol_list_worker (name0, block0, domain, results, 1);
+}
+
+/* Implementation of the la_iterate_over_symbols method. */
+
+static void
+ada_iterate_over_symbols (const struct block *block,
+ const char *name, domain_enum domain,
+ symbol_found_callback_ftype *callback,
+ void *data)
+{
+ int ndefs, i;
+ struct ada_symbol_info *results;
+
+ ndefs = ada_lookup_symbol_list_worker (name, block, domain, &results, 0);
+ for (i = 0; i < ndefs; ++i)
+ {
+ if (! (*callback) (results[i].sym, data))
+ break;
+ }
+}
+
/* If NAME is the name of an entity, return a string that should
be used to look that entity up in Ada units. This string should
be deallocated after use using xfree.
return canon;
}
-/* Implementation of the la_iterate_over_symbols method. */
-
-static void
-ada_iterate_over_symbols (const struct block *block,
- const char *name, domain_enum domain,
- symbol_found_callback_ftype *callback,
- void *data)
-{
- int ndefs, i;
- struct ada_symbol_info *results;
+/* The result is as for ada_lookup_symbol_list with FULL_SEARCH set
+ to 1, but choosing the first symbol found if there are multiple
+ choices.
- ndefs = ada_lookup_symbol_list (name, block, domain, &results, 0);
- for (i = 0; i < ndefs; ++i)
- {
- if (! (*callback) (results[i].sym, data))
- break;
- }
-}
+ The result is stored in *INFO, which must be non-NULL.
+ If no match is found, INFO->SYM is set to NULL. */
-struct symbol *
-ada_lookup_encoded_symbol (const char *name, const struct block *block0,
- domain_enum namespace, struct block **block_found)
+void
+ada_lookup_encoded_symbol (const char *name, const struct block *block,
+ domain_enum namespace,
+ struct ada_symbol_info *info)
{
struct ada_symbol_info *candidates;
int n_candidates;
- n_candidates = ada_lookup_symbol_list (name, block0, namespace, &candidates,
- 1);
+ gdb_assert (info != NULL);
+ memset (info, 0, sizeof (struct ada_symbol_info));
+ n_candidates = ada_lookup_symbol_list (name, block, namespace, &candidates);
if (n_candidates == 0)
- return NULL;
-
- if (block_found != NULL)
- *block_found = candidates[0].block;
+ return;
- return fixup_symbol_section (candidates[0].sym, NULL);
-}
+ *info = candidates[0];
+ info->sym = fixup_symbol_section (info->sym, NULL);
+}
/* Return a symbol in DOMAIN matching NAME, in BLOCK0 and enclosing
scope and in global scopes, or NULL if none. NAME is folded and
encoded first. Otherwise, the result is as for ada_lookup_symbol_list,
choosing the first symbol if there are multiple choices.
- *IS_A_FIELD_OF_THIS is set to 0 and *SYMTAB is set to the symbol
- table in which the symbol was found (in both cases, these
- assignments occur only if the pointers are non-null). */
+ If IS_A_FIELD_OF_THIS is not NULL, it is set to zero. */
+
struct symbol *
ada_lookup_symbol (const char *name, const struct block *block0,
domain_enum namespace, int *is_a_field_of_this)
{
+ struct ada_symbol_info info;
+
if (is_a_field_of_this != NULL)
*is_a_field_of_this = 0;
- return
- ada_lookup_encoded_symbol (ada_encode (ada_fold_name (name)),
- block0, namespace, NULL);
+ ada_lookup_encoded_symbol (ada_encode (ada_fold_name (name)),
+ block0, namespace, &info);
+ return info.sym;
}
static struct symbol *
static int
wild_match (const char *name, const char *patn)
{
- const char *p, *n;
+ const char *p;
const char *name0 = name;
while (1)
/* Add symbols from BLOCK matching identifier NAME in DOMAIN to
vector *defn_symbols, updating the list of symbols in OBSTACKP
(if necessary). If WILD, treat as NAME with a wildcard prefix.
- OBJFILE is the section containing BLOCK.
- SYMTAB is recorded with each symbol added. */
+ OBJFILE is the section containing BLOCK. */
static void
ada_add_block_symbols (struct obstack *obstackp,
domain_enum domain, struct objfile *objfile,
int wild)
{
- struct dict_iterator iter;
+ struct block_iterator iter;
int name_len = strlen (name);
/* A matching argument symbol, if any. */
struct symbol *arg_sym;
found_sym = 0;
if (wild)
{
- for (sym = dict_iter_match_first (BLOCK_DICT (block), name,
- wild_match, &iter);
- sym != NULL; sym = dict_iter_match_next (name, wild_match, &iter))
+ for (sym = block_iter_match_first (block, name, wild_match, &iter);
+ sym != NULL; sym = block_iter_match_next (name, wild_match, &iter))
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
SYMBOL_DOMAIN (sym), domain)
}
else
{
- for (sym = dict_iter_match_first (BLOCK_DICT (block), name,
- full_match, &iter);
- sym != NULL; sym = dict_iter_match_next (name, full_match, &iter))
+ for (sym = block_iter_match_first (block, name, full_match, &iter);
+ sym != NULL; sym = block_iter_match_next (name, full_match, &iter))
{
if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
SYMBOL_DOMAIN (sym), domain))
does not need to be deallocated, but is only good until the next call.
TEXT_LEN is equal to the length of TEXT.
- Perform a wild match if WILD_MATCH is set.
- ENCODED should be set if TEXT represents the start of a symbol name
+ Perform a wild match if WILD_MATCH_P is set.
+ ENCODED_P should be set if TEXT represents the start of a symbol name
in its encoded form. */
static const char *
symbol_completion_match (const char *sym_name,
const char *text, int text_len,
- int wild_match, int encoded)
+ int wild_match_p, int encoded_p)
{
const int verbatim_match = (text[0] == '<');
int match = 0;
if (strncmp (sym_name, text, text_len) == 0)
match = 1;
- if (match && !encoded)
+ if (match && !encoded_p)
{
/* One needed check before declaring a positive match is to verify
that iff we are doing a verbatim match, the decoded version
/* Second: Try wild matching... */
- if (!match && wild_match)
+ if (!match && wild_match_p)
{
/* Since we are doing wild matching, this means that TEXT
may represent an unqualified symbol name. We therefore must
if (verbatim_match)
sym_name = add_angle_brackets (sym_name);
- if (!encoded)
+ if (!encoded_p)
sym_name = ada_decode (sym_name);
return sym_name;
completion should be performed. These two parameters are used to
determine which part of the symbol name should be added to the
completion vector.
- if WILD_MATCH is set, then wild matching is performed.
- ENCODED should be set if TEXT represents a symbol name in its
+ if WILD_MATCH_P is set, then wild matching is performed.
+ ENCODED_P should be set if TEXT represents a symbol name in its
encoded formed (in which case the completion should also be
encoded). */
const char *sym_name,
const char *text, int text_len,
const char *orig_text, const char *word,
- int wild_match, int encoded)
+ int wild_match_p, int encoded_p)
{
const char *match = symbol_completion_match (sym_name, text, text_len,
- wild_match, encoded);
+ wild_match_p, encoded_p);
char *completion;
if (match == NULL)
struct add_partial_datum
{
VEC(char_ptr) **completions;
- char *text;
+ const char *text;
int text_len;
- char *text0;
- char *word;
+ const char *text0;
+ const char *word;
int wild_match;
int encoded;
};
data->wild_match, data->encoded) != NULL;
}
-/* Return a list of possible symbol names completing TEXT0. The list
- is NULL terminated. WORD is the entire command on which completion
- is made. */
+/* Return a list of possible symbol names completing TEXT0. WORD is
+ the entire command on which completion is made. */
-static char **
-ada_make_symbol_completion_list (char *text0, char *word)
+static VEC (char_ptr) *
+ada_make_symbol_completion_list (const char *text0, const char *word,
+ enum type_code code)
{
char *text;
int text_len;
- int wild_match;
- int encoded;
+ int wild_match_p;
+ int encoded_p;
VEC(char_ptr) *completions = VEC_alloc (char_ptr, 128);
struct symbol *sym;
struct symtab *s;
struct objfile *objfile;
struct block *b, *surrounding_static_block = 0;
int i;
- struct dict_iterator iter;
+ struct block_iterator iter;
+ struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+
+ gdb_assert (code == TYPE_CODE_UNDEF);
if (text0[0] == '<')
{
text = xstrdup (text0);
make_cleanup (xfree, text);
text_len = strlen (text);
- wild_match = 0;
- encoded = 1;
+ wild_match_p = 0;
+ encoded_p = 1;
}
else
{
for (i = 0; i < text_len; i++)
text[i] = tolower (text[i]);
- encoded = (strstr (text0, "__") != NULL);
+ encoded_p = (strstr (text0, "__") != NULL);
/* If the name contains a ".", then the user is entering a fully
qualified entity name, and the match must not be done in wild
mode. Similarly, if the user wants to complete what looks like
an encoded name, the match must not be done in wild mode. */
- wild_match = (strchr (text0, '.') == NULL && !encoded);
+ wild_match_p = (strchr (text0, '.') == NULL && !encoded_p);
}
/* First, look at the partial symtab symbols. */
data.text_len = text_len;
data.text0 = text0;
data.word = word;
- data.wild_match = wild_match;
- data.encoded = encoded;
+ data.wild_match = wild_match_p;
+ data.encoded = encoded_p;
expand_partial_symbol_names (ada_expand_partial_symbol_name, &data);
}
{
QUIT;
symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (msymbol),
- text, text_len, text0, word, wild_match, encoded);
+ text, text_len, text0, word, wild_match_p,
+ encoded_p);
}
/* Search upwards from currently selected frame (so that we can
{
symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
text, text_len, text0, word,
- wild_match, encoded);
+ wild_match_p, encoded_p);
}
}
{
symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
text, text_len, text0, word,
- wild_match, encoded);
+ wild_match_p, encoded_p);
}
}
{
symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
text, text_len, text0, word,
- wild_match, encoded);
+ wild_match_p, encoded_p);
}
}
- /* Append the closing NULL entry. */
- VEC_safe_push (char_ptr, completions, NULL);
-
- /* Make a copy of the COMPLETIONS VEC before we free it, and then
- return the copy. It's unfortunate that we have to make a copy
- of an array that we're about to destroy, but there is nothing much
- we can do about it. Fortunately, it's typically not a very large
- array. */
- {
- const size_t completions_size =
- VEC_length (char_ptr, completions) * sizeof (char *);
- char **result = xmalloc (completions_size);
-
- memcpy (result, VEC_address (char_ptr, completions), completions_size);
-
- VEC_free (char_ptr, completions);
- return result;
- }
+ do_cleanups (old_chain);
+ return completions;
}
/* Field Access */
return (strcmp (name, "ada__tags__dispatch_table") == 0);
}
+/* Return non-zero if TYPE is an interface tag. */
+
+static int
+ada_is_interface_tag (struct type *type)
+{
+ const char *name = TYPE_NAME (type);
+
+ if (name == NULL)
+ return 0;
+
+ return (strcmp (name, "ada__tags__interface_tag") == 0);
+}
+
/* True if field number FIELD_NUM in struct or union type TYPE is supposed
to be invisible to users. */
{
if (field_num < 0 || field_num > TYPE_NFIELDS (type))
return 1;
-
+
/* Check the name of that field. */
{
const char *name = TYPE_FIELD_NAME (type, field_num);
if (name == NULL)
return 1;
- /* A field named "_parent" is internally generated by GNAT for
- tagged types, and should not be printed either. */
+ /* Normally, fields whose name start with an underscore ("_")
+ are fields that have been internally generated by the compiler,
+ and thus should not be printed. The "_parent" field is special,
+ however: This is a field internally generated by the compiler
+ for tagged types, and it contains the components inherited from
+ the parent type. This field should not be printed as is, but
+ should not be ignored either. */
if (name[0] == '_' && strncmp (name, "_parent", 7) != 0)
return 1;
}
- /* If this is the dispatch table of a tagged type, then ignore. */
+ /* If this is the dispatch table of a tagged type or an interface tag,
+ then ignore. */
if (ada_is_tagged_type (type, 1)
- && ada_is_dispatch_table_ptr_type (TYPE_FIELD_TYPE (type, field_num)))
+ && (ada_is_dispatch_table_ptr_type (TYPE_FIELD_TYPE (type, field_num))
+ || ada_is_interface_tag (TYPE_FIELD_TYPE (type, field_num))))
return 1;
/* Not a special field, so it should not be ignored. */
return ada_lookup_struct_elt_type (value_type (val), "_tag", 1, 0, NULL);
}
+/* Return 1 if TAG follows the old scheme for Ada tags (used for Ada 95,
+ retired at Ada 05). */
+
+static int
+is_ada95_tag (struct value *tag)
+{
+ return ada_value_struct_elt (tag, "tsd", 1) != NULL;
+}
+
/* The value of the tag on VAL. */
struct value *
return NULL;
}
-struct tag_args
+/* Given a value OBJ of a tagged type, return a value of this
+ type at the base address of the object. The base address, as
+ defined in Ada.Tags, it is the address of the primary tag of
+ the object, and therefore where the field values of its full
+ view can be fetched. */
+
+struct value *
+ada_tag_value_at_base_address (struct value *obj)
{
+ volatile struct gdb_exception e;
+ struct value *val;
+ LONGEST offset_to_top = 0;
+ struct type *ptr_type, *obj_type;
struct value *tag;
- char *name;
-};
+ CORE_ADDR base_address;
+ obj_type = value_type (obj);
-static int ada_tag_name_1 (void *);
-static int ada_tag_name_2 (struct tag_args *);
+ /* It is the responsability of the caller to deref pointers. */
-/* Wrapper function used by ada_tag_name. Given a struct tag_args*
- value ARGS, sets ARGS->name to the tag name of ARGS->tag.
- The value stored in ARGS->name is valid until the next call to
- ada_tag_name_1. */
+ if (TYPE_CODE (obj_type) == TYPE_CODE_PTR
+ || TYPE_CODE (obj_type) == TYPE_CODE_REF)
+ return obj;
-static int
-ada_tag_name_1 (void *args0)
-{
- struct tag_args *args = (struct tag_args *) args0;
- static char name[1024];
- char *p;
- struct value *val;
+ tag = ada_value_tag (obj);
+ if (!tag)
+ return obj;
- args->name = NULL;
- val = ada_value_struct_elt (args->tag, "tsd", 1);
- if (val == NULL)
- return ada_tag_name_2 (args);
- val = ada_value_struct_elt (val, "expanded_name", 1);
- if (val == NULL)
- return 0;
- read_memory_string (value_as_address (val), name, sizeof (name) - 1);
- for (p = name; *p != '\0'; p += 1)
- if (isalpha (*p))
- *p = tolower (*p);
- args->name = name;
- return 0;
+ /* Base addresses only appeared with Ada 05 and multiple inheritance. */
+
+ if (is_ada95_tag (tag))
+ return obj;
+
+ ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
+ ptr_type = lookup_pointer_type (ptr_type);
+ val = value_cast (ptr_type, tag);
+ if (!val)
+ return obj;
+
+ /* It is perfectly possible that an exception be raised while
+ trying to determine the base address, just like for the tag;
+ see ada_tag_name for more details. We do not print the error
+ message for the same reason. */
+
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ offset_to_top = value_as_long (value_ind (value_ptradd (val, -2)));
+ }
+
+ if (e.reason < 0)
+ return obj;
+
+ /* If offset is null, nothing to do. */
+
+ if (offset_to_top == 0)
+ return obj;
+
+ /* -1 is a special case in Ada.Tags; however, what should be done
+ is not quite clear from the documentation. So do nothing for
+ now. */
+
+ if (offset_to_top == -1)
+ return obj;
+
+ 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.
+ Otherwise, offset_to_top is bogus (which can happen when
+ the object is not initialized yet). */
+
+ if (!tag)
+ return obj;
+
+ obj_type = type_from_tag (tag);
+
+ if (!obj_type)
+ return obj;
+
+ return value_from_contents_and_address (obj_type, NULL, base_address);
}
/* Return the "ada__tags__type_specific_data" type. */
return data->tsd_type;
}
-/* Utility function for ada_tag_name_1 that tries the second
- representation for the dispatch table (in which there is no
- explicit 'tsd' field in the referent of the tag pointer, and instead
- the tsd pointer is stored just before the dispatch table. */
-
-static int
-ada_tag_name_2 (struct tag_args *args)
+/* Return the TSD (type-specific data) associated to the given TAG.
+ TAG is assumed to be the tag of a tagged-type entity.
+
+ May return NULL if we are unable to get the TSD. */
+
+static struct value *
+ada_get_tsd_from_tag (struct value *tag)
+{
+ struct value *val;
+ struct type *type;
+
+ /* First option: The TSD is simply stored as a field of our TAG.
+ Only older versions of GNAT would use this format, but we have
+ to test it first, because there are no visible markers for
+ the current approach except the absence of that field. */
+
+ val = ada_value_struct_elt (tag, "tsd", 1);
+ if (val)
+ return val;
+
+ /* Try the second representation for the dispatch table (in which
+ there is no explicit 'tsd' field in the referent of the tag pointer,
+ and instead the tsd pointer is stored just before the dispatch
+ table. */
+
+ type = ada_get_tsd_type (current_inferior());
+ if (type == NULL)
+ return NULL;
+ type = lookup_pointer_type (lookup_pointer_type (type));
+ val = value_cast (type, tag);
+ if (val == NULL)
+ return NULL;
+ return value_ind (value_ptradd (val, -1));
+}
+
+/* Given the TSD of a tag (type-specific data), return a string
+ containing the name of the associated type.
+
+ The returned value is good until the next call. May return NULL
+ if we are unable to determine the tag name. */
+
+static char *
+ada_tag_name_from_tsd (struct value *tsd)
{
- struct type *info_type;
static char name[1024];
char *p;
- struct value *val, *valp;
+ struct value *val;
- args->name = NULL;
- info_type = ada_get_tsd_type (current_inferior());
- if (info_type == NULL)
- return 0;
- info_type = lookup_pointer_type (lookup_pointer_type (info_type));
- valp = value_cast (info_type, args->tag);
- if (valp == NULL)
- return 0;
- val = value_ind (value_ptradd (valp, -1));
- if (val == NULL)
- return 0;
- val = ada_value_struct_elt (val, "expanded_name", 1);
+ val = ada_value_struct_elt (tsd, "expanded_name", 1);
if (val == NULL)
- return 0;
+ return NULL;
read_memory_string (value_as_address (val), name, sizeof (name) - 1);
for (p = name; *p != '\0'; p += 1)
if (isalpha (*p))
*p = tolower (*p);
- args->name = name;
- return 0;
+ return name;
}
/* The type name of the dynamic type denoted by the 'tag value TAG, as
- a C string. */
+ a C string.
+
+ Return NULL if the TAG is not an Ada tag, or if we were unable to
+ determine the name of that tag. The result is good until the next
+ call. */
const char *
ada_tag_name (struct value *tag)
{
- struct tag_args args;
+ volatile struct gdb_exception e;
+ char *name = NULL;
if (!ada_is_tag_type (value_type (tag)))
return NULL;
- args.tag = tag;
- args.name = NULL;
- catch_errors (ada_tag_name_1, &args, NULL, RETURN_MASK_ALL);
- return args.name;
-}
-/* The parent type of TYPE, or NULL if none. */
+ /* It is perfectly possible that an exception be raised while trying
+ to determine the TAG's name, even under normal circumstances:
+ The associated variable may be uninitialized or corrupted, for
+ instance. We do not let any exception propagate past this point.
+ instead we return NULL.
-struct type *
+ We also do not print the error message either (which often is very
+ low-level (Eg: "Cannot read memory at 0x[...]"), but instead let
+ the caller print a more meaningful message if necessary. */
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ struct value *tsd = ada_get_tsd_from_tag (tag);
+
+ if (tsd != NULL)
+ name = ada_tag_name_from_tsd (tsd);
+ }
+
+ return name;
+}
+
+/* The parent type of TYPE, or NULL if none. */
+
+struct type *
ada_parent_type (struct type *type)
{
int i;
CORE_ADDR address;
if (TYPE_CODE (t) == TYPE_CODE_PTR)
- address = value_as_address (arg);
+ address = value_address (ada_value_ind (arg));
else
- address = unpack_pointer (t, value_contents (arg));
+ address = value_address (ada_coerce_ref (arg));
t1 = ada_to_fixed_type (ada_get_base_type (t1), NULL, address, NULL, 1);
if (find_struct_field (name, t1, 0,
struct value *
ada_value_ind (struct value *val0)
{
- struct value *val = unwrap_value (value_ind (val0));
+ struct value *val = value_ind (val0);
+
+ if (ada_is_tagged_type (value_type (val), 0))
+ val = ada_tag_value_at_base_address (val);
return ada_to_fixed_value (val);
}
struct value *val = val0;
val = coerce_ref (val);
- val = unwrap_value (val);
+
+ if (ada_is_tagged_type (value_type (val), 0))
+ val = ada_tag_value_at_base_address (val);
+
return ada_to_fixed_value (val);
}
else
return atoi (name + align_offset) * TARGET_CHAR_BIT;
}
-/* Find a symbol named NAME. Ignores ambiguity. */
+/* Find a typedef or tag symbol named NAME. Ignores ambiguity. */
-struct symbol *
-ada_find_any_symbol (const char *name)
+static struct symbol *
+ada_find_any_type_symbol (const char *name)
{
struct symbol *sym;
solely for types defined by debug info, it will not search the GDB
primitive types. */
-struct type *
+static struct type *
ada_find_any_type (const char *name)
{
- struct symbol *sym = ada_find_any_symbol (name);
+ struct symbol *sym = ada_find_any_type_symbol (name);
if (sym != NULL)
return SYMBOL_TYPE (sym);
return NULL;
}
-/* Given NAME and an associated BLOCK, search all symbols for
- NAME suffixed with "___XR", which is the ``renaming'' symbol
- associated to NAME. Return this symbol if found, return
- NULL otherwise. */
+/* Given NAME_SYM and an associated BLOCK, find a "renaming" symbol
+ associated with NAME_SYM's name. NAME_SYM may itself be a renaming
+ symbol, in which case it is returned. Otherwise, this looks for
+ symbols whose name is that of NAME_SYM suffixed with "___XR".
+ Return symbol if found, and NULL otherwise. */
struct symbol *
-ada_find_renaming_symbol (const char *name, struct block *block)
+ada_find_renaming_symbol (struct symbol *name_sym, const struct block *block)
{
+ const char *name = SYMBOL_LINKAGE_NAME (name_sym);
struct symbol *sym;
+ if (strstr (name, "___XR") != NULL)
+ return name_sym;
+
sym = find_old_style_renaming_symbol (name, block);
if (sym != NULL)
return sym;
/* Not right yet. FIXME pnh 7/20/2007. */
- sym = ada_find_any_symbol (name);
+ sym = ada_find_any_type_symbol (name);
if (sym != NULL && strstr (SYMBOL_LINKAGE_NAME (sym), "___XR") != NULL)
return sym;
else
}
static struct symbol *
-find_old_style_renaming_symbol (const char *name, struct block *block)
+find_old_style_renaming_symbol (const char *name, const struct block *block)
{
const struct symbol *function_sym = block_linkage_function (block);
char *rename;
xsnprintf (rename, rename_len * sizeof (char), "%s___XR", name);
}
- return ada_find_any_symbol (rename);
+ return ada_find_any_type_symbol (rename);
}
/* Because of GNAT encoding conventions, several GDB symbols may match a
{
off = align_value (off, field_alignment (type, f))
+ TYPE_FIELD_BITPOS (type, f);
- TYPE_FIELD_BITPOS (rtype, f) = off;
+ SET_FIELD_BITPOS (TYPE_FIELD (rtype, f), off);
TYPE_FIELD_BITSIZE (rtype, f) = 0;
if (ada_is_variant_part (type, f))
}
else
{
- struct type *field_type = TYPE_FIELD_TYPE (type, f);
-
- /* If our field is a typedef type (most likely a typedef of
- a fat pointer, encoding an array access), then we need to
- look at its target type to determine its characteristics.
- In particular, we would miscompute the field size if we took
- the size of the typedef (zero), instead of the size of
- the target type. */
- if (TYPE_CODE (field_type) == TYPE_CODE_TYPEDEF)
- field_type = ada_typedef_target_type (field_type);
-
- TYPE_FIELD_TYPE (rtype, f) = field_type;
+ /* Note: If this field's type is a typedef, it is important
+ to preserve the typedef layer.
+
+ Otherwise, we might be transforming a typedef to a fat
+ pointer (encoding a pointer to an unconstrained array),
+ into a basic fat pointer (encoding an unconstrained
+ array). As both types are implemented using the same
+ structure, the typedef is the only clue which allows us
+ to distinguish between the two options. Stripping it
+ would prevent us from printing this field appropriately. */
+ TYPE_FIELD_TYPE (rtype, f) = TYPE_FIELD_TYPE (type, f);
TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f);
if (TYPE_FIELD_BITSIZE (type, f) > 0)
fld_bit_len =
TYPE_FIELD_BITSIZE (rtype, f) = TYPE_FIELD_BITSIZE (type, f);
else
- fld_bit_len =
- TYPE_LENGTH (ada_check_typedef (field_type)) * TARGET_CHAR_BIT;
+ {
+ struct type *field_type = TYPE_FIELD_TYPE (type, f);
+
+ /* We need to be careful of typedefs when computing
+ the length of our field. If this is a typedef,
+ get the length of the target type, not the length
+ of the typedef. */
+ if (TYPE_CODE (field_type) == TYPE_CODE_TYPEDEF)
+ field_type = ada_typedef_target_type (field_type);
+
+ fld_bit_len =
+ TYPE_LENGTH (ada_check_typedef (field_type)) * TARGET_CHAR_BIT;
+ }
}
if (off + fld_bit_len > bit_len)
bit_len = off + fld_bit_len;
error (_("array type with dynamic size is larger than varsize-limit"));
}
+ /* We want to preserve the type name. This can be useful when
+ trying to get the type name of a value that has already been
+ printed (for instance, if the user did "print VAR; whatis $". */
+ TYPE_NAME (result) = TYPE_NAME (type0);
+
if (constrained_packed_array_p)
{
/* So far, the resulting type has been created as if the original
if (check_tag && address != 0 && ada_is_tagged_type (static_type, 0))
{
- struct type *real_type =
- type_from_tag (value_tag_from_contents_and_address
- (fixed_record_type,
- valaddr,
- address));
-
+ struct value *tag =
+ value_tag_from_contents_and_address
+ (fixed_record_type,
+ valaddr,
+ address);
+ struct type *real_type = type_from_tag (tag);
+ struct value *obj =
+ value_from_contents_and_address (fixed_record_type,
+ valaddr,
+ address);
if (real_type != NULL)
- return to_fixed_record_type (real_type, valaddr, address, NULL);
+ return to_fixed_record_type
+ (real_type, NULL,
+ value_address (ada_tag_value_at_base_address (obj)), NULL);
}
/* Check to see if there is a parallel ___XVZ variable.
struct value *
ada_to_fixed_value (struct value *val)
{
- return ada_to_fixed_value_create (value_type (val),
- value_address (val),
- val);
+ val = unwrap_value (val);
+ val = ada_to_fixed_value_create (value_type (val),
+ value_address (val),
+ val);
+ return val;
}
\f
for (i = 0; i < TYPE_NFIELDS (type); i += 1)
{
- if (v == TYPE_FIELD_BITPOS (type, i))
+ if (v == TYPE_FIELD_ENUMVAL (type, i))
return i;
}
error (_("enumeration value is invalid: can't find 'POS"));
if (pos < 0 || pos >= TYPE_NFIELDS (type))
error (_("argument to 'VAL out of range"));
- return value_from_longest (type, TYPE_FIELD_BITPOS (type, pos));
+ return value_from_longest (type, TYPE_FIELD_ENUMVAL (type, pos));
}
else
return value_from_longest (type, value_as_long (arg));
return value_from_double (type, val);
}
+/* Given two array types T1 and T2, return nonzero iff both arrays
+ contain the same number of elements. */
+
+static int
+ada_same_array_size_p (struct type *t1, struct type *t2)
+{
+ LONGEST lo1, hi1, lo2, hi2;
+
+ /* Get the array bounds in order to verify that the size of
+ the two arrays match. */
+ if (!get_array_bounds (t1, &lo1, &hi1)
+ || !get_array_bounds (t2, &lo2, &hi2))
+ error (_("unable to determine array bounds"));
+
+ /* To make things easier for size comparison, normalize a bit
+ the case of empty arrays by making sure that the difference
+ between upper bound and lower bound is always -1. */
+ if (lo1 > hi1)
+ hi1 = lo1 - 1;
+ if (lo2 > hi2)
+ hi2 = lo2 - 1;
+
+ return (hi1 - lo1 == hi2 - lo2);
+}
+
+/* Assuming that VAL is an array of integrals, and TYPE represents
+ an array with the same number of elements, but with wider integral
+ elements, return an array "casted" to TYPE. In practice, this
+ means that the returned array is built by casting each element
+ of the original array into TYPE's (wider) element type. */
+
+static struct value *
+ada_promote_array_of_integrals (struct type *type, struct value *val)
+{
+ struct type *elt_type = TYPE_TARGET_TYPE (type);
+ LONGEST lo, hi;
+ struct value *res;
+ LONGEST i;
+
+ /* Verify that both val and type are arrays of scalars, and
+ that the size of val's elements is smaller than the size
+ of type's element. */
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY);
+ gdb_assert (is_integral_type (TYPE_TARGET_TYPE (type)));
+ gdb_assert (TYPE_CODE (value_type (val)) == TYPE_CODE_ARRAY);
+ gdb_assert (is_integral_type (TYPE_TARGET_TYPE (value_type (val))));
+ gdb_assert (TYPE_LENGTH (TYPE_TARGET_TYPE (type))
+ > TYPE_LENGTH (TYPE_TARGET_TYPE (value_type (val))));
+
+ if (!get_array_bounds (type, &lo, &hi))
+ error (_("unable to determine array bounds"));
+
+ res = allocate_value (type);
+
+ /* Promote each array element. */
+ for (i = 0; i < hi - lo + 1; i++)
+ {
+ struct value *elt = value_cast (elt_type, value_subscript (val, lo + i));
+
+ memcpy (value_contents_writeable (res) + (i * TYPE_LENGTH (elt_type)),
+ value_contents_all (elt), TYPE_LENGTH (elt_type));
+ }
+
+ return res;
+}
+
/* Coerce VAL as necessary for assignment to an lval of type TYPE, and
return the converted value. */
if (TYPE_CODE (type2) == TYPE_CODE_ARRAY
&& TYPE_CODE (type) == TYPE_CODE_ARRAY)
{
- if (TYPE_LENGTH (type2) != TYPE_LENGTH (type)
- || TYPE_LENGTH (TYPE_TARGET_TYPE (type2))
- != TYPE_LENGTH (TYPE_TARGET_TYPE (type2)))
+ if (!ada_same_array_size_p (type, type2))
+ error (_("cannot assign arrays of different length"));
+
+ if (is_integral_type (TYPE_TARGET_TYPE (type))
+ && is_integral_type (TYPE_TARGET_TYPE (type2))
+ && TYPE_LENGTH (TYPE_TARGET_TYPE (type2))
+ < TYPE_LENGTH (TYPE_TARGET_TYPE (type)))
+ {
+ /* Allow implicit promotion of the array elements to
+ a wider type. */
+ return ada_promote_array_of_integrals (type, val);
+ }
+
+ if (TYPE_LENGTH (TYPE_TARGET_TYPE (type2))
+ != TYPE_LENGTH (TYPE_TARGET_TYPE (type)))
error (_("Incompatible types in assignment"));
deprecated_set_value_type (val, type);
}
else
{
elt = ada_index_struct_field (index, lhs, 0, value_type (lhs));
- elt = ada_to_fixed_value (unwrap_value (elt));
+ elt = ada_to_fixed_value (elt);
}
if (exp->elts[*pos].opcode == OP_AGGREGATE)
int num_specs;
LONGEST *indices;
int max_indices, num_indices;
- int is_array_aggregate;
int i;
*pos += 3;
lhs_type = value_type (lhs);
low_index = TYPE_ARRAY_LOWER_BOUND_VALUE (lhs_type);
high_index = TYPE_ARRAY_UPPER_BOUND_VALUE (lhs_type);
- is_array_aggregate = 1;
}
else if (TYPE_CODE (lhs_type) == TYPE_CODE_STRUCT)
{
low_index = 0;
high_index = num_visible_fields (lhs_type) - 1;
- is_array_aggregate = 0;
}
else
error (_("Left-hand side must be array or record."));
default:
*pos -= 1;
arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
- arg1 = unwrap_value (arg1);
+
+ if (noside == EVAL_NORMAL)
+ arg1 = unwrap_value (arg1);
/* If evaluating an OP_DOUBLE and an EXPECT_TYPE was provided,
then we need to perform the conversion manually, because
a fixed type would result in the loss of that type name,
thus preventing us from printing the name of the ancestor
type in the type description. */
- struct type *actual_type;
-
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
- actual_type = type_from_tag (ada_value_tag (arg1));
- if (actual_type == NULL)
- /* If, for some reason, we were unable to determine
- the actual type from the tag, then use the static
- approximation that we just computed as a fallback.
- This can happen if the debugging information is
- incomplete, for instance. */
- actual_type = type;
-
- return value_zero (actual_type, not_lval);
+
+ if (TYPE_CODE (type) != TYPE_CODE_REF)
+ {
+ struct type *actual_type;
+
+ actual_type = type_from_tag (ada_value_tag (arg1));
+ if (actual_type == NULL)
+ /* If, for some reason, we were unable to determine
+ the actual type from the tag, then use the static
+ approximation that we just computed as a fallback.
+ This can happen if the debugging information is
+ incomplete, for instance. */
+ actual_type = type;
+ return value_zero (actual_type, not_lval);
+ }
+ else
+ {
+ /* In the case of a ref, ada_coerce_ref takes care
+ of determining the actual type. But the evaluation
+ should return a ref as it should be valid to ask
+ for its address; so rebuild a ref after coerce. */
+ arg1 = ada_coerce_ref (arg1);
+ return value_ref (arg1);
+ }
}
*pos += 4;
else
{
arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
- arg1 = unwrap_value (arg1);
return ada_to_fixed_value (arg1);
}
{
case TYPE_CODE_FUNC:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return allocate_value (TYPE_TARGET_TYPE (type));
+ {
+ struct type *rtype = TYPE_TARGET_TYPE (type);
+
+ if (TYPE_GNU_IFUNC (type))
+ return allocate_value (TYPE_TARGET_TYPE (rtype));
+ return allocate_value (rtype);
+ }
return call_function_by_hand (argvec[0], nargs, argvec + 1);
+ case TYPE_CODE_INTERNAL_FUNCTION:
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ /* We don't know anything about what the internal
+ function might return, but we have to return
+ something. */
+ return value_zero (builtin_type (exp->gdbarch)->builtin_int,
+ not_lval);
+ else
+ return call_internal_function (exp->gdbarch, exp->language_defn,
+ argvec[0], nargs, argvec + 1);
+
case TYPE_CODE_STRUCT:
{
int arity;
int nsyms;
nsyms = ada_lookup_symbol_list (name, get_selected_block (0), VAR_DOMAIN,
- &syms, 1);
+ &syms);
if (nsyms != 1)
{
&& TYPE_UNSIGNED (subranged_type));
}
-/* Try to determine the lower and upper bounds of the given modular type
- using the type name only. Return non-zero and set L and U as the lower
- and upper bounds (respectively) if successful. */
-
-int
-ada_modulus_from_name (struct type *type, ULONGEST *modulus)
-{
- const char *name = ada_type_name (type);
- const char *suffix;
- int k;
- LONGEST U;
-
- if (name == NULL)
- return 0;
-
- /* Discrete type bounds are encoded using an __XD suffix. In our case,
- we are looking for static bounds, which means an __XDLU suffix.
- Moreover, we know that the lower bound of modular types is always
- zero, so the actual suffix should start with "__XDLU_0__", and
- then be followed by the upper bound value. */
- suffix = strstr (name, "__XDLU_0__");
- if (suffix == NULL)
- return 0;
- k = 10;
- if (!ada_scan_number (suffix, k, &U, NULL))
- return 0;
-
- *modulus = (ULONGEST) U + 1;
- return 1;
-}
-
/* Assuming ada_is_modular_type (TYPE), the modulus of TYPE. */
ULONGEST
variants of the runtime, we use a sniffer that will determine
the runtime variant used by the program being debugged. */
-/* The different types of catchpoints that we introduced for catching
- Ada exceptions. */
-
-enum exception_catchpoint_kind
-{
- ex_catch_exception,
- ex_catch_exception_unhandled,
- ex_catch_assert
-};
-
/* Ada's standard exceptions. */
static char *standard_exc[] = {
the name of the exception being raised (this name is printed in
the catchpoint message, and is also used when trying to catch
a specific exception). We do not handle this case for now. */
- if (lookup_minimal_symbol (einfo->catch_exception_sym, NULL, NULL))
+ struct minimal_symbol *msym
+ = lookup_minimal_symbol (einfo->catch_exception_sym, NULL, NULL);
+
+ if (msym && MSYMBOL_TYPE (msym) != mst_solib_trampoline)
error (_("Your Ada runtime appears to be missing some debugging "
"information.\nCannot insert Ada exception catchpoint "
"in this configuration."));
ada_exception_support_info_sniffer (void)
{
struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ());
- struct symbol *sym;
/* If the exception info is already known, then no need to recompute it. */
if (data->exception_info != NULL)
is_known_support_routine (struct frame_info *frame)
{
struct symtab_and_line sal;
- const char *func_name;
+ char *func_name;
enum language func_lang;
int i;
+ const char *fullname;
/* If this code does not have any debugging information (no symtab),
This cannot be any user code. */
for the user. This should also take care of case such as VxWorks
where the kernel has some debugging info provided for a few units. */
- if (symtab_to_fullname (sal.symtab) == NULL)
+ fullname = symtab_to_fullname (sal.symtab);
+ if (access (fullname, R_OK) != 0)
return 1;
/* Check the unit filename againt the Ada runtime file naming.
for (i = 0; known_runtime_file_name_patterns[i] != NULL; i += 1)
{
re_comp (known_runtime_file_name_patterns[i]);
- if (re_exec (sal.symtab->filename))
+ if (re_exec (lbasename (sal.symtab->filename)))
return 1;
if (sal.symtab->objfile != NULL
- && re_exec (sal.symtab->objfile->name))
+ && re_exec (objfile_name (sal.symtab->objfile)))
return 1;
}
{
re_comp (known_auxiliary_function_name_patterns[i]);
if (re_exec (func_name))
- return 1;
+ {
+ xfree (func_name);
+ return 1;
+ }
}
+ xfree (func_name);
return 0;
}
int frame_level;
struct frame_info *fi;
struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ());
+ struct cleanup *old_chain;
/* To determine the name of this exception, we need to select
the frame corresponding to RAISE_SYM_NAME. This frame is
if (fi != NULL)
fi = get_prev_frame (fi);
+ old_chain = make_cleanup (null_cleanup, NULL);
while (fi != NULL)
{
- const char *func_name;
+ char *func_name;
enum language func_lang;
find_frame_funname (fi, &func_name, &func_lang, NULL);
- if (func_name != NULL
- && strcmp (func_name, data->exception_info->catch_exception_sym) == 0)
- break; /* We found the frame we were looking for... */
- fi = get_prev_frame (fi);
+ if (func_name != NULL)
+ {
+ make_cleanup (xfree, func_name);
+
+ if (strcmp (func_name,
+ data->exception_info->catch_exception_sym) == 0)
+ break; /* We found the frame we were looking for... */
+ fi = get_prev_frame (fi);
+ }
}
+ do_cleanups (old_chain);
if (fi == NULL)
return 0;
Return zero if the address could not be computed, or if not relevant. */
static CORE_ADDR
-ada_exception_name_addr_1 (enum exception_catchpoint_kind ex,
+ada_exception_name_addr_1 (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b)
{
struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ());
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
return (parse_and_eval_address ("e.full_name"));
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
return data->exception_info->unhandled_exception_name_addr ();
break;
- case ex_catch_assert:
+ case ada_catch_assert:
return 0; /* Exception name is not relevant in this case. */
break;
and zero is returned. */
static CORE_ADDR
-ada_exception_name_addr (enum exception_catchpoint_kind ex,
+ada_exception_name_addr (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b)
{
volatile struct gdb_exception e;
return result;
}
-static struct symtab_and_line ada_exception_sal (enum exception_catchpoint_kind,
- char *, char **,
- const struct breakpoint_ops **);
static char *ada_exception_catchpoint_cond_string (const char *excep_string);
/* Ada catchpoints.
if (!bl->shlib_disabled)
{
volatile struct gdb_exception e;
- char *s;
+ const char *s;
s = cond_string;
TRY_CATCH (e, RETURN_MASK_ERROR)
{
- exp = parse_exp_1 (&s, block_for_pc (bl->address), 0);
+ exp = parse_exp_1 (&s, bl->address,
+ block_for_pc (bl->address), 0);
}
if (e.reason < 0)
- warning (_("failed to reevaluate internal exception condition "
- "for catchpoint %d: %s"),
- c->base.number, e.message);
+ {
+ warning (_("failed to reevaluate internal exception condition "
+ "for catchpoint %d: %s"),
+ c->base.number, e.message);
+ /* There is a bug in GCC on sparc-solaris when building with
+ optimization which causes EXP to change unexpectedly
+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56982).
+ The problem should be fixed starting with GCC 4.9.
+ In the meantime, work around it by forcing EXP back
+ to NULL. */
+ exp = NULL;
+ }
}
ada_loc->excep_cond_expr = exp;
exception catchpoint kinds. */
static void
-dtor_exception (enum exception_catchpoint_kind ex, struct breakpoint *b)
+dtor_exception (enum ada_exception_catchpoint_kind ex, struct breakpoint *b)
{
struct ada_catchpoint *c = (struct ada_catchpoint *) b;
structure for all exception catchpoint kinds. */
static struct bp_location *
-allocate_location_exception (enum exception_catchpoint_kind ex,
+allocate_location_exception (enum ada_exception_catchpoint_kind ex,
struct breakpoint *self)
{
struct ada_catchpoint_location *loc;
exception catchpoint kinds. */
static void
-re_set_exception (enum exception_catchpoint_kind ex, struct breakpoint *b)
+re_set_exception (enum ada_exception_catchpoint_kind ex, struct breakpoint *b)
{
struct ada_catchpoint *c = (struct ada_catchpoint *) b;
for all exception catchpoint kinds. */
static void
-check_status_exception (enum exception_catchpoint_kind ex, bpstat bs)
+check_status_exception (enum ada_exception_catchpoint_kind ex, bpstat bs)
{
bs->stop = should_stop_exception (bs->bp_location_at);
}
for all exception catchpoint kinds. */
static enum print_stop_action
-print_it_exception (enum exception_catchpoint_kind ex, bpstat bs)
+print_it_exception (enum ada_exception_catchpoint_kind ex, bpstat bs)
{
struct ui_out *uiout = current_uiout;
struct breakpoint *b = bs->breakpoint_at;
switch (ex)
{
- case ex_catch_exception:
- case ex_catch_exception_unhandled:
+ case ada_catch_exception:
+ case ada_catch_exception_unhandled:
{
const CORE_ADDR addr = ada_exception_name_addr (ex, b);
char exception_name[256];
if (addr != 0)
{
- read_memory (addr, exception_name, sizeof (exception_name) - 1);
+ read_memory (addr, (gdb_byte *) exception_name,
+ sizeof (exception_name) - 1);
exception_name [sizeof (exception_name) - 1] = '\0';
}
else
it clearer to the user which kind of catchpoint just got
hit. We used ui_out_text to make sure that this extra
info does not pollute the exception name in the MI case. */
- if (ex == ex_catch_exception_unhandled)
+ if (ex == ada_catch_exception_unhandled)
ui_out_text (uiout, "unhandled ");
ui_out_field_string (uiout, "exception-name", exception_name);
}
break;
- case ex_catch_assert:
+ case ada_catch_assert:
/* In this case, the name of the exception is not really
important. Just print "failed assertion" to make it clearer
that his program just hit an assertion-failure catchpoint.
for all exception catchpoint kinds. */
static void
-print_one_exception (enum exception_catchpoint_kind ex,
+print_one_exception (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b, struct bp_location **last_loc)
{
struct ui_out *uiout = current_uiout;
*last_loc = b->loc;
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
if (c->excep_string != NULL)
{
char *msg = xstrprintf (_("`%s' Ada exception"), c->excep_string);
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
ui_out_field_string (uiout, "what", "unhandled Ada exceptions");
break;
- case ex_catch_assert:
+ case ada_catch_assert:
ui_out_field_string (uiout, "what", "failed Ada assertions");
break;
for all exception catchpoint kinds. */
static void
-print_mention_exception (enum exception_catchpoint_kind ex,
+print_mention_exception (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b)
{
struct ada_catchpoint *c = (struct ada_catchpoint *) b;
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
if (c->excep_string != NULL)
{
char *info = xstrprintf (_("`%s' Ada exception"), c->excep_string);
ui_out_text (uiout, _("all Ada exceptions"));
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
ui_out_text (uiout, _("unhandled Ada exceptions"));
break;
- case ex_catch_assert:
+ case ada_catch_assert:
ui_out_text (uiout, _("failed Ada assertions"));
break;
for all exception catchpoint kinds. */
static void
-print_recreate_exception (enum exception_catchpoint_kind ex,
+print_recreate_exception (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b, struct ui_file *fp)
{
struct ada_catchpoint *c = (struct ada_catchpoint *) b;
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
fprintf_filtered (fp, "catch exception");
if (c->excep_string != NULL)
fprintf_filtered (fp, " %s", c->excep_string);
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
fprintf_filtered (fp, "catch exception unhandled");
break;
- case ex_catch_assert:
+ case ada_catch_assert:
fprintf_filtered (fp, "catch assert");
break;
static void
dtor_catch_exception (struct breakpoint *b)
{
- dtor_exception (ex_catch_exception, b);
+ dtor_exception (ada_catch_exception, b);
}
static struct bp_location *
allocate_location_catch_exception (struct breakpoint *self)
{
- return allocate_location_exception (ex_catch_exception, self);
+ return allocate_location_exception (ada_catch_exception, self);
}
static void
re_set_catch_exception (struct breakpoint *b)
{
- re_set_exception (ex_catch_exception, b);
+ re_set_exception (ada_catch_exception, b);
}
static void
check_status_catch_exception (bpstat bs)
{
- check_status_exception (ex_catch_exception, bs);
+ check_status_exception (ada_catch_exception, bs);
}
static enum print_stop_action
print_it_catch_exception (bpstat bs)
{
- return print_it_exception (ex_catch_exception, bs);
+ return print_it_exception (ada_catch_exception, bs);
}
static void
print_one_catch_exception (struct breakpoint *b, struct bp_location **last_loc)
{
- print_one_exception (ex_catch_exception, b, last_loc);
+ print_one_exception (ada_catch_exception, b, last_loc);
}
static void
print_mention_catch_exception (struct breakpoint *b)
{
- print_mention_exception (ex_catch_exception, b);
+ print_mention_exception (ada_catch_exception, b);
}
static void
print_recreate_catch_exception (struct breakpoint *b, struct ui_file *fp)
{
- print_recreate_exception (ex_catch_exception, b, fp);
+ print_recreate_exception (ada_catch_exception, b, fp);
}
static struct breakpoint_ops catch_exception_breakpoint_ops;
static void
dtor_catch_exception_unhandled (struct breakpoint *b)
{
- dtor_exception (ex_catch_exception_unhandled, b);
+ dtor_exception (ada_catch_exception_unhandled, b);
}
static struct bp_location *
allocate_location_catch_exception_unhandled (struct breakpoint *self)
{
- return allocate_location_exception (ex_catch_exception_unhandled, self);
+ return allocate_location_exception (ada_catch_exception_unhandled, self);
}
static void
re_set_catch_exception_unhandled (struct breakpoint *b)
{
- re_set_exception (ex_catch_exception_unhandled, b);
+ re_set_exception (ada_catch_exception_unhandled, b);
}
static void
check_status_catch_exception_unhandled (bpstat bs)
{
- check_status_exception (ex_catch_exception_unhandled, bs);
+ check_status_exception (ada_catch_exception_unhandled, bs);
}
static enum print_stop_action
print_it_catch_exception_unhandled (bpstat bs)
{
- return print_it_exception (ex_catch_exception_unhandled, bs);
+ return print_it_exception (ada_catch_exception_unhandled, bs);
}
static void
print_one_catch_exception_unhandled (struct breakpoint *b,
struct bp_location **last_loc)
{
- print_one_exception (ex_catch_exception_unhandled, b, last_loc);
+ print_one_exception (ada_catch_exception_unhandled, b, last_loc);
}
static void
print_mention_catch_exception_unhandled (struct breakpoint *b)
{
- print_mention_exception (ex_catch_exception_unhandled, b);
+ print_mention_exception (ada_catch_exception_unhandled, b);
}
static void
print_recreate_catch_exception_unhandled (struct breakpoint *b,
struct ui_file *fp)
{
- print_recreate_exception (ex_catch_exception_unhandled, b, fp);
+ print_recreate_exception (ada_catch_exception_unhandled, b, fp);
}
static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops;
static void
dtor_catch_assert (struct breakpoint *b)
{
- dtor_exception (ex_catch_assert, b);
+ dtor_exception (ada_catch_assert, b);
}
static struct bp_location *
allocate_location_catch_assert (struct breakpoint *self)
{
- return allocate_location_exception (ex_catch_assert, self);
+ return allocate_location_exception (ada_catch_assert, self);
}
static void
re_set_catch_assert (struct breakpoint *b)
{
- return re_set_exception (ex_catch_assert, b);
+ re_set_exception (ada_catch_assert, b);
}
static void
check_status_catch_assert (bpstat bs)
{
- check_status_exception (ex_catch_assert, bs);
+ check_status_exception (ada_catch_assert, bs);
}
static enum print_stop_action
print_it_catch_assert (bpstat bs)
{
- return print_it_exception (ex_catch_assert, bs);
+ return print_it_exception (ada_catch_assert, bs);
}
static void
print_one_catch_assert (struct breakpoint *b, struct bp_location **last_loc)
{
- print_one_exception (ex_catch_assert, b, last_loc);
+ print_one_exception (ada_catch_assert, b, last_loc);
}
static void
print_mention_catch_assert (struct breakpoint *b)
{
- print_mention_exception (ex_catch_assert, b);
+ print_mention_exception (ada_catch_assert, b);
}
static void
print_recreate_catch_assert (struct breakpoint *b, struct ui_file *fp)
{
- print_recreate_exception (ex_catch_assert, b, fp);
+ print_recreate_exception (ada_catch_assert, b, fp);
}
static struct breakpoint_ops catch_assert_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. */
+ specified by the user.
+ 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 (char *args,
- enum exception_catchpoint_kind *ex,
- char **excep_string)
+ enum ada_exception_catchpoint_kind *ex,
+ char **excep_string,
+ char **cond_string)
{
struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
char *exception_name;
+ char *cond = NULL;
exception_name = ada_get_next_arg (&args);
+ if (exception_name != NULL && strcmp (exception_name, "if") == 0)
+ {
+ /* 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;
+ args -= 2;
+ }
make_cleanup (xfree, exception_name);
- /* Check that we do not have any more arguments. Anything else
- is unexpected. */
+ /* Check to see if we have a condition. */
args = skip_spaces (args);
+ if (strncmp (args, "if", 2) == 0
+ && (isspace (args[2]) || args[2] == '\0'))
+ {
+ args += 2;
+ args = skip_spaces (args);
+
+ if (args[0] == '\0')
+ error (_("Condition missing after `if' keyword"));
+ cond = xstrdup (args);
+ make_cleanup (xfree, cond);
+
+ args += strlen (args);
+ }
+
+ /* Check that we do not have any more arguments. Anything else
+ is unexpected. */
if (args[0] != '\0')
error (_("Junk at end of expression"));
if (exception_name == NULL)
{
/* Catch all exceptions. */
- *ex = ex_catch_exception;
+ *ex = ada_catch_exception;
*excep_string = NULL;
}
else if (strcmp (exception_name, "unhandled") == 0)
{
/* Catch unhandled exceptions. */
- *ex = ex_catch_exception_unhandled;
+ *ex = ada_catch_exception_unhandled;
*excep_string = NULL;
}
else
{
/* Catch a specific exception. */
- *ex = ex_catch_exception;
+ *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
implement a catchpoint of the EX kind. */
static const char *
-ada_exception_sym_name (enum exception_catchpoint_kind ex)
+ada_exception_sym_name (enum ada_exception_catchpoint_kind ex)
{
struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ());
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
return (data->exception_info->catch_exception_sym);
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
return (data->exception_info->catch_exception_unhandled_sym);
break;
- case ex_catch_assert:
+ case ada_catch_assert:
return (data->exception_info->catch_assert_sym);
break;
default:
of the EX kind. */
static const struct breakpoint_ops *
-ada_exception_breakpoint_ops (enum exception_catchpoint_kind ex)
+ada_exception_breakpoint_ops (enum ada_exception_catchpoint_kind ex)
{
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
return (&catch_exception_breakpoint_ops);
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
return (&catch_exception_unhandled_breakpoint_ops);
break;
- case ex_catch_assert:
+ case ada_catch_assert:
return (&catch_assert_breakpoint_ops);
break;
default:
type of catchpoint we need to create. */
static struct symtab_and_line
-ada_exception_sal (enum exception_catchpoint_kind ex, char *excep_string,
+ada_exception_sal (enum ada_exception_catchpoint_kind ex, char *excep_string,
char **addr_string, const struct breakpoint_ops **ops)
{
const char *sym_name;
return find_function_start_sal (sym, 1);
}
-/* Parse the arguments (ARGS) of the "catch exception" command.
-
- If the user asked the catchpoint to catch only a specific
- exception, then save the exception name in ADDR_STRING.
+/* Create an Ada exception catchpoint.
- See ada_exception_sal for a description of all the remaining
- function arguments of this function. */
+ EX_KIND is the kind of exception catchpoint to be created.
-static struct symtab_and_line
-ada_decode_exception_location (char *args, char **addr_string,
- char **excep_string,
- const struct breakpoint_ops **ops)
-{
- enum exception_catchpoint_kind ex;
+ If EXCEPT_STRING is NULL, 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.
- catch_ada_exception_command_split (args, &ex, excep_string);
- return ada_exception_sal (ex, *excep_string, addr_string, ops);
-}
+ 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.
-/* Create an Ada exception catchpoint. */
+ TEMPFLAG, if nonzero, means that the underlying breakpoint
+ should be temporary.
-static void
+ FROM_TTY is the usual argument passed to all commands implementations. */
+
+void
create_ada_exception_catchpoint (struct gdbarch *gdbarch,
- struct symtab_and_line sal,
- char *addr_string,
+ enum ada_exception_catchpoint_kind ex_kind,
char *excep_string,
- const struct breakpoint_ops *ops,
+ char *cond_string,
int tempflag,
+ int disabled,
int from_tty)
{
struct ada_catchpoint *c;
+ 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);
c = XNEW (struct ada_catchpoint);
init_ada_exception_breakpoint (&c->base, gdbarch, sal, addr_string,
- ops, tempflag, from_tty);
+ ops, tempflag, disabled, from_tty);
c->excep_string = excep_string;
create_excep_cond_exprs (c);
+ if (cond_string != NULL)
+ set_breakpoint_condition (&c->base, cond_string, from_tty);
install_breakpoint (0, &c->base, 1);
}
{
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
- struct symtab_and_line sal;
- char *addr_string = NULL;
+ enum ada_exception_catchpoint_kind ex_kind;
char *excep_string = NULL;
- const struct breakpoint_ops *ops = NULL;
+ char *cond_string = NULL;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
if (!arg)
arg = "";
- sal = ada_decode_exception_location (arg, &addr_string, &excep_string, &ops);
- create_ada_exception_catchpoint (gdbarch, sal, addr_string,
- excep_string, ops, tempflag, from_tty);
+ catch_ada_exception_command_split (arg, &ex_kind, &excep_string,
+ &cond_string);
+ create_ada_exception_catchpoint (gdbarch, ex_kind,
+ excep_string, cond_string,
+ tempflag, 1 /* enabled */,
+ from_tty);
}
-static struct symtab_and_line
-ada_decode_assert_location (char *args, char **addr_string,
- const struct breakpoint_ops **ops)
+/* Split the arguments specified in a "catch assert" command.
+
+ ARGS contains the command's arguments (or the empty string if
+ no arguments were passed).
+
+ If ARGS contains a condition, set COND_STRING to that condition
+ (the memory needs to be deallocated after use). */
+
+static void
+catch_ada_assert_command_split (char *args, char **cond_string)
{
- /* Check that no argument where provided at the end of the command. */
+ args = skip_spaces (args);
- if (args != NULL)
+ /* Check whether a condition was provided. */
+ if (strncmp (args, "if", 2) == 0
+ && (isspace (args[2]) || args[2] == '\0'))
{
+ args += 2;
args = skip_spaces (args);
- if (*args != '\0')
- error (_("Junk at end of arguments."));
+ if (args[0] == '\0')
+ error (_("condition missing after `if' keyword"));
+ *cond_string = xstrdup (args);
}
- return ada_exception_sal (ex_catch_assert, NULL, addr_string, ops);
+ /* Otherwise, there should be no other argument at the end of
+ the command. */
+ else if (args[0] != '\0')
+ error (_("Junk at end of arguments."));
}
/* Implement the "catch assert" command. */
{
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
- struct symtab_and_line sal;
- char *addr_string = NULL;
- const struct breakpoint_ops *ops = NULL;
+ char *cond_string = NULL;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
if (!arg)
arg = "";
- sal = ada_decode_assert_location (arg, &addr_string, &ops);
- create_ada_exception_catchpoint (gdbarch, sal, addr_string,
- NULL, ops, tempflag, from_tty);
+ catch_ada_assert_command_split (arg, &cond_string);
+ create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
+ NULL, cond_string,
+ tempflag, 1 /* enabled */,
+ from_tty);
+}
+
+/* Return non-zero if the symbol SYM is an Ada exception object. */
+
+static int
+ada_is_exception_sym (struct symbol *sym)
+{
+ const char *type_name = type_name_no_tag (SYMBOL_TYPE (sym));
+
+ return (SYMBOL_CLASS (sym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (sym) != LOC_BLOCK
+ && SYMBOL_CLASS (sym) != LOC_CONST
+ && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
+ && type_name != NULL && strcmp (type_name, "exception") == 0);
}
+
+/* Given a global symbol SYM, return non-zero iff SYM is a non-standard
+ Ada exception object. This matches all exceptions except the ones
+ defined by the Ada language. */
+
+static int
+ada_is_non_standard_exception_sym (struct symbol *sym)
+{
+ int i;
+
+ if (!ada_is_exception_sym (sym))
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE (standard_exc); i++)
+ if (strcmp (SYMBOL_LINKAGE_NAME (sym), standard_exc[i]) == 0)
+ return 0; /* A standard exception. */
+
+ /* Numeric_Error is also a standard exception, so exclude it.
+ See the STANDARD_EXC description for more details as to why
+ this exception is not listed in that array. */
+ if (strcmp (SYMBOL_LINKAGE_NAME (sym), "numeric_error") == 0)
+ return 0;
+
+ return 1;
+}
+
+/* A helper function for qsort, comparing two struct ada_exc_info
+ objects.
+
+ The comparison is determined first by exception name, and then
+ by exception address. */
+
+static int
+compare_ada_exception_info (const void *a, const void *b)
+{
+ const struct ada_exc_info *exc_a = (struct ada_exc_info *) a;
+ const struct ada_exc_info *exc_b = (struct ada_exc_info *) b;
+ int result;
+
+ result = strcmp (exc_a->name, exc_b->name);
+ if (result != 0)
+ return result;
+
+ if (exc_a->addr < exc_b->addr)
+ return -1;
+ if (exc_a->addr > exc_b->addr)
+ return 1;
+
+ return 0;
+}
+
+/* Sort EXCEPTIONS using compare_ada_exception_info as the comparison
+ routine, but keeping the first SKIP elements untouched.
+
+ All duplicates are also removed. */
+
+static void
+sort_remove_dups_ada_exceptions_list (VEC(ada_exc_info) **exceptions,
+ int skip)
+{
+ struct ada_exc_info *to_sort
+ = VEC_address (ada_exc_info, *exceptions) + skip;
+ int to_sort_len
+ = VEC_length (ada_exc_info, *exceptions) - skip;
+ int i, j;
+
+ qsort (to_sort, to_sort_len, sizeof (struct ada_exc_info),
+ compare_ada_exception_info);
+
+ for (i = 1, j = 1; i < to_sort_len; i++)
+ if (compare_ada_exception_info (&to_sort[i], &to_sort[j - 1]) != 0)
+ to_sort[j++] = to_sort[i];
+ to_sort_len = j;
+ VEC_truncate(ada_exc_info, *exceptions, skip + to_sort_len);
+}
+
+/* A function intended as the "name_matcher" callback in the struct
+ quick_symbol_functions' expand_symtabs_matching method.
+
+ SEARCH_NAME is the symbol's search name.
+
+ If USER_DATA is not NULL, it is a pointer to a regext_t object
+ used to match the symbol (by natural name). Otherwise, when USER_DATA
+ is null, no filtering is performed, and all symbols are a positive
+ match. */
+
+static int
+ada_exc_search_name_matches (const char *search_name, void *user_data)
+{
+ regex_t *preg = user_data;
+
+ if (preg == NULL)
+ return 1;
+
+ /* 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. */
+ return (regexec (preg, ada_decode (search_name), 0, NULL, 0) == 0);
+}
+
+/* Add all exceptions defined by the Ada standard whose name match
+ a regular expression.
+
+ If PREG is not NULL, then this regexp_t object is used to
+ perform the symbol name matching. Otherwise, no name-based
+ filtering is performed.
+
+ EXCEPTIONS is a vector of exceptions to which matching exceptions
+ gets pushed. */
+
+static void
+ada_add_standard_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE (standard_exc); i++)
+ {
+ if (preg == NULL
+ || regexec (preg, standard_exc[i], 0, NULL, 0) == 0)
+ {
+ struct bound_minimal_symbol msymbol
+ = ada_lookup_simple_minsym (standard_exc[i]);
+
+ if (msymbol.minsym != NULL)
+ {
+ struct ada_exc_info info
+ = {standard_exc[i], SYMBOL_VALUE_ADDRESS (msymbol.minsym)};
+
+ VEC_safe_push (ada_exc_info, *exceptions, &info);
+ }
+ }
+ }
+}
+
+/* Add all Ada exceptions defined locally and accessible from the given
+ FRAME.
+
+ If PREG is not NULL, then this regexp_t object is used to
+ perform the symbol name matching. Otherwise, no name-based
+ filtering is performed.
+
+ EXCEPTIONS is a vector of exceptions to which matching exceptions
+ gets pushed. */
+
+static void
+ada_add_exceptions_from_frame (regex_t *preg, struct frame_info *frame,
+ VEC(ada_exc_info) **exceptions)
+{
+ struct block *block = get_frame_block (frame, 0);
+
+ while (block != 0)
+ {
+ struct block_iterator iter;
+ struct symbol *sym;
+
+ ALL_BLOCK_SYMBOLS (block, iter, sym)
+ {
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_TYPEDEF:
+ case LOC_BLOCK:
+ case LOC_CONST:
+ break;
+ default:
+ if (ada_is_exception_sym (sym))
+ {
+ struct ada_exc_info info = {SYMBOL_PRINT_NAME (sym),
+ SYMBOL_VALUE_ADDRESS (sym)};
+
+ VEC_safe_push (ada_exc_info, *exceptions, &info);
+ }
+ }
+ }
+ if (BLOCK_FUNCTION (block) != NULL)
+ break;
+ block = BLOCK_SUPERBLOCK (block);
+ }
+}
+
+/* Add all exceptions defined globally whose name name match
+ a regular expression, excluding standard exceptions.
+
+ The reason we exclude standard exceptions is that they need
+ to be handled separately: Standard exceptions are defined inside
+ a runtime unit which is normally not compiled with debugging info,
+ and thus usually do not show up in our symbol search. However,
+ if the unit was in fact built with debugging info, we need to
+ exclude them because they would duplicate the entry we found
+ during the special loop that specifically searches for those
+ standard exceptions.
+
+ If PREG is not NULL, then this regexp_t object is used to
+ perform the symbol name matching. Otherwise, no name-based
+ filtering is performed.
+
+ EXCEPTIONS is a vector of exceptions to which matching exceptions
+ gets pushed. */
+
+static void
+ada_add_global_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
+{
+ struct objfile *objfile;
+ struct symtab *s;
+
+ ALL_OBJFILES (objfile)
+ if (objfile->sf)
+ objfile->sf->qf->expand_symtabs_matching
+ (objfile, NULL, ada_exc_search_name_matches,
+ VARIABLES_DOMAIN, preg);
+
+ ALL_PRIMARY_SYMTABS (objfile, s)
+ {
+ struct blockvector *bv = BLOCKVECTOR (s);
+ int i;
+
+ for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+ {
+ struct block *b = BLOCKVECTOR_BLOCK (bv, i);
+ struct block_iterator iter;
+ struct symbol *sym;
+
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ if (ada_is_non_standard_exception_sym (sym)
+ && (preg == NULL
+ || regexec (preg, SYMBOL_NATURAL_NAME (sym),
+ 0, NULL, 0) == 0))
+ {
+ struct ada_exc_info info
+ = {SYMBOL_PRINT_NAME (sym), SYMBOL_VALUE_ADDRESS (sym)};
+
+ VEC_safe_push (ada_exc_info, *exceptions, &info);
+ }
+ }
+ }
+}
+
+/* Implements ada_exceptions_list with the regular expression passed
+ as a regex_t, rather than a string.
+
+ If not NULL, PREG is used to filter out exceptions whose names
+ do not match. Otherwise, all exceptions are listed. */
+
+static VEC(ada_exc_info) *
+ada_exceptions_list_1 (regex_t *preg)
+{
+ VEC(ada_exc_info) *result = NULL;
+ struct cleanup *old_chain
+ = make_cleanup (VEC_cleanup (ada_exc_info), &result);
+ int prev_len;
+
+ /* First, list the known standard exceptions. These exceptions
+ need to be handled separately, as they are usually defined in
+ runtime units that have been compiled without debugging info. */
+
+ ada_add_standard_exceptions (preg, &result);
+
+ /* Next, find all exceptions whose scope is local and accessible
+ from the currently selected frame. */
+
+ if (has_stack_frames ())
+ {
+ prev_len = VEC_length (ada_exc_info, result);
+ ada_add_exceptions_from_frame (preg, get_selected_frame (NULL),
+ &result);
+ if (VEC_length (ada_exc_info, result) > prev_len)
+ sort_remove_dups_ada_exceptions_list (&result, prev_len);
+ }
+
+ /* Add all exceptions whose scope is global. */
+
+ prev_len = VEC_length (ada_exc_info, result);
+ ada_add_global_exceptions (preg, &result);
+ if (VEC_length (ada_exc_info, result) > prev_len)
+ sort_remove_dups_ada_exceptions_list (&result, prev_len);
+
+ discard_cleanups (old_chain);
+ return result;
+}
+
+/* Return a vector of ada_exc_info.
+
+ If REGEXP is NULL, all exceptions are included in the result.
+ Otherwise, it should contain a valid regular expression,
+ and only the exceptions whose names match that regular expression
+ are included in the result.
+
+ The exceptions are sorted in the following order:
+ - Standard exceptions (defined by the Ada language), in
+ alphabetical order;
+ - Exceptions only visible from the current frame, in
+ alphabetical order;
+ - Exceptions whose scope is global, in alphabetical order. */
+
+VEC(ada_exc_info) *
+ada_exceptions_list (const char *regexp)
+{
+ VEC(ada_exc_info) *result = NULL;
+ struct cleanup *old_chain = NULL;
+ regex_t reg;
+
+ if (regexp != NULL)
+ old_chain = compile_rx_or_error (®, regexp,
+ _("invalid regular expression"));
+
+ result = ada_exceptions_list_1 (regexp != NULL ? ® : NULL);
+
+ if (old_chain != NULL)
+ do_cleanups (old_chain);
+ return result;
+}
+
+/* Implement the "info exceptions" command. */
+
+static void
+info_exceptions_command (char *regexp, int from_tty)
+{
+ VEC(ada_exc_info) *exceptions;
+ struct cleanup *cleanup;
+ struct gdbarch *gdbarch = get_current_arch ();
+ int ix;
+ struct ada_exc_info *info;
+
+ exceptions = ada_exceptions_list (regexp);
+ cleanup = make_cleanup (VEC_cleanup (ada_exc_info), &exceptions);
+
+ if (regexp != NULL)
+ printf_filtered
+ (_("All Ada exceptions matching regular expression \"%s\":\n"), regexp);
+ else
+ printf_filtered (_("All defined Ada exceptions:\n"));
+
+ for (ix = 0; VEC_iterate(ada_exc_info, exceptions, ix, info); ix++)
+ printf_filtered ("%s: %s\n", info->name, paddress (gdbarch, info->addr));
+
+ do_cleanups (cleanup);
+}
+
/* Operators */
/* Information about operators given special treatment in functions
below. */
if (exp->elts[*pos].opcode == OP_TYPE)
{
if (TYPE_CODE (exp->elts[*pos + 1].type) != TYPE_CODE_VOID)
- LA_PRINT_TYPE (exp->elts[*pos + 1].type, "", stream, 0, 0);
+ LA_PRINT_TYPE (exp->elts[*pos + 1].type, "", stream, 0, 0,
+ &type_print_raw_options);
*pos += 3;
}
else
/* XXX: sprint_subexp */
print_subexp (exp, pos, stream, PREC_SUFFIX);
fputs_filtered (" in ", stream);
- LA_PRINT_TYPE (exp->elts[pc + 1].type, "", stream, 1, 0);
+ LA_PRINT_TYPE (exp->elts[pc + 1].type, "", stream, 1, 0,
+ &type_print_raw_options);
return;
case OP_DISCRETE_RANGE:
return compare_names;
}
+/* Implement the "la_read_var_value" language_defn method for Ada. */
+
+static struct value *
+ada_read_var_value (struct symbol *var, struct frame_info *frame)
+{
+ struct block *frame_block = NULL;
+ struct symbol *renaming_sym = NULL;
+
+ /* The only case where default_read_var_value is not sufficient
+ is when VAR is a renaming... */
+ if (frame)
+ frame_block = get_frame_block (frame, NULL);
+ if (frame_block)
+ renaming_sym = ada_find_renaming_symbol (var, frame_block);
+ if (renaming_sym != NULL)
+ return ada_read_renaming_var_value (renaming_sym, frame_block);
+
+ /* This is a typical case where we expect the default_read_var_value
+ function to work. */
+ return default_read_var_value (var, frame);
+}
+
const struct language_defn ada_language_defn = {
"ada", /* Language name */
+ "Ada",
language_ada,
range_check_off,
- type_check_off,
case_sensitive_on, /* Yes, Ada is case-insensitive, but
that's not quite what this means. */
array_row_major,
ada_print_typedef, /* Print a typedef using appropriate syntax */
ada_val_print, /* Print a value using appropriate syntax */
ada_value_print, /* Print a top-level value */
+ ada_read_var_value, /* la_read_var_value */
NULL, /* Language specific skip_trampoline */
NULL, /* name_of_this */
ada_lookup_symbol_nonlocal, /* Looking up non-local symbols. */
c_get_string,
ada_get_symbol_name_cmp, /* la_get_symbol_name_cmp */
ada_iterate_over_symbols,
+ &ada_varobj_ops,
LANG_MAGIC
};
varsize_limit = 65536;
+ add_info ("exceptions", info_exceptions_command,
+ _("\
+List all Ada exception names.\n\
+If a regular expression is passed as an argument, only those matching\n\
+the regular expression are listed."));
+
obstack_init (&symbol_list_obstack);
decoded_names_store = htab_create_alloc
/* Setup per-inferior data. */
observer_attach_inferior_exit (ada_inferior_exit);
ada_inferior_data
- = register_inferior_data_with_cleanup (ada_inferior_data_cleanup);
+ = register_inferior_data_with_cleanup (NULL, ada_inferior_data_cleanup);
}