/* Ada language support routines for GDB, the GNU debugger.
- Copyright (C) 1992-2018 Free Software Foundation, Inc.
+ Copyright (C) 1992-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "valprint.h"
#include "source.h"
#include "observable.h"
-#include "vec.h"
+#include "common/vec.h"
#include "stack.h"
-#include "gdb_vecs.h"
+#include "common/gdb_vecs.h"
#include "typeprint.h"
#include "namespace.h"
#include "common/function-view.h"
#include "common/byte-vector.h"
#include <algorithm>
+#include <map>
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C).
static struct block_symbol *defns_collected (struct obstack *, int);
static struct value *resolve_subexp (expression_up *, int *, int,
- struct type *);
+ struct type *, int,
+ innermost_block_tracker *);
static void replace_operator_with_call (expression_up *, int, int, int,
struct symbol *, const struct block *);
static struct value *value_subscript_packed (struct value *, int,
struct value **);
-static void move_bits (gdb_byte *, int, const gdb_byte *, int, int, int);
-
static struct value *coerce_unspec_val_to_type (struct value *,
struct type *);
static int ada_resolve_function (struct block_symbol *, int,
struct value **, int, const char *,
- struct type *);
+ struct type *, int);
static int ada_is_direct_array_type (struct type *);
return v;
}
-/* Move N bits from SOURCE, starting at bit offset SRC_OFFSET to
- TARGET, starting at bit offset TARG_OFFSET. SOURCE and TARGET must
- not overlap. */
-static void
-move_bits (gdb_byte *target, int targ_offset, const gdb_byte *source,
- int src_offset, int n, int bits_big_endian_p)
-{
- unsigned int accum, mask;
- int accum_bits, chunk_size;
-
- target += targ_offset / HOST_CHAR_BIT;
- targ_offset %= HOST_CHAR_BIT;
- source += src_offset / HOST_CHAR_BIT;
- src_offset %= HOST_CHAR_BIT;
- if (bits_big_endian_p)
- {
- accum = (unsigned char) *source;
- source += 1;
- accum_bits = HOST_CHAR_BIT - src_offset;
-
- while (n > 0)
- {
- int unused_right;
-
- accum = (accum << HOST_CHAR_BIT) + (unsigned char) *source;
- accum_bits += HOST_CHAR_BIT;
- source += 1;
- chunk_size = HOST_CHAR_BIT - targ_offset;
- if (chunk_size > n)
- chunk_size = n;
- unused_right = HOST_CHAR_BIT - (chunk_size + targ_offset);
- mask = ((1 << chunk_size) - 1) << unused_right;
- *target =
- (*target & ~mask)
- | ((accum >> (accum_bits - chunk_size - unused_right)) & mask);
- n -= chunk_size;
- accum_bits -= chunk_size;
- target += 1;
- targ_offset = 0;
- }
- }
- else
- {
- accum = (unsigned char) *source >> src_offset;
- source += 1;
- accum_bits = HOST_CHAR_BIT - src_offset;
-
- while (n > 0)
- {
- accum = accum + ((unsigned char) *source << accum_bits);
- accum_bits += HOST_CHAR_BIT;
- source += 1;
- chunk_size = HOST_CHAR_BIT - targ_offset;
- if (chunk_size > n)
- chunk_size = n;
- mask = ((1 << chunk_size) - 1) << targ_offset;
- *target = (*target & ~mask) | ((accum << targ_offset) & mask);
- n -= chunk_size;
- accum_bits -= chunk_size;
- accum >>= chunk_size;
- target += 1;
- targ_offset = 0;
- }
- }
-}
-
/* Store the contents of FROMVAL into the location of TOVAL.
Return a new value with the location of TOVAL and contents of
FROMVAL. Handles assignment into packed fields that have
from_size = value_bitsize (fromval);
if (from_size == 0)
from_size = TYPE_LENGTH (value_type (fromval)) * TARGET_CHAR_BIT;
- if (gdbarch_bits_big_endian (get_type_arch (type)))
- move_bits (buffer, value_bitpos (toval),
- value_contents (fromval), from_size - bits, bits, 1);
- else
- move_bits (buffer, value_bitpos (toval),
- value_contents (fromval), 0, bits, 0);
+
+ const int is_big_endian = gdbarch_bits_big_endian (get_type_arch (type));
+ ULONGEST from_offset = 0;
+ if (is_big_endian && is_scalar_type (value_type (fromval)))
+ from_offset = from_size - bits;
+ copy_bitwise (buffer, value_bitpos (toval),
+ value_contents (fromval), from_offset,
+ bits, is_big_endian);
write_memory_with_notification (to_addr, buffer, len);
val = value_copy (toval);
= TYPE_LENGTH (value_type (component)) * TARGET_CHAR_BIT - bits;
else
src_offset = 0;
- move_bits (value_contents_writeable (container) + offset_in_container,
- value_bitpos (container) + bit_offset_in_container,
- value_contents (val), src_offset, bits, 1);
+ copy_bitwise (value_contents_writeable (container) + offset_in_container,
+ value_bitpos (container) + bit_offset_in_container,
+ value_contents (val), src_offset, bits, 1);
}
else
- move_bits (value_contents_writeable (container) + offset_in_container,
- value_bitpos (container) + bit_offset_in_container,
- value_contents (val), 0, bits, 0);
+ copy_bitwise (value_contents_writeable (container) + offset_in_container,
+ value_bitpos (container) + bit_offset_in_container,
+ value_contents (val), 0, bits, 0);
}
/* Determine if TYPE is an access to an unconstrained array. */
return high - low + 1;
}
-/* An empty array whose type is that of ARR_TYPE (an array type),
- with bounds LOW to LOW-1. */
+/* An array whose type is that of ARR_TYPE (an array type), with
+ bounds LOW to HIGH, but whose contents are unimportant. If HIGH is
+ less than LOW, then LOW-1 is used. */
static struct value *
-empty_array (struct type *arr_type, int low)
+empty_array (struct type *arr_type, int low, int high)
{
struct type *arr_type0 = ada_check_typedef (arr_type);
struct type *index_type
= create_static_range_type
- (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)), low, low - 1);
+ (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)), low,
+ high < low ? low - 1 : high);
struct type *elt_type = ada_array_element_type (arr_type0, 1);
return allocate_value (create_array_type (NULL, elt_type, index_type));
return type is preferred. May change (expand) *EXP. */
static void
-resolve (expression_up *expp, int void_context_p)
+resolve (expression_up *expp, int void_context_p, int parse_completion,
+ innermost_block_tracker *tracker)
{
struct type *context_type = NULL;
int pc = 0;
if (void_context_p)
context_type = builtin_type ((*expp)->gdbarch)->builtin_void;
- resolve_subexp (expp, &pc, 1, context_type);
+ resolve_subexp (expp, &pc, 1, context_type, parse_completion, tracker);
}
/* Resolve the operator of the subexpression beginning at
static struct value *
resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
- struct type *context_type)
+ struct type *context_type, int parse_completion,
+ innermost_block_tracker *tracker)
{
int pc = *pos;
int i;
else
{
*pos += 3;
- resolve_subexp (expp, pos, 0, NULL);
+ resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
}
nargs = longest_to_int (exp->elts[pc + 1].longconst);
break;
case UNOP_ADDR:
*pos += 1;
- resolve_subexp (expp, pos, 0, NULL);
+ resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
break;
case UNOP_QUAL:
*pos += 3;
- resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type));
+ resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type),
+ parse_completion, tracker);
break;
case OP_ATR_MODULUS:
struct value *arg1;
*pos += 1;
- arg1 = resolve_subexp (expp, pos, 0, NULL);
+ arg1 = resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
if (arg1 == NULL)
- resolve_subexp (expp, pos, 1, NULL);
+ resolve_subexp (expp, pos, 1, NULL, parse_completion, tracker);
else
- resolve_subexp (expp, pos, 1, value_type (arg1));
+ resolve_subexp (expp, pos, 1, value_type (arg1), parse_completion,
+ tracker);
break;
}
argvec = XALLOCAVEC (struct value *, nargs + 1);
for (i = 0; i < nargs; i += 1)
- argvec[i] = resolve_subexp (expp, pos, 1, NULL);
+ argvec[i] = resolve_subexp (expp, pos, 1, NULL, parse_completion,
+ tracker);
argvec[i] = NULL;
exp = expp->get ();
i = ada_resolve_function
(candidates.data (), n_candidates, NULL, 0,
SYMBOL_LINKAGE_NAME (exp->elts[pc + 2].symbol),
- context_type);
+ context_type, parse_completion);
if (i < 0)
error (_("Could not find a match for %s"),
SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol));
exp->elts[pc + 1].block = candidates[i].block;
exp->elts[pc + 2].symbol = candidates[i].symbol;
- innermost_block.update (candidates[i]);
+ tracker->update (candidates[i]);
}
if (deprocedure_p
(candidates.data (), n_candidates,
argvec, nargs,
SYMBOL_LINKAGE_NAME (exp->elts[pc + 5].symbol),
- context_type);
+ context_type, parse_completion);
if (i < 0)
error (_("Could not find a match for %s"),
SYMBOL_PRINT_NAME (exp->elts[pc + 5].symbol));
exp->elts[pc + 4].block = candidates[i].block;
exp->elts[pc + 5].symbol = candidates[i].symbol;
- innermost_block.update (candidates[i]);
+ tracker->update (candidates[i]);
}
}
break;
n_candidates =
ada_lookup_symbol_list (ada_decoded_op_name (op),
- (struct block *) NULL, VAR_DOMAIN,
+ NULL, VAR_DOMAIN,
&candidates);
i = ada_resolve_function (candidates.data (), n_candidates, argvec,
- nargs, ada_decoded_op_name (op), NULL);
+ nargs, ada_decoded_op_name (op), NULL,
+ parse_completion);
if (i < 0)
break;
static int
ada_resolve_function (struct block_symbol syms[],
int nsyms, struct value **args, int nargs,
- const char *name, struct type *context_type)
+ const char *name, struct type *context_type,
+ int parse_completion)
{
int fallback;
int k;
error (_("\
canceled because the command is ambiguous\n\
See set/show multiple-symbol."));
-
+
/* If select_mode is "all", then return all possible symbols.
Only do that if more than one symbol can be selected, of course.
Otherwise, display the menu as usual. */
if (select_mode == multiple_symbols_all && max_results > 1)
return nsyms;
- printf_unfiltered (_("[0] cancel\n"));
+ printf_filtered (_("[0] cancel\n"));
if (max_results > 1)
- printf_unfiltered (_("[1] all\n"));
+ printf_filtered (_("[1] all\n"));
sort_choices (syms, nsyms);
struct symtab_and_line sal =
find_function_start_sal (syms[i].symbol, 1);
- printf_unfiltered ("[%d] ", i + first_choice);
+ printf_filtered ("[%d] ", i + first_choice);
ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
&type_print_raw_options);
if (sal.symtab == NULL)
- printf_unfiltered (_(" at <no source file available>:%d\n"),
- sal.line);
+ printf_filtered (_(" at <no source file available>:%d\n"),
+ sal.line);
else
- printf_unfiltered (_(" at %s:%d\n"),
- symtab_to_filename_for_display (sal.symtab),
- sal.line);
+ printf_filtered (_(" at %s:%d\n"),
+ symtab_to_filename_for_display (sal.symtab),
+ sal.line);
continue;
}
else
if (SYMBOL_LINE (syms[i].symbol) != 0 && symtab != NULL)
{
- printf_unfiltered ("[%d] ", i + first_choice);
+ printf_filtered ("[%d] ", i + first_choice);
ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
&type_print_raw_options);
- printf_unfiltered (_(" at %s:%d\n"),
- symtab_to_filename_for_display (symtab),
- SYMBOL_LINE (syms[i].symbol));
+ printf_filtered (_(" at %s:%d\n"),
+ symtab_to_filename_for_display (symtab),
+ SYMBOL_LINE (syms[i].symbol));
}
else if (is_enumeral
&& TYPE_NAME (SYMBOL_TYPE (syms[i].symbol)) != NULL)
{
- printf_unfiltered (("[%d] "), i + first_choice);
+ printf_filtered (("[%d] "), i + first_choice);
ada_print_type (SYMBOL_TYPE (syms[i].symbol), NULL,
gdb_stdout, -1, 0, &type_print_raw_options);
- printf_unfiltered (_("'(%s) (enumeral)\n"),
- SYMBOL_PRINT_NAME (syms[i].symbol));
+ printf_filtered (_("'(%s) (enumeral)\n"),
+ SYMBOL_PRINT_NAME (syms[i].symbol));
}
else
{
- printf_unfiltered ("[%d] ", i + first_choice);
+ printf_filtered ("[%d] ", i + first_choice);
ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
&type_print_raw_options);
if (symtab != NULL)
- printf_unfiltered (is_enumeral
- ? _(" in %s (enumeral)\n")
- : _(" at %s:?\n"),
- symtab_to_filename_for_display (symtab));
+ printf_filtered (is_enumeral
+ ? _(" in %s (enumeral)\n")
+ : _(" at %s:?\n"),
+ symtab_to_filename_for_display (symtab));
else
- printf_unfiltered (is_enumeral
- ? _(" (enumeral)\n")
- : _(" at ?\n"));
+ printf_filtered (is_enumeral
+ ? _(" (enumeral)\n")
+ : _(" at ?\n"));
}
}
}
domain_enum domain)
{
/* Initialize it just to avoid a GCC false warning. */
- struct block_symbol sym = {NULL, NULL};
+ struct block_symbol sym = {};
if (lookup_cached_symbol (name, domain, &sym.symbol, NULL))
return sym.symbol;
- sym = lookup_symbol_in_language (name, block, domain, language_c, 0);
+ ada_lookup_encoded_symbol (name, block, domain, &sym);
cache_symbol (name, domain, sym.symbol, sym.block);
return sym.symbol;
}
ada_lookup_simple_minsym (const char *name)
{
struct bound_minimal_symbol result;
- struct objfile *objfile;
- struct minimal_symbol *msymbol;
memset (&result, 0, sizeof (result));
symbol_name_matcher_ftype *match_name
= ada_get_symbol_name_matcher (lookup_name);
- ALL_MSYMBOLS (objfile, msymbol)
- {
- if (match_name (MSYMBOL_LINKAGE_NAME (msymbol), lookup_name, NULL)
- && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
- {
- result.minsym = msymbol;
- result.objfile = objfile;
- break;
- }
- }
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ for (minimal_symbol *msymbol : objfile->msymbols ())
+ {
+ if (match_name (MSYMBOL_LINKAGE_NAME (msymbol), lookup_name, NULL)
+ && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
+ {
+ result.minsym = msymbol;
+ result.objfile = objfile;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+/* Return all the bound minimal symbols matching NAME according to Ada
+ decoding rules. Returns an empty vector 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. */
+
+static std::vector<struct bound_minimal_symbol>
+ada_lookup_simple_minsyms (const char *name)
+{
+ std::vector<struct bound_minimal_symbol> result;
+
+ symbol_name_match_type match_type = name_match_type_from_name (name);
+ lookup_name_info lookup_name (name, match_type);
+
+ symbol_name_matcher_ftype *match_name
+ = ada_get_symbol_name_matcher (lookup_name);
+
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ for (minimal_symbol *msymbol : objfile->msymbols ())
+ {
+ if (match_name (MSYMBOL_LINKAGE_NAME (msymbol), lookup_name, NULL)
+ && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
+ result.push_back ({msymbol, objfile});
+ }
+ }
return result;
}
other has been found. */
static int
-aux_add_nonlocal_symbols (struct block *block, struct symbol *sym, void *data0)
+aux_add_nonlocal_symbols (const struct block *block, struct symbol *sym,
+ void *data0)
{
struct match_data *data = (struct match_data *) data0;
const lookup_name_info &lookup_name,
domain_enum domain, int global)
{
- struct objfile *objfile;
- struct compunit_symtab *cu;
struct match_data data;
memset (&data, 0, sizeof data);
bool is_wild_match = lookup_name.ada ().wild_match_p ();
- ALL_OBJFILES (objfile)
+ for (objfile *objfile : current_program_space->objfiles ())
{
data.objfile = objfile;
symbol_name_match_type::FULL,
compare_names);
- ALL_OBJFILE_COMPUNITS (objfile, cu)
+ for (compunit_symtab *cu : objfile->compunits ())
{
const struct block *global_block
= BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cu), GLOBAL_BLOCK);
const char *name = ada_lookup_name (lookup_name);
std::string name1 = std::string ("<_ada_") + name + '>';
- ALL_OBJFILES (objfile)
+ for (objfile *objfile : current_program_space->objfiles ())
{
data.objfile = objfile;
objfile->sf->qf->map_matching_symbols (objfile, name1.c_str (),
return sym;
}
- return (struct block_symbol) {NULL, NULL};
+ return {};
}
enum type_code code)
{
struct symbol *sym;
- struct compunit_symtab *s;
- struct minimal_symbol *msymbol;
- struct objfile *objfile;
const struct block *b, *surrounding_static_block = 0;
struct block_iterator iter;
anything that isn't a text symbol (everything else will be
handled by the psymtab code above). */
- ALL_MSYMBOLS (objfile, msymbol)
- {
- QUIT;
-
- if (completion_skip_symbol (mode, msymbol))
- continue;
-
- language symbol_language = MSYMBOL_LANGUAGE (msymbol);
-
- /* Ada minimal symbols won't have their language set to Ada. If
- we let completion_list_add_name compare using the
- default/C-like matcher, then when completing e.g., symbols in a
- package named "pck", we'd match internal Ada symbols like
- "pckS", which are invalid in an Ada expression, unless you wrap
- them in '<' '>' to request a verbatim match.
-
- Unfortunately, some Ada encoded names successfully demangle as
- C++ symbols (using an old mangling scheme), such as "name__2Xn"
- -> "Xn::name(void)" and thus some Ada minimal symbols end up
- with the wrong language set. Paper over that issue here. */
- if (symbol_language == language_auto
- || symbol_language == language_cplus)
- symbol_language = language_ada;
-
- completion_list_add_name (tracker,
- symbol_language,
- MSYMBOL_LINKAGE_NAME (msymbol),
- lookup_name, text, word);
- }
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ for (minimal_symbol *msymbol : objfile->msymbols ())
+ {
+ QUIT;
+
+ if (completion_skip_symbol (mode, msymbol))
+ continue;
+
+ language symbol_language = MSYMBOL_LANGUAGE (msymbol);
+
+ /* Ada minimal symbols won't have their language set to Ada. If
+ we let completion_list_add_name compare using the
+ default/C-like matcher, then when completing e.g., symbols in a
+ package named "pck", we'd match internal Ada symbols like
+ "pckS", which are invalid in an Ada expression, unless you wrap
+ them in '<' '>' to request a verbatim match.
+
+ Unfortunately, some Ada encoded names successfully demangle as
+ C++ symbols (using an old mangling scheme), such as "name__2Xn"
+ -> "Xn::name(void)" and thus some Ada minimal symbols end up
+ with the wrong language set. Paper over that issue here. */
+ if (symbol_language == language_auto
+ || symbol_language == language_cplus)
+ symbol_language = language_ada;
+
+ completion_list_add_name (tracker,
+ symbol_language,
+ MSYMBOL_LINKAGE_NAME (msymbol),
+ lookup_name, text, word);
+ }
+ }
/* Search upwards from currently selected frame (so that we can
complete on local vars. */
/* Go through the symtabs and check the externs and statics for
symbols which match. */
- ALL_COMPUNITS (objfile, s)
- {
- QUIT;
- b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), GLOBAL_BLOCK);
- ALL_BLOCK_SYMBOLS (b, iter, sym)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- if (completion_skip_symbol (mode, sym))
- continue;
+ for (compunit_symtab *s : objfile->compunits ())
+ {
+ QUIT;
+ b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), GLOBAL_BLOCK);
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ {
+ if (completion_skip_symbol (mode, sym))
+ continue;
- completion_list_add_name (tracker,
- SYMBOL_LANGUAGE (sym),
- SYMBOL_LINKAGE_NAME (sym),
- lookup_name, text, word);
+ completion_list_add_name (tracker,
+ SYMBOL_LANGUAGE (sym),
+ SYMBOL_LINKAGE_NAME (sym),
+ lookup_name, text, word);
+ }
+ }
}
- }
- ALL_COMPUNITS (objfile, s)
- {
- QUIT;
- b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), STATIC_BLOCK);
- /* Don't do this block twice. */
- if (b == surrounding_static_block)
- continue;
- ALL_BLOCK_SYMBOLS (b, iter, sym)
- {
- if (completion_skip_symbol (mode, sym))
- continue;
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ for (compunit_symtab *s : objfile->compunits ())
+ {
+ QUIT;
+ b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (s), STATIC_BLOCK);
+ /* Don't do this block twice. */
+ if (b == surrounding_static_block)
+ continue;
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ {
+ if (completion_skip_symbol (mode, sym))
+ continue;
- completion_list_add_name (tracker,
- SYMBOL_LANGUAGE (sym),
- SYMBOL_LINKAGE_NAME (sym),
- lookup_name, text, word);
+ completion_list_add_name (tracker,
+ SYMBOL_LANGUAGE (sym),
+ SYMBOL_LINKAGE_NAME (sym),
+ lookup_name, text, word);
+ }
+ }
}
- }
}
/* Field Access */
see ada_tag_name for more details. We do not print the error
message for the same reason. */
- TRY
+ try
{
offset_to_top = value_as_long (value_ind (value_ptradd (val, -2)));
}
- CATCH (e, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &e)
{
return obj;
}
- END_CATCH
/* If offset is null, nothing to do. */
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
+ try
{
struct value *tsd = ada_get_tsd_from_tag (tag);
if (tsd != NULL)
name = ada_tag_name_from_tsd (tsd);
}
- CATCH (e, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &e)
{
}
- END_CATCH
return name;
}
int
ada_is_variant_part (struct type *type, int field_num)
{
+ /* Only Ada types are eligible. */
+ if (!ADA_TYPE_P (type))
+ return 0;
+
struct type *field_type = TYPE_FIELD_TYPE (type, field_num);
return (TYPE_CODE (field_type) == TYPE_CODE_UNION
arg_type = ada_check_typedef (arg_type);
type = TYPE_FIELD_TYPE (arg_type, fieldno);
- /* Handle packed fields. */
-
- if (TYPE_FIELD_BITSIZE (arg_type, fieldno) != 0)
+ /* Handle packed fields. It might be that the field is not packed
+ relative to its containing structure, but the structure itself is
+ packed; in this case we must take the bit-field path. */
+ if (TYPE_FIELD_BITSIZE (arg_type, fieldno) != 0 || value_bitpos (arg1) != 0)
{
int bit_pos = TYPE_FIELD_BITPOS (arg_type, fieldno);
int bit_size = TYPE_FIELD_BITSIZE (arg_type, fieldno);
TYPE_CODE (type) = TYPE_CODE_STRUCT;
TYPE_NFIELDS (type) = 0;
TYPE_FIELDS (type) = NULL;
- INIT_CPLUS_SPECIFIC (type);
+ INIT_NONE_SPECIFIC (type);
TYPE_NAME (type) = "<empty>";
TYPE_LENGTH (type) = 0;
return type;
rtype = alloc_type_copy (type);
TYPE_CODE (rtype) = TYPE_CODE_STRUCT;
- INIT_CPLUS_SPECIFIC (rtype);
+ INIT_NONE_SPECIFIC (rtype);
TYPE_NFIELDS (rtype) = nfields;
TYPE_FIELDS (rtype) = (struct field *)
TYPE_ALLOC (rtype, nfields * sizeof (struct field));
if (TYPE_LENGTH (type) <= 0)
{
if (TYPE_NAME (rtype))
- warning (_("Invalid type size for `%s' detected: %d."),
- TYPE_NAME (rtype), TYPE_LENGTH (type));
+ warning (_("Invalid type size for `%s' detected: %s."),
+ TYPE_NAME (rtype), pulongest (TYPE_LENGTH (type)));
else
- warning (_("Invalid type size for <unnamed> detected: %d."),
- TYPE_LENGTH (type));
+ warning (_("Invalid type size for <unnamed> detected: %s."),
+ pulongest (TYPE_LENGTH (type)));
}
else
{
{
TYPE_TARGET_TYPE (type0) = type = alloc_type_copy (type0);
TYPE_CODE (type) = TYPE_CODE (type0);
- INIT_CPLUS_SPECIFIC (type);
+ INIT_NONE_SPECIFIC (type);
TYPE_NFIELDS (type) = nfields;
TYPE_FIELDS (type) = (struct field *)
TYPE_ALLOC (type, nfields * sizeof (struct field));
rtype = alloc_type_copy (type);
TYPE_CODE (rtype) = TYPE_CODE_STRUCT;
- INIT_CPLUS_SPECIFIC (rtype);
+ INIT_NONE_SPECIFIC (rtype);
TYPE_NFIELDS (rtype) = nfields;
TYPE_FIELDS (rtype) =
(struct field *) TYPE_ALLOC (rtype, nfields * sizeof (struct field));
CORE_ADDR address, struct value *dval, int check_tag)
{
type = ada_check_typedef (type);
+
+ /* Only un-fixed types need to be handled here. */
+ if (!HAVE_GNAT_AUX_INFO (type))
+ return type;
+
switch (TYPE_CODE (type))
{
default:
LONGEST size;
xsnprintf (xvz_name, strlen (name) + 7, "%s___XVZ", name);
- TRY
+ try
{
xvz_found = get_int_var_value (xvz_name, size);
}
- CATCH (except, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &except)
{
/* We found the variable, but somehow failed to read
its value. Rethrow the same error, but with a little
optimized out). */
throw_error (except.error,
_("unable to read value of %s (%s)"),
- xvz_name, except.message);
+ xvz_name, except.what ());
}
- END_CATCH
if (xvz_found && TYPE_LENGTH (fixed_record_type) != size)
{
[At the moment, this is true only for Character and Wide_Character;
It is a heuristic test that could stand improvement]. */
-int
+bool
ada_is_character_type (struct type *type)
{
const char *name;
/* If the type code says it's a character, then assume it really is,
and don't check any further. */
if (TYPE_CODE (type) == TYPE_CODE_CHAR)
- return 1;
+ return true;
/* Otherwise, assume it's a character type iff it is a discrete type
with a known character type name. */
/* True if TYPE appears to be an Ada string type. */
-int
+bool
ada_is_string_type (struct type *type)
{
type = ada_check_typedef (type);
return ada_is_character_type (elttype);
}
else
- return 0;
+ return false;
}
/* The compiler sometimes provides a parallel XVS type for a given
error_call_unknown_return_type (NULL);
return allocate_value (TYPE_TARGET_TYPE (type));
}
- return call_function_by_hand (argvec[0], NULL, nargs, argvec + 1);
+ return call_function_by_hand (argvec[0], NULL,
+ gdb::make_array_view (argvec + 1,
+ nargs));
case TYPE_CODE_INTERNAL_FUNCTION:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
/* We don't know anything about what the internal
if (noside == EVAL_AVOID_SIDE_EFFECTS
&& ada_is_array_descriptor_type (ada_check_typedef
(value_type (array))))
- return empty_array (ada_type_of_array (array, 0), low_bound);
+ return empty_array (ada_type_of_array (array, 0), low_bound,
+ high_bound);
array = ada_coerce_to_simple_array_ptr (array);
struct type *type0 = ada_check_typedef (value_type (array));
if (high_bound < low_bound || noside == EVAL_AVOID_SIDE_EFFECTS)
- return empty_array (TYPE_TARGET_TYPE (type0), low_bound);
+ return empty_array (TYPE_TARGET_TYPE (type0), low_bound, high_bound);
else
{
struct type *arr_type0 =
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
return array;
else if (high_bound < low_bound)
- return empty_array (value_type (array), low_bound);
+ return empty_array (value_type (array), low_bound, high_bound);
else
return ada_value_slice (array, longest_to_int (low_bound),
longest_to_int (high_bound));
{
gdb::unique_xmalloc_ptr<char> e_msg;
- TRY
+ try
{
e_msg = ada_exception_message_1 ();
}
- CATCH (e, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &e)
{
e_msg.reset (nullptr);
}
- END_CATCH
return e_msg;
}
{
CORE_ADDR result = 0;
- TRY
+ try
{
result = ada_exception_name_addr_1 (ex, b);
}
- CATCH (e, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &e)
{
- warning (_("failed to get exception name: %s"), e.message);
+ warning (_("failed to get exception name: %s"), e.what ());
return 0;
}
- END_CATCH
return result;
}
class ada_catchpoint_location : public bp_location
{
public:
- ada_catchpoint_location (const bp_location_ops *ops, breakpoint *owner)
- : bp_location (ops, owner)
+ ada_catchpoint_location (breakpoint *owner)
+ : bp_location (owner)
{}
/* The condition that checks whether the exception that was raised
expression_up excep_cond_expr;
};
-/* Implement the DTOR method in the bp_location_ops structure for all
- Ada exception catchpoint kinds. */
-
-static void
-ada_catchpoint_location_dtor (struct bp_location *bl)
-{
- struct ada_catchpoint_location *al = (struct ada_catchpoint_location *) bl;
-
- al->excep_cond_expr.reset ();
-}
-
-/* The vtable to be used in Ada catchpoint locations. */
-
-static const struct bp_location_ops ada_catchpoint_location_ops =
-{
- ada_catchpoint_location_dtor
-};
-
/* An instance of this type is used to represent an Ada catchpoint. */
struct ada_catchpoint : public breakpoint
create_excep_cond_exprs (struct ada_catchpoint *c,
enum ada_exception_catchpoint_kind ex)
{
- struct bp_location *bl;
-
/* Nothing to do if there's no specific exception to catch. */
if (c->excep_string.empty ())
return;
if (c->loc == NULL)
return;
- /* Compute the condition expression in text form, from the specific
- expection we want to catch. */
- std::string cond_string
- = ada_exception_catchpoint_cond_string (c->excep_string.c_str (), ex);
+ /* We have to compute the expression once for each program space,
+ because the expression may hold the addresses of multiple symbols
+ in some cases. */
+ std::multimap<program_space *, struct bp_location *> loc_map;
+ for (struct bp_location *bl = c->loc; bl != NULL; bl = bl->next)
+ loc_map.emplace (bl->pspace, bl);
- /* Iterate over all the catchpoint's locations, and parse an
- expression for each. */
- for (bl = c->loc; bl != NULL; bl = bl->next)
+ scoped_restore_current_program_space save_pspace;
+
+ std::string cond_string;
+ program_space *last_ps = nullptr;
+ for (auto iter : loc_map)
{
struct ada_catchpoint_location *ada_loc
- = (struct ada_catchpoint_location *) bl;
+ = (struct ada_catchpoint_location *) iter.second;
+
+ if (ada_loc->pspace != last_ps)
+ {
+ last_ps = ada_loc->pspace;
+ set_current_program_space (last_ps);
+
+ /* Compute the condition expression in text form, from the
+ specific expection we want to catch. */
+ cond_string
+ = ada_exception_catchpoint_cond_string (c->excep_string.c_str (),
+ ex);
+ }
+
expression_up exp;
- if (!bl->shlib_disabled)
+ if (!ada_loc->shlib_disabled)
{
const char *s;
s = cond_string.c_str ();
- TRY
+ try
{
- exp = parse_exp_1 (&s, bl->address,
- block_for_pc (bl->address),
+ exp = parse_exp_1 (&s, ada_loc->address,
+ block_for_pc (ada_loc->address),
0);
}
- CATCH (e, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &e)
{
warning (_("failed to reevaluate internal exception condition "
"for catchpoint %d: %s"),
- c->number, e.message);
+ c->number, e.what ());
}
- END_CATCH
}
ada_loc->excep_cond_expr = std::move (exp);
allocate_location_exception (enum ada_exception_catchpoint_kind ex,
struct breakpoint *self)
{
- return new ada_catchpoint_location (&ada_catchpoint_location_ops, self);
+ return new ada_catchpoint_location (self);
}
/* Implement the RE_SET method in the breakpoint_ops structure for all
}
stop = 1;
- TRY
+ try
{
struct value *mark;
stop = value_true (evaluate_expression (ada_loc->excep_cond_expr.get ()));
value_free_to_mark (mark);
}
- CATCH (ex, RETURN_MASK_ALL)
+ catch (const gdb_exception &ex)
{
exception_fprintf (gdb_stderr, ex,
_("Error in testing exception condition:\n"));
}
- END_CATCH
return stop;
}
enum ada_exception_catchpoint_kind ex)
{
int i;
- bool is_standard_exc = false;
std::string result;
+ const char *name;
if (ex == ada_catch_handlers)
{
/* For exception handlers catchpoints, the condition string does
not use the same parameter as for the other exceptions. */
- result = ("long_integer (GNAT_GCC_exception_Access"
- "(gcc_exception).all.occurrence.id)");
+ name = ("long_integer (GNAT_GCC_exception_Access"
+ "(gcc_exception).all.occurrence.id)");
}
else
- result = "long_integer (e)";
+ name = "long_integer (e)";
/* The standard exceptions are a special case. They are defined in
runtime units that have been compiled without debugging info; if
If an exception named contraint_error is defined in another package of
the inferior program, then the only way to specify this exception as a
breakpoint condition is to use its fully-qualified named:
- e.g. my_package.constraint_error. */
+ e.g. my_package.constraint_error.
+
+ Furthermore, in some situations a standard exception's symbol may
+ be present in more than one objfile, because the compiler may
+ choose to emit copy relocations for them. So, we have to compare
+ against all the possible addresses. */
+ /* Storage for a rewritten symbol name. */
+ std::string std_name;
for (i = 0; i < sizeof (standard_exc) / sizeof (char *); i++)
{
if (strcmp (standard_exc [i], excep_string) == 0)
{
- is_standard_exc = true;
+ std_name = std::string ("standard.") + excep_string;
+ excep_string = std_name.c_str ();
break;
}
}
- result += " = ";
-
- if (is_standard_exc)
- string_appendf (result, "long_integer (&standard.%s)", excep_string);
- else
- string_appendf (result, "long_integer (&%s)", excep_string);
+ excep_string = ada_encode (excep_string);
+ std::vector<struct bound_minimal_symbol> symbols
+ = ada_lookup_simple_minsyms (excep_string);
+ for (const struct bound_minimal_symbol &msym : symbols)
+ {
+ if (!result.empty ())
+ result += " or ";
+ string_appendf (result, "%s = %s", name,
+ pulongest (BMSYMBOL_VALUE_ADDRESS (msym)));
+ }
return result;
}
static struct symtab_and_line
ada_exception_sal (enum ada_exception_catchpoint_kind ex,
- const char **addr_string, const struct breakpoint_ops **ops)
+ std::string *addr_string, const struct breakpoint_ops **ops)
{
const char *sym_name;
struct symbol *sym;
error (_("Unable to insert catchpoint. %s is not a function."), sym_name);
/* Set ADDR_STRING. */
- *addr_string = xstrdup (sym_name);
+ *addr_string = sym_name;
/* Set OPS. */
*ops = ada_exception_breakpoint_ops (ex);
int disabled,
int from_tty)
{
- const char *addr_string = NULL;
+ std::string addr_string;
const struct breakpoint_ops *ops = NULL;
struct symtab_and_line sal = ada_exception_sal (ex_kind, &addr_string, &ops);
std::unique_ptr<ada_catchpoint> c (new ada_catchpoint ());
- init_ada_exception_breakpoint (c.get (), gdbarch, sal, addr_string,
+ init_ada_exception_breakpoint (c.get (), gdbarch, sal, addr_string.c_str (),
ops, tempflag, disabled, from_tty);
c->excep_string = excep_string;
create_excep_cond_exprs (c.get (), ex_kind);
ada_add_global_exceptions (compiled_regex *preg,
std::vector<ada_exc_info> *exceptions)
{
- struct objfile *objfile;
- struct compunit_symtab *s;
-
/* In Ada, the symbol "search name" is a linkage name, whereas the
regular expression used to do the matching refers to the natural
name. So match against the decoded name. */
NULL,
VARIABLES_DOMAIN);
- ALL_COMPUNITS (objfile, s)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (s);
- int i;
-
- for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+ for (compunit_symtab *s : objfile->compunits ())
{
- struct block *b = BLOCKVECTOR_BLOCK (bv, i);
- struct block_iterator iter;
- struct symbol *sym;
+ const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (s);
+ int i;
- ALL_BLOCK_SYMBOLS (b, iter, sym)
- if (ada_is_non_standard_exception_sym (sym)
- && name_matches_regex (SYMBOL_NATURAL_NAME (sym), preg))
- {
- struct ada_exc_info info
- = {SYMBOL_PRINT_NAME (sym), SYMBOL_VALUE_ADDRESS (sym)};
+ for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+ {
+ const struct block *b = BLOCKVECTOR_BLOCK (bv, i);
+ struct block_iterator iter;
+ struct symbol *sym;
- exceptions->push_back (info);
- }
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ if (ada_is_non_standard_exception_sym (sym)
+ && name_matches_regex (SYMBOL_NATURAL_NAME (sym), preg))
+ {
+ struct ada_exc_info info
+ = {SYMBOL_PRINT_NAME (sym), SYMBOL_VALUE_ADDRESS (sym)};
+
+ exceptions->push_back (info);
+ }
+ }
}
}
}
return full_match (symbol_search_name, ada_lookup_name (lookup_name));
}
+/* symbol_name_matcher_ftype for exact (verbatim) matches. */
+
+static bool
+do_exact_match (const char *symbol_search_name,
+ const lookup_name_info &lookup_name,
+ completion_match_result *comp_match_res)
+{
+ return strcmp (symbol_search_name, ada_lookup_name (lookup_name)) == 0;
+}
+
/* Build the Ada lookup name for LOOKUP_NAME. */
ada_lookup_name_info::ada_lookup_name_info (const lookup_name_info &lookup_name)
{
if (lookup_name.ada ().wild_match_p ())
return do_wild_match;
+ else if (lookup_name.ada ().verbatim_p ())
+ return do_exact_match;
else
return do_full_match;
}
&ada_varobj_ops,
NULL,
NULL,
- LANG_MAGIC
+ ada_is_string_type,
+ "(...)" /* la_struct_too_deep_ellipsis */
};
/* Command-list for the "set/show ada" prefix command. */
add_catch_command ("exception", _("\
Catch Ada exceptions, when raised.\n\
-With an argument, catch only exceptions with the given name."),
+Usage: catch exception [ ARG ]\n\
+\n\
+Without any argument, stop when any Ada exception is raised.\n\
+If ARG is \"unhandled\" (without the quotes), only stop when the exception\n\
+being raised does not have a handler (and will therefore lead to the task's\n\
+termination).\n\
+Otherwise, the catchpoint only stops when the name of the exception being\n\
+raised is the same as ARG."),
catch_ada_exception_command,
NULL,
CATCH_PERMANENT,