Index: gdb/ada-lang.c |
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c |
index aa090af81bd7f04fde80c2c3fbd385830986b513..786ca7acd437672e07faa854d7faa4c959f52cdc 100644 |
--- a/gdb/ada-lang.c |
+++ b/gdb/ada-lang.c |
@@ -1,7 +1,6 @@ |
/* 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-2013 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -21,7 +20,7 @@ |
#include "defs.h" |
#include <stdio.h> |
-#include "gdb_string.h" |
+#include <string.h> |
#include <ctype.h> |
#include <stdarg.h> |
#include "demangle.h" |
@@ -33,6 +32,7 @@ |
#include "expression.h" |
#include "parser-defs.h" |
#include "language.h" |
+#include "varobj.h" |
#include "c-lang.h" |
#include "inferior.h" |
#include "symfile.h" |
@@ -43,7 +43,7 @@ |
#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 |
@@ -58,6 +58,7 @@ |
#include "vec.h" |
#include "stack.h" |
#include "gdb_vecs.h" |
+#include "typeprint.h" |
#include "psymtab.h" |
#include "value.h" |
@@ -127,7 +128,7 @@ static struct value *resolve_subexp (struct expression **, int *, int, |
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 **); |
@@ -149,7 +150,7 @@ static enum ada_renaming_category parse_old_style_renaming (struct type *, |
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 *); |
@@ -581,6 +582,7 @@ coerce_unspec_val_to_type (struct value *val, struct type *type) |
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; |
} |
} |
@@ -1295,29 +1297,29 @@ static struct htab *decoded_names_store; |
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); |
@@ -2324,7 +2326,6 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr, |
/* Also set the parent value. This is needed when trying to |
assign a new value (in inferior memory). */ |
set_value_parent (v, obj); |
- value_incref (obj); |
} |
else |
set_value_bitsize (v, bit_size); |
@@ -2517,7 +2518,7 @@ ada_value_assign (struct value *toval, struct value *fromval) |
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); |
@@ -3109,7 +3110,7 @@ resolve_subexp (struct expression **expp, int *pos, int deprocedure_p, |
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) |
{ |
@@ -3201,7 +3202,7 @@ resolve_subexp (struct expression **expp, int *pos, int deprocedure_p, |
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 |
@@ -3253,7 +3254,7 @@ resolve_subexp (struct expression **expp, int *pos, int deprocedure_p, |
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) |
@@ -3572,7 +3573,8 @@ See set/show multiple-symbol.")); |
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 |
@@ -3581,19 +3583,20 @@ See set/show multiple-symbol.")); |
(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)); |
} |
@@ -3603,7 +3606,7 @@ See set/show multiple-symbol.")); |
: _("[%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") |
@@ -3717,7 +3720,7 @@ get_selections (int *choices, int n_choices, int max_results, |
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). */ |
@@ -4053,15 +4056,14 @@ static struct value * |
ada_read_renaming_var_value (struct symbol *renaming_sym, |
struct block *block) |
{ |
- char *sym_name; |
+ const char *sym_name; |
struct expression *expr; |
struct value *value; |
struct cleanup *old_chain = NULL; |
- sym_name = xstrdup (SYMBOL_LINKAGE_NAME (renaming_sym)); |
- old_chain = make_cleanup (xfree, sym_name); |
+ sym_name = SYMBOL_LINKAGE_NAME (renaming_sym); |
expr = parse_exp_1 (&sym_name, 0, block, 0); |
- make_cleanup (free_current_contents, &expr); |
+ old_chain = make_cleanup (free_current_contents, &expr); |
value = evaluate_expression (expr); |
do_cleanups (old_chain); |
@@ -4230,7 +4232,7 @@ lookup_cached_symbol (const char *name, domain_enum namespace, |
static void |
cache_symbol (const char *name, domain_enum namespace, struct symbol *sym, |
- struct block *block) |
+ const struct block *block) |
{ |
} |
@@ -4404,18 +4406,22 @@ defns_collected (struct obstack *obstackp, int finish) |
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_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 |
the "standard__" prefix. This was primarily introduced in order |
@@ -4430,10 +4436,14 @@ ada_lookup_simple_minsym (const char *name) |
{ |
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 |
@@ -4725,17 +4735,20 @@ static int |
old_renaming_is_invisible (const struct symbol *sym, const char *function_name) |
{ |
char *scope; |
+ struct cleanup *old_chain; |
if (SYMBOL_CLASS (sym) != LOC_TYPEDEF) |
return 0; |
scope = xget_renaming_scope (SYMBOL_TYPE (sym)); |
- |
- 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. */ |
@@ -4747,7 +4760,12 @@ old_renaming_is_invisible (const struct symbol *sym, const char *function_name) |
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 |
@@ -4803,7 +4821,7 @@ remove_irrelevant_renamings (struct ada_symbol_info *syms, |
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; |
@@ -4965,23 +4983,37 @@ aux_add_nonlocal_symbols (struct block *block, struct symbol *sym, void *data0) |
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 '(': |
@@ -4999,10 +5031,43 @@ compare_names (const char *string1, const char *string2) |
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. */ |
@@ -5023,11 +5088,11 @@ add_nonlocal_symbols (struct obstack *obstackp, const char *name, |
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); |
} |
@@ -5040,8 +5105,8 @@ add_nonlocal_symbols (struct obstack *obstackp, const char *name, |
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); |
@@ -5049,26 +5114,28 @@ add_nonlocal_symbols (struct obstack *obstackp, const char *name, |
} |
} |
-/* Find symbols in DOMAIN matching NAME0, in BLOCK0 and enclosing |
- scope and in global scopes, returning the number of matches. |
+/* 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. |
+ 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; |
@@ -5104,10 +5171,24 @@ ada_lookup_symbol_list (const char *name0, const struct block *block0, |
/* 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_p); |
- 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 |
@@ -5150,6 +5231,37 @@ done: |
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. |
@@ -5175,25 +5287,6 @@ ada_name_for_lookup (const char *name) |
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; |
- |
- 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 as for ada_lookup_symbol_list with FULL_SEARCH set |
to 1, but choosing the first symbol found if there are multiple |
choices. |
@@ -5212,9 +5305,7 @@ ada_lookup_encoded_symbol (const char *name, const struct block *block, |
gdb_assert (info != NULL); |
memset (info, 0, sizeof (struct ada_symbol_info)); |
- n_candidates = ada_lookup_symbol_list (name, block, namespace, &candidates, |
- 1); |
- |
+ n_candidates = ada_lookup_symbol_list (name, block, namespace, &candidates); |
if (n_candidates == 0) |
return; |
@@ -5506,8 +5597,7 @@ full_match (const char *sym_name, const char *search_name) |
/* 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, |
@@ -5778,10 +5868,10 @@ symbol_completion_add (VEC(char_ptr) **sv, |
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; |
}; |
@@ -5800,7 +5890,8 @@ ada_expand_partial_symbol_name (const char *name, void *user_data) |
the entire command on which completion is made. */ |
static VEC (char_ptr) * |
-ada_make_symbol_completion_list (char *text0, char *word) |
+ada_make_symbol_completion_list (const char *text0, const char *word, |
+ enum type_code code) |
{ |
char *text; |
int text_len; |
@@ -5814,6 +5905,9 @@ ada_make_symbol_completion_list (char *text0, char *word) |
struct block *b, *surrounding_static_block = 0; |
int i; |
struct block_iterator iter; |
+ struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); |
+ |
+ gdb_assert (code == TYPE_CODE_UNDEF); |
if (text0[0] == '<') |
{ |
@@ -5912,6 +6006,7 @@ ada_make_symbol_completion_list (char *text0, char *word) |
} |
} |
+ do_cleanups (old_chain); |
return completions; |
} |
@@ -5935,6 +6030,19 @@ ada_is_dispatch_table_ptr_type (struct type *type) |
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. */ |
@@ -5965,9 +6073,11 @@ ada_is_ignored_field (struct type *type, int field_num) |
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. */ |
@@ -6007,6 +6117,15 @@ ada_tag_type (struct value *val) |
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 * |
@@ -6050,6 +6169,88 @@ type_from_tag (struct value *tag) |
return NULL; |
} |
+/* 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; |
+ CORE_ADDR base_address; |
+ |
+ obj_type = value_type (obj); |
+ |
+ /* It is the responsability of the caller to deref pointers. */ |
+ |
+ if (TYPE_CODE (obj_type) == TYPE_CODE_PTR |
+ || TYPE_CODE (obj_type) == TYPE_CODE_REF) |
+ return obj; |
+ |
+ tag = ada_value_tag (obj); |
+ if (!tag) |
+ return obj; |
+ |
+ /* 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. */ |
static struct type * |
@@ -6705,9 +6906,9 @@ ada_value_struct_elt (struct value *arg, char *name, int no_err) |
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, |
@@ -6983,6 +7184,9 @@ ada_value_ind (struct value *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); |
} |
@@ -6997,6 +7201,10 @@ ada_coerce_ref (struct value *val0) |
struct value *val = val0; |
val = coerce_ref (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 |
@@ -7080,7 +7288,7 @@ ada_find_any_type (const char *name) |
Return symbol if found, and NULL otherwise. */ |
struct symbol * |
-ada_find_renaming_symbol (struct symbol *name_sym, 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; |
@@ -7102,7 +7310,7 @@ ada_find_renaming_symbol (struct symbol *name_sym, struct block *block) |
} |
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; |
@@ -7503,25 +7711,35 @@ ada_template_to_fixed_record_type_1 (struct type *type, |
} |
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; |
@@ -7970,14 +8188,20 @@ ada_to_fixed_type_1 (struct type *type, const gdb_byte *valaddr, |
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. |
@@ -8618,6 +8842,72 @@ cast_from_fixed (struct type *type, struct value *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. */ |
@@ -8642,9 +8932,21 @@ coerce_for_assign (struct type *type, struct value *val) |
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); |
} |
@@ -8819,7 +9121,6 @@ assign_aggregate (struct value *container, |
int num_specs; |
LONGEST *indices; |
int max_indices, num_indices; |
- int is_array_aggregate; |
int i; |
*pos += 3; |
@@ -8844,13 +9145,11 @@ assign_aggregate (struct value *container, |
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.")); |
@@ -9363,7 +9662,9 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, |
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 |
@@ -9600,19 +9901,31 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, |
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; |
@@ -10469,7 +10782,7 @@ get_var_value (char *name, char *err_msg) |
int nsyms; |
nsyms = ada_lookup_symbol_list (name, get_selected_block (0), VAR_DOMAIN, |
- &syms, 1); |
+ &syms); |
if (nsyms != 1) |
{ |
@@ -10669,16 +10982,6 @@ ada_modulus (struct type *type) |
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[] = { |
@@ -10774,7 +11077,10 @@ ada_has_this_exception_support (const struct exception_support_info *einfo) |
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.")); |
@@ -10856,9 +11162,10 @@ static int |
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. */ |
@@ -10873,7 +11180,8 @@ is_known_support_routine (struct frame_info *frame) |
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. |
@@ -10884,10 +11192,10 @@ is_known_support_routine (struct frame_info *frame) |
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; |
} |
@@ -10901,9 +11209,13 @@ is_known_support_routine (struct frame_info *frame) |
{ |
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; |
} |
@@ -10947,6 +11259,7 @@ ada_unhandled_exception_name_addr_from_raise (void) |
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 |
@@ -10957,17 +11270,24 @@ ada_unhandled_exception_name_addr_from_raise (void) |
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; |
@@ -10983,22 +11303,22 @@ ada_unhandled_exception_name_addr_from_raise (void) |
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; |
@@ -11016,7 +11336,7 @@ ada_exception_name_addr_1 (enum exception_catchpoint_kind ex, |
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; |
@@ -11036,9 +11356,6 @@ ada_exception_name_addr (enum exception_catchpoint_kind ex, |
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. |
@@ -11135,7 +11452,7 @@ create_excep_cond_exprs (struct ada_catchpoint *c) |
if (!bl->shlib_disabled) |
{ |
volatile struct gdb_exception e; |
- char *s; |
+ const char *s; |
s = cond_string; |
TRY_CATCH (e, RETURN_MASK_ERROR) |
@@ -11144,9 +11461,18 @@ create_excep_cond_exprs (struct ada_catchpoint *c) |
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; |
@@ -11159,7 +11485,7 @@ create_excep_cond_exprs (struct ada_catchpoint *c) |
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; |
@@ -11172,7 +11498,7 @@ dtor_exception (enum exception_catchpoint_kind ex, struct breakpoint *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; |
@@ -11187,7 +11513,7 @@ allocate_location_exception (enum exception_catchpoint_kind ex, |
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; |
@@ -11243,7 +11569,7 @@ should_stop_exception (const struct bp_location *bl) |
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); |
} |
@@ -11252,7 +11578,7 @@ check_status_exception (enum exception_catchpoint_kind ex, bpstat bs) |
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; |
@@ -11274,15 +11600,16 @@ print_it_exception (enum exception_catchpoint_kind ex, bpstat bs) |
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 |
@@ -11300,12 +11627,12 @@ print_it_exception (enum exception_catchpoint_kind ex, bpstat bs) |
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. |
@@ -11324,7 +11651,7 @@ print_it_exception (enum exception_catchpoint_kind ex, bpstat bs) |
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; |
@@ -11342,7 +11669,7 @@ print_one_exception (enum exception_catchpoint_kind ex, |
*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); |
@@ -11355,11 +11682,11 @@ print_one_exception (enum exception_catchpoint_kind ex, |
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; |
@@ -11373,7 +11700,7 @@ print_one_exception (enum exception_catchpoint_kind ex, |
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; |
@@ -11386,7 +11713,7 @@ print_mention_exception (enum exception_catchpoint_kind ex, |
switch (ex) |
{ |
- case ex_catch_exception: |
+ case ada_catch_exception: |
if (c->excep_string != NULL) |
{ |
char *info = xstrprintf (_("`%s' Ada exception"), c->excep_string); |
@@ -11399,11 +11726,11 @@ print_mention_exception (enum exception_catchpoint_kind ex, |
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; |
@@ -11417,24 +11744,24 @@ print_mention_exception (enum exception_catchpoint_kind ex, |
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; |
@@ -11449,49 +11776,49 @@ print_recreate_exception (enum exception_catchpoint_kind ex, |
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; |
@@ -11501,51 +11828,51 @@ 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; |
@@ -11555,49 +11882,49 @@ 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; |
@@ -11646,7 +11973,7 @@ ada_get_next_arg (char **argsp) |
static void |
catch_ada_exception_command_split (char *args, |
- enum exception_catchpoint_kind *ex, |
+ enum ada_exception_catchpoint_kind *ex, |
char **excep_string, |
char **cond_string) |
{ |
@@ -11694,19 +12021,19 @@ catch_ada_exception_command_split (char *args, |
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; |
@@ -11716,7 +12043,7 @@ catch_ada_exception_command_split (char *args, |
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 ()); |
@@ -11724,13 +12051,13 @@ ada_exception_sym_name (enum exception_catchpoint_kind ex) |
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: |
@@ -11743,17 +12070,17 @@ ada_exception_sym_name (enum exception_catchpoint_kind ex) |
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: |
@@ -11816,7 +12143,7 @@ ada_exception_catchpoint_cond_string (const char *excep_string) |
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; |
@@ -11848,47 +12175,43 @@ ada_exception_sal (enum exception_catchpoint_kind ex, char *excep_string, |
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. |
- If the user provided a condition, then set COND_STRING to |
- that condition expression (the memory must be deallocated |
- after use). Otherwise, set COND_STRING to NULL. |
+ EX_KIND is the kind of exception catchpoint to be created. |
- See ada_exception_sal for a description of all the remaining |
- function arguments of this function. */ |
+ 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. |
-static struct symtab_and_line |
-ada_decode_exception_location (char *args, char **addr_string, |
- char **excep_string, |
- char **cond_string, |
- const struct breakpoint_ops **ops) |
-{ |
- enum exception_catchpoint_kind ex; |
+ 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. |
- catch_ada_exception_command_split (args, &ex, excep_string, cond_string); |
- return ada_exception_sal (ex, *excep_string, addr_string, ops); |
-} |
+ TEMPFLAG, if nonzero, means that the underlying breakpoint |
+ should be temporary. |
-/* Create an Ada exception catchpoint. */ |
+ FROM_TTY is the usual argument passed to all commands implementations. */ |
-static void |
+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, |
char *cond_string, |
- const struct breakpoint_ops *ops, |
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) |
@@ -11904,38 +12227,32 @@ catch_ada_exception_command (char *arg, int from_tty, |
{ |
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; |
char *cond_string = NULL; |
- const struct breakpoint_ops *ops = NULL; |
tempflag = get_cmd_context (command) == CATCH_TEMPORARY; |
if (!arg) |
arg = ""; |
- sal = ada_decode_exception_location (arg, &addr_string, &excep_string, |
- &cond_string, &ops); |
- create_ada_exception_catchpoint (gdbarch, sal, addr_string, |
- excep_string, cond_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); |
} |
-/* Assuming that ARGS contains the arguments of a "catch assert" |
- command, parse those arguments and return a symtab_and_line object |
- for a failed assertion catchpoint. |
+/* Split the arguments specified in a "catch assert" command. |
- Set ADDR_STRING to the name of the function where the real |
- breakpoint that implements the catchpoint is set. |
+ 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). Otherwise, set |
- COND_STRING to NULL. */ |
+ (the memory needs to be deallocated after use). */ |
-static struct symtab_and_line |
-ada_decode_assert_location (char *args, char **addr_string, |
- char **cond_string, |
- const struct breakpoint_ops **ops) |
+static void |
+catch_ada_assert_command_split (char *args, char **cond_string) |
{ |
args = skip_spaces (args); |
@@ -11954,8 +12271,6 @@ ada_decode_assert_location (char *args, char **addr_string, |
the command. */ |
else if (args[0] != '\0') |
error (_("Junk at end of arguments.")); |
- |
- return ada_exception_sal (ex_catch_assert, NULL, addr_string, ops); |
} |
/* Implement the "catch assert" command. */ |
@@ -11966,20 +12281,369 @@ catch_assert_command (char *arg, int from_tty, |
{ |
struct gdbarch *gdbarch = get_current_arch (); |
int tempflag; |
- struct symtab_and_line sal; |
- char *addr_string = NULL; |
char *cond_string = NULL; |
- const struct breakpoint_ops *ops = NULL; |
tempflag = get_cmd_context (command) == CATCH_TEMPORARY; |
if (!arg) |
arg = ""; |
- sal = ada_decode_assert_location (arg, &addr_string, &cond_string, &ops); |
- create_ada_exception_catchpoint (gdbarch, sal, addr_string, |
- NULL, cond_string, ops, tempflag, |
+ 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. */ |
@@ -12257,7 +12921,8 @@ ada_print_subexp (struct expression *exp, int *pos, |
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 |
@@ -12287,7 +12952,8 @@ ada_print_subexp (struct expression *exp, int *pos, |
/* 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: |
@@ -12497,9 +13163,9 @@ ada_read_var_value (struct symbol *var, struct frame_info *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, |
@@ -12534,6 +13200,7 @@ const struct language_defn ada_language_defn = { |
c_get_string, |
ada_get_symbol_name_cmp, /* la_get_symbol_name_cmp */ |
ada_iterate_over_symbols, |
+ &ada_varobj_ops, |
LANG_MAGIC |
}; |
@@ -12649,6 +13316,12 @@ With an argument, catch only exceptions with the given name."), |
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 |
@@ -12658,5 +13331,5 @@ With an argument, catch only exceptions with the given name."), |
/* 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); |
} |