/* Ada language support routines for GDB, the GNU debugger.
- Copyright (C) 1992-2014 Free Software Foundation, Inc.
+ Copyright (C) 1992-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
-#include <stdio.h>
-#include <string.h>
#include <ctype.h>
-#include <stdarg.h>
-#include "demangle.h"
#include "gdb_regex.h"
#include "frame.h"
#include "symtab.h"
#include "parser-defs.h"
#include "language.h"
#include "varobj.h"
-#include "c-lang.h"
#include "inferior.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdb_obstack.h"
#include "ada-lang.h"
#include "completer.h"
-#include <sys/stat.h>
#include "ui-out.h"
#include "block.h"
#include "infcall.h"
-#include "dictionary.h"
-#include "exceptions.h"
#include "annotate.h"
#include "valprint.h"
#include "source.h"
-#include "observer.h"
-#include "vec.h"
+#include "observable.h"
#include "stack.h"
-#include "gdb_vecs.h"
#include "typeprint.h"
+#include "namespace.h"
+#include "cli/cli-style.h"
-#include "psymtab.h"
#include "value.h"
#include "mi/mi-common.h"
#include "arch-utils.h"
#include "cli/cli-utils.h"
+#include "gdbsupport/function-view.h"
+#include "gdbsupport/byte-vector.h"
+#include <algorithm>
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C).
static int ada_args_match (struct symbol *, struct value **, int);
-static int full_match (const char *, const char *);
-
static struct value *make_array_descriptor (struct type *, struct value *);
static void ada_add_block_symbols (struct obstack *,
- const struct block *, const char *,
- domain_enum, struct objfile *, int);
+ const struct block *,
+ const lookup_name_info &lookup_name,
+ domain_enum, struct objfile *);
+
+static void ada_add_all_symbols (struct obstack *, const struct block *,
+ const lookup_name_info &lookup_name,
+ domain_enum, int, int *);
-static int is_nonfunction (struct ada_symbol_info *, int);
+static int is_nonfunction (struct block_symbol *, int);
static void add_defn_to_vec (struct obstack *, struct symbol *,
const struct block *);
static int num_defns_collected (struct obstack *);
-static struct ada_symbol_info *defns_collected (struct obstack *, int);
+static struct block_symbol *defns_collected (struct obstack *, int);
-static struct value *resolve_subexp (struct expression **, int *, int,
- struct type *);
+static struct value *resolve_subexp (expression_up *, int *, int,
+ struct type *, int,
+ innermost_block_tracker *);
-static void replace_operator_with_call (struct expression **, int, int, int,
+static void replace_operator_with_call (expression_up *, int, int, int,
struct symbol *, const struct block *);
static int possible_user_operator_p (enum exp_opcode, struct value **);
-static char *ada_op_name (enum exp_opcode);
+static const char *ada_op_name (enum exp_opcode);
static const char *ada_decoded_op_name (enum exp_opcode);
static int discrete_type_p (struct type *);
-static enum ada_renaming_category parse_old_style_renaming (struct type *,
- const char **,
- int *,
- const char **);
-
-static struct symbol *find_old_style_renaming_symbol (const char *,
- const struct block *);
-
-static struct type *ada_lookup_struct_elt_type (struct type *, char *,
- int, int, int *);
+static struct type *ada_lookup_struct_elt_type (struct type *, const char *,
+ int, int);
static struct value *evaluate_subexp_type (struct expression *, int *);
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 struct value *get_var_value (char *, char *);
-
static int lesseq_defined_than (struct symbol *, struct symbol *);
static int equiv_types (struct type *, struct type *);
static int advance_wild_match (const char **, const char *, int);
-static int wild_match (const char *, const char *);
+static bool wild_match (const char *name, const char *patn);
static struct value *ada_coerce_ref (struct value *);
static struct symbol *standard_lookup (const char *, const struct block *,
domain_enum);
-static struct value *ada_search_struct_field (char *, struct value *, int,
+static struct value *ada_search_struct_field (const char *, struct value *, int,
struct type *);
static struct value *ada_value_primitive_field (struct value *, int, int,
static int find_struct_field (const char *, struct type *, int,
struct type **, int *, int *, int *, int *);
-static struct value *ada_to_fixed_value_create (struct type *, CORE_ADDR,
- struct value *);
-
-static int ada_resolve_function (struct ada_symbol_info *, int,
+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 *);
static void ada_language_arch_info (struct gdbarch *,
struct language_arch_info *);
-static void check_size (const struct type *);
-
static struct value *ada_index_struct_field (int, struct value *, int,
struct type *);
int *);
static struct type *ada_find_any_type (const char *name);
+
+static symbol_name_matcher_ftype *ada_get_symbol_name_matcher
+ (const lookup_name_info &lookup_name);
+
\f
/* The result of a symbol lookup to be stored in our symbol cache. */
/* The name used to perform the lookup. */
const char *name;
/* The namespace used during the lookup. */
- domain_enum namespace;
+ domain_enum domain;
/* The symbol returned by the lookup, or NULL if no matching symbol
was found. */
struct symbol *sym;
/* Maximum-sized dynamic type. */
static unsigned int varsize_limit;
-/* FIXME: brobecker/2003-09-17: No longer a const because it is
- returned by a function that does not return a const char *. */
-static char *ada_completer_word_break_characters =
+static const char ada_completer_word_break_characters[] =
#ifdef VMS
" \t\n!@#%^&*()+=|~`}{[]\";:?/,-";
#else
ADA_KNOWN_AUXILIARY_FUNCTION_NAME_PATTERNS NULL
};
-/* Space for allocating results of ada_lookup_symbol_list. */
-static struct obstack symbol_list_obstack;
-
/* Maintenance-related settings for this module. */
static struct cmd_list_element *maint_set_ada_cmdlist;
/* Implement the "maintenance set ada" (prefix) command. */
static void
-maint_set_ada_cmd (char *args, int from_tty)
+maint_set_ada_cmd (const char *args, int from_tty)
{
- help_list (maint_set_ada_cmdlist, "maintenance set ada ", -1, gdb_stdout);
+ help_list (maint_set_ada_cmdlist, "maintenance set ada ", all_commands,
+ gdb_stdout);
}
/* Implement the "maintenance show ada" (prefix) command. */
static void
-maint_show_ada_cmd (char *args, int from_tty)
+maint_show_ada_cmd (const char *args, int from_tty)
{
cmd_show_list (maint_show_ada_cmdlist, from_tty, "");
}
/* The "maintenance ada set/show ignore-descriptive-type" value. */
-static int ada_ignore_descriptive_types_p = 0;
+static bool ada_ignore_descriptive_types_p = false;
/* Inferior-specific data. */
tagged types. With older versions of GNAT, this type was directly
accessible through a component ("tsd") in the object tag. But this
is no longer the case, so we cache it for each inferior. */
- struct type *tsd_type;
+ struct type *tsd_type = nullptr;
/* The exception_support_info data. This data is used to determine
how to implement support for Ada exception catchpoints in a given
inferior. */
- const struct exception_support_info *exception_info;
+ const struct exception_support_info *exception_info = nullptr;
};
/* Our key to this module's inferior data. */
-static const struct inferior_data *ada_inferior_data;
-
-/* A cleanup routine for our inferior data. */
-static void
-ada_inferior_data_cleanup (struct inferior *inf, void *arg)
-{
- struct ada_inferior_data *data;
-
- data = inferior_data (inf, ada_inferior_data);
- if (data != NULL)
- xfree (data);
-}
+static const struct inferior_key<ada_inferior_data> ada_inferior_data;
/* Return our inferior data for the given inferior (INF).
{
struct ada_inferior_data *data;
- data = inferior_data (inf, ada_inferior_data);
+ data = ada_inferior_data.get (inf);
if (data == NULL)
- {
- data = XCNEW (struct ada_inferior_data);
- set_inferior_data (inf, ada_inferior_data, data);
- }
+ data = ada_inferior_data.emplace (inf);
return data;
}
static void
ada_inferior_exit (struct inferior *inf)
{
- ada_inferior_data_cleanup (inf, NULL);
- set_inferior_data (inf, ada_inferior_data, NULL);
+ ada_inferior_data.clear (inf);
}
/* This module's per-program-space data. */
struct ada_pspace_data
{
+ ~ada_pspace_data ()
+ {
+ if (sym_cache != NULL)
+ ada_free_symbol_cache (sym_cache);
+ }
+
/* The Ada symbol cache. */
- struct ada_symbol_cache *sym_cache;
+ struct ada_symbol_cache *sym_cache = nullptr;
};
/* Key to our per-program-space data. */
-static const struct program_space_data *ada_pspace_data_handle;
+static const struct program_space_key<ada_pspace_data> ada_pspace_data_handle;
/* Return this module's data for the given program space (PSPACE).
If not is found, add a zero'ed one now.
{
struct ada_pspace_data *data;
- data = program_space_data (pspace, ada_pspace_data_handle);
+ data = ada_pspace_data_handle.get (pspace);
if (data == NULL)
- {
- data = XCNEW (struct ada_pspace_data);
- set_program_space_data (pspace, ada_pspace_data_handle, data);
- }
+ data = ada_pspace_data_handle.emplace (pspace);
return data;
}
-/* The cleanup callback for this module's per-program-space data. */
-
-static void
-ada_pspace_data_cleanup (struct program_space *pspace, void *data)
-{
- struct ada_pspace_data *pspace_data = data;
-
- if (pspace_data->sym_cache != NULL)
- ada_free_symbol_cache (pspace_data->sym_cache);
- xfree (pspace_data);
-}
-
/* Utilities */
/* If TYPE is a TYPE_CODE_TYPEDEF type, return the target type after
static const char *
ada_unqualified_name (const char *decoded_name)
{
- const char *result = strrchr (decoded_name, '.');
+ const char *result;
+
+ /* If the decoded name starts with '<', it means that the encoded
+ name does not follow standard naming conventions, and thus that
+ it is not your typical Ada symbol name. Trying to unqualify it
+ is therefore pointless and possibly erroneous. */
+ if (decoded_name[0] == '<')
+ return decoded_name;
+ result = strrchr (decoded_name, '.');
if (result != NULL)
result++; /* Skip the dot... */
else
return result;
}
-/* Return a string starting with '<', followed by STR, and '>'.
- The result is good until the next call. */
+/* Return a string starting with '<', followed by STR, and '>'. */
-static char *
+static std::string
add_angle_brackets (const char *str)
{
- static char *result = NULL;
-
- xfree (result);
- result = xstrprintf ("<%s>", str);
- return result;
+ return string_printf ("<%s>", str);
}
-static char *
+static const char *
ada_get_gdb_completer_word_break_characters (void)
{
return ada_completer_word_break_characters;
fprintf_filtered (stream, " => ");
}
+/* la_watch_location_expression for Ada. */
+
+static gdb::unique_xmalloc_ptr<char>
+ada_watch_location_expression (struct type *type, CORE_ADDR addr)
+{
+ type = check_typedef (TYPE_TARGET_TYPE (check_typedef (type)));
+ std::string name = type_to_string (type);
+ return gdb::unique_xmalloc_ptr<char>
+ (xstrprintf ("{%s} %s", name.c_str (), core_addr_to_string (addr)));
+}
+
+/* Assuming V points to an array of S objects, make sure that it contains at
+ least M objects, updating V and S as necessary. */
+
+#define GROW_VECT(v, s, m) \
+ if ((s) < (m)) (v) = (char *) grow_vect (v, &(s), m, sizeof *(v));
+
/* Assuming VECT points to an array of *SIZE objects of size
ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
updating *SIZE as necessary and returning the (new) array. */
-void *
+static void *
grow_vect (void *vect, size_t *size, size_t min_size, int element_size)
{
if (*size < min_size)
return
(strncmp (field_name, target, len) == 0
&& (field_name[len] == '\0'
- || (strncmp (field_name + len, "___", 3) == 0
+ || (startswith (field_name + len, "___")
&& strcmp (field_name + strlen (field_name) - 6,
"___XVN") != 0)));
}
/* Make sure that the object size is not unreasonable before
trying to allocate some memory for it. */
- check_size (type);
+ ada_ensure_varsize_limit (type);
if (value_lazy (val)
|| TYPE_LENGTH (type) > TYPE_LENGTH (value_type (val)))
else
{
result = allocate_value (type);
- memcpy (value_contents_raw (result), value_contents (val),
- TYPE_LENGTH (type));
+ value_contents_copy_raw (result, 0, val, 0, TYPE_LENGTH (type));
}
set_value_component_location (result, val);
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));
+ if (VALUE_LVAL (result) == lval_memory)
+ set_value_address (result, value_address (val));
return result;
}
}
i.e. if it would be a bad idea to allocate a value of this type in
GDB. */
-static void
-check_size (const struct type *type)
+void
+ada_ensure_varsize_limit (const struct type *type)
{
if (TYPE_LENGTH (type) > varsize_limit)
error (_("object size is larger than varsize-limit"));
LONGEST
ada_discrete_type_high_bound (struct type *type)
{
+ type = resolve_dynamic_type (type, NULL, 0);
switch (TYPE_CODE (type))
{
case TYPE_CODE_RANGE:
LONGEST
ada_discrete_type_low_bound (struct type *type)
{
+ type = resolve_dynamic_type (type, NULL, 0);
switch (TYPE_CODE (type))
{
case TYPE_CODE_RANGE:
/* Return a decoded version of the given VALUE. This means returning
a value whose type is obtained by applying all the GNAT-specific
- encondings, making the resulting type a static but standard description
+ encodings, making the resulting type a static but standard description
of the initial type. */
struct value *
/* If the main program is in Ada, return language_ada, otherwise return LANG
(the main program is in Ada iif the adainit symbol is found). */
-enum language
+static enum language
ada_update_initial_language (enum language lang)
{
- if (lookup_minimal_symbol ("adainit", (const char *) NULL,
- (struct objfile *) NULL).minsym != NULL)
+ if (lookup_minimal_symbol ("adainit", NULL, NULL).minsym != NULL)
return language_ada;
return lang;
ada_main_name (void)
{
struct bound_minimal_symbol msym;
- static char *main_program_name = NULL;
+ static gdb::unique_xmalloc_ptr<char> main_program_name;
/* For Ada, the name of the main procedure is stored in a specific
string constant, generated by the binder. Look for that symbol,
if (main_program_name_addr == 0)
error (_("Invalid address for Ada main program name."));
- xfree (main_program_name);
target_read_string (main_program_name_addr, &main_program_name,
1024, &err_code);
if (err_code != 0)
return NULL;
- return main_program_name;
+ return main_program_name.get ();
}
/* The main procedure doesn't seem to be in Ada. */
{NULL, NULL}
};
-/* The "encoded" form of DECODED, according to GNAT conventions.
- The result is valid until the next call to ada_encode. */
+/* The "encoded" form of DECODED, according to GNAT conventions. The
+ result is valid until the next call to ada_encode. If
+ THROW_ERRORS, throw an error if invalid operator name is found.
+ Otherwise, return NULL in that case. */
-char *
-ada_encode (const char *decoded)
+static char *
+ada_encode_1 (const char *decoded, bool throw_errors)
{
static char *encoding_buffer = NULL;
static size_t encoding_buffer_size = 0;
for (mapping = ada_opname_table;
mapping->encoded != NULL
- && strncmp (mapping->decoded, p,
- strlen (mapping->decoded)) != 0; mapping += 1)
+ && !startswith (p, mapping->decoded); mapping += 1)
;
if (mapping->encoded == NULL)
- error (_("invalid Ada operator name: %s"), p);
+ {
+ if (throw_errors)
+ error (_("invalid Ada operator name: %s"), p);
+ else
+ return NULL;
+ }
strcpy (encoding_buffer + k, mapping->encoded);
k += strlen (mapping->encoded);
break;
return encoding_buffer;
}
+/* The "encoded" form of DECODED, according to GNAT conventions.
+ The result is valid until the next call to ada_encode. */
+
+char *
+ada_encode (const char *decoded)
+{
+ return ada_encode_1 (decoded, true);
+}
+
/* Return NAME folded to lower case, or, if surrounded by single
quotes, unfolded, but with the quotes stripped away. Result good
to next call. */
-char *
+static char *
ada_fold_name (const char *name)
{
static char *fold_buffer = NULL;
*len = i;
else if (i >= 0 && encoded[i] == '$')
*len = i;
- else if (i >= 2 && strncmp (encoded + i - 2, "___", 3) == 0)
+ else if (i >= 2 && startswith (encoded + i - 2, "___"))
*len = i - 2;
- else if (i >= 1 && strncmp (encoded + i - 1, "__", 2) == 0)
+ else if (i >= 1 && startswith (encoded + i - 1, "__"))
*len = i - 1;
}
}
*len = *len - 1;
}
-/* Remove trailing X[bn]* suffixes (indicating names in package bodies). */
-
-static void
-ada_remove_Xbn_suffix (const char *encoded, int *len)
-{
- int i = *len - 1;
-
- while (i > 0 && (encoded[i] == 'b' || encoded[i] == 'n'))
- i--;
-
- if (encoded[i] != 'X')
- return;
-
- if (i == 0)
- return;
-
- if (isalnum (encoded[i-1]))
- *len = i;
-}
-
/* If ENCODED follows the GNAT entity encoding conventions, then return
the decoded form of ENCODED. Otherwise, return "<%s>" where "%s" is
- replaced by ENCODED.
-
- The resulting string is valid until the next call of ada_decode.
- If the string is unchanged by decoding, the original string pointer
- is returned. */
+ replaced by ENCODED. */
-const char *
+std::string
ada_decode (const char *encoded)
{
int i, j;
int len0;
const char *p;
- char *decoded;
int at_start_name;
- static char *decoding_buffer = NULL;
- static size_t decoding_buffer_size = 0;
+ std::string decoded;
+
+ /* With function descriptors on PPC64, the value of a symbol named
+ ".FN", if it exists, is the entry point of the function "FN". */
+ if (encoded[0] == '.')
+ encoded += 1;
/* The name of the Ada main procedure starts with "_ada_".
This prefix is not part of the decoded name, so skip this part
if we see this prefix. */
- if (strncmp (encoded, "_ada_", 5) == 0)
+ if (startswith (encoded, "_ada_"))
encoded += 5;
/* If the name starts with '_', then it is not a properly encoded
is for the body of a task, but that information does not actually
appear in the decoded name. */
- if (len0 > 3 && strncmp (encoded + len0 - 3, "TKB", 3) == 0)
+ if (len0 > 3 && startswith (encoded + len0 - 3, "TKB"))
len0 -= 3;
/* Remove any trailing TB suffix. The TB suffix is slightly different
from the TKB suffix because it is used for non-anonymous task
bodies. */
- if (len0 > 2 && strncmp (encoded + len0 - 2, "TB", 2) == 0)
+ if (len0 > 2 && startswith (encoded + len0 - 2, "TB"))
len0 -= 2;
/* Remove trailing "B" suffixes. */
/* FIXME: brobecker/2006-04-19: Not sure what this are used for... */
- if (len0 > 1 && strncmp (encoded + len0 - 1, "B", 1) == 0)
+ if (len0 > 1 && startswith (encoded + len0 - 1, "B"))
len0 -= 1;
/* Make decoded big enough for possible expansion by operator name. */
- GROW_VECT (decoding_buffer, decoding_buffer_size, 2 * len0 + 1);
- decoded = decoding_buffer;
+ decoded.resize (2 * len0 + 1, 'X');
/* Remove trailing __{digit}+ or trailing ${digit}+. */
op_len - 1) == 0)
&& !isalnum (encoded[i + op_len]))
{
- strcpy (decoded + j, ada_opname_table[k].decoded);
+ strcpy (&decoded.front() + j, ada_opname_table[k].decoded);
at_start_name = 0;
i += op_len;
j += strlen (ada_opname_table[k].decoded);
/* Replace "TK__" with "__", which will eventually be translated
into "." (just below). */
- if (i < len0 - 4 && strncmp (encoded + i, "TK__", 4) == 0)
+ if (i < len0 - 4 && startswith (encoded + i, "TK__"))
i += 2;
/* Replace "__B_{DIGITS}+__" sequences by "__", which will eventually
j += 1;
}
}
- decoded[j] = '\000';
+ decoded.resize (j);
/* Decoded names should never contain any uppercase character.
Double-check this, and abort the decoding if we find one. */
- for (i = 0; decoded[i] != '\0'; i += 1)
+ for (i = 0; i < decoded.length(); ++i)
if (isupper (decoded[i]) || decoded[i] == ' ')
goto Suppress;
- if (strcmp (decoded, encoded) == 0)
- return encoded;
- else
- return decoded;
+ return decoded;
Suppress:
- GROW_VECT (decoding_buffer, decoding_buffer_size, strlen (encoded) + 3);
- decoded = decoding_buffer;
if (encoded[0] == '<')
- strcpy (decoded, encoded);
+ decoded = encoded;
else
- xsnprintf (decoded, decoding_buffer_size, "<%s>", encoded);
+ decoded = '<' + std::string(encoded) + '>';
return decoded;
}
{
struct general_symbol_info *gsymbol = (struct general_symbol_info *) arg;
const char **resultp =
- &gsymbol->language_specific.mangled_lang.demangled_name;
+ &gsymbol->language_specific.demangled_name;
if (!gsymbol->ada_mangled)
{
- const char *decoded = ada_decode (gsymbol->name);
+ std::string decoded = ada_decode (gsymbol->name);
struct obstack *obstack = gsymbol->language_specific.obstack;
gsymbol->ada_mangled = 1;
if (obstack != NULL)
- *resultp = obstack_copy0 (obstack, decoded, strlen (decoded));
+ *resultp = obstack_strdup (obstack, decoded.c_str ());
else
{
/* Sometimes, we can't find a corresponding objfile, in
significant memory leak (FIXME). */
char **slot = (char **) htab_find_slot (decoded_names_store,
- decoded, INSERT);
+ decoded.c_str (), INSERT);
if (*slot == NULL)
- *slot = xstrdup (decoded);
+ *slot = xstrdup (decoded.c_str ());
*resultp = *slot;
}
}
static char *
ada_la_decode (const char *encoded, int options)
{
- return xstrdup (ada_decode (encoded));
+ return xstrdup (ada_decode (encoded).c_str ());
}
-/* Returns non-zero iff SYM_NAME matches NAME, ignoring any trailing
- suffixes that encode debugging information or leading _ada_ on
- SYM_NAME (see is_name_suffix commentary for the debugging
- information that is ignored). If WILD, then NAME need only match a
- suffix of SYM_NAME minus the same suffixes. Also returns 0 if
- either argument is NULL. */
+/* Implement la_sniff_from_mangled_name for Ada. */
static int
-match_name (const char *sym_name, const char *name, int wild)
+ada_sniff_from_mangled_name (const char *mangled, char **out)
{
- if (sym_name == NULL || name == NULL)
- return 0;
- else if (wild)
- return wild_match (sym_name, name) == 0;
- else
+ std::string demangled = ada_decode (mangled);
+
+ *out = NULL;
+
+ if (demangled != mangled && demangled[0] != '<')
{
- int len_name = strlen (name);
+ /* Set the gsymbol language to Ada, but still return 0.
+ Two reasons for that:
- return (strncmp (sym_name, name, len_name) == 0
- && is_name_suffix (sym_name + len_name))
- || (strncmp (sym_name, "_ada_", 5) == 0
- && strncmp (sym_name + 5, name, len_name) == 0
- && is_name_suffix (sym_name + len_name + 5));
+ 1. For Ada, we prefer computing the symbol's decoded name
+ on the fly rather than pre-compute it, in order to save
+ memory (Ada projects are typically very large).
+
+ 2. There are some areas in the definition of the GNAT
+ encoding where, with a bit of bad luck, we might be able
+ to decode a non-Ada symbol, generating an incorrect
+ demangled name (Eg: names ending with "TB" for instance
+ are identified as task bodies and so stripped from
+ the decoded name returned).
+
+ Returning 1, here, but not setting *DEMANGLED, helps us get a
+ little bit of the best of both worlds. Because we're last,
+ we should not affect any of the other languages that were
+ able to demangle the symbol before us; we get to correctly
+ tag Ada symbols as such; and even if we incorrectly tagged a
+ non-Ada symbol, which should be rare, any routing through the
+ Ada language should be transparent (Ada tries to behave much
+ like C/C++ with non-Ada symbols). */
+ return 1;
}
+
+ return 0;
}
+
\f
/* Arrays */
Otherwise, do nothing. This function also does nothing if
INDEX_DESC_TYPE is NULL.
- The GNAT encoding used to describle the array index type evolved a bit.
+ The GNAT encoding used to describe the array index type evolved a bit.
Initially, the information would be provided through the name of each
field of the structure type only, while the type of these fields was
described as unspecified and irrelevant. The debugger was then expected
/* Names of MAX_ADA_DIMENS bounds in P_BOUNDS fields of array descriptors. */
-static char *bound_name[] = {
+static const char *bound_name[] = {
"LB0", "UB0", "LB1", "UB1", "LB2", "UB2", "LB3", "UB3",
"LB4", "UB4", "LB5", "UB5", "LB6", "UB6", "LB7", "UB7"
};
the ARR denotes a null array descriptor and BOUNDS is non-zero,
returns NULL. The result is simply the type of ARR if ARR is not
a descriptor. */
-struct type *
+
+static struct type *
ada_type_of_array (struct value *arr, int bounds)
{
if (ada_is_constrained_packed_array_type (value_type (arr)))
struct value *high = desc_one_bound (descriptor, arity, 1);
arity -= 1;
- create_range_type (range_type, value_type (low),
- longest_to_int (value_as_long (low)),
- longest_to_int (value_as_long (high)));
+ create_static_range_type (range_type, value_type (low),
+ longest_to_int (value_as_long (low)),
+ longest_to_int (value_as_long (high)));
elt_type = create_array_type (array_type, elt_type, range_type);
if (ada_is_unconstrained_packed_array_type (value_type (arr)))
if (arrVal == NULL)
error (_("Bounds unavailable for null array pointer."));
- check_size (TYPE_TARGET_TYPE (value_type (arrVal)));
+ ada_ensure_varsize_limit (TYPE_TARGET_TYPE (value_type (arrVal)));
return value_ind (arrVal);
}
else if (ada_is_constrained_packed_array_type (value_type (arr)))
but with the bit sizes of its elements (and those of any
constituent arrays) recorded in the BITSIZE components of its
TYPE_FIELD_BITSIZE values, and with *ELT_BITS set to its total size
- in bits. */
+ in bits.
+
+ Note that, for arrays whose index type has an XA encoding where
+ a bound references a record discriminant, getting that discriminant,
+ and therefore the actual value of that bound, is not possible
+ because none of the given parameters gives us access to the record.
+ This function assumes that it is OK in the context where it is being
+ used to return an array whose bounds are still dynamic and where
+ the length is arbitrary. */
static struct type *
constrained_packed_array_type (struct type *type, long *elt_bits)
TYPE_FIELD_BITSIZE (new_type, 0) = *elt_bits;
TYPE_NAME (new_type) = ada_type_name (type);
- if (get_discrete_bounds (index_type, &low_bound, &high_bound) < 0)
+ if ((TYPE_CODE (check_typedef (index_type)) == TYPE_CODE_RANGE
+ && is_dynamic_type (check_typedef (index_type)))
+ || get_discrete_bounds (index_type, &low_bound, &high_bound) < 0)
low_bound = high_bound = 0;
if (high_bound < low_bound)
*elt_bits = TYPE_LENGTH (new_type) = 0;
lim_warning (_("could not find bounds information on packed array"));
return NULL;
}
- CHECK_TYPEDEF (shadow_type);
+ shadow_type = check_typedef (shadow_type);
if (TYPE_CODE (shadow_type) != TYPE_CODE_ARRAY)
{
{
struct type *type;
- arr = ada_coerce_ref (arr);
-
- /* If our value is a pointer, then dererence it. Make sure that
- this operation does not cause the target type to be fixed, as
- this would indirectly cause this array to be decoded. The rest
- of the routine assumes that the array hasn't been decoded yet,
- so we use the basic "value_ind" routine to perform the dereferencing,
- as opposed to using "ada_value_ind". */
+ /* If our value is a pointer, then dereference it. Likewise if
+ the value is a reference. Make sure that this operation does not
+ cause the target type to be fixed, as this would indirectly cause
+ this array to be decoded. The rest of the routine assumes that
+ the array hasn't been decoded yet, so we use the basic "coerce_ref"
+ and "value_ind" routines to perform the dereferencing, as opposed
+ to using "ada_coerce_ref" or "ada_value_ind". */
+ arr = coerce_ref (arr);
if (TYPE_CODE (ada_check_typedef (value_type (arr))) == TYPE_CODE_PTR)
arr = value_ind (arr);
return NULL;
}
- if (gdbarch_bits_big_endian (get_type_arch (value_type (arr)))
+ if (type_byte_order (value_type (arr)) == BFD_ENDIAN_BIG
&& ada_is_modular_type (value_type (arr)))
{
/* This is a (right-justified) modular type representing a packed
case TYPE_CODE_INT:
return !TYPE_UNSIGNED (type);
case TYPE_CODE_RANGE:
- return TYPE_LOW_BOUND (type) < 0;
+ return TYPE_LOW_BOUND (type) - TYPE_RANGE_DATA (type)->bias < 0;
}
}
+/* With SRC being a buffer containing BIT_SIZE bits of data at BIT_OFFSET,
+ unpack that data into UNPACKED. UNPACKED_LEN is the size in bytes of
+ the unpacked buffer.
-/* Create a new value of type TYPE from the contents of OBJ starting
- at byte OFFSET, and bit offset BIT_OFFSET within that byte,
- proceeding for BIT_SIZE bits. If OBJ is an lval in memory, then
- assigning through the result will set the field fetched from.
- VALADDR is ignored unless OBJ is NULL, in which case,
- VALADDR+OFFSET must address the start of storage containing the
- packed value. The value returned in this case is never an lval.
- Assumes 0 <= BIT_OFFSET < HOST_CHAR_BIT. */
+ The size of the unpacked buffer (UNPACKED_LEN) is expected to be large
+ enough to contain at least BIT_OFFSET bits. If not, an error is raised.
-struct value *
-ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr,
- long offset, int bit_offset, int bit_size,
- struct type *type)
-{
- struct value *v;
- int src, /* Index into the source area */
- targ, /* Index into the target area */
- srcBitsLeft, /* Number of source bits left to move */
- nsrc, ntarg, /* Number of source and target bytes */
- unusedLS, /* Number of bits in next significant
+ IS_BIG_ENDIAN is nonzero if the data is stored in big endian mode,
+ zero otherwise.
+
+ IS_SIGNED_TYPE is nonzero if the data corresponds to a signed type.
+
+ IS_SCALAR is nonzero if the data corresponds to a signed type. */
+
+static void
+ada_unpack_from_contents (const gdb_byte *src, int bit_offset, int bit_size,
+ gdb_byte *unpacked, int unpacked_len,
+ int is_big_endian, int is_signed_type,
+ int is_scalar)
+{
+ int src_len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8;
+ int src_idx; /* Index into the source area */
+ int src_bytes_left; /* Number of source bytes left to process. */
+ int srcBitsLeft; /* Number of source bits left to move */
+ int unusedLS; /* Number of bits in next significant
byte of source that are unused */
- accumSize; /* Number of meaningful bits in accum */
- unsigned char *bytes; /* First byte containing data to unpack */
- unsigned char *unpacked;
+
+ int unpacked_idx; /* Index into the unpacked buffer */
+ int unpacked_bytes_left; /* Number of bytes left to set in unpacked. */
+
unsigned long accum; /* Staging area for bits being transferred */
+ int accumSize; /* Number of meaningful bits in accum */
unsigned char sign;
- int len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8;
+
/* Transmit bytes from least to most significant; delta is the direction
the indices move. */
- int delta = gdbarch_bits_big_endian (get_type_arch (type)) ? -1 : 1;
-
- type = ada_check_typedef (type);
-
- if (obj == NULL)
- {
- v = allocate_value (type);
- bytes = (unsigned char *) (valaddr + offset);
- }
- else if (VALUE_LVAL (obj) == lval_memory && value_lazy (obj))
- {
- v = value_at (type, value_address (obj));
- bytes = (unsigned char *) alloca (len);
- read_memory (value_address (v) + offset, bytes, len);
- }
- else
- {
- v = allocate_value (type);
- bytes = (unsigned char *) value_contents (obj) + offset;
- }
-
- if (obj != NULL)
- {
- long new_offset = offset;
-
- set_value_component_location (v, obj);
- set_value_bitpos (v, bit_offset + value_bitpos (obj));
- set_value_bitsize (v, bit_size);
- if (value_bitpos (v) >= HOST_CHAR_BIT)
- {
- ++new_offset;
- set_value_bitpos (v, value_bitpos (v) - HOST_CHAR_BIT);
- }
- set_value_offset (v, new_offset);
+ int delta = is_big_endian ? -1 : 1;
- /* Also set the parent value. This is needed when trying to
- assign a new value (in inferior memory). */
- set_value_parent (v, obj);
- }
- else
- set_value_bitsize (v, bit_size);
- unpacked = (unsigned char *) value_contents (v);
+ /* Make sure that unpacked is large enough to receive the BIT_SIZE
+ bits from SRC. .*/
+ if ((bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT > unpacked_len)
+ error (_("Cannot unpack %d bits into buffer of %d bytes"),
+ bit_size, unpacked_len);
srcBitsLeft = bit_size;
- nsrc = len;
- ntarg = TYPE_LENGTH (type);
+ src_bytes_left = src_len;
+ unpacked_bytes_left = unpacked_len;
sign = 0;
- if (bit_size == 0)
- {
- memset (unpacked, 0, TYPE_LENGTH (type));
- return v;
- }
- else if (gdbarch_bits_big_endian (get_type_arch (type)))
+
+ if (is_big_endian)
{
- src = len - 1;
- if (has_negatives (type)
- && ((bytes[0] << bit_offset) & (1 << (HOST_CHAR_BIT - 1))))
+ src_idx = src_len - 1;
+ if (is_signed_type
+ && ((src[0] << bit_offset) & (1 << (HOST_CHAR_BIT - 1))))
sign = ~0;
unusedLS =
(HOST_CHAR_BIT - (bit_size + bit_offset) % HOST_CHAR_BIT)
% HOST_CHAR_BIT;
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_ARRAY:
- case TYPE_CODE_UNION:
- case TYPE_CODE_STRUCT:
+ if (is_scalar)
+ {
+ accumSize = 0;
+ unpacked_idx = unpacked_len - 1;
+ }
+ else
+ {
/* Non-scalar values must be aligned at a byte boundary... */
accumSize =
(HOST_CHAR_BIT - bit_size % HOST_CHAR_BIT) % HOST_CHAR_BIT;
/* ... And are placed at the beginning (most-significant) bytes
of the target. */
- targ = (bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT - 1;
- ntarg = targ + 1;
- break;
- default:
- accumSize = 0;
- targ = TYPE_LENGTH (type) - 1;
- break;
- }
+ unpacked_idx = (bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT - 1;
+ unpacked_bytes_left = unpacked_idx + 1;
+ }
}
else
{
int sign_bit_offset = (bit_size + bit_offset - 1) % 8;
- src = targ = 0;
+ src_idx = unpacked_idx = 0;
unusedLS = bit_offset;
accumSize = 0;
- if (has_negatives (type) && (bytes[len - 1] & (1 << sign_bit_offset)))
+ if (is_signed_type && (src[src_len - 1] & (1 << sign_bit_offset)))
sign = ~0;
}
accum = 0;
- while (nsrc > 0)
+ while (src_bytes_left > 0)
{
/* Mask for removing bits of the next source byte that are not
part of the value. */
unsigned int signMask = sign & ~unusedMSMask;
accum |=
- (((bytes[src] >> unusedLS) & unusedMSMask) | signMask) << accumSize;
+ (((src[src_idx] >> unusedLS) & unusedMSMask) | signMask) << accumSize;
accumSize += HOST_CHAR_BIT - unusedLS;
if (accumSize >= HOST_CHAR_BIT)
{
- unpacked[targ] = accum & ~(~0L << HOST_CHAR_BIT);
+ unpacked[unpacked_idx] = accum & ~(~0UL << HOST_CHAR_BIT);
accumSize -= HOST_CHAR_BIT;
accum >>= HOST_CHAR_BIT;
- ntarg -= 1;
- targ += delta;
+ unpacked_bytes_left -= 1;
+ unpacked_idx += delta;
}
srcBitsLeft -= HOST_CHAR_BIT - unusedLS;
unusedLS = 0;
- nsrc -= 1;
- src += delta;
+ src_bytes_left -= 1;
+ src_idx += delta;
}
- while (ntarg > 0)
+ while (unpacked_bytes_left > 0)
{
accum |= sign << accumSize;
- unpacked[targ] = accum & ~(~0L << HOST_CHAR_BIT);
+ unpacked[unpacked_idx] = accum & ~(~0UL << HOST_CHAR_BIT);
accumSize -= HOST_CHAR_BIT;
+ if (accumSize < 0)
+ accumSize = 0;
accum >>= HOST_CHAR_BIT;
- ntarg -= 1;
- targ += delta;
+ unpacked_bytes_left -= 1;
+ unpacked_idx += delta;
}
-
- 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)
+/* Create a new value of type TYPE from the contents of OBJ starting
+ at byte OFFSET, and bit offset BIT_OFFSET within that byte,
+ proceeding for BIT_SIZE bits. If OBJ is an lval in memory, then
+ assigning through the result will set the field fetched from.
+ VALADDR is ignored unless OBJ is NULL, in which case,
+ VALADDR+OFFSET must address the start of storage containing the
+ packed value. The value returned in this case is never an lval.
+ Assumes 0 <= BIT_OFFSET < HOST_CHAR_BIT. */
+
+struct value *
+ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr,
+ long offset, int bit_offset, int bit_size,
+ struct type *type)
{
- unsigned int accum, mask;
- int accum_bits, chunk_size;
+ struct value *v;
+ const gdb_byte *src; /* First byte containing data to unpack */
+ gdb_byte *unpacked;
+ const int is_scalar = is_scalar_type (type);
+ const int is_big_endian = type_byte_order (type) == BFD_ENDIAN_BIG;
+ gdb::byte_vector staging;
+
+ type = ada_check_typedef (type);
+
+ if (obj == NULL)
+ src = valaddr + offset;
+ else
+ src = value_contents (obj) + offset;
+
+ if (is_dynamic_type (type))
+ {
+ /* The length of TYPE might by dynamic, so we need to resolve
+ TYPE in order to know its actual size, which we then use
+ to create the contents buffer of the value we return.
+ The difficulty is that the data containing our object is
+ packed, and therefore maybe not at a byte boundary. So, what
+ we do, is unpack the data into a byte-aligned buffer, and then
+ use that buffer as our object's value for resolving the type. */
+ int staging_len = (bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ staging.resize (staging_len);
+
+ ada_unpack_from_contents (src, bit_offset, bit_size,
+ staging.data (), staging.size (),
+ is_big_endian, has_negatives (type),
+ is_scalar);
+ type = resolve_dynamic_type (type, staging.data (), 0);
+ if (TYPE_LENGTH (type) < (bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT)
+ {
+ /* This happens when the length of the object is dynamic,
+ and is actually smaller than the space reserved for it.
+ For instance, in an array of variant records, the bit_size
+ we're given is the array stride, which is constant and
+ normally equal to the maximum size of its element.
+ But, in reality, each element only actually spans a portion
+ of that stride. */
+ bit_size = TYPE_LENGTH (type) * HOST_CHAR_BIT;
+ }
+ }
- 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)
+ if (obj == NULL)
+ {
+ v = allocate_value (type);
+ src = valaddr + offset;
+ }
+ else if (VALUE_LVAL (obj) == lval_memory && value_lazy (obj))
{
- accum = (unsigned char) *source;
- source += 1;
- accum_bits = HOST_CHAR_BIT - src_offset;
+ int src_len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8;
+ gdb_byte *buf;
- 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;
- }
+ v = value_at (type, value_address (obj) + offset);
+ buf = (gdb_byte *) alloca (src_len);
+ read_memory (value_address (v), buf, src_len);
+ src = buf;
}
else
{
- accum = (unsigned char) *source >> src_offset;
- source += 1;
- accum_bits = HOST_CHAR_BIT - src_offset;
+ v = allocate_value (type);
+ src = value_contents (obj) + offset;
+ }
+
+ if (obj != NULL)
+ {
+ long new_offset = offset;
- while (n > 0)
+ set_value_component_location (v, obj);
+ set_value_bitpos (v, bit_offset + value_bitpos (obj));
+ set_value_bitsize (v, bit_size);
+ if (value_bitpos (v) >= HOST_CHAR_BIT)
{
- 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;
+ ++new_offset;
+ set_value_bitpos (v, value_bitpos (v) - HOST_CHAR_BIT);
}
+ set_value_offset (v, new_offset);
+
+ /* Also set the parent value. This is needed when trying to
+ assign a new value (in inferior memory). */
+ set_value_parent (v, obj);
+ }
+ else
+ set_value_bitsize (v, bit_size);
+ unpacked = value_contents_writeable (v);
+
+ if (bit_size == 0)
+ {
+ memset (unpacked, 0, TYPE_LENGTH (type));
+ return v;
}
+
+ if (staging.size () == TYPE_LENGTH (type))
+ {
+ /* Small short-cut: If we've unpacked the data into a buffer
+ of the same size as TYPE's length, then we can reuse that,
+ instead of doing the unpacking again. */
+ memcpy (unpacked, staging.data (), staging.size ());
+ }
+ else
+ ada_unpack_from_contents (src, bit_offset, bit_size,
+ unpacked, TYPE_LENGTH (type),
+ is_big_endian, has_negatives (type), is_scalar);
+
+ return v;
}
/* Store the contents of FROMVAL into the location of TOVAL.
int len = (value_bitpos (toval)
+ bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
int from_size;
- gdb_byte *buffer = alloca (len);
+ gdb_byte *buffer = (gdb_byte *) alloca (len);
struct value *val;
CORE_ADDR to_addr = value_address (toval);
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 = type_byte_order (type) == BFD_ENDIAN_BIG;
+ 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);
}
-/* Given that COMPONENT is a memory lvalue that is part of the lvalue
- * CONTAINER, assign the contents of VAL to COMPONENTS's place in
- * CONTAINER. Modifies the VALUE_CONTENTS of CONTAINER only, not
- * COMPONENT, and not the inferior's memory. The current contents
- * of COMPONENT are ignored. */
+/* Given that COMPONENT is a memory lvalue that is part of the lvalue
+ CONTAINER, assign the contents of VAL to COMPONENTS's place in
+ CONTAINER. Modifies the VALUE_CONTENTS of CONTAINER only, not
+ COMPONENT, and not the inferior's memory. The current contents
+ of COMPONENT are ignored.
+
+ Although not part of the initial design, this function also works
+ when CONTAINER and COMPONENT are not_lval's: it works as if CONTAINER
+ had a null address, and COMPONENT had an address which is equal to
+ its offset inside CONTAINER. */
+
static void
value_assign_to_component (struct value *container, struct value *component,
struct value *val)
{
LONGEST offset_in_container =
(LONGEST) (value_address (component) - value_address (container));
- int bit_offset_in_container =
+ int bit_offset_in_container =
value_bitpos (component) - value_bitpos (container);
int bits;
-
+
val = value_cast (value_type (component), val);
if (value_bitsize (component) == 0)
else
bits = value_bitsize (component);
- if (gdbarch_bits_big_endian (get_type_arch (value_type (container))))
- move_bits (value_contents_writeable (container) + offset_in_container,
- value_bitpos (container) + bit_offset_in_container,
- value_contents (val),
- TYPE_LENGTH (value_type (component)) * TARGET_CHAR_BIT - bits,
- bits, 1);
+ if (type_byte_order (value_type (container)) == BFD_ENDIAN_BIG)
+ {
+ int src_offset;
+
+ if (is_scalar_type (check_typedef (value_type (component))))
+ src_offset
+ = TYPE_LENGTH (value_type (component)) * TARGET_CHAR_BIT - bits;
+ else
+ src_offset = 0;
+ copy_bitwise (value_contents_writeable (container) + offset_in_container,
+ value_bitpos (container) + bit_offset_in_container,
+ value_contents (val), src_offset, bits, 1);
+ }
else
- move_bits (value_contents_writeable (container) + offset_in_container,
- value_bitpos (container) + bit_offset_in_container,
- value_contents (val), 0, bits, 0);
-}
-
+ copy_bitwise (value_contents_writeable (container) + offset_in_container,
+ value_bitpos (container) + bit_offset_in_container,
+ value_contents (val), 0, bits, 0);
+}
+
+/* Determine if TYPE is an access to an unconstrained array. */
+
+bool
+ada_is_access_to_unconstrained_array (struct type *type)
+{
+ return (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
+ && is_thick_pntr (ada_typedef_target_type (type)));
+}
+
/* The value of the element of array ARR at the ARITY indices given in IND.
ARR may be either a simple array, GNAT array descriptor, or pointer
thereto. */
for (k = 0; k < arity; k += 1)
{
+ struct type *saved_elt_type = TYPE_TARGET_TYPE (elt_type);
+
if (TYPE_CODE (elt_type) != TYPE_CODE_ARRAY)
error (_("too many subscripts (%d expected)"), k);
- elt = value_subscript (elt, pos_atr (ind[k]));
- }
- return elt;
-}
-/* Assuming ARR is a pointer to a standard GDB array of type TYPE, the
- value of the element of *ARR at the ARITY indices given in
- IND. Does not read the entire array into memory. */
+ elt = value_subscript (elt, pos_atr (ind[k]));
+
+ if (ada_is_access_to_unconstrained_array (saved_elt_type)
+ && TYPE_CODE (value_type (elt)) != TYPE_CODE_TYPEDEF)
+ {
+ /* The element is a typedef to an unconstrained array,
+ except that the value_subscript call stripped the
+ typedef layer. The typedef layer is GNAT's way to
+ specify that the element is, at the source level, an
+ access to the unconstrained array, rather than the
+ unconstrained array. So, we need to restore that
+ typedef layer, which we can do by forcing the element's
+ type back to its original type. Otherwise, the returned
+ value is going to be printed as the array, rather
+ than as an access. Another symptom of the same issue
+ would be that an expression trying to dereference the
+ element would also be improperly rejected. */
+ deprecated_set_value_type (elt, saved_elt_type);
+ }
+
+ elt_type = ada_check_typedef (value_type (elt));
+ }
+
+ return elt;
+}
+
+/* Assuming ARR is a pointer to a GDB array, the value of the element
+ of *ARR at the ARITY indices given in IND.
+ Does not read the entire array into memory.
+
+ Note: Unlike what one would expect, this function is used instead of
+ ada_value_subscript for basically all non-packed array types. The reason
+ for this is that a side effect of doing our own pointer arithmetics instead
+ of relying on value_subscript is that there is no implicit typedef peeling.
+ This is important for arrays of array accesses, where it allows us to
+ preserve the fact that the array's element is an array access, where the
+ access part os encoded in a typedef layer. */
static struct value *
-ada_value_ptr_subscript (struct value *arr, struct type *type, int arity,
- struct value **ind)
+ada_value_ptr_subscript (struct value *arr, int arity, struct value **ind)
{
int k;
+ struct value *array_ind = ada_value_ind (arr);
+ struct type *type
+ = check_typedef (value_enclosing_type (array_ind));
+
+ if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_FIELD_BITSIZE (type, 0) > 0)
+ return value_subscript_packed (array_ind, arity, ind);
for (k = 0; k < arity; k += 1)
{
LONGEST lwb, upb;
+ struct value *lwb_value;
if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
error (_("too many subscripts (%d expected)"), k);
arr = value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
value_copy (arr));
get_discrete_bounds (TYPE_INDEX_TYPE (type), &lwb, &upb);
- arr = value_ptradd (arr, pos_atr (ind[k]) - lwb);
+ lwb_value = value_from_longest (value_type(ind[k]), lwb);
+ arr = value_ptradd (arr, pos_atr (ind[k]) - pos_atr (lwb_value));
type = TYPE_TARGET_TYPE (type);
}
}
/* Given that ARRAY_PTR is a pointer or reference to an array of type TYPE (the
- actual type of ARRAY_PTR is ignored), returns the Ada slice of HIGH-LOW+1
- elements starting at index LOW. The lower bound of this array is LOW, as
- per Ada rules. */
+ actual type of ARRAY_PTR is ignored), returns the Ada slice of
+ HIGH'Pos-LOW'Pos+1 elements starting at index LOW. The lower bound of
+ this array is LOW, as per Ada rules. */
static struct value *
ada_value_slice_from_ptr (struct value *array_ptr, struct type *type,
int low, int high)
{
struct type *type0 = ada_check_typedef (type);
- CORE_ADDR base = value_as_address (array_ptr)
- + ((low - ada_discrete_type_low_bound (TYPE_INDEX_TYPE (type0)))
+ struct type *base_index_type = TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0));
+ struct type *index_type
+ = create_static_range_type (NULL, base_index_type, low, high);
+ struct type *slice_type = create_array_type_with_stride
+ (NULL, TYPE_TARGET_TYPE (type0), index_type,
+ get_dyn_prop (DYN_PROP_BYTE_STRIDE, type0),
+ TYPE_FIELD_BITSIZE (type0, 0));
+ int base_low = ada_discrete_type_low_bound (TYPE_INDEX_TYPE (type0));
+ LONGEST base_low_pos, low_pos;
+ CORE_ADDR base;
+
+ if (!discrete_position (base_index_type, low, &low_pos)
+ || !discrete_position (base_index_type, base_low, &base_low_pos))
+ {
+ warning (_("unable to get positions in slice, use bounds instead"));
+ low_pos = low;
+ base_low_pos = base_low;
+ }
+
+ base = value_as_address (array_ptr)
+ + ((low_pos - base_low_pos)
* TYPE_LENGTH (TYPE_TARGET_TYPE (type0)));
- struct type *index_type =
- create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0)),
- low, high);
- struct type *slice_type =
- create_array_type (NULL, TYPE_TARGET_TYPE (type0), index_type);
-
return value_at_lazy (slice_type, base);
}
ada_value_slice (struct value *array, int low, int high)
{
struct type *type = ada_check_typedef (value_type (array));
- struct type *index_type =
- create_range_type (NULL, TYPE_INDEX_TYPE (type), low, high);
- struct type *slice_type =
- create_array_type (NULL, TYPE_TARGET_TYPE (type), index_type);
+ struct type *base_index_type = TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type));
+ struct type *index_type
+ = create_static_range_type (NULL, TYPE_INDEX_TYPE (type), low, high);
+ struct type *slice_type = create_array_type_with_stride
+ (NULL, TYPE_TARGET_TYPE (type), index_type,
+ get_dyn_prop (DYN_PROP_BYTE_STRIDE, type),
+ TYPE_FIELD_BITSIZE (type, 0));
+ LONGEST low_pos, high_pos;
- return value_cast (slice_type, value_slice (array, low, high - low + 1));
+ if (!discrete_position (base_index_type, low, &low_pos)
+ || !discrete_position (base_index_type, high, &high_pos))
+ {
+ warning (_("unable to get positions in slice, use bounds instead"));
+ low_pos = low;
+ high_pos = high;
+ }
+
+ return value_cast (slice_type,
+ value_slice (array, low, high_pos - low_pos + 1));
}
/* If type is a record type in the form of a standard GNAT array
else
type = arr_type;
- index_type_desc = ada_find_parallel_type (type, "___XA");
- ada_fixup_array_indexes_type (index_type_desc);
+ if (TYPE_FIXED_INSTANCE (type))
+ {
+ /* The array has already been fixed, so we do not need to
+ check the parallel ___XA type again. That encoding has
+ already been applied, so ignore it now. */
+ index_type_desc = NULL;
+ }
+ else
+ {
+ index_type_desc = ada_find_parallel_type (type, "___XA");
+ ada_fixup_array_indexes_type (index_type_desc);
+ }
+
if (index_type_desc != NULL)
index_type = to_fixed_range_type (TYPE_FIELD_TYPE (index_type_desc, n - 1),
NULL);
static LONGEST
ada_array_bound (struct value *arr, int n, int which)
{
- struct type *arr_type = value_type (arr);
+ struct type *arr_type;
+
+ if (TYPE_CODE (check_typedef (value_type (arr))) == TYPE_CODE_PTR)
+ arr = value_ind (arr);
+ arr_type = value_enclosing_type (arr);
if (ada_is_constrained_packed_array_type (arr_type))
return ada_array_bound (decode_constrained_packed_array (arr), n, which);
static LONGEST
ada_array_length (struct value *arr, int n)
{
- struct type *arr_type = ada_check_typedef (value_type (arr));
+ struct type *arr_type, *index_type;
+ int low, high;
+
+ if (TYPE_CODE (check_typedef (value_type (arr))) == TYPE_CODE_PTR)
+ arr = value_ind (arr);
+ arr_type = value_enclosing_type (arr);
if (ada_is_constrained_packed_array_type (arr_type))
return ada_array_length (decode_constrained_packed_array (arr), n);
if (ada_is_simple_array_type (arr_type))
- return (ada_array_bound_from_type (arr_type, n, 1)
- - ada_array_bound_from_type (arr_type, n, 0) + 1);
+ {
+ low = ada_array_bound_from_type (arr_type, n, 0);
+ high = ada_array_bound_from_type (arr_type, n, 1);
+ }
else
- return (value_as_long (desc_one_bound (desc_bounds (arr), n, 1))
- - value_as_long (desc_one_bound (desc_bounds (arr), n, 0)) + 1);
+ {
+ low = value_as_long (desc_one_bound (desc_bounds (arr), n, 0));
+ high = value_as_long (desc_one_bound (desc_bounds (arr), n, 1));
+ }
+
+ arr_type = check_typedef (arr_type);
+ index_type = ada_index_type (arr_type, n, "length");
+ if (index_type != NULL)
+ {
+ struct type *base_type;
+ if (TYPE_CODE (index_type) == TYPE_CODE_RANGE)
+ base_type = TYPE_TARGET_TYPE (index_type);
+ else
+ base_type = index_type;
+
+ low = pos_atr (value_from_longest (base_type, low));
+ high = pos_atr (value_from_longest (base_type, high));
+ }
+ 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_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)),
- low, low - 1);
+ struct type *index_type
+ = create_static_range_type
+ (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));
error (_("Could not find operator name for opcode"));
}
+/* Returns true (non-zero) iff decoded name N0 should appear before N1
+ in a listing of choices during disambiguation (see sort_choices, below).
+ The idea is that overloadings of a subprogram name from the
+ same package should sort in their source order. We settle for ordering
+ such symbols by their trailing number (__N or $N). */
+
+static int
+encoded_ordered_before (const char *N0, const char *N1)
+{
+ if (N1 == NULL)
+ return 0;
+ else if (N0 == NULL)
+ return 1;
+ else
+ {
+ int k0, k1;
+
+ for (k0 = strlen (N0) - 1; k0 > 0 && isdigit (N0[k0]); k0 -= 1)
+ ;
+ for (k1 = strlen (N1) - 1; k1 > 0 && isdigit (N1[k1]); k1 -= 1)
+ ;
+ if ((N0[k0] == '_' || N0[k0] == '$') && N0[k0 + 1] != '\000'
+ && (N1[k1] == '_' || N1[k1] == '$') && N1[k1 + 1] != '\000')
+ {
+ int n0, n1;
+
+ n0 = k0;
+ while (N0[n0] == '_' && n0 > 0 && N0[n0 - 1] == '_')
+ n0 -= 1;
+ n1 = k1;
+ while (N1[n1] == '_' && n1 > 0 && N1[n1 - 1] == '_')
+ n1 -= 1;
+ if (n0 == n1 && strncmp (N0, N1, n0) == 0)
+ return (atoi (N0 + k0 + 1) < atoi (N1 + k1 + 1));
+ }
+ return (strcmp (N0, N1) < 0);
+ }
+}
+
+/* Sort SYMS[0..NSYMS-1] to put the choices in a canonical order by the
+ encoded names. */
+
+static void
+sort_choices (struct block_symbol syms[], int nsyms)
+{
+ int i;
+
+ for (i = 1; i < nsyms; i += 1)
+ {
+ struct block_symbol sym = syms[i];
+ int j;
+
+ for (j = i - 1; j >= 0; j -= 1)
+ {
+ if (encoded_ordered_before (syms[j].symbol->linkage_name (),
+ sym.symbol->linkage_name ()))
+ break;
+ syms[j + 1] = syms[j];
+ }
+ syms[j + 1] = sym;
+ }
+}
+
+/* Whether GDB should display formals and return types for functions in the
+ overloads selection menu. */
+static bool print_signatures = true;
+
+/* Print the signature for SYM on STREAM according to the FLAGS options. For
+ all but functions, the signature is just the name of the symbol. For
+ functions, this is the name of the function, the list of types for formals
+ and the return type (if any). */
+
+static void
+ada_print_symbol_signature (struct ui_file *stream, struct symbol *sym,
+ const struct type_print_options *flags)
+{
+ struct type *type = SYMBOL_TYPE (sym);
+
+ fprintf_filtered (stream, "%s", sym->print_name ());
+ if (!print_signatures
+ || type == NULL
+ || TYPE_CODE (type) != TYPE_CODE_FUNC)
+ return;
+
+ if (TYPE_NFIELDS (type) > 0)
+ {
+ int i;
+
+ fprintf_filtered (stream, " (");
+ for (i = 0; i < TYPE_NFIELDS (type); ++i)
+ {
+ if (i > 0)
+ fprintf_filtered (stream, "; ");
+ ada_print_type (TYPE_FIELD_TYPE (type, i), NULL, stream, -1, 0,
+ flags);
+ }
+ fprintf_filtered (stream, ")");
+ }
+ if (TYPE_TARGET_TYPE (type) != NULL
+ && TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
+ {
+ fprintf_filtered (stream, " return ");
+ ada_print_type (TYPE_TARGET_TYPE (type), NULL, stream, -1, 0, flags);
+ }
+}
+
+/* Read and validate a set of numeric choices from the user in the
+ range 0 .. N_CHOICES-1. Place the results in increasing
+ order in CHOICES[0 .. N-1], and return N.
+
+ The user types choices as a sequence of numbers on one line
+ separated by blanks, encoding them as follows:
+
+ + A choice of 0 means to cancel the selection, throwing an error.
+ + If IS_ALL_CHOICE, a choice of 1 selects the entire set 0 .. N_CHOICES-1.
+ + The user chooses k by typing k+IS_ALL_CHOICE+1.
+
+ The user is not allowed to choose more than MAX_RESULTS values.
+
+ ANNOTATION_SUFFIX, if present, is used to annotate the input
+ prompts (for use with the -f switch). */
+
+static int
+get_selections (int *choices, int n_choices, int max_results,
+ int is_all_choice, const char *annotation_suffix)
+{
+ const char *args;
+ const char *prompt;
+ int n_chosen;
+ int first_choice = is_all_choice ? 2 : 1;
+
+ prompt = getenv ("PS2");
+ if (prompt == NULL)
+ prompt = "> ";
+
+ args = command_line_input (prompt, annotation_suffix);
+
+ if (args == NULL)
+ error_no_arg (_("one or more choice numbers"));
+
+ n_chosen = 0;
+
+ /* Set choices[0 .. n_chosen-1] to the users' choices in ascending
+ order, as given in args. Choices are validated. */
+ while (1)
+ {
+ char *args2;
+ int choice, j;
+
+ args = skip_spaces (args);
+ if (*args == '\0' && n_chosen == 0)
+ error_no_arg (_("one or more choice numbers"));
+ else if (*args == '\0')
+ break;
+
+ choice = strtol (args, &args2, 10);
+ if (args == args2 || choice < 0
+ || choice > n_choices + first_choice - 1)
+ error (_("Argument must be choice number"));
+ args = args2;
+
+ if (choice == 0)
+ error (_("cancelled"));
+
+ if (choice < first_choice)
+ {
+ n_chosen = n_choices;
+ for (j = 0; j < n_choices; j += 1)
+ choices[j] = j;
+ break;
+ }
+ choice -= first_choice;
+
+ for (j = n_chosen - 1; j >= 0 && choice < choices[j]; j -= 1)
+ {
+ }
+
+ if (j < 0 || choice != choices[j])
+ {
+ int k;
+
+ for (k = n_chosen - 1; k > j; k -= 1)
+ choices[k + 1] = choices[k];
+ choices[j + 1] = choice;
+ n_chosen += 1;
+ }
+ }
+
+ if (n_chosen > max_results)
+ error (_("Select no more than %d of the above"), max_results);
+
+ return n_chosen;
+}
+
+/* Given a list of NSYMS symbols in SYMS, select up to MAX_RESULTS>0
+ by asking the user (if necessary), returning the number selected,
+ and setting the first elements of SYMS items. Error if no symbols
+ selected. */
+
+/* NOTE: Adapted from decode_line_2 in symtab.c, with which it ought
+ to be re-integrated one of these days. */
+
+static int
+user_select_syms (struct block_symbol *syms, int nsyms, int max_results)
+{
+ int i;
+ int *chosen = XALLOCAVEC (int , nsyms);
+ int n_chosen;
+ int first_choice = (max_results == 1) ? 1 : 2;
+ const char *select_mode = multiple_symbols_select_mode ();
+
+ if (max_results < 1)
+ error (_("Request to select 0 symbols!"));
+ if (nsyms <= 1)
+ return nsyms;
+
+ if (select_mode == multiple_symbols_cancel)
+ 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_filtered (_("[0] cancel\n"));
+ if (max_results > 1)
+ printf_filtered (_("[1] all\n"));
+
+ sort_choices (syms, nsyms);
+
+ for (i = 0; i < nsyms; i += 1)
+ {
+ if (syms[i].symbol == NULL)
+ continue;
+
+ if (SYMBOL_CLASS (syms[i].symbol) == LOC_BLOCK)
+ {
+ struct symtab_and_line sal =
+ find_function_start_sal (syms[i].symbol, 1);
+
+ printf_filtered ("[%d] ", i + first_choice);
+ ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
+ &type_print_raw_options);
+ if (sal.symtab == NULL)
+ printf_filtered (_(" at %p[<no source file available>%p]:%d\n"),
+ metadata_style.style ().ptr (), nullptr, sal.line);
+ else
+ printf_filtered
+ (_(" at %ps:%d\n"),
+ styled_string (file_name_style.style (),
+ symtab_to_filename_for_display (sal.symtab)),
+ sal.line);
+ continue;
+ }
+ else
+ {
+ int is_enumeral =
+ (SYMBOL_CLASS (syms[i].symbol) == LOC_CONST
+ && SYMBOL_TYPE (syms[i].symbol) != NULL
+ && TYPE_CODE (SYMBOL_TYPE (syms[i].symbol)) == TYPE_CODE_ENUM);
+ struct symtab *symtab = NULL;
+
+ if (SYMBOL_OBJFILE_OWNED (syms[i].symbol))
+ symtab = symbol_symtab (syms[i].symbol);
+
+ if (SYMBOL_LINE (syms[i].symbol) != 0 && symtab != NULL)
+ {
+ printf_filtered ("[%d] ", i + first_choice);
+ ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
+ &type_print_raw_options);
+ 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_filtered (("[%d] "), i + first_choice);
+ ada_print_type (SYMBOL_TYPE (syms[i].symbol), NULL,
+ gdb_stdout, -1, 0, &type_print_raw_options);
+ printf_filtered (_("'(%s) (enumeral)\n"),
+ syms[i].symbol->print_name ());
+ }
+ else
+ {
+ printf_filtered ("[%d] ", i + first_choice);
+ ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
+ &type_print_raw_options);
+
+ if (symtab != NULL)
+ printf_filtered (is_enumeral
+ ? _(" in %s (enumeral)\n")
+ : _(" at %s:?\n"),
+ symtab_to_filename_for_display (symtab));
+ else
+ printf_filtered (is_enumeral
+ ? _(" (enumeral)\n")
+ : _(" at ?\n"));
+ }
+ }
+ }
+
+ n_chosen = get_selections (chosen, nsyms, max_results, max_results > 1,
+ "overload-choice");
+
+ for (i = 0; i < n_chosen; i += 1)
+ syms[i] = syms[chosen[i]];
+
+ return n_chosen;
+}
/* Same as evaluate_type (*EXP), but resolves ambiguous symbol
references (marked by OP_VAR_VALUE nodes in which the symbol has an
return type is preferred. May change (expand) *EXP. */
static void
-resolve (struct expression **expp, int void_context_p)
+resolve (expression_up *expp, int void_context_p, int parse_completion,
+ innermost_block_tracker *tracker)
{
struct type *context_type = NULL;
int pc = 0;
if (void_context_p)
context_type = builtin_type ((*expp)->gdbarch)->builtin_void;
- resolve_subexp (expp, &pc, 1, context_type);
+ resolve_subexp (expp, &pc, 1, context_type, parse_completion, tracker);
}
/* Resolve the operator of the subexpression beginning at
are as in ada_resolve, above. */
static struct value *
-resolve_subexp (struct expression **expp, int *pos, int deprocedure_p,
- struct type *context_type)
+resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
+ struct type *context_type, int parse_completion,
+ innermost_block_tracker *tracker)
{
int pc = *pos;
int i;
argvec = NULL;
nargs = 0;
- exp = *expp;
+ exp = expp->get ();
/* Pass one: resolve operands, saving their types and updating *pos,
if needed. */
else
{
*pos += 3;
- resolve_subexp (expp, pos, 0, NULL);
+ resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
}
nargs = longest_to_int (exp->elts[pc + 1].longconst);
break;
case UNOP_ADDR:
*pos += 1;
- resolve_subexp (expp, pos, 0, NULL);
+ resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
break;
case UNOP_QUAL:
*pos += 3;
- resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type));
+ resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type),
+ parse_completion, tracker);
break;
case OP_ATR_MODULUS:
struct value *arg1;
*pos += 1;
- arg1 = resolve_subexp (expp, pos, 0, NULL);
+ arg1 = resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
if (arg1 == NULL)
- resolve_subexp (expp, pos, 1, NULL);
+ resolve_subexp (expp, pos, 1, NULL, parse_completion, tracker);
else
- resolve_subexp (expp, pos, 1, value_type (arg1));
+ resolve_subexp (expp, pos, 1, value_type (arg1), parse_completion,
+ tracker);
break;
}
break;
case OP_LONG:
- case OP_DOUBLE:
+ case OP_FLOAT:
case OP_VAR_VALUE:
+ case OP_VAR_MSYM_VALUE:
*pos += 4;
break;
error (_("Unexpected operator during name resolution"));
}
- argvec = (struct value * *) alloca (sizeof (struct value *) * (nargs + 1));
+ argvec = XALLOCAVEC (struct value *, nargs + 1);
for (i = 0; i < nargs; i += 1)
- argvec[i] = resolve_subexp (expp, pos, 1, NULL);
+ argvec[i] = resolve_subexp (expp, pos, 1, NULL, parse_completion,
+ tracker);
argvec[i] = NULL;
- exp = *expp;
+ exp = expp->get ();
/* Pass two: perform any resolution on principal operator. */
switch (op)
case OP_VAR_VALUE:
if (SYMBOL_DOMAIN (exp->elts[pc + 2].symbol) == UNDEF_DOMAIN)
{
- struct ada_symbol_info *candidates;
+ std::vector<struct block_symbol> candidates;
int n_candidates;
n_candidates =
- ada_lookup_symbol_list (SYMBOL_LINKAGE_NAME
- (exp->elts[pc + 2].symbol),
+ ada_lookup_symbol_list (exp->elts[pc + 2].symbol->linkage_name (),
exp->elts[pc + 1].block, VAR_DOMAIN,
&candidates);
out all types. */
int j;
for (j = 0; j < n_candidates; j += 1)
- switch (SYMBOL_CLASS (candidates[j].sym))
+ switch (SYMBOL_CLASS (candidates[j].symbol))
{
case LOC_REGISTER:
case LOC_ARG:
j = 0;
while (j < n_candidates)
{
- if (SYMBOL_CLASS (candidates[j].sym) == LOC_TYPEDEF)
+ if (SYMBOL_CLASS (candidates[j].symbol) == LOC_TYPEDEF)
{
candidates[j] = candidates[n_candidates - 1];
n_candidates -= 1;
if (n_candidates == 0)
error (_("No definition found for %s"),
- SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol));
+ exp->elts[pc + 2].symbol->print_name ());
else if (n_candidates == 1)
i = 0;
else if (deprocedure_p
- && !is_nonfunction (candidates, n_candidates))
+ && !is_nonfunction (candidates.data (), n_candidates))
{
i = ada_resolve_function
- (candidates, n_candidates, NULL, 0,
- SYMBOL_LINKAGE_NAME (exp->elts[pc + 2].symbol),
- context_type);
+ (candidates.data (), n_candidates, NULL, 0,
+ exp->elts[pc + 2].symbol->linkage_name (),
+ 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 + 2].symbol->print_name ());
}
else
{
printf_filtered (_("Multiple matches for %s\n"),
- SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol));
- user_select_syms (candidates, n_candidates, 1);
+ exp->elts[pc + 2].symbol->print_name ());
+ user_select_syms (candidates.data (), n_candidates, 1);
i = 0;
}
exp->elts[pc + 1].block = candidates[i].block;
- exp->elts[pc + 2].symbol = candidates[i].sym;
- if (innermost_block == NULL
- || contained_in (candidates[i].block, innermost_block))
- innermost_block = candidates[i].block;
+ exp->elts[pc + 2].symbol = candidates[i].symbol;
+ tracker->update (candidates[i]);
}
if (deprocedure_p
&& (TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 2].symbol))
== TYPE_CODE_FUNC))
{
- replace_operator_with_call (expp, pc, 0, 0,
+ replace_operator_with_call (expp, pc, 0, 4,
exp->elts[pc + 2].symbol,
exp->elts[pc + 1].block);
- exp = *expp;
+ exp = expp->get ();
}
break;
if (exp->elts[pc + 3].opcode == OP_VAR_VALUE
&& SYMBOL_DOMAIN (exp->elts[pc + 5].symbol) == UNDEF_DOMAIN)
{
- struct ada_symbol_info *candidates;
+ std::vector<struct block_symbol> candidates;
int n_candidates;
n_candidates =
- ada_lookup_symbol_list (SYMBOL_LINKAGE_NAME
- (exp->elts[pc + 5].symbol),
+ ada_lookup_symbol_list (exp->elts[pc + 5].symbol->linkage_name (),
exp->elts[pc + 4].block, VAR_DOMAIN,
&candidates);
+
if (n_candidates == 1)
i = 0;
else
{
i = ada_resolve_function
- (candidates, n_candidates,
+ (candidates.data (), n_candidates,
argvec, nargs,
- SYMBOL_LINKAGE_NAME (exp->elts[pc + 5].symbol),
- context_type);
+ exp->elts[pc + 5].symbol->linkage_name (),
+ 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 + 5].symbol->print_name ());
}
exp->elts[pc + 4].block = candidates[i].block;
- exp->elts[pc + 5].symbol = candidates[i].sym;
- if (innermost_block == NULL
- || contained_in (candidates[i].block, innermost_block))
- innermost_block = candidates[i].block;
+ exp->elts[pc + 5].symbol = candidates[i].symbol;
+ tracker->update (candidates[i]);
}
}
break;
case UNOP_ABS:
if (possible_user_operator_p (op, argvec))
{
- struct ada_symbol_info *candidates;
+ std::vector<struct block_symbol> candidates;
int n_candidates;
n_candidates =
- ada_lookup_symbol_list (ada_encode (ada_decoded_op_name (op)),
- (struct block *) NULL, VAR_DOMAIN,
+ ada_lookup_symbol_list (ada_decoded_op_name (op),
+ NULL, VAR_DOMAIN,
&candidates);
- i = ada_resolve_function (candidates, n_candidates, argvec, nargs,
- ada_decoded_op_name (op), NULL);
+
+ i = ada_resolve_function (candidates.data (), n_candidates, argvec,
+ nargs, ada_decoded_op_name (op), NULL,
+ parse_completion);
if (i < 0)
break;
- replace_operator_with_call (expp, pc, nargs, 1,
- candidates[i].sym, candidates[i].block);
- exp = *expp;
+ replace_operator_with_call (expp, pc, nargs, 1,
+ candidates[i].symbol,
+ candidates[i].block);
+ exp = expp->get ();
}
break;
}
*pos = pc;
- return evaluate_subexp_type (exp, pos);
+ if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE)
+ return evaluate_var_msym_value (EVAL_AVOID_SIDE_EFFECTS,
+ exp->elts[pc + 1].objfile,
+ exp->elts[pc + 2].msymbol);
+ else
+ return evaluate_subexp_type (exp, pos);
}
/* Return non-zero if formal type FTYPE matches actual type ATYPE. If
may also be an enumeral, in which case it is treated as a 0-
argument function. */
-static int
-ada_args_match (struct symbol *func, struct value **actuals, int n_actuals)
-{
- int i;
- struct type *func_type = SYMBOL_TYPE (func);
-
- if (SYMBOL_CLASS (func) == LOC_CONST
- && TYPE_CODE (func_type) == TYPE_CODE_ENUM)
- return (n_actuals == 0);
- else if (func_type == NULL || TYPE_CODE (func_type) != TYPE_CODE_FUNC)
- return 0;
-
- if (TYPE_NFIELDS (func_type) != n_actuals)
- return 0;
-
- for (i = 0; i < n_actuals; i += 1)
- {
- if (actuals[i] == NULL)
- return 0;
- else
- {
- struct type *ftype = ada_check_typedef (TYPE_FIELD_TYPE (func_type,
- i));
- struct type *atype = ada_check_typedef (value_type (actuals[i]));
-
- if (!ada_type_match (ftype, atype, 1))
- return 0;
- }
- }
- return 1;
-}
-
-/* False iff function type FUNC_TYPE definitely does not produce a value
- compatible with type CONTEXT_TYPE. Conservatively returns 1 if
- FUNC_TYPE is not a valid function type with a non-null return type
- or an enumerated type. A null CONTEXT_TYPE indicates any non-void type. */
-
-static int
-return_match (struct type *func_type, struct type *context_type)
-{
- struct type *return_type;
-
- if (func_type == NULL)
- return 1;
-
- if (TYPE_CODE (func_type) == TYPE_CODE_FUNC)
- return_type = get_base_type (TYPE_TARGET_TYPE (func_type));
- else
- return_type = get_base_type (func_type);
- if (return_type == NULL)
- return 1;
-
- context_type = get_base_type (context_type);
-
- if (TYPE_CODE (return_type) == TYPE_CODE_ENUM)
- return context_type == NULL || return_type == context_type;
- else if (context_type == NULL)
- return TYPE_CODE (return_type) != TYPE_CODE_VOID;
- else
- return TYPE_CODE (return_type) == TYPE_CODE (context_type);
-}
-
-
-/* Returns the index in SYMS[0..NSYMS-1] that contains the symbol for the
- function (if any) that matches the types of the NARGS arguments in
- ARGS. If CONTEXT_TYPE is non-null and there is at least one match
- that returns that type, then eliminate matches that don't. If
- CONTEXT_TYPE is void and there is at least one match that does not
- return void, eliminate all matches that do.
-
- Asks the user if there is more than one match remaining. Returns -1
- if there is no such symbol or none is selected. NAME is used
- solely for messages. May re-arrange and modify SYMS in
- the process; the index returned is for the modified vector. */
-
-static int
-ada_resolve_function (struct ada_symbol_info syms[],
- int nsyms, struct value **args, int nargs,
- const char *name, struct type *context_type)
-{
- int fallback;
- int k;
- int m; /* Number of hits */
-
- m = 0;
- /* In the first pass of the loop, we only accept functions matching
- context_type. If none are found, we add a second pass of the loop
- where every function is accepted. */
- for (fallback = 0; m == 0 && fallback < 2; fallback++)
- {
- for (k = 0; k < nsyms; k += 1)
- {
- struct type *type = ada_check_typedef (SYMBOL_TYPE (syms[k].sym));
-
- if (ada_args_match (syms[k].sym, args, nargs)
- && (fallback || return_match (type, context_type)))
- {
- syms[m] = syms[k];
- m += 1;
- }
- }
- }
-
- if (m == 0)
- return -1;
- else if (m > 1)
- {
- printf_filtered (_("Multiple matches for %s\n"), name);
- user_select_syms (syms, m, 1);
- return 0;
- }
- return 0;
-}
-
-/* Returns true (non-zero) iff decoded name N0 should appear before N1
- in a listing of choices during disambiguation (see sort_choices, below).
- The idea is that overloadings of a subprogram name from the
- same package should sort in their source order. We settle for ordering
- such symbols by their trailing number (__N or $N). */
-
-static int
-encoded_ordered_before (const char *N0, const char *N1)
-{
- if (N1 == NULL)
- return 0;
- else if (N0 == NULL)
- return 1;
- else
- {
- int k0, k1;
-
- for (k0 = strlen (N0) - 1; k0 > 0 && isdigit (N0[k0]); k0 -= 1)
- ;
- for (k1 = strlen (N1) - 1; k1 > 0 && isdigit (N1[k1]); k1 -= 1)
- ;
- if ((N0[k0] == '_' || N0[k0] == '$') && N0[k0 + 1] != '\000'
- && (N1[k1] == '_' || N1[k1] == '$') && N1[k1 + 1] != '\000')
- {
- int n0, n1;
-
- n0 = k0;
- while (N0[n0] == '_' && n0 > 0 && N0[n0 - 1] == '_')
- n0 -= 1;
- n1 = k1;
- while (N1[n1] == '_' && n1 > 0 && N1[n1 - 1] == '_')
- n1 -= 1;
- if (n0 == n1 && strncmp (N0, N1, n0) == 0)
- return (atoi (N0 + k0 + 1) < atoi (N1 + k1 + 1));
- }
- return (strcmp (N0, N1) < 0);
- }
-}
-
-/* Sort SYMS[0..NSYMS-1] to put the choices in a canonical order by the
- encoded names. */
-
-static void
-sort_choices (struct ada_symbol_info syms[], int nsyms)
-{
- int i;
-
- for (i = 1; i < nsyms; i += 1)
- {
- struct ada_symbol_info sym = syms[i];
- int j;
-
- for (j = i - 1; j >= 0; j -= 1)
- {
- if (encoded_ordered_before (SYMBOL_LINKAGE_NAME (syms[j].sym),
- SYMBOL_LINKAGE_NAME (sym.sym)))
- break;
- syms[j + 1] = syms[j];
- }
- syms[j + 1] = sym;
- }
-}
-
-/* Given a list of NSYMS symbols in SYMS, select up to MAX_RESULTS>0
- by asking the user (if necessary), returning the number selected,
- and setting the first elements of SYMS items. Error if no symbols
- selected. */
-
-/* NOTE: Adapted from decode_line_2 in symtab.c, with which it ought
- to be re-integrated one of these days. */
-
-int
-user_select_syms (struct ada_symbol_info *syms, int nsyms, int max_results)
-{
- int i;
- int *chosen = (int *) alloca (sizeof (int) * nsyms);
- int n_chosen;
- int first_choice = (max_results == 1) ? 1 : 2;
- const char *select_mode = multiple_symbols_select_mode ();
-
- if (max_results < 1)
- error (_("Request to select 0 symbols!"));
- if (nsyms <= 1)
- return nsyms;
-
- if (select_mode == multiple_symbols_cancel)
- 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"));
- if (max_results > 1)
- printf_unfiltered (_("[1] all\n"));
-
- sort_choices (syms, nsyms);
-
- for (i = 0; i < nsyms; i += 1)
- {
- if (syms[i].sym == NULL)
- continue;
-
- if (SYMBOL_CLASS (syms[i].sym) == LOC_BLOCK)
- {
- struct symtab_and_line sal =
- find_function_start_sal (syms[i].sym, 1);
-
- if (sal.symtab == NULL)
- printf_unfiltered (_("[%d] %s at <no source file available>:%d\n"),
- i + first_choice,
- SYMBOL_PRINT_NAME (syms[i].sym),
- sal.line);
- else
- printf_unfiltered (_("[%d] %s at %s:%d\n"), i + first_choice,
- SYMBOL_PRINT_NAME (syms[i].sym),
- symtab_to_filename_for_display (sal.symtab),
- sal.line);
- continue;
- }
- else
- {
- int is_enumeral =
- (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 = 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_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, &type_print_raw_options);
- printf_unfiltered (_("'(%s) (enumeral)\n"),
- SYMBOL_PRINT_NAME (syms[i].sym));
- }
- else if (symtab != NULL)
- printf_unfiltered (is_enumeral
- ? _("[%d] %s in %s (enumeral)\n")
- : _("[%d] %s at %s:?\n"),
- i + first_choice,
- SYMBOL_PRINT_NAME (syms[i].sym),
- symtab_to_filename_for_display (symtab));
- else
- printf_unfiltered (is_enumeral
- ? _("[%d] %s (enumeral)\n")
- : _("[%d] %s at ?\n"),
- i + first_choice,
- SYMBOL_PRINT_NAME (syms[i].sym));
- }
- }
-
- n_chosen = get_selections (chosen, nsyms, max_results, max_results > 1,
- "overload-choice");
-
- for (i = 0; i < n_chosen; i += 1)
- syms[i] = syms[chosen[i]];
-
- return n_chosen;
-}
+static int
+ada_args_match (struct symbol *func, struct value **actuals, int n_actuals)
+{
+ int i;
+ struct type *func_type = SYMBOL_TYPE (func);
-/* Read and validate a set of numeric choices from the user in the
- range 0 .. N_CHOICES-1. Place the results in increasing
- order in CHOICES[0 .. N-1], and return N.
+ if (SYMBOL_CLASS (func) == LOC_CONST
+ && TYPE_CODE (func_type) == TYPE_CODE_ENUM)
+ return (n_actuals == 0);
+ else if (func_type == NULL || TYPE_CODE (func_type) != TYPE_CODE_FUNC)
+ return 0;
- The user types choices as a sequence of numbers on one line
- separated by blanks, encoding them as follows:
+ if (TYPE_NFIELDS (func_type) != n_actuals)
+ return 0;
- + A choice of 0 means to cancel the selection, throwing an error.
- + If IS_ALL_CHOICE, a choice of 1 selects the entire set 0 .. N_CHOICES-1.
- + The user chooses k by typing k+IS_ALL_CHOICE+1.
+ for (i = 0; i < n_actuals; i += 1)
+ {
+ if (actuals[i] == NULL)
+ return 0;
+ else
+ {
+ struct type *ftype = ada_check_typedef (TYPE_FIELD_TYPE (func_type,
+ i));
+ struct type *atype = ada_check_typedef (value_type (actuals[i]));
- The user is not allowed to choose more than MAX_RESULTS values.
+ if (!ada_type_match (ftype, atype, 1))
+ return 0;
+ }
+ }
+ return 1;
+}
- ANNOTATION_SUFFIX, if present, is used to annotate the input
- prompts (for use with the -f switch). */
+/* False iff function type FUNC_TYPE definitely does not produce a value
+ compatible with type CONTEXT_TYPE. Conservatively returns 1 if
+ FUNC_TYPE is not a valid function type with a non-null return type
+ or an enumerated type. A null CONTEXT_TYPE indicates any non-void type. */
-int
-get_selections (int *choices, int n_choices, int max_results,
- int is_all_choice, char *annotation_suffix)
+static int
+return_match (struct type *func_type, struct type *context_type)
{
- char *args;
- char *prompt;
- int n_chosen;
- int first_choice = is_all_choice ? 2 : 1;
-
- prompt = getenv ("PS2");
- if (prompt == NULL)
- prompt = "> ";
-
- args = command_line_input (prompt, 0, annotation_suffix);
+ struct type *return_type;
- if (args == NULL)
- error_no_arg (_("one or more choice numbers"));
+ if (func_type == NULL)
+ return 1;
- n_chosen = 0;
+ if (TYPE_CODE (func_type) == TYPE_CODE_FUNC)
+ return_type = get_base_type (TYPE_TARGET_TYPE (func_type));
+ else
+ return_type = get_base_type (func_type);
+ if (return_type == NULL)
+ return 1;
- /* Set choices[0 .. n_chosen-1] to the users' choices in ascending
- order, as given in args. Choices are validated. */
- while (1)
- {
- char *args2;
- int choice, j;
+ context_type = get_base_type (context_type);
- args = skip_spaces (args);
- if (*args == '\0' && n_chosen == 0)
- error_no_arg (_("one or more choice numbers"));
- else if (*args == '\0')
- break;
+ if (TYPE_CODE (return_type) == TYPE_CODE_ENUM)
+ return context_type == NULL || return_type == context_type;
+ else if (context_type == NULL)
+ return TYPE_CODE (return_type) != TYPE_CODE_VOID;
+ else
+ return TYPE_CODE (return_type) == TYPE_CODE (context_type);
+}
- choice = strtol (args, &args2, 10);
- if (args == args2 || choice < 0
- || choice > n_choices + first_choice - 1)
- error (_("Argument must be choice number"));
- args = args2;
- if (choice == 0)
- error (_("cancelled"));
+/* Returns the index in SYMS[0..NSYMS-1] that contains the symbol for the
+ function (if any) that matches the types of the NARGS arguments in
+ ARGS. If CONTEXT_TYPE is non-null and there is at least one match
+ that returns that type, then eliminate matches that don't. If
+ CONTEXT_TYPE is void and there is at least one match that does not
+ return void, eliminate all matches that do.
- if (choice < first_choice)
- {
- n_chosen = n_choices;
- for (j = 0; j < n_choices; j += 1)
- choices[j] = j;
- break;
- }
- choice -= first_choice;
+ Asks the user if there is more than one match remaining. Returns -1
+ if there is no such symbol or none is selected. NAME is used
+ solely for messages. May re-arrange and modify SYMS in
+ the process; the index returned is for the modified vector. */
- for (j = n_chosen - 1; j >= 0 && choice < choices[j]; j -= 1)
- {
- }
+static int
+ada_resolve_function (struct block_symbol syms[],
+ int nsyms, struct value **args, int nargs,
+ const char *name, struct type *context_type,
+ int parse_completion)
+{
+ int fallback;
+ int k;
+ int m; /* Number of hits */
- if (j < 0 || choice != choices[j])
+ m = 0;
+ /* In the first pass of the loop, we only accept functions matching
+ context_type. If none are found, we add a second pass of the loop
+ where every function is accepted. */
+ for (fallback = 0; m == 0 && fallback < 2; fallback++)
+ {
+ for (k = 0; k < nsyms; k += 1)
{
- int k;
+ struct type *type = ada_check_typedef (SYMBOL_TYPE (syms[k].symbol));
- for (k = n_chosen - 1; k > j; k -= 1)
- choices[k + 1] = choices[k];
- choices[j + 1] = choice;
- n_chosen += 1;
+ if (ada_args_match (syms[k].symbol, args, nargs)
+ && (fallback || return_match (type, context_type)))
+ {
+ syms[m] = syms[k];
+ m += 1;
+ }
}
}
- if (n_chosen > max_results)
- error (_("Select no more than %d of the above"), max_results);
-
- return n_chosen;
+ /* If we got multiple matches, ask the user which one to use. Don't do this
+ interactive thing during completion, though, as the purpose of the
+ completion is providing a list of all possible matches. Prompting the
+ user to filter it down would be completely unexpected in this case. */
+ if (m == 0)
+ return -1;
+ else if (m > 1 && !parse_completion)
+ {
+ printf_filtered (_("Multiple matches for %s\n"), name);
+ user_select_syms (syms, m, 1);
+ return 0;
+ }
+ return 0;
}
/* Replace the operator of length OPLEN at position PC in *EXPP with a call
arguments. Update *EXPP as needed to hold more space. */
static void
-replace_operator_with_call (struct expression **expp, int pc, int nargs,
+replace_operator_with_call (expression_up *expp, int pc, int nargs,
int oplen, struct symbol *sym,
const struct block *block)
{
struct expression *newexp = (struct expression *)
xzalloc (sizeof (struct expression)
+ EXP_ELEM_TO_BYTES ((*expp)->nelts + 7 - oplen));
- struct expression *exp = *expp;
+ struct expression *exp = expp->get ();
newexp->nelts = exp->nelts + 7 - oplen;
newexp->language_defn = exp->language_defn;
newexp->elts[pc + 4].block = block;
newexp->elts[pc + 5].symbol = sym;
- *expp = newexp;
- xfree (exp);
+ expp->reset (newexp);
}
/* Type-class predicates */
{
default:
return ADA_NOT_RENAMING;
- case LOC_TYPEDEF:
- return parse_old_style_renaming (SYMBOL_TYPE (sym),
- renamed_entity, len, renaming_expr);
case LOC_LOCAL:
case LOC_STATIC:
case LOC_COMPUTED:
case LOC_OPTIMIZED_OUT:
- info = strstr (SYMBOL_LINKAGE_NAME (sym), "___XR");
+ info = strstr (sym->linkage_name (), "___XR");
if (info == NULL)
return ADA_NOT_RENAMING;
switch (info[5])
return kind;
}
-/* Assuming TYPE encodes a renaming according to the old encoding in
- exp_dbug.ads, returns details of that renaming in *RENAMED_ENTITY,
- *LEN, and *RENAMING_EXPR, as for ada_parse_renaming, above. Returns
- ADA_NOT_RENAMING otherwise. */
-static enum ada_renaming_category
-parse_old_style_renaming (struct type *type,
- const char **renamed_entity, int *len,
- const char **renaming_expr)
+/* Compute the value of the given RENAMING_SYM, which is expected to
+ be a symbol encoding a renaming expression. BLOCK is the block
+ used to evaluate the renaming. */
+
+static struct value *
+ada_read_renaming_var_value (struct symbol *renaming_sym,
+ const struct block *block)
{
- enum ada_renaming_category kind;
- const char *name;
- const char *info;
- const char *suffix;
+ const char *sym_name;
- if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM
- || TYPE_NFIELDS (type) != 1)
- return ADA_NOT_RENAMING;
+ sym_name = renaming_sym->linkage_name ();
+ expression_up expr = parse_exp_1 (&sym_name, 0, block, 0);
+ return evaluate_expression (expr.get ());
+}
+\f
- name = type_name_no_tag (type);
- if (name == NULL)
- return ADA_NOT_RENAMING;
-
- name = strstr (name, "___XR");
- if (name == NULL)
- return ADA_NOT_RENAMING;
- switch (name[5])
+ /* Evaluation: Function Calls */
+
+/* Return an lvalue containing the value VAL. This is the identity on
+ lvalues, and otherwise has the side-effect of allocating memory
+ in the inferior where a copy of the value contents is copied. */
+
+static struct value *
+ensure_lval (struct value *val)
+{
+ if (VALUE_LVAL (val) == not_lval
+ || VALUE_LVAL (val) == lval_internalvar)
{
- case '\0':
- case '_':
- kind = ADA_OBJECT_RENAMING;
- break;
- case 'E':
- kind = ADA_EXCEPTION_RENAMING;
- break;
- case 'P':
- kind = ADA_PACKAGE_RENAMING;
- break;
- case 'S':
- kind = ADA_SUBPROGRAM_RENAMING;
- break;
- default:
- return ADA_NOT_RENAMING;
+ int len = TYPE_LENGTH (ada_check_typedef (value_type (val)));
+ const CORE_ADDR addr =
+ value_as_long (value_allocate_space_in_inferior (len));
+
+ VALUE_LVAL (val) = lval_memory;
+ set_value_address (val, addr);
+ write_memory (addr, value_contents (val), len);
}
- info = TYPE_FIELD_NAME (type, 0);
- if (info == NULL)
- return ADA_NOT_RENAMING;
- if (renamed_entity != NULL)
- *renamed_entity = info;
- suffix = strstr (info, "___XE");
- if (renaming_expr != NULL)
- *renaming_expr = suffix + 5;
- if (suffix == NULL || suffix == info)
- return ADA_NOT_RENAMING;
- if (len != NULL)
- *len = suffix - info;
- return kind;
+ return val;
}
-/* Compute the value of the given RENAMING_SYM, which is expected to
- be a symbol encoding a renaming expression. BLOCK is the block
- used to evaluate the renaming. */
+/* Given ARG, a value of type (pointer or reference to a)*
+ structure/union, extract the component named NAME from the ultimate
+ target structure/union and return it as a value with its
+ appropriate type.
+
+ The routine searches for NAME among all members of the structure itself
+ and (recursively) among all members of any wrapper members
+ (e.g., '_parent').
+
+ If NO_ERR, then simply return NULL in case of error, rather than
+ calling error. */
+
+static struct value *
+ada_value_struct_elt (struct value *arg, const char *name, int no_err)
+{
+ struct type *t, *t1;
+ struct value *v;
+ int check_tag;
+
+ v = NULL;
+ t1 = t = ada_check_typedef (value_type (arg));
+ if (TYPE_CODE (t) == TYPE_CODE_REF)
+ {
+ t1 = TYPE_TARGET_TYPE (t);
+ if (t1 == NULL)
+ goto BadValue;
+ t1 = ada_check_typedef (t1);
+ if (TYPE_CODE (t1) == TYPE_CODE_PTR)
+ {
+ arg = coerce_ref (arg);
+ t = t1;
+ }
+ }
+
+ while (TYPE_CODE (t) == TYPE_CODE_PTR)
+ {
+ t1 = TYPE_TARGET_TYPE (t);
+ if (t1 == NULL)
+ goto BadValue;
+ t1 = ada_check_typedef (t1);
+ if (TYPE_CODE (t1) == TYPE_CODE_PTR)
+ {
+ arg = value_ind (arg);
+ t = t1;
+ }
+ else
+ break;
+ }
+
+ if (TYPE_CODE (t1) != TYPE_CODE_STRUCT && TYPE_CODE (t1) != TYPE_CODE_UNION)
+ goto BadValue;
-static struct value *
-ada_read_renaming_var_value (struct symbol *renaming_sym,
- struct block *block)
-{
- const char *sym_name;
- struct expression *expr;
- struct value *value;
- struct cleanup *old_chain = NULL;
+ if (t1 == t)
+ v = ada_search_struct_field (name, arg, 0, t);
+ else
+ {
+ int bit_offset, bit_size, byte_offset;
+ struct type *field_type;
+ CORE_ADDR address;
- sym_name = SYMBOL_LINKAGE_NAME (renaming_sym);
- expr = parse_exp_1 (&sym_name, 0, block, 0);
- old_chain = make_cleanup (free_current_contents, &expr);
- value = evaluate_expression (expr);
+ if (TYPE_CODE (t) == TYPE_CODE_PTR)
+ address = value_address (ada_value_ind (arg));
+ else
+ address = value_address (ada_coerce_ref (arg));
- do_cleanups (old_chain);
- return value;
-}
-\f
+ /* Check to see if this is a tagged type. We also need to handle
+ the case where the type is a reference to a tagged type, but
+ we have to be careful to exclude pointers to tagged types.
+ The latter should be shown as usual (as a pointer), whereas
+ a reference should mostly be transparent to the user. */
- /* Evaluation: Function Calls */
+ if (ada_is_tagged_type (t1, 0)
+ || (TYPE_CODE (t1) == TYPE_CODE_REF
+ && ada_is_tagged_type (TYPE_TARGET_TYPE (t1), 0)))
+ {
+ /* We first try to find the searched field in the current type.
+ If not found then let's look in the fixed type. */
-/* Return an lvalue containing the value VAL. This is the identity on
- lvalues, and otherwise has the side-effect of allocating memory
- in the inferior where a copy of the value contents is copied. */
+ if (!find_struct_field (name, t1, 0,
+ &field_type, &byte_offset, &bit_offset,
+ &bit_size, NULL))
+ check_tag = 1;
+ else
+ check_tag = 0;
+ }
+ else
+ check_tag = 0;
-static struct value *
-ensure_lval (struct value *val)
-{
- if (VALUE_LVAL (val) == not_lval
- || VALUE_LVAL (val) == lval_internalvar)
- {
- int len = TYPE_LENGTH (ada_check_typedef (value_type (val)));
- const CORE_ADDR addr =
- value_as_long (value_allocate_space_in_inferior (len));
+ /* Convert to fixed type in all cases, so that we have proper
+ offsets to each field in unconstrained record types. */
+ t1 = ada_to_fixed_type (ada_get_base_type (t1), NULL,
+ address, NULL, check_tag);
- set_value_address (val, addr);
- VALUE_LVAL (val) = lval_memory;
- write_memory (addr, value_contents (val), len);
+ if (find_struct_field (name, t1, 0,
+ &field_type, &byte_offset, &bit_offset,
+ &bit_size, NULL))
+ {
+ if (bit_size != 0)
+ {
+ if (TYPE_CODE (t) == TYPE_CODE_REF)
+ arg = ada_coerce_ref (arg);
+ else
+ arg = ada_value_ind (arg);
+ v = ada_value_primitive_packed_val (arg, NULL, byte_offset,
+ bit_offset, bit_size,
+ field_type);
+ }
+ else
+ v = value_at_lazy (field_type, address + byte_offset);
+ }
}
- return val;
+ if (v != NULL || no_err)
+ return v;
+ else
+ error (_("There is no member named %s."), name);
+
+ BadValue:
+ if (no_err)
+ return NULL;
+ else
+ error (_("Attempt to extract a component of "
+ "a value that is not a record."));
}
/* Return the value ACTUAL, converted to be an appropriate value for a
if (TYPE_CODE (formal_target) == TYPE_CODE_ARRAY
&& ada_is_array_descriptor_type (actual_target))
result = desc_data (actual);
- else if (TYPE_CODE (actual_type) != TYPE_CODE_PTR)
+ else if (TYPE_CODE (formal_type) != TYPE_CODE_PTR)
{
if (VALUE_LVAL (actual) != lval_memory)
{
}
else if (TYPE_CODE (actual_type) == TYPE_CODE_PTR)
return ada_value_ind (actual);
+ else if (ada_is_aligner_type (formal_type))
+ {
+ /* We need to turn this parameter into an aligner type
+ as well. */
+ struct value *aligner = allocate_value (formal_type);
+ struct value *component = ada_value_struct_elt (aligner, "F", 0);
+
+ value_assign_to_component (aligner, component, actual);
+ return aligner;
+ }
return actual;
}
{
struct gdbarch *gdbarch = get_type_arch (type);
unsigned len = TYPE_LENGTH (type);
- gdb_byte *buf = alloca (len);
+ gdb_byte *buf = (gdb_byte *) alloca (len);
CORE_ADDR addr;
addr = value_address (value);
gdbarch_address_to_pointer (gdbarch, type, buf, addr);
- addr = extract_unsigned_integer (buf, len, gdbarch_byte_order (gdbarch));
+ addr = extract_unsigned_integer (buf, len, type_byte_order (type));
return addr;
}
ada_get_symbol_cache (struct program_space *pspace)
{
struct ada_pspace_data *pspace_data = get_ada_pspace_data (pspace);
- struct ada_symbol_cache *sym_cache = pspace_data->sym_cache;
- if (sym_cache == NULL)
+ if (pspace_data->sym_cache == NULL)
{
- sym_cache = XCNEW (struct ada_symbol_cache);
- ada_init_symbol_cache (sym_cache);
+ pspace_data->sym_cache = XCNEW (struct ada_symbol_cache);
+ ada_init_symbol_cache (pspace_data->sym_cache);
}
- return sym_cache;
+ return pspace_data->sym_cache;
}
/* Clear all entries from the symbol cache. */
ada_init_symbol_cache (sym_cache);
}
-/* Search our cache for an entry matching NAME and NAMESPACE.
+/* Search our cache for an entry matching NAME and DOMAIN.
Return it if found, or NULL otherwise. */
static struct cache_entry **
-find_entry (const char *name, domain_enum namespace)
+find_entry (const char *name, domain_enum domain)
{
struct ada_symbol_cache *sym_cache
= ada_get_symbol_cache (current_program_space);
for (e = &sym_cache->root[h]; *e != NULL; e = &(*e)->next)
{
- if (namespace == (*e)->namespace && strcmp (name, (*e)->name) == 0)
+ if (domain == (*e)->domain && strcmp (name, (*e)->name) == 0)
return e;
}
return NULL;
}
-/* Search the symbol cache for an entry matching NAME and NAMESPACE.
+/* Search the symbol cache for an entry matching NAME and DOMAIN.
Return 1 if found, 0 otherwise.
If an entry was found and SYM is not NULL, set *SYM to the entry's
SYM. Same principle for BLOCK if not NULL. */
static int
-lookup_cached_symbol (const char *name, domain_enum namespace,
+lookup_cached_symbol (const char *name, domain_enum domain,
struct symbol **sym, const struct block **block)
{
- struct cache_entry **e = find_entry (name, namespace);
+ struct cache_entry **e = find_entry (name, domain);
if (e == NULL)
return 0;
}
/* Assuming that (SYM, BLOCK) is the result of the lookup of NAME
- in domain NAMESPACE, save this result in our symbol cache. */
+ in domain DOMAIN, save this result in our symbol cache. */
static void
-cache_symbol (const char *name, domain_enum namespace, struct symbol *sym,
+cache_symbol (const char *name, domain_enum domain, struct symbol *sym,
const struct block *block)
{
struct ada_symbol_cache *sym_cache
char *copy;
struct cache_entry *e;
+ /* Symbols for builtin types don't have a block.
+ For now don't cache such symbols. */
+ if (sym != NULL && !SYMBOL_OBJFILE_OWNED (sym))
+ return;
+
/* If the symbol is a local symbol, then do not cache it, as a search
for that symbol depends on the context. To determine whether
the symbol is local or not, we check the block where we found it
against the global and static blocks of its associated symtab. */
if (sym
- && BLOCKVECTOR_BLOCK (BLOCKVECTOR (sym->symtab), GLOBAL_BLOCK) != block
- && BLOCKVECTOR_BLOCK (BLOCKVECTOR (sym->symtab), STATIC_BLOCK) != block)
+ && BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symbol_symtab (sym)),
+ GLOBAL_BLOCK) != block
+ && BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symbol_symtab (sym)),
+ STATIC_BLOCK) != block)
return;
h = msymbol_hash (name) % HASH_SIZE;
- e = (struct cache_entry *) obstack_alloc (&sym_cache->cache_space,
- sizeof (*e));
+ e = XOBNEW (&sym_cache->cache_space, cache_entry);
e->next = sym_cache->root[h];
sym_cache->root[h] = e;
- e->name = copy = obstack_alloc (&sym_cache->cache_space, strlen (name) + 1);
+ e->name = copy
+ = (char *) obstack_alloc (&sym_cache->cache_space, strlen (name) + 1);
strcpy (copy, name);
e->sym = sym;
- e->namespace = namespace;
+ e->domain = domain;
e->block = block;
}
\f
/* Symbol Lookup */
-/* Return nonzero if wild matching should be used when searching for
- all symbols matching LOOKUP_NAME.
+/* Return the symbol name match type that should be used used when
+ searching for all symbols matching LOOKUP_NAME.
LOOKUP_NAME is expected to be a symbol name after transformation
- for Ada lookups (see ada_name_for_lookup). */
+ for Ada lookups. */
-static int
-should_use_wild_match (const char *lookup_name)
+static symbol_name_match_type
+name_match_type_from_name (const char *lookup_name)
{
- return (strstr (lookup_name, "__") == NULL);
+ return (strstr (lookup_name, "__") == NULL
+ ? symbol_name_match_type::WILD
+ : symbol_name_match_type::FULL);
}
/* Return the result of a standard (literal, C-like) lookup of NAME in
domain_enum domain)
{
/* Initialize it just to avoid a GCC false warning. */
- struct symbol *sym = NULL;
+ struct block_symbol sym = {};
- if (lookup_cached_symbol (name, domain, &sym, NULL))
- return sym;
- sym = lookup_symbol_in_language (name, block, domain, language_c, 0);
- cache_symbol (name, domain, sym, block_found);
- return sym;
+ if (lookup_cached_symbol (name, domain, &sym.symbol, NULL))
+ return sym.symbol;
+ ada_lookup_encoded_symbol (name, block, domain, &sym);
+ cache_symbol (name, domain, sym.symbol, sym.block);
+ return sym.symbol;
}
in the symbol fields of SYMS[0..N-1]. We treat enumerals as functions,
since they contend in overloading in the same way. */
static int
-is_nonfunction (struct ada_symbol_info syms[], int n)
+is_nonfunction (struct block_symbol syms[], int n)
{
int i;
for (i = 0; i < n; i += 1)
- if (TYPE_CODE (SYMBOL_TYPE (syms[i].sym)) != TYPE_CODE_FUNC
- && (TYPE_CODE (SYMBOL_TYPE (syms[i].sym)) != TYPE_CODE_ENUM
- || SYMBOL_CLASS (syms[i].sym) != LOC_CONST))
+ if (TYPE_CODE (SYMBOL_TYPE (syms[i].symbol)) != TYPE_CODE_FUNC
+ && (TYPE_CODE (SYMBOL_TYPE (syms[i].symbol)) != TYPE_CODE_ENUM
+ || SYMBOL_CLASS (syms[i].symbol) != LOC_CONST))
return 1;
return 0;
{
struct type *type0 = SYMBOL_TYPE (sym0);
struct type *type1 = SYMBOL_TYPE (sym1);
- const char *name0 = SYMBOL_LINKAGE_NAME (sym0);
- const char *name1 = SYMBOL_LINKAGE_NAME (sym1);
+ const char *name0 = sym0->linkage_name ();
+ const char *name1 = sym1->linkage_name ();
int len0 = strlen (name0);
return
TYPE_CODE (type0) == TYPE_CODE (type1)
&& (equiv_types (type0, type1)
|| (len0 < strlen (name1) && strncmp (name0, name1, len0) == 0
- && strncmp (name1 + len0, "___XV", 5) == 0));
+ && startswith (name1 + len0, "___XV")));
}
case LOC_CONST:
return SYMBOL_VALUE (sym0) == SYMBOL_VALUE (sym1)
&& equiv_types (SYMBOL_TYPE (sym0), SYMBOL_TYPE (sym1));
+
+ case LOC_STATIC:
+ {
+ const char *name0 = sym0->linkage_name ();
+ const char *name1 = sym1->linkage_name ();
+ return (strcmp (name0, name1) == 0
+ && SYMBOL_VALUE_ADDRESS (sym0) == SYMBOL_VALUE_ADDRESS (sym1));
+ }
+
default:
return 0;
}
}
-/* Append (SYM,BLOCK,SYMTAB) to the end of the array of struct ada_symbol_info
+/* Append (SYM,BLOCK,SYMTAB) to the end of the array of struct block_symbol
records in OBSTACKP. Do nothing if SYM is a duplicate. */
static void
const struct block *block)
{
int i;
- struct ada_symbol_info *prevDefns = defns_collected (obstackp, 0);
+ struct block_symbol *prevDefns = defns_collected (obstackp, 0);
/* Do not try to complete stub types, as the debugger is probably
already scanning all symbols matching a certain name at the
for (i = num_defns_collected (obstackp) - 1; i >= 0; i -= 1)
{
- if (lesseq_defined_than (sym, prevDefns[i].sym))
+ if (lesseq_defined_than (sym, prevDefns[i].symbol))
return;
- else if (lesseq_defined_than (prevDefns[i].sym, sym))
+ else if (lesseq_defined_than (prevDefns[i].symbol, sym))
{
- prevDefns[i].sym = sym;
+ prevDefns[i].symbol = sym;
prevDefns[i].block = block;
return;
}
}
{
- struct ada_symbol_info info;
+ struct block_symbol info;
- info.sym = sym;
+ info.symbol = sym;
info.block = block;
- obstack_grow (obstackp, &info, sizeof (struct ada_symbol_info));
+ obstack_grow (obstackp, &info, sizeof (struct block_symbol));
}
}
-/* Number of ada_symbol_info structures currently collected in
- current vector in *OBSTACKP. */
+/* Number of block_symbol structures currently collected in current vector in
+ OBSTACKP. */
static int
num_defns_collected (struct obstack *obstackp)
{
- return obstack_object_size (obstackp) / sizeof (struct ada_symbol_info);
+ return obstack_object_size (obstackp) / sizeof (struct block_symbol);
}
-/* Vector of ada_symbol_info structures currently collected in current
- vector in *OBSTACKP. If FINISH, close off the vector and return
- its final address. */
+/* Vector of block_symbol structures currently collected in current vector in
+ OBSTACKP. If FINISH, close off the vector and return its final address. */
-static struct ada_symbol_info *
+static struct block_symbol *
defns_collected (struct obstack *obstackp, int finish)
{
if (finish)
- return obstack_finish (obstackp);
+ return (struct block_symbol *) obstack_finish (obstackp);
else
- return (struct ada_symbol_info *) obstack_base (obstackp);
+ return (struct block_symbol *) obstack_base (obstackp);
}
/* Return a bound minimal symbol matching NAME according to Ada
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
- to allow the user to specifically access the standard exceptions
- using, for instance, Standard.Constraint_Error when Constraint_Error
- is ambiguous (due to the user defining its own Constraint_Error
- entity inside its program). */
- if (strncmp (name, "standard__", sizeof ("standard__") - 1) == 0)
- name += sizeof ("standard__") - 1;
+ symbol_name_match_type match_type = name_match_type_from_name (name);
+ lookup_name_info lookup_name (name, match_type);
- ALL_MSYMBOLS (objfile, msymbol)
- {
- if (match_name (MSYMBOL_LINKAGE_NAME (msymbol), name, wild_match_p)
- && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
- {
- result.minsym = msymbol;
- result.objfile = objfile;
- break;
- }
- }
+ 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 (), lookup_name, NULL)
+ && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
+ {
+ result.minsym = msymbol;
+ result.objfile = objfile;
+ break;
+ }
+ }
+ }
return result;
}
static void
add_symbols_from_enclosing_procs (struct obstack *obstackp,
- const char *name, domain_enum namespace,
- int wild_match_p)
+ const lookup_name_info &lookup_name,
+ domain_enum domain)
{
}
So, for practical purposes, we consider them as the same. */
static int
-symbols_are_identical_enums (struct ada_symbol_info *syms, int nsyms)
+symbols_are_identical_enums (const std::vector<struct block_symbol> &syms)
{
int i;
(see ada_identical_enum_types_p). */
/* Quick check: All symbols should have an enum type. */
- for (i = 0; i < nsyms; i++)
- if (TYPE_CODE (SYMBOL_TYPE (syms[i].sym)) != TYPE_CODE_ENUM)
+ for (i = 0; i < syms.size (); i++)
+ if (TYPE_CODE (SYMBOL_TYPE (syms[i].symbol)) != TYPE_CODE_ENUM)
return 0;
/* Quick check: They should all have the same value. */
- for (i = 1; i < nsyms; i++)
- if (SYMBOL_VALUE (syms[i].sym) != SYMBOL_VALUE (syms[0].sym))
+ for (i = 1; i < syms.size (); i++)
+ if (SYMBOL_VALUE (syms[i].symbol) != SYMBOL_VALUE (syms[0].symbol))
return 0;
/* Quick check: They should all have the same number of enumerals. */
- for (i = 1; i < nsyms; i++)
- if (TYPE_NFIELDS (SYMBOL_TYPE (syms[i].sym))
- != TYPE_NFIELDS (SYMBOL_TYPE (syms[0].sym)))
+ for (i = 1; i < syms.size (); i++)
+ if (TYPE_NFIELDS (SYMBOL_TYPE (syms[i].symbol))
+ != TYPE_NFIELDS (SYMBOL_TYPE (syms[0].symbol)))
return 0;
/* All the sanity checks passed, so we might have a set of
identical enumeration types. Perform a more complete
comparison of the type of each symbol. */
- for (i = 1; i < nsyms; i++)
- if (!ada_identical_enum_types_p (SYMBOL_TYPE (syms[i].sym),
- SYMBOL_TYPE (syms[0].sym)))
+ for (i = 1; i < syms.size (); i++)
+ if (!ada_identical_enum_types_p (SYMBOL_TYPE (syms[i].symbol),
+ SYMBOL_TYPE (syms[0].symbol)))
return 0;
return 1;
}
-/* Remove any non-debugging symbols in SYMS[0 .. NSYMS-1] that definitely
+/* Remove any non-debugging symbols in SYMS that definitely
duplicate other symbols in the list (The only case I know of where
this happens is when object files containing stabs-in-ecoff are
linked with files containing ordinary ecoff debugging symbols (or no
Returns the number of items in the modified list. */
static int
-remove_extra_symbols (struct ada_symbol_info *syms, int nsyms)
+remove_extra_symbols (std::vector<struct block_symbol> *syms)
{
int i, j;
/* We should never be called with less than 2 symbols, as there
cannot be any extra symbol in that case. But it's easy to
handle, since we have nothing to do in that case. */
- if (nsyms < 2)
- return nsyms;
+ if (syms->size () < 2)
+ return syms->size ();
i = 0;
- while (i < nsyms)
+ while (i < syms->size ())
{
int remove_p = 0;
/* If two symbols have the same name and one of them is a stub type,
the get rid of the stub. */
- if (TYPE_STUB (SYMBOL_TYPE (syms[i].sym))
- && SYMBOL_LINKAGE_NAME (syms[i].sym) != NULL)
+ if (TYPE_STUB (SYMBOL_TYPE ((*syms)[i].symbol))
+ && (*syms)[i].symbol->linkage_name () != NULL)
{
- for (j = 0; j < nsyms; j++)
+ for (j = 0; j < syms->size (); j++)
{
if (j != i
- && !TYPE_STUB (SYMBOL_TYPE (syms[j].sym))
- && SYMBOL_LINKAGE_NAME (syms[j].sym) != NULL
- && strcmp (SYMBOL_LINKAGE_NAME (syms[i].sym),
- SYMBOL_LINKAGE_NAME (syms[j].sym)) == 0)
+ && !TYPE_STUB (SYMBOL_TYPE ((*syms)[j].symbol))
+ && (*syms)[j].symbol->linkage_name () != NULL
+ && strcmp ((*syms)[i].symbol->linkage_name (),
+ (*syms)[j].symbol->linkage_name ()) == 0)
remove_p = 1;
}
}
/* Two symbols with the same name, same class and same address
should be identical. */
- else if (SYMBOL_LINKAGE_NAME (syms[i].sym) != NULL
- && SYMBOL_CLASS (syms[i].sym) == LOC_STATIC
- && is_nondebugging_type (SYMBOL_TYPE (syms[i].sym)))
+ else if ((*syms)[i].symbol->linkage_name () != NULL
+ && SYMBOL_CLASS ((*syms)[i].symbol) == LOC_STATIC
+ && is_nondebugging_type (SYMBOL_TYPE ((*syms)[i].symbol)))
{
- for (j = 0; j < nsyms; j += 1)
+ for (j = 0; j < syms->size (); j += 1)
{
if (i != j
- && SYMBOL_LINKAGE_NAME (syms[j].sym) != NULL
- && strcmp (SYMBOL_LINKAGE_NAME (syms[i].sym),
- SYMBOL_LINKAGE_NAME (syms[j].sym)) == 0
- && SYMBOL_CLASS (syms[i].sym) == SYMBOL_CLASS (syms[j].sym)
- && SYMBOL_VALUE_ADDRESS (syms[i].sym)
- == SYMBOL_VALUE_ADDRESS (syms[j].sym))
+ && (*syms)[j].symbol->linkage_name () != NULL
+ && strcmp ((*syms)[i].symbol->linkage_name (),
+ (*syms)[j].symbol->linkage_name ()) == 0
+ && SYMBOL_CLASS ((*syms)[i].symbol)
+ == SYMBOL_CLASS ((*syms)[j].symbol)
+ && SYMBOL_VALUE_ADDRESS ((*syms)[i].symbol)
+ == SYMBOL_VALUE_ADDRESS ((*syms)[j].symbol))
remove_p = 1;
}
}
if (remove_p)
- {
- for (j = i + 1; j < nsyms; j += 1)
- syms[j - 1] = syms[j];
- nsyms -= 1;
- }
+ syms->erase (syms->begin () + i);
i += 1;
}
to ask the user to disambiguate anyways. And if we have to
present a multiple-choice menu, it's less confusing if the list
isn't missing some choices that were identical and yet distinct. */
- if (symbols_are_identical_enums (syms, nsyms))
- nsyms = 1;
+ if (symbols_are_identical_enums (*syms))
+ syms->resize (1);
- return nsyms;
+ return syms->size ();
}
/* Given a type that corresponds to a renaming entity, use the type name
to extract the scope (package name or function name, fully qualified,
and following the GNAT encoding convention) where this renaming has been
- defined. The string returned needs to be deallocated after use. */
+ defined. */
-static char *
+static std::string
xget_renaming_scope (struct type *renaming_type)
{
/* The renaming types adhere to the following convention:
So, to extract the scope, we search for the "___XR" extension,
and then backtrack until we find the first "__". */
- const char *name = type_name_no_tag (renaming_type);
- char *suffix = strstr (name, "___XR");
- char *last;
- int scope_len;
- char *scope;
+ const char *name = TYPE_NAME (renaming_type);
+ const char *suffix = strstr (name, "___XR");
+ const char *last;
/* Now, backtrack a bit until we find the first "__". Start looking
at suffix - 3, as the <rename> part is at least one character long. */
break;
/* Make a copy of scope and return it. */
-
- scope_len = last - name;
- scope = (char *) xmalloc ((scope_len + 1) * sizeof (char));
-
- strncpy (scope, name, scope_len);
- scope[scope_len] = '\0';
-
- return scope;
+ return std::string (name, last);
}
/* Return nonzero if NAME corresponds to a package name. */
to NAME not existing in our list of symbols. There is only one
small complication with library-level functions (see below). */
- char *fun_name;
-
/* If it is a function that has not been defined at library level,
then we should be able to look it up in the symbols. */
if (standard_lookup (name, NULL, VAR_DOMAIN) != NULL)
if (strstr (name, "__") != NULL)
return 0;
- fun_name = xstrprintf ("_ada_%s", name);
+ std::string fun_name = string_printf ("_ada_%s", name);
- return (standard_lookup (fun_name, NULL, VAR_DOMAIN) == NULL);
+ return (standard_lookup (fun_name.c_str (), NULL, VAR_DOMAIN) == NULL);
}
/* Return nonzero if SYM corresponds to a renaming entity that is
static int
old_renaming_is_invisible (const struct symbol *sym, const char *function_name)
{
- char *scope;
- struct cleanup *old_chain;
-
if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
return 0;
- scope = xget_renaming_scope (SYMBOL_TYPE (sym));
- old_chain = make_cleanup (xfree, scope);
+ std::string scope = xget_renaming_scope (SYMBOL_TYPE (sym));
/* If the rename has been defined in a package, then it is visible. */
- if (is_package_name (scope))
- {
- do_cleanups (old_chain);
- return 0;
- }
+ if (is_package_name (scope.c_str ()))
+ return 0;
/* Check that the rename is in the current function scope by checking
that its name starts with SCOPE. */
a library-level function. Strip this prefix before doing the
comparison, as the encoding for the renaming does not contain
this prefix. */
- if (strncmp (function_name, "_ada_", 5) == 0)
+ if (startswith (function_name, "_ada_"))
function_name += 5;
- {
- int is_invisible = strncmp (function_name, scope, strlen (scope)) != 0;
-
- do_cleanups (old_chain);
- return is_invisible;
- }
+ return !startswith (function_name, scope.c_str ());
}
/* Remove entries from SYMS that corresponds to a renaming entity that
the user will be unable to print such rename entities. */
static int
-remove_irrelevant_renamings (struct ada_symbol_info *syms,
- int nsyms, const struct block *current_block)
+remove_irrelevant_renamings (std::vector<struct block_symbol> *syms,
+ const struct block *current_block)
{
struct symbol *current_function;
const char *current_function_name;
a simple variable foo in the same block, discard the latter.
First, zero out such symbols, then compress. */
is_new_style_renaming = 0;
- for (i = 0; i < nsyms; i += 1)
+ for (i = 0; i < syms->size (); i += 1)
{
- struct symbol *sym = syms[i].sym;
- const struct block *block = syms[i].block;
+ struct symbol *sym = (*syms)[i].symbol;
+ const struct block *block = (*syms)[i].block;
const char *name;
const char *suffix;
if (sym == NULL || SYMBOL_CLASS (sym) == LOC_TYPEDEF)
continue;
- name = SYMBOL_LINKAGE_NAME (sym);
+ name = sym->linkage_name ();
suffix = strstr (name, "___XR");
if (suffix != NULL)
int j;
is_new_style_renaming = 1;
- for (j = 0; j < nsyms; j += 1)
- if (i != j && syms[j].sym != NULL
- && strncmp (name, SYMBOL_LINKAGE_NAME (syms[j].sym),
+ for (j = 0; j < syms->size (); j += 1)
+ if (i != j && (*syms)[j].symbol != NULL
+ && strncmp (name, (*syms)[j].symbol->linkage_name (),
name_len) == 0
- && block == syms[j].block)
- syms[j].sym = NULL;
+ && block == (*syms)[j].block)
+ (*syms)[j].symbol = NULL;
}
}
if (is_new_style_renaming)
{
int j, k;
- for (j = k = 0; j < nsyms; j += 1)
- if (syms[j].sym != NULL)
+ for (j = k = 0; j < syms->size (); j += 1)
+ if ((*syms)[j].symbol != NULL)
{
- syms[k] = syms[j];
+ (*syms)[k] = (*syms)[j];
k += 1;
}
return k;
Abort if unable to do so. */
if (current_block == NULL)
- return nsyms;
+ return syms->size ();
current_function = block_linkage_function (current_block);
if (current_function == NULL)
- return nsyms;
+ return syms->size ();
- current_function_name = SYMBOL_LINKAGE_NAME (current_function);
+ current_function_name = current_function->linkage_name ();
if (current_function_name == NULL)
- return nsyms;
+ return syms->size ();
/* Check each of the symbols, and remove it from the list if it is
a type corresponding to a renaming that is out of the scope of
the current block. */
i = 0;
- while (i < nsyms)
+ while (i < syms->size ())
{
- if (ada_parse_renaming (syms[i].sym, NULL, NULL, NULL)
+ if (ada_parse_renaming ((*syms)[i].symbol, NULL, NULL, NULL)
== ADA_OBJECT_RENAMING
- && old_renaming_is_invisible (syms[i].sym, current_function_name))
- {
- int j;
-
- for (j = i + 1; j < nsyms; j += 1)
- syms[j - 1] = syms[j];
- nsyms -= 1;
- }
+ && old_renaming_is_invisible ((*syms)[i].symbol,
+ current_function_name))
+ syms->erase (syms->begin () + i);
else
i += 1;
}
- return nsyms;
+ return syms->size ();
}
/* Add to OBSTACKP all symbols from BLOCK (and its super-blocks)
Note: This function assumes that OBSTACKP has 0 (zero) element in it. */
static void
-ada_add_local_symbols (struct obstack *obstackp, const char *name,
- const struct block *block, domain_enum domain,
- int wild_match_p)
+ada_add_local_symbols (struct obstack *obstackp,
+ const lookup_name_info &lookup_name,
+ const struct block *block, domain_enum domain)
{
int block_depth = 0;
while (block != NULL)
{
block_depth += 1;
- ada_add_block_symbols (obstackp, block, name, domain, NULL,
- wild_match_p);
+ ada_add_block_symbols (obstackp, block, lookup_name, domain, NULL);
/* If we found a non-function match, assume that's the one. */
if (is_nonfunction (defns_collected (obstackp, 0),
/* If no luck so far, try to find NAME as a local symbol in some lexically
enclosing subprogram. */
if (num_defns_collected (obstackp) == 0 && block_depth > 2)
- add_symbols_from_enclosing_procs (obstackp, name, domain, wild_match_p);
+ add_symbols_from_enclosing_procs (obstackp, lookup_name, domain);
}
/* An object of this type is used as the user_data argument when
int found_sym;
};
-/* A callback for add_matching_symbols that adds SYM, found in BLOCK,
- to a list of symbols. DATA0 is a pointer to a struct match_data *
+/* A callback for add_nonlocal_symbols that adds symbol, found in BSYM,
+ to a list of symbols. DATA is a pointer to a struct match_data *
containing the obstack that collects the symbol list, the file that SYM
must come from, a flag indicating whether a non-argument symbol has
been found in the current block, and the last argument symbol
marking the end of a block, the argument symbol is added if no
other has been found. */
-static int
-aux_add_nonlocal_symbols (struct block *block, struct symbol *sym, void *data0)
+static bool
+aux_add_nonlocal_symbols (struct block_symbol *bsym,
+ struct match_data *data)
{
- struct match_data *data = (struct match_data *) data0;
-
+ const struct block *block = bsym->block;
+ struct symbol *sym = bsym->symbol;
+
if (sym == NULL)
{
if (!data->found_sym && data->arg_sym != NULL)
else
{
if (SYMBOL_CLASS (sym) == LOC_UNRESOLVED)
- return 0;
+ return true;
else if (SYMBOL_IS_ARGUMENT (sym))
data->arg_sym = sym;
else
block);
}
}
- return 0;
+ return true;
+}
+
+/* Helper for add_nonlocal_symbols. Find symbols in DOMAIN which are
+ targeted by renamings matching LOOKUP_NAME in BLOCK. Add these
+ symbols to OBSTACKP. Return whether we found such symbols. */
+
+static int
+ada_add_block_renamings (struct obstack *obstackp,
+ const struct block *block,
+ const lookup_name_info &lookup_name,
+ domain_enum domain)
+{
+ struct using_direct *renaming;
+ int defns_mark = num_defns_collected (obstackp);
+
+ symbol_name_matcher_ftype *name_match
+ = ada_get_symbol_name_matcher (lookup_name);
+
+ for (renaming = block_using (block);
+ renaming != NULL;
+ renaming = renaming->next)
+ {
+ const char *r_name;
+
+ /* Avoid infinite recursions: skip this renaming if we are actually
+ already traversing it.
+
+ Currently, symbol lookup in Ada don't use the namespace machinery from
+ C++/Fortran support: skip namespace imports that use them. */
+ if (renaming->searched
+ || (renaming->import_src != NULL
+ && renaming->import_src[0] != '\0')
+ || (renaming->import_dest != NULL
+ && renaming->import_dest[0] != '\0'))
+ continue;
+ renaming->searched = 1;
+
+ /* TODO: here, we perform another name-based symbol lookup, which can
+ pull its own multiple overloads. In theory, we should be able to do
+ better in this case since, in DWARF, DW_AT_import is a DIE reference,
+ not a simple name. But in order to do this, we would need to enhance
+ the DWARF reader to associate a symbol to this renaming, instead of a
+ name. So, for now, we do something simpler: re-use the C++/Fortran
+ namespace machinery. */
+ r_name = (renaming->alias != NULL
+ ? renaming->alias
+ : renaming->declaration);
+ if (name_match (r_name, lookup_name, NULL))
+ {
+ lookup_name_info decl_lookup_name (renaming->declaration,
+ lookup_name.match_type ());
+ ada_add_all_symbols (obstackp, block, decl_lookup_name, domain,
+ 1, NULL);
+ }
+ renaming->searched = 0;
+ }
+ return num_defns_collected (obstackp) != defns_mark;
}
/* Implements compare_names, but only applying the comparision using
return result;
}
+/* Convenience function to get at the Ada encoded lookup name for
+ LOOKUP_NAME, as a C string. */
+
+static const char *
+ada_lookup_name (const lookup_name_info &lookup_name)
+{
+ return lookup_name.ada ().lookup_name ().c_str ();
+}
+
/* 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. */
+ LOOKUP_NAME and DOMAIN respectively. The search is performed on
+ GLOBAL_BLOCK symbols if GLOBAL is non-zero, or on STATIC_BLOCK
+ symbols otherwise. */
static void
-add_nonlocal_symbols (struct obstack *obstackp, const char *name,
- domain_enum domain, int global,
- int is_wild_match)
+add_nonlocal_symbols (struct obstack *obstackp,
+ const lookup_name_info &lookup_name,
+ domain_enum domain, int global)
{
- struct objfile *objfile;
struct match_data data;
memset (&data, 0, sizeof data);
data.obstackp = obstackp;
- ALL_OBJFILES (objfile)
+ bool is_wild_match = lookup_name.ada ().wild_match_p ();
+
+ auto callback = [&] (struct block_symbol *bsym)
+ {
+ return aux_add_nonlocal_symbols (bsym, &data);
+ };
+
+ for (objfile *objfile : current_program_space->objfiles ())
{
data.objfile = objfile;
- if (is_wild_match)
- 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 (objfile, name, domain, global,
- aux_add_nonlocal_symbols, &data,
- full_match, compare_names);
+ objfile->sf->qf->map_matching_symbols (objfile, lookup_name,
+ domain, global, callback,
+ (is_wild_match
+ ? NULL : compare_names));
+
+ for (compunit_symtab *cu : objfile->compunits ())
+ {
+ const struct block *global_block
+ = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cu), GLOBAL_BLOCK);
+
+ if (ada_add_block_renamings (obstackp, global_block, lookup_name,
+ domain))
+ data.found_sym = 1;
+ }
}
if (num_defns_collected (obstackp) == 0 && global && !is_wild_match)
{
- ALL_OBJFILES (objfile)
+ const char *name = ada_lookup_name (lookup_name);
+ lookup_name_info name1 (std::string ("<_ada_") + name + '>',
+ symbol_name_match_type::FULL);
+
+ for (objfile *objfile : current_program_space->objfiles ())
{
- char *name1 = alloca (strlen (name) + sizeof ("_ada_"));
- strcpy (name1, "_ada_");
- strcpy (name1 + sizeof ("_ada_") - 1, name);
data.objfile = objfile;
- objfile->sf->qf->map_matching_symbols (objfile, name1, domain,
- global,
- aux_add_nonlocal_symbols,
- &data,
- full_match, compare_names);
+ objfile->sf->qf->map_matching_symbols (objfile, name1,
+ domain, global, callback,
+ compare_names);
}
}
}
-/* 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 is transient---good only to
- the next call of ada_lookup_symbol_list.
+/* Find symbols in DOMAIN matching LOOKUP_NAME, in BLOCK and, if
+ FULL_SEARCH is non-zero, enclosing scope and in global scopes,
+ returning the number of matches. Add these to OBSTACKP.
- When full_search is non-zero, any non-function/non-enumeral
- symbol match within the nest of blocks whose innermost member is BLOCK0,
+ When FULL_SEARCH is non-zero, any non-function/non-enumeral
+ symbol match within the nest of blocks whose innermost member is BLOCK,
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.
+ surrounding BLOCK, 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. */
+ Names prefixed with "standard__" are handled specially:
+ "standard__" is first stripped off (by the lookup_name
+ constructor), and only static and global symbols are searched.
-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)
+ If MADE_GLOBAL_LOOKUP_P is non-null, set it before return to whether we had
+ to lookup global symbols. */
+
+static void
+ada_add_all_symbols (struct obstack *obstackp,
+ const struct block *block,
+ const lookup_name_info &lookup_name,
+ domain_enum domain,
+ int full_search,
+ int *made_global_lookup_p)
{
struct symbol *sym;
- const struct block *block;
- const char *name;
- const int wild_match_p = should_use_wild_match (name0);
- int cacheIfUnique;
- int ndefns;
-
- obstack_free (&symbol_list_obstack, NULL);
- obstack_init (&symbol_list_obstack);
-
- cacheIfUnique = 0;
- /* Search specified block and its superiors. */
-
- name = name0;
- block = block0;
+ if (made_global_lookup_p)
+ *made_global_lookup_p = 0;
/* Special case: If the user specifies a symbol name inside package
Standard, do a non-wild matching of the symbol name without
using, for instance, Standard.Constraint_Error when Constraint_Error
is ambiguous (due to the user defining its own Constraint_Error
entity inside its program). */
- if (strncmp (name0, "standard__", sizeof ("standard__") - 1) == 0)
- {
- block = NULL;
- name = name0 + sizeof ("standard__") - 1;
- }
+ if (lookup_name.ada ().standard_p ())
+ block = NULL;
/* Check the non-global symbols. If we have ANY match, then we're done. */
if (block != NULL)
{
if (full_search)
- {
- ada_add_local_symbols (&symbol_list_obstack, name, block,
- namespace, wild_match_p);
- }
+ ada_add_local_symbols (obstackp, lookup_name, block, domain);
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);
+ ada_add_block_symbols (obstackp, block, lookup_name, domain, NULL);
}
- if (num_defns_collected (&symbol_list_obstack) > 0 || !full_search)
- goto done;
+ if (num_defns_collected (obstackp) > 0 || !full_search)
+ return;
}
/* No non-global symbols found. Check our cache to see if we have
already performed this search before. If we have, then return
the same result. */
- cacheIfUnique = 1;
- if (lookup_cached_symbol (name0, namespace, &sym, &block))
+ if (lookup_cached_symbol (ada_lookup_name (lookup_name),
+ domain, &sym, &block))
{
if (sym != NULL)
- add_defn_to_vec (&symbol_list_obstack, sym, block);
- goto done;
+ add_defn_to_vec (obstackp, sym, block);
+ return;
}
+ if (made_global_lookup_p)
+ *made_global_lookup_p = 1;
+
/* Search symbols from all global blocks. */
- add_nonlocal_symbols (&symbol_list_obstack, name, namespace, 1,
- wild_match_p);
+ add_nonlocal_symbols (obstackp, lookup_name, domain, 1);
/* Now add symbols from all per-file blocks if we've gotten no hits
(not strictly correct, but perhaps better than an error). */
- if (num_defns_collected (&symbol_list_obstack) == 0)
- add_nonlocal_symbols (&symbol_list_obstack, name, namespace, 0,
- wild_match_p);
+ if (num_defns_collected (obstackp) == 0)
+ add_nonlocal_symbols (obstackp, lookup_name, domain, 0);
+}
+
+/* Find symbols in DOMAIN matching LOOKUP_NAME, in BLOCK and, if FULL_SEARCH
+ is non-zero, enclosing scope and in global scopes, returning the number of
+ matches.
+ Fills *RESULTS with (SYM,BLOCK) tuples, indicating the symbols
+ found and the blocks and symbol tables (if any) in which they were
+ found.
+
+ When full_search is non-zero, any non-function/non-enumeral
+ symbol match within the nest of blocks whose innermost member is BLOCK,
+ is the one match returned (no other matches in that or
+ enclosing blocks is returned). If there are any matches in or
+ surrounding BLOCK, 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. */
+
+static int
+ada_lookup_symbol_list_worker (const lookup_name_info &lookup_name,
+ const struct block *block,
+ domain_enum domain,
+ std::vector<struct block_symbol> *results,
+ int full_search)
+{
+ int syms_from_global_search;
+ int ndefns;
+ auto_obstack obstack;
+
+ ada_add_all_symbols (&obstack, block, lookup_name,
+ domain, full_search, &syms_from_global_search);
-done:
- ndefns = num_defns_collected (&symbol_list_obstack);
- *results = defns_collected (&symbol_list_obstack, 1);
+ ndefns = num_defns_collected (&obstack);
- ndefns = remove_extra_symbols (*results, ndefns);
+ struct block_symbol *base = defns_collected (&obstack, 1);
+ for (int i = 0; i < ndefns; ++i)
+ results->push_back (base[i]);
- if (ndefns == 0 && full_search)
- cache_symbol (name0, namespace, NULL, NULL);
+ ndefns = remove_extra_symbols (results);
- if (ndefns == 1 && full_search && cacheIfUnique)
- cache_symbol (name0, namespace, (*results)[0].sym, (*results)[0].block);
+ if (ndefns == 0 && full_search && syms_from_global_search)
+ cache_symbol (ada_lookup_name (lookup_name), domain, NULL, NULL);
- ndefns = remove_irrelevant_renamings (*results, ndefns, block0);
+ if (ndefns == 1 && full_search && syms_from_global_search)
+ cache_symbol (ada_lookup_name (lookup_name), domain,
+ (*results)[0].symbol, (*results)[0].block);
+
+ ndefns = remove_irrelevant_renamings (results, block);
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.
+/* Find symbols in DOMAIN matching NAME, in BLOCK and enclosing scope and
+ in global scopes, returning the number of matches, and filling *RESULTS
+ with (SYM,BLOCK) tuples.
+
See ada_lookup_symbol_list_worker for further details. */
int
-ada_lookup_symbol_list (const char *name0, const struct block *block0,
- domain_enum domain, struct ada_symbol_info **results)
+ada_lookup_symbol_list (const char *name, const struct block *block,
+ domain_enum domain,
+ std::vector<struct block_symbol> *results)
{
- return ada_lookup_symbol_list_worker (name0, block0, domain, results, 1);
+ symbol_name_match_type name_match_type = name_match_type_from_name (name);
+ lookup_name_info lookup_name (name, name_match_type);
+
+ return ada_lookup_symbol_list_worker (lookup_name, block, 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)
+static bool
+ada_iterate_over_symbols
+ (const struct block *block, const lookup_name_info &name,
+ domain_enum domain,
+ gdb::function_view<symbol_found_callback_ftype> callback)
{
int ndefs, i;
- struct ada_symbol_info *results;
+ std::vector<struct block_symbol> results;
ndefs = ada_lookup_symbol_list_worker (name, block, domain, &results, 0);
+
for (i = 0; i < ndefs; ++i)
{
- if (! (*callback) (results[i].sym, data))
- break;
+ if (!callback (&results[i]))
+ return false;
}
-}
-
-/* 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.
-
- NAME can have any form that the "break" or "print" commands might
- recognize. In other words, it does not have to be the "natural"
- name, or the "encoded" name. */
-
-char *
-ada_name_for_lookup (const char *name)
-{
- char *canon;
- int nlen = strlen (name);
- if (name[0] == '<' && name[nlen - 1] == '>')
- {
- canon = xmalloc (nlen - 1);
- memcpy (canon, name + 1, nlen - 2);
- canon[nlen - 2] = '\0';
- }
- else
- canon = xstrdup (ada_encode (ada_fold_name (name)));
- return canon;
+ return true;
}
/* The result is as for ada_lookup_symbol_list with FULL_SEARCH set
void
ada_lookup_encoded_symbol (const char *name, const struct block *block,
- domain_enum namespace,
- struct ada_symbol_info *info)
+ domain_enum domain,
+ struct block_symbol *info)
{
- struct ada_symbol_info *candidates;
- int n_candidates;
+ /* Since we already have an encoded name, wrap it in '<>' to force a
+ verbatim match. Otherwise, if the name happens to not look like
+ an encoded name (because it doesn't include a "__"),
+ ada_lookup_name_info would re-encode/fold it again, and that
+ would e.g., incorrectly lowercase object renaming names like
+ "R28b" -> "r28b". */
+ std::string verbatim = std::string ("<") + name + '>';
gdb_assert (info != NULL);
- memset (info, 0, sizeof (struct ada_symbol_info));
-
- n_candidates = ada_lookup_symbol_list (name, block, namespace, &candidates);
- if (n_candidates == 0)
- return;
-
- *info = candidates[0];
- info->sym = fixup_symbol_section (info->sym, NULL);
+ *info = ada_lookup_symbol (verbatim.c_str (), block, domain);
}
/* Return a symbol in DOMAIN matching NAME, in BLOCK0 and enclosing
scope and in global scopes, or NULL if none. NAME is folded and
encoded first. Otherwise, the result is as for ada_lookup_symbol_list,
- choosing the first symbol if there are multiple choices.
- If IS_A_FIELD_OF_THIS is not NULL, it is set to zero. */
+ choosing the first symbol if there are multiple choices. */
-struct symbol *
+struct block_symbol
ada_lookup_symbol (const char *name, const struct block *block0,
- domain_enum namespace, int *is_a_field_of_this)
+ domain_enum domain)
{
- struct ada_symbol_info info;
+ std::vector<struct block_symbol> candidates;
+ int n_candidates;
+
+ n_candidates = ada_lookup_symbol_list (name, block0, domain, &candidates);
- if (is_a_field_of_this != NULL)
- *is_a_field_of_this = 0;
+ if (n_candidates == 0)
+ return {};
- ada_lookup_encoded_symbol (ada_encode (ada_fold_name (name)),
- block0, namespace, &info);
- return info.sym;
+ block_symbol info = candidates[0];
+ info.symbol = fixup_symbol_section (info.symbol, NULL);
+ return info;
}
-static struct symbol *
-ada_lookup_symbol_nonlocal (const char *name,
+static struct block_symbol
+ada_lookup_symbol_nonlocal (const struct language_defn *langdef,
+ const char *name,
const struct block *block,
const domain_enum domain)
{
- return ada_lookup_symbol (name, block_static_block (block), domain, NULL);
+ struct block_symbol sym;
+
+ sym = ada_lookup_symbol (name, block_static_block (block), domain);
+ if (sym.symbol != NULL)
+ return sym;
+
+ /* If we haven't found a match at this point, try the primitive
+ types. In other languages, this search is performed before
+ searching for global symbols in order to short-circuit that
+ global-symbol search if it happens that the name corresponds
+ to a primitive type. But we cannot do the same in Ada, because
+ it is perfectly legitimate for a program to declare a type which
+ has the same name as a standard type. If looking up a type in
+ that situation, we have traditionally ignored the primitive type
+ in favor of user-defined types. This is why, unlike most other
+ languages, we search the primitive types this late and only after
+ having searched the global symbols without success. */
+
+ if (domain == VAR_DOMAIN)
+ {
+ struct gdbarch *gdbarch;
+
+ if (block == NULL)
+ gdbarch = target_gdbarch ();
+ else
+ gdbarch = block_gdbarch (block);
+ sym.symbol = language_lookup_primitive_type_as_symbol (langdef, gdbarch, name);
+ if (sym.symbol != NULL)
+ return sym;
+ }
+
+ return {};
}
static int
is_valid_name_for_wild_match (const char *name0)
{
- const char *decoded_name = ada_decode (name0);
+ std::string decoded_name = ada_decode (name0);
int i;
/* If the decoded name starts with an angle bracket, it means that
if ((t1 >= 'a' && t1 <= 'z') || (t1 >= '0' && t1 <= '9'))
{
name += 1;
- if (name == name0 + 5 && strncmp (name0, "_ada", 4) == 0)
+ if (name == name0 + 5 && startswith (name0, "_ada"))
break;
else
name += 1;
return 1;
}
-/* Return 0 iff NAME encodes a name of the form prefix.PATN. Ignores any
- informational suffixes of NAME (i.e., for which is_name_suffix is
- true). Assumes that PATN is a lower-cased Ada simple name. */
+/* Return true iff NAME encodes a name of the form prefix.PATN.
+ Ignores any informational suffixes of NAME (i.e., for which
+ is_name_suffix is true). Assumes that PATN is a lower-cased Ada
+ simple name. */
-static int
+static bool
wild_match (const char *name, const char *patn)
{
const char *p;
if (*p != *name)
break;
if (*p == '\0' && is_name_suffix (name))
- return match != name0 && !is_valid_name_for_wild_match (name0);
+ return match == name0 || is_valid_name_for_wild_match (name0);
if (name[-1] == '_')
name -= 1;
}
if (!advance_wild_match (&name, name0, *patn))
- return 1;
+ return false;
}
}
-/* Returns 0 iff symbol name SYM_NAME matches SEARCH_NAME, apart from
- informational suffix. */
+/* Returns true iff symbol name SYM_NAME matches SEARCH_NAME, ignoring
+ any trailing suffixes that encode debugging information or leading
+ _ada_ on SYM_NAME (see is_name_suffix commentary for the debugging
+ information that is ignored). */
-static int
+static bool
full_match (const char *sym_name, const char *search_name)
{
- return !match_name (sym_name, search_name, 0);
-}
+ size_t search_name_len = strlen (search_name);
+
+ if (strncmp (sym_name, search_name, search_name_len) == 0
+ && is_name_suffix (sym_name + search_name_len))
+ return true;
+ if (startswith (sym_name, "_ada_")
+ && strncmp (sym_name + 5, search_name, search_name_len) == 0
+ && is_name_suffix (sym_name + search_name_len + 5))
+ return true;
+
+ return false;
+}
-/* 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. */
+/* Add symbols from BLOCK matching LOOKUP_NAME in DOMAIN to vector
+ *defn_symbols, updating the list of symbols in OBSTACKP (if
+ necessary). OBJFILE is the section containing BLOCK. */
static void
ada_add_block_symbols (struct obstack *obstackp,
- const struct block *block, const char *name,
- domain_enum domain, struct objfile *objfile,
- int wild)
+ const struct block *block,
+ const lookup_name_info &lookup_name,
+ domain_enum domain, struct objfile *objfile)
{
struct block_iterator iter;
- int name_len = strlen (name);
/* A matching argument symbol, if any. */
struct symbol *arg_sym;
/* Set true when we find a matching non-argument symbol. */
arg_sym = NULL;
found_sym = 0;
- if (wild)
- {
- for (sym = block_iter_match_first (block, name, wild_match, &iter);
- sym != NULL; sym = block_iter_match_next (name, wild_match, &iter))
- {
- if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
- SYMBOL_DOMAIN (sym), domain)
- && wild_match (SYMBOL_LINKAGE_NAME (sym), name) == 0)
- {
- if (SYMBOL_CLASS (sym) == LOC_UNRESOLVED)
- continue;
- else if (SYMBOL_IS_ARGUMENT (sym))
- arg_sym = sym;
- else
- {
- found_sym = 1;
- add_defn_to_vec (obstackp,
- fixup_symbol_section (sym, objfile),
- block);
- }
- }
- }
- }
- else
+ for (sym = block_iter_match_first (block, lookup_name, &iter);
+ sym != NULL;
+ sym = block_iter_match_next (lookup_name, &iter))
{
- for (sym = block_iter_match_first (block, name, full_match, &iter);
- sym != NULL; sym = block_iter_match_next (name, full_match, &iter))
- {
- if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
- SYMBOL_DOMAIN (sym), domain))
- {
- if (SYMBOL_CLASS (sym) != LOC_UNRESOLVED)
- {
- if (SYMBOL_IS_ARGUMENT (sym))
- arg_sym = sym;
- else
- {
- found_sym = 1;
- add_defn_to_vec (obstackp,
- fixup_symbol_section (sym, objfile),
- block);
- }
- }
- }
- }
+ if (symbol_matches_domain (sym->language (), SYMBOL_DOMAIN (sym), domain))
+ {
+ if (SYMBOL_CLASS (sym) != LOC_UNRESOLVED)
+ {
+ if (SYMBOL_IS_ARGUMENT (sym))
+ arg_sym = sym;
+ else
+ {
+ found_sym = 1;
+ add_defn_to_vec (obstackp,
+ fixup_symbol_section (sym, objfile),
+ block);
+ }
+ }
+ }
}
+ /* Handle renamings. */
+
+ if (ada_add_block_renamings (obstackp, block, lookup_name, domain))
+ found_sym = 1;
+
if (!found_sym && arg_sym != NULL)
{
add_defn_to_vec (obstackp,
block);
}
- if (!wild)
+ if (!lookup_name.ada ().wild_match_p ())
{
arg_sym = NULL;
found_sym = 0;
+ const std::string &ada_lookup_name = lookup_name.ada ().lookup_name ();
+ const char *name = ada_lookup_name.c_str ();
+ size_t name_len = ada_lookup_name.size ();
ALL_BLOCK_SYMBOLS (block, iter, sym)
{
- if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
+ if (symbol_matches_domain (sym->language (),
SYMBOL_DOMAIN (sym), domain))
{
int cmp;
- cmp = (int) '_' - (int) SYMBOL_LINKAGE_NAME (sym)[0];
+ cmp = (int) '_' - (int) sym->linkage_name ()[0];
if (cmp == 0)
{
- cmp = strncmp ("_ada_", SYMBOL_LINKAGE_NAME (sym), 5);
+ cmp = !startswith (sym->linkage_name (), "_ada_");
if (cmp == 0)
- cmp = strncmp (name, SYMBOL_LINKAGE_NAME (sym) + 5,
+ cmp = strncmp (name, sym->linkage_name () + 5,
name_len);
}
if (cmp == 0
- && is_name_suffix (SYMBOL_LINKAGE_NAME (sym) + name_len + 5))
+ && is_name_suffix (sym->linkage_name () + name_len + 5))
{
if (SYMBOL_CLASS (sym) != LOC_UNRESOLVED)
{
/* Symbol Completion */
-/* If SYM_NAME is a completion candidate for TEXT, return this symbol
- name in a form that's appropriate for the completion. The result
- does not need to be deallocated, but is only good until the next call.
+/* See symtab.h. */
- TEXT_LEN is equal to the length of TEXT.
- Perform a wild match if WILD_MATCH_P is set.
- ENCODED_P should be set if TEXT represents the start of a symbol name
- in its encoded form. */
-
-static const char *
-symbol_completion_match (const char *sym_name,
- const char *text, int text_len,
- int wild_match_p, int encoded_p)
+bool
+ada_lookup_name_info::matches
+ (const char *sym_name,
+ symbol_name_match_type match_type,
+ completion_match_result *comp_match_res) const
{
- const int verbatim_match = (text[0] == '<');
- int match = 0;
-
- if (verbatim_match)
- {
- /* Strip the leading angle bracket. */
- text = text + 1;
- text_len--;
- }
+ bool match = false;
+ const char *text = m_encoded_name.c_str ();
+ size_t text_len = m_encoded_name.size ();
/* First, test against the fully qualified name of the symbol. */
if (strncmp (sym_name, text, text_len) == 0)
- match = 1;
+ match = true;
- if (match && !encoded_p)
+ std::string decoded_name = ada_decode (sym_name);
+ if (match && !m_encoded_p)
{
/* One needed check before declaring a positive match is to verify
that iff we are doing a verbatim match, the decoded version
of the symbol name starts with '<'. Otherwise, this symbol name
is not a suitable completion. */
- const char *sym_name_copy = sym_name;
- int has_angle_bracket;
- sym_name = ada_decode (sym_name);
- has_angle_bracket = (sym_name[0] == '<');
- match = (has_angle_bracket == verbatim_match);
- sym_name = sym_name_copy;
+ bool has_angle_bracket = (decoded_name[0] == '<');
+ match = (has_angle_bracket == m_verbatim_p);
}
- if (match && !verbatim_match)
+ if (match && !m_verbatim_p)
{
/* When doing non-verbatim match, another check that needs to
be done is to verify that the potentially matching symbol name
for (tmp = sym_name; *tmp != '\0' && !isupper (*tmp); tmp++);
if (*tmp != '\0')
- match = 0;
+ match = false;
}
/* Second: Try wild matching... */
- if (!match && wild_match_p)
+ if (!match && m_wild_match_p)
{
/* Since we are doing wild matching, this means that TEXT
may represent an unqualified symbol name. We therefore must
also compare TEXT against the unqualified name of the symbol. */
- sym_name = ada_unqualified_name (ada_decode (sym_name));
+ sym_name = ada_unqualified_name (decoded_name.c_str ());
if (strncmp (sym_name, text, text_len) == 0)
- match = 1;
+ match = true;
}
- /* Finally: If we found a mach, prepare the result to return. */
+ /* Finally: If we found a match, prepare the result to return. */
if (!match)
- return NULL;
-
- if (verbatim_match)
- sym_name = add_angle_brackets (sym_name);
-
- if (!encoded_p)
- sym_name = ada_decode (sym_name);
+ return false;
- return sym_name;
-}
-
-/* A companion function to ada_make_symbol_completion_list().
- Check if SYM_NAME represents a symbol which name would be suitable
- to complete TEXT (TEXT_LEN is the length of TEXT), in which case
- it is appended at the end of the given string vector SV.
-
- ORIG_TEXT is the string original string from the user command
- that needs to be completed. WORD is the entire command on which
- completion should be performed. These two parameters are used to
- determine which part of the symbol name should be added to the
- completion vector.
- if WILD_MATCH_P is set, then wild matching is performed.
- ENCODED_P should be set if TEXT represents a symbol name in its
- encoded formed (in which case the completion should also be
- encoded). */
-
-static void
-symbol_completion_add (VEC(char_ptr) **sv,
- const char *sym_name,
- const char *text, int text_len,
- const char *orig_text, const char *word,
- int wild_match_p, int encoded_p)
-{
- const char *match = symbol_completion_match (sym_name, text, text_len,
- wild_match_p, encoded_p);
- char *completion;
-
- if (match == NULL)
- return;
-
- /* We found a match, so add the appropriate completion to the given
- string vector. */
-
- if (word == orig_text)
- {
- completion = xmalloc (strlen (match) + 5);
- strcpy (completion, match);
- }
- else if (word > orig_text)
+ if (comp_match_res != NULL)
{
- /* Return some portion of sym_name. */
- completion = xmalloc (strlen (match) + 5);
- strcpy (completion, match + (word - orig_text));
- }
- else
- {
- /* Return some of ORIG_TEXT plus sym_name. */
- completion = xmalloc (strlen (match) + (orig_text - word) + 5);
- strncpy (completion, word, orig_text - word);
- completion[orig_text - word] = '\0';
- strcat (completion, match);
- }
+ std::string &match_str = comp_match_res->match.storage ();
- VEC_safe_push (char_ptr, *sv, completion);
-}
+ if (!m_encoded_p)
+ match_str = ada_decode (sym_name);
+ else
+ {
+ if (m_verbatim_p)
+ match_str = add_angle_brackets (sym_name);
+ else
+ match_str = sym_name;
-/* An object of this type is passed as the user_data argument to the
- expand_symtabs_matching method. */
-struct add_partial_datum
-{
- VEC(char_ptr) **completions;
- const char *text;
- int text_len;
- const char *text0;
- const char *word;
- int wild_match;
- int encoded;
-};
+ }
-/* A callback for expand_symtabs_matching. */
+ comp_match_res->set_match (match_str.c_str ());
+ }
-static int
-ada_complete_symbol_matcher (const char *name, void *user_data)
-{
- struct add_partial_datum *data = user_data;
-
- return symbol_completion_match (name, data->text, data->text_len,
- data->wild_match, data->encoded) != NULL;
+ return true;
}
-/* Return a list of possible symbol names completing TEXT0. WORD is
- the entire command on which completion is made. */
+/* Add the list of possible symbol names completing TEXT to TRACKER.
+ WORD is the entire command on which completion is made. */
-static VEC (char_ptr) *
-ada_make_symbol_completion_list (const char *text0, const char *word,
- enum type_code code)
+static void
+ada_collect_symbol_completion_matches (completion_tracker &tracker,
+ complete_symbol_mode mode,
+ symbol_name_match_type name_match_type,
+ const char *text, const char *word,
+ enum type_code code)
{
- char *text;
- int text_len;
- int wild_match_p;
- int encoded_p;
- VEC(char_ptr) *completions = VEC_alloc (char_ptr, 128);
struct symbol *sym;
- struct symtab *s;
- struct minimal_symbol *msymbol;
- struct objfile *objfile;
- struct block *b, *surrounding_static_block = 0;
- int i;
+ const struct block *b, *surrounding_static_block = 0;
struct block_iterator iter;
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
gdb_assert (code == TYPE_CODE_UNDEF);
- if (text0[0] == '<')
- {
- text = xstrdup (text0);
- make_cleanup (xfree, text);
- text_len = strlen (text);
- wild_match_p = 0;
- encoded_p = 1;
- }
- else
- {
- text = xstrdup (ada_encode (text0));
- make_cleanup (xfree, text);
- text_len = strlen (text);
- for (i = 0; i < text_len; i++)
- text[i] = tolower (text[i]);
-
- encoded_p = (strstr (text0, "__") != NULL);
- /* If the name contains a ".", then the user is entering a fully
- qualified entity name, and the match must not be done in wild
- mode. Similarly, if the user wants to complete what looks like
- an encoded name, the match must not be done in wild mode. */
- wild_match_p = (strchr (text0, '.') == NULL && !encoded_p);
- }
+ lookup_name_info lookup_name (text, name_match_type, true);
/* First, look at the partial symtab symbols. */
- {
- struct add_partial_datum data;
-
- data.completions = &completions;
- data.text = text;
- data.text_len = text_len;
- data.text0 = text0;
- data.word = word;
- data.wild_match = wild_match_p;
- data.encoded = encoded_p;
- expand_symtabs_matching (NULL, ada_complete_symbol_matcher, ALL_DOMAIN,
- &data);
- }
+ expand_symtabs_matching (NULL,
+ lookup_name,
+ NULL,
+ NULL,
+ ALL_DOMAIN);
/* At this point scan through the misc symbol vectors and add each
symbol you find to the list. Eventually we want to ignore
anything that isn't a text symbol (everything else will be
handled by the psymtab code above). */
- ALL_MSYMBOLS (objfile, msymbol)
- {
- QUIT;
- symbol_completion_add (&completions, MSYMBOL_LINKAGE_NAME (msymbol),
- text, text_len, text0, word, wild_match_p,
- encoded_p);
- }
+ 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 ();
+
+ /* 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 (),
+ lookup_name, text, word);
+ }
+ }
/* Search upwards from currently selected frame (so that we can
complete on local vars. */
ALL_BLOCK_SYMBOLS (b, iter, sym)
{
- symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
- text, text_len, text0, word,
- wild_match_p, encoded_p);
+ if (completion_skip_symbol (mode, sym))
+ continue;
+
+ completion_list_add_name (tracker,
+ sym->language (),
+ sym->linkage_name (),
+ lookup_name, text, word);
}
}
/* Go through the symtabs and check the externs and statics for
symbols which match. */
- ALL_SYMTABS (objfile, s)
- {
- QUIT;
- b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
- ALL_BLOCK_SYMBOLS (b, iter, sym)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
- text, text_len, text0, word,
- wild_match_p, encoded_p);
+ 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,
+ sym->language (),
+ sym->linkage_name (),
+ lookup_name, text, word);
+ }
+ }
}
- }
- ALL_SYMTABS (objfile, s)
- {
- QUIT;
- b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
- /* Don't do this block twice. */
- if (b == surrounding_static_block)
- continue;
- ALL_BLOCK_SYMBOLS (b, iter, sym)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (sym),
- text, text_len, text0, word,
- wild_match_p, encoded_p);
- }
- }
+ 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;
- do_cleanups (old_chain);
- return completions;
+ completion_list_add_name (tracker,
+ sym->language (),
+ sym->linkage_name (),
+ lookup_name, text, word);
+ }
+ }
+ }
}
/* Field Access */
/* Anonymous field names should not be printed.
brobecker/2007-02-20: I don't think this can actually happen
- but we don't want to print the value of annonymous fields anyway. */
+ but we don't want to print the value of anonymous fields anyway. */
if (name == NULL)
return 1;
for tagged types, and it contains the components inherited from
the parent type. This field should not be printed as is, but
should not be ignored either. */
- if (name[0] == '_' && strncmp (name, "_parent", 7) != 0)
+ if (name[0] == '_' && !startswith (name, "_parent"))
return 1;
}
int
ada_is_tagged_type (struct type *type, int refok)
{
- return (ada_lookup_struct_elt_type (type, "_tag", refok, 1, NULL) != NULL);
+ return (ada_lookup_struct_elt_type (type, "_tag", refok, 1) != NULL);
}
/* True iff TYPE represents the type of X'Tag */
int
ada_is_tag_type (struct type *type)
{
+ type = ada_check_typedef (type);
+
if (type == NULL || TYPE_CODE (type) != TYPE_CODE_PTR)
return 0;
else
/* The type of the tag on VAL. */
-struct type *
+static struct type *
ada_tag_type (struct value *val)
{
- return ada_lookup_struct_elt_type (value_type (val), "_tag", 1, 0, NULL);
+ return ada_lookup_struct_elt_type (value_type (val), "_tag", 1, 0);
}
/* Return 1 if TAG follows the old scheme for Ada tags (used for Ada 95,
/* The value of the tag on VAL. */
-struct value *
+static struct value *
ada_value_tag (struct value *val)
{
return ada_value_struct_elt (val, "_tag", 0);
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;
if (is_ada95_tag (tag))
return obj;
- ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
+ ptr_type = language_lookup_primitive_type
+ (language_def (language_ada), target_gdbarch(), "storage_offset");
ptr_type = lookup_pointer_type (ptr_type);
val = value_cast (ptr_type, tag);
if (!val)
see ada_tag_name for more details. We do not print the error
message for the same reason. */
- TRY_CATCH (e, RETURN_MASK_ERROR)
+ try
{
offset_to_top = value_as_long (value_ind (value_ptradd (val, -2)));
}
- if (e.reason < 0)
- return obj;
+ catch (const gdb_exception_error &e)
+ {
+ return obj;
+ }
/* If offset is null, nothing to do. */
if (offset_to_top == -1)
return obj;
- base_address = value_address (obj) - offset_to_top;
+ /* OFFSET_TO_TOP used to be a positive value to be subtracted
+ from the base address. This was however incompatible with
+ C++ dispatch table: C++ uses a *negative* value to *add*
+ to the base address. Ada's convention has therefore been
+ changed in GNAT 19.0w 20171023: since then, C++ and Ada
+ use the same convention. Here, we support both cases by
+ checking the sign of OFFSET_TO_TOP. */
+
+ if (offset_to_top > 0)
+ offset_to_top = -offset_to_top;
+
+ base_address = value_address (obj) + offset_to_top;
tag = value_tag_from_contents_and_address (obj_type, NULL, base_address);
/* Make sure that we have a proper tag at the new address.
const char *
ada_tag_name (struct value *tag)
{
- volatile struct gdb_exception e;
char *name = NULL;
if (!ada_is_tag_type (value_type (tag)))
We also do not print the error message either (which often is very
low-level (Eg: "Cannot read memory at 0x[...]"), but instead let
the caller print a more meaningful message if necessary. */
- TRY_CATCH (e, RETURN_MASK_ERROR)
+ try
{
struct value *tsd = ada_get_tsd_from_tag (tag);
if (tsd != NULL)
name = ada_tag_name_from_tsd (tsd);
}
+ catch (const gdb_exception_error &e)
+ {
+ }
return name;
}
const char *name = TYPE_FIELD_NAME (ada_check_typedef (type), field_num);
return (name != NULL
- && (strncmp (name, "PARENT", 6) == 0
- || strncmp (name, "_parent", 7) == 0));
+ && (startswith (name, "PARENT")
+ || startswith (name, "_parent")));
}
/* True iff field number FIELD_NUM of structure type TYPE is a
{
const char *name = TYPE_FIELD_NAME (type, field_num);
+ if (name != NULL && strcmp (name, "RETVAL") == 0)
+ {
+ /* This happens in functions with "out" or "in out" parameters
+ which are passed by copy. For such functions, GNAT describes
+ the function's return type as being a struct where the return
+ value is in a field called RETVAL, and where the other "out"
+ or "in out" parameters are fields of that struct. This is not
+ a wrapper. */
+ return 0;
+ }
+
return (name != NULL
- && (strncmp (name, "PARENT", 6) == 0
+ && (startswith (name, "PARENT")
|| strcmp (name, "REP") == 0
- || strncmp (name, "_parent", 7) == 0
+ || startswith (name, "_parent")
|| name[0] == 'S' || name[0] == 'R' || name[0] == 'O'));
}
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
struct type *
ada_variant_discrim_type (struct type *var_type, struct type *outer_type)
{
- char *name = ada_variant_discrim_name (var_type);
+ const char *name = ada_variant_discrim_name (var_type);
- return ada_lookup_struct_elt_type (outer_type, name, 1, 1, NULL);
+ return ada_lookup_struct_elt_type (outer_type, name, 1, 1);
}
/* Assuming that TYPE is the type of a variant wrapper, and FIELD_NUM is a
valid field number within it, returns 1 iff field FIELD_NUM of TYPE
represents a 'when others' clause; otherwise 0. */
-int
+static int
ada_is_others_clause (struct type *type, int field_num)
{
const char *name = TYPE_FIELD_NAME (type, field_num);
returns the name of the discriminant controlling the variant.
The value is valid until the next call to ada_variant_discrim_name. */
-char *
+const char *
ada_variant_discrim_name (struct type *type0)
{
static char *result = NULL;
for (discrim_end = name + strlen (name) - 6; discrim_end != name;
discrim_end -= 1)
{
- if (strncmp (discrim_end, "___XVN", 6) == 0)
+ if (startswith (discrim_end, "___XVN"))
break;
}
if (discrim_end == name)
if (discrim_start == name + 1)
return "";
if ((discrim_start > name + 3
- && strncmp (discrim_start - 3, "___", 3) == 0)
+ && startswith (discrim_start - 3, "___"))
|| discrim_start[-1] == '.')
break;
}
and FIELD_NUM is a valid field number within it, returns 1 iff VAL is
in the range encoded by field FIELD_NUM of TYPE; otherwise 0. */
-int
+static int
ada_in_variant (LONGEST val, struct type *type, int field_num)
{
const char *name = TYPE_FIELD_NAME (type, field_num);
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);
number of fields if not found. A NULL value of NAME never
matches; the function just counts visible fields in this case.
+ Notice that we need to handle when a tagged record hierarchy
+ has some components with the same name, like in this scenario:
+
+ type Top_T is tagged record
+ N : Integer := 1;
+ U : Integer := 974;
+ A : Integer := 48;
+ end record;
+
+ type Middle_T is new Top.Top_T with record
+ N : Character := 'a';
+ C : Integer := 3;
+ end record;
+
+ type Bottom_T is new Middle.Middle_T with record
+ N : Float := 4.0;
+ C : Character := '5';
+ X : Integer := 6;
+ A : Character := 'J';
+ end record;
+
+ Let's say we now have a variable declared and initialized as follow:
+
+ TC : Top_A := new Bottom_T;
+
+ And then we use this variable to call this function
+
+ procedure Assign (Obj: in out Top_T; TV : Integer);
+
+ as follow:
+
+ Assign (Top_T (B), 12);
+
+ Now, we're in the debugger, and we're inside that procedure
+ then and we want to print the value of obj.c:
+
+ Usually, the tagged record or one of the parent type owns the
+ component to print and there's no issue but in this particular
+ case, what does it mean to ask for Obj.C? Since the actual
+ type for object is type Bottom_T, it could mean two things: type
+ component C from the Middle_T view, but also component C from
+ Bottom_T. So in that "undefined" case, when the component is
+ not found in the non-resolved type (which includes all the
+ components of the parent type), then resolve it and see if we
+ get better luck once expanded.
+
+ In the case of homonyms in the derived tagged type, we don't
+ guaranty anything, and pick the one that's easiest for us
+ to program.
+
Returns 1 if found, 0 otherwise. */
static int
int *index_p)
{
int i;
+ int parent_offset = -1;
type = ada_check_typedef (type);
if (t_field_name == NULL)
continue;
+ else if (ada_is_parent_field (type, i))
+ {
+ /* This is a field pointing us to the parent type of a tagged
+ type. As hinted in this function's documentation, we give
+ preference to fields in the current record first, so what
+ we do here is just record the index of this field before
+ we skip it. If it turns out we couldn't find our field
+ in the current record, then we'll get back to it and search
+ inside it whether the field might exist in the parent. */
+
+ parent_offset = i;
+ continue;
+ }
+
else if (name != NULL && field_name_match (t_field_name, name))
{
int bit_size = TYPE_FIELD_BITSIZE (type, i);
else if (index_p != NULL)
*index_p += 1;
}
+
+ /* Field not found so far. If this is a tagged type which
+ has a parent, try finding that field in the parent now. */
+
+ if (parent_offset != -1)
+ {
+ int bit_pos = TYPE_FIELD_BITPOS (type, parent_offset);
+ int fld_offset = offset + bit_pos / 8;
+
+ if (find_struct_field (name, TYPE_FIELD_TYPE (type, parent_offset),
+ fld_offset, field_type_p, byte_offset_p,
+ bit_offset_p, bit_size_p, index_p))
+ return 1;
+ }
+
return 0;
}
and search in it assuming it has (class) type TYPE.
If found, return value, else return NULL.
- Searches recursively through wrapper fields (e.g., '_parent'). */
+ Searches recursively through wrapper fields (e.g., '_parent').
+
+ In the case of homonyms in the tagged types, please refer to the
+ long explanation in find_struct_field's function documentation. */
static struct value *
-ada_search_struct_field (char *name, struct value *arg, int offset,
+ada_search_struct_field (const char *name, struct value *arg, int offset,
struct type *type)
{
int i;
+ int parent_offset = -1;
type = ada_check_typedef (type);
for (i = 0; i < TYPE_NFIELDS (type); i += 1)
if (t_field_name == NULL)
continue;
+ else if (ada_is_parent_field (type, i))
+ {
+ /* This is a field pointing us to the parent type of a tagged
+ type. As hinted in this function's documentation, we give
+ preference to fields in the current record first, so what
+ we do here is just record the index of this field before
+ we skip it. If it turns out we couldn't find our field
+ in the current record, then we'll get back to it and search
+ inside it whether the field might exist in the parent. */
+
+ parent_offset = i;
+ continue;
+ }
+
else if (field_name_match (t_field_name, name))
return ada_value_primitive_field (arg, offset, i, type);
}
}
}
+
+ /* Field not found so far. If this is a tagged type which
+ has a parent, try finding that field in the parent now. */
+
+ if (parent_offset != -1)
+ {
+ struct value *v = ada_search_struct_field (
+ name, arg, offset + TYPE_FIELD_BITPOS (type, parent_offset) / 8,
+ TYPE_FIELD_TYPE (type, parent_offset));
+
+ if (v != NULL)
+ return v;
+ }
+
return NULL;
}
return NULL;
}
-/* Given ARG, a value of type (pointer or reference to a)*
- structure/union, extract the component named NAME from the ultimate
- target structure/union and return it as a value with its
- appropriate type.
-
- The routine searches for NAME among all members of the structure itself
- and (recursively) among all members of any wrapper members
- (e.g., '_parent').
-
- If NO_ERR, then simply return NULL in case of error, rather than
- calling error. */
+/* Return a string representation of type TYPE. */
-struct value *
-ada_value_struct_elt (struct value *arg, char *name, int no_err)
+static std::string
+type_as_string (struct type *type)
{
- struct type *t, *t1;
- struct value *v;
-
- v = NULL;
- t1 = t = ada_check_typedef (value_type (arg));
- if (TYPE_CODE (t) == TYPE_CODE_REF)
- {
- t1 = TYPE_TARGET_TYPE (t);
- if (t1 == NULL)
- goto BadValue;
- t1 = ada_check_typedef (t1);
- if (TYPE_CODE (t1) == TYPE_CODE_PTR)
- {
- arg = coerce_ref (arg);
- t = t1;
- }
- }
-
- while (TYPE_CODE (t) == TYPE_CODE_PTR)
- {
- t1 = TYPE_TARGET_TYPE (t);
- if (t1 == NULL)
- goto BadValue;
- t1 = ada_check_typedef (t1);
- if (TYPE_CODE (t1) == TYPE_CODE_PTR)
- {
- arg = value_ind (arg);
- t = t1;
- }
- else
- break;
- }
-
- if (TYPE_CODE (t1) != TYPE_CODE_STRUCT && TYPE_CODE (t1) != TYPE_CODE_UNION)
- goto BadValue;
-
- if (t1 == t)
- v = ada_search_struct_field (name, arg, 0, t);
- else
- {
- int bit_offset, bit_size, byte_offset;
- struct type *field_type;
- CORE_ADDR address;
-
- if (TYPE_CODE (t) == TYPE_CODE_PTR)
- address = value_address (ada_value_ind (arg));
- else
- 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,
- &field_type, &byte_offset, &bit_offset,
- &bit_size, NULL))
- {
- if (bit_size != 0)
- {
- if (TYPE_CODE (t) == TYPE_CODE_REF)
- arg = ada_coerce_ref (arg);
- else
- arg = ada_value_ind (arg);
- v = ada_value_primitive_packed_val (arg, NULL, byte_offset,
- bit_offset, bit_size,
- field_type);
- }
- else
- v = value_at_lazy (field_type, address + byte_offset);
- }
- }
+ string_file tmp_stream;
- if (v != NULL || no_err)
- return v;
- else
- error (_("There is no member named %s."), name);
+ type_print (type, "", &tmp_stream, -1);
- BadValue:
- if (no_err)
- return NULL;
- else
- error (_("Attempt to extract a component of "
- "a value that is not a record."));
+ return std::move (tmp_stream.string ());
}
/* Given a type TYPE, look up the type of the component of type named NAME.
Looks recursively into variant clauses and parent types.
+ In the case of homonyms in the tagged types, please refer to the
+ long explanation in find_struct_field's function documentation.
+
If NOERR is nonzero, return NULL if NAME is not suitably defined or
TYPE is not a type of the right kind. */
static struct type *
-ada_lookup_struct_elt_type (struct type *type, char *name, int refok,
- int noerr, int *dispp)
+ada_lookup_struct_elt_type (struct type *type, const char *name, int refok,
+ int noerr)
{
int i;
+ int parent_offset = -1;
if (name == NULL)
goto BadName;
{
if (noerr)
return NULL;
- else
- {
- target_terminal_ours ();
- gdb_flush (gdb_stdout);
- if (type == NULL)
- error (_("Type (null) is not a structure or union type"));
- else
- {
- /* XXX: type_sprint */
- fprintf_unfiltered (gdb_stderr, _("Type "));
- type_print (type, "", gdb_stderr, -1);
- error (_(" is not a structure or union type"));
- }
- }
+
+ error (_("Type %s is not a structure or union type"),
+ type != NULL ? type_as_string (type).c_str () : _("(null)"));
}
type = to_static_fixed_type (type);
{
const char *t_field_name = TYPE_FIELD_NAME (type, i);
struct type *t;
- int disp;
if (t_field_name == NULL)
continue;
- else if (field_name_match (t_field_name, name))
+ else if (ada_is_parent_field (type, i))
{
- if (dispp != NULL)
- *dispp += TYPE_FIELD_BITPOS (type, i) / 8;
- return ada_check_typedef (TYPE_FIELD_TYPE (type, i));
+ /* This is a field pointing us to the parent type of a tagged
+ type. As hinted in this function's documentation, we give
+ preference to fields in the current record first, so what
+ we do here is just record the index of this field before
+ we skip it. If it turns out we couldn't find our field
+ in the current record, then we'll get back to it and search
+ inside it whether the field might exist in the parent. */
+
+ parent_offset = i;
+ continue;
}
+ else if (field_name_match (t_field_name, name))
+ return TYPE_FIELD_TYPE (type, i);
+
else if (ada_is_wrapper_field (type, i))
{
- disp = 0;
t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (type, i), name,
- 0, 1, &disp);
+ 0, 1);
if (t != NULL)
- {
- if (dispp != NULL)
- *dispp += disp + TYPE_FIELD_BITPOS (type, i) / 8;
- return t;
- }
+ return t;
}
else if (ada_is_variant_part (type, i))
generates these for unchecked variant types. Revisit
if the compiler changes this practice. */
const char *v_field_name = TYPE_FIELD_NAME (field_type, j);
- disp = 0;
+
if (v_field_name != NULL
&& field_name_match (v_field_name, name))
- t = ada_check_typedef (TYPE_FIELD_TYPE (field_type, j));
+ t = TYPE_FIELD_TYPE (field_type, j);
else
t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (field_type,
j),
- name, 0, 1, &disp);
+ name, 0, 1);
if (t != NULL)
- {
- if (dispp != NULL)
- *dispp += disp + TYPE_FIELD_BITPOS (type, i) / 8;
- return t;
- }
+ return t;
}
}
}
+ /* Field not found so far. If this is a tagged type which
+ has a parent, try finding that field in the parent now. */
+
+ if (parent_offset != -1)
+ {
+ struct type *t;
+
+ t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (type, parent_offset),
+ name, 0, 1);
+ if (t != NULL)
+ return t;
+ }
+
BadName:
if (!noerr)
{
- target_terminal_ours ();
- gdb_flush (gdb_stdout);
- if (name == NULL)
- {
- /* XXX: type_sprint */
- fprintf_unfiltered (gdb_stderr, _("Type "));
- type_print (type, "", gdb_stderr, -1);
- error (_(" has no component named <null>"));
- }
- else
- {
- /* XXX: type_sprint */
- fprintf_unfiltered (gdb_stderr, _("Type "));
- type_print (type, "", gdb_stderr, -1);
- error (_(" has no component named %s"), name);
- }
+ const char *name_str = name != NULL ? name : _("<null>");
+
+ error (_("Type %s has no component named %s"),
+ type_as_string (type).c_str (), name_str);
}
return NULL;
static int
is_unchecked_variant (struct type *var_type, struct type *outer_type)
{
- char *discrim_name = ada_variant_discrim_name (var_type);
+ const char *discrim_name = ada_variant_discrim_name (var_type);
- return (ada_lookup_struct_elt_type (outer_type, discrim_name, 0, 1, NULL)
- == NULL);
+ return (ada_lookup_struct_elt_type (outer_type, discrim_name, 0, 1) == NULL);
}
{
int others_clause;
int i;
- char *discrim_name = ada_variant_discrim_name (var_type);
+ const char *discrim_name = ada_variant_discrim_name (var_type);
struct value *outer;
struct value *discrim;
LONGEST discrim_val;
- outer = value_from_contents_and_address (outer_type, outer_valaddr, 0);
+ /* Using plain value_from_contents_and_address here causes problems
+ because we will end up trying to resolve a type that is currently
+ being constructed. */
+ outer = value_from_contents_and_address_unresolved (outer_type,
+ outer_valaddr, 0);
discrim = ada_value_struct_elt (outer, discrim_name, 1);
if (discrim == NULL)
return -1;
else
align_offset = len - 1;
- if (align_offset < 7 || strncmp ("___XV", name + align_offset - 6, 5) != 0)
+ if (align_offset < 7 || !startswith (name + align_offset - 6, "___XV"))
return TARGET_CHAR_BIT;
return atoi (name + align_offset) * TARGET_CHAR_BIT;
symbols whose name is that of NAME_SYM suffixed with "___XR".
Return symbol if found, and NULL otherwise. */
-struct symbol *
-ada_find_renaming_symbol (struct symbol *name_sym, const struct block *block)
+static bool
+ada_is_renaming_symbol (struct symbol *name_sym)
{
- const char *name = SYMBOL_LINKAGE_NAME (name_sym);
- struct symbol *sym;
-
- if (strstr (name, "___XR") != NULL)
- return name_sym;
-
- sym = find_old_style_renaming_symbol (name, block);
-
- if (sym != NULL)
- return sym;
-
- /* Not right yet. FIXME pnh 7/20/2007. */
- sym = ada_find_any_type_symbol (name);
- if (sym != NULL && strstr (SYMBOL_LINKAGE_NAME (sym), "___XR") != NULL)
- return sym;
- else
- return NULL;
-}
-
-static struct symbol *
-find_old_style_renaming_symbol (const char *name, const struct block *block)
-{
- const struct symbol *function_sym = block_linkage_function (block);
- char *rename;
-
- if (function_sym != NULL)
- {
- /* If the symbol is defined inside a function, NAME is not fully
- qualified. This means we need to prepend the function name
- as well as adding the ``___XR'' suffix to build the name of
- the associated renaming symbol. */
- const char *function_name = SYMBOL_LINKAGE_NAME (function_sym);
- /* Function names sometimes contain suffixes used
- for instance to qualify nested subprograms. When building
- the XR type name, we need to make sure that this suffix is
- not included. So do not include any suffix in the function
- name length below. */
- int function_name_len = ada_name_prefix_len (function_name);
- const int rename_len = function_name_len + 2 /* "__" */
- + strlen (name) + 6 /* "___XR\0" */ ;
-
- /* Strip the suffix if necessary. */
- ada_remove_trailing_digits (function_name, &function_name_len);
- ada_remove_po_subprogram_suffix (function_name, &function_name_len);
- ada_remove_Xbn_suffix (function_name, &function_name_len);
-
- /* Library-level functions are a special case, as GNAT adds
- a ``_ada_'' prefix to the function name to avoid namespace
- pollution. However, the renaming symbols themselves do not
- have this prefix, so we need to skip this prefix if present. */
- if (function_name_len > 5 /* "_ada_" */
- && strstr (function_name, "_ada_") == function_name)
- {
- function_name += 5;
- function_name_len -= 5;
- }
-
- rename = (char *) alloca (rename_len * sizeof (char));
- strncpy (rename, function_name, function_name_len);
- xsnprintf (rename + function_name_len, rename_len - function_name_len,
- "__%s___XR", name);
- }
- else
- {
- const int rename_len = strlen (name) + 6;
-
- rename = (char *) alloca (rename_len * sizeof (char));
- xsnprintf (rename, rename_len * sizeof (char), "%s___XR", name);
- }
-
- return ada_find_any_type_symbol (rename);
+ const char *name = name_sym->linkage_name ();
+ return strstr (name, "___XR") != NULL;
}
/* Because of GNAT encoding conventions, several GDB symbols may match a
return 1;
else
{
- const char *type0_name = type_name_no_tag (type0);
- const char *type1_name = type_name_no_tag (type1);
+ const char *type0_name = TYPE_NAME (type0);
+ const char *type1_name = TYPE_NAME (type1);
if (type0_name != NULL && strstr (type0_name, "___XR") != NULL
&& (type1_name == NULL || strstr (type1_name, "___XR") == NULL))
return 0;
}
-/* The name of TYPE, which is either its TYPE_NAME, or, if that is
- null, its TYPE_TAG_NAME. Null if TYPE is null. */
+/* The name of TYPE, which is its TYPE_NAME. Null if TYPE is
+ null. */
const char *
ada_type_name (struct type *type)
{
if (type == NULL)
return NULL;
- else if (TYPE_NAME (type) != NULL)
- return TYPE_NAME (type);
- else
- return TYPE_TAG_NAME (type);
+ return TYPE_NAME (type);
}
/* Search the list of "descriptive" types associated to TYPE for a type
static struct type *
find_parallel_type_by_descriptive_type (struct type *type, const char *name)
{
- struct type *result;
+ struct type *result, *tmp;
if (ada_ignore_descriptive_types_p)
return NULL;
/* Otherwise, look at the next item on the list, if any. */
if (HAVE_GNAT_AUX_INFO (result))
- result = TYPE_DESCRIPTIVE_TYPE (result);
+ tmp = TYPE_DESCRIPTIVE_TYPE (result);
+ else
+ tmp = NULL;
+
+ /* If not found either, try after having resolved the typedef. */
+ if (tmp != NULL)
+ result = tmp;
else
- result = NULL;
+ {
+ result = check_typedef (result);
+ if (HAVE_GNAT_AUX_INFO (result))
+ result = TYPE_DESCRIPTIVE_TYPE (result);
+ else
+ result = NULL;
+ }
}
/* If we didn't find a match, see whether this is a packed array. With
ada_find_parallel_type (struct type *type, const char *suffix)
{
char *name;
- const char *typename = ada_type_name (type);
+ const char *type_name = ada_type_name (type);
int len;
- if (typename == NULL)
+ if (type_name == NULL)
return NULL;
- len = strlen (typename);
+ len = strlen (type_name);
name = (char *) alloca (len + strlen (suffix) + 1);
- strcpy (name, typename);
+ strcpy (name, type_name);
strcpy (name + len, suffix);
return ada_find_parallel_type_with_name (type, name);
/* A record type with no fields. */
static struct type *
-empty_record (struct type *template)
+empty_record (struct type *templ)
{
- struct type *type = alloc_type_copy (template);
+ struct type *type = alloc_type_copy (templ);
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_TAG_NAME (type) = NULL;
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));
memset (TYPE_FIELDS (rtype), 0, sizeof (struct field) * nfields);
TYPE_NAME (rtype) = ada_type_name (type);
- TYPE_TAG_NAME (rtype) = NULL;
TYPE_FIXED_INSTANCE (rtype) = 1;
off = 0;
initialized, the type size may be completely bogus and
GDB may fail to allocate a value for it. So check the
size first before creating the value. */
- check_size (rtype);
- dval = value_from_contents_and_address (rtype, valaddr, address);
+ ada_ensure_varsize_limit (rtype);
+ /* Using plain value_from_contents_and_address here
+ causes problems because we will end up trying to
+ resolve a type that is currently being
+ constructed. */
+ dval = value_from_contents_and_address_unresolved (rtype,
+ valaddr,
+ address);
+ rtype = value_type (dval);
}
else
dval = dval0;
large (due to an uninitialized variable in the inferior)
that it would cause an overflow when adding it to the
record size. */
- check_size (field_type);
+ ada_ensure_varsize_limit (field_type);
TYPE_FIELD_TYPE (rtype, f) = field_type;
TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f);
off = TYPE_FIELD_BITPOS (rtype, variant_field);
if (dval0 == NULL)
- dval = value_from_contents_and_address (rtype, valaddr, address);
+ {
+ /* Using plain value_from_contents_and_address here causes
+ problems because we will end up trying to resolve a type
+ that is currently being constructed. */
+ dval = value_from_contents_and_address_unresolved (rtype, valaddr,
+ address);
+ rtype = value_type (dval);
+ }
else
dval = dval0;
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
{
int nfields;
int f;
+ /* No need no do anything if the input type is already fixed. */
+ if (TYPE_FIXED_INSTANCE (type0))
+ return type0;
+
+ /* Likewise if we already have computed the static approximation. */
if (TYPE_TARGET_TYPE (type0) != NULL)
return TYPE_TARGET_TYPE (type0);
- nfields = TYPE_NFIELDS (type0);
+ /* Don't clone TYPE0 until we are sure we are going to need a copy. */
type = type0;
+ nfields = TYPE_NFIELDS (type0);
+
+ /* Whether or not we cloned TYPE0, cache the result so that we don't do
+ recompute all over next time. */
+ TYPE_TARGET_TYPE (type0) = type;
for (f = 0; f < nfields; f += 1)
{
- struct type *field_type = ada_check_typedef (TYPE_FIELD_TYPE (type0, f));
+ struct type *field_type = TYPE_FIELD_TYPE (type0, f);
struct type *new_type;
if (is_dynamic_field (type0, f))
- new_type = to_static_fixed_type (TYPE_TARGET_TYPE (field_type));
+ {
+ field_type = ada_check_typedef (field_type);
+ new_type = to_static_fixed_type (TYPE_TARGET_TYPE (field_type));
+ }
else
new_type = static_unwrap_type (field_type);
- if (type == type0 && new_type != field_type)
- {
- TYPE_TARGET_TYPE (type0) = type = alloc_type_copy (type0);
- TYPE_CODE (type) = TYPE_CODE (type0);
- INIT_CPLUS_SPECIFIC (type);
- TYPE_NFIELDS (type) = nfields;
- TYPE_FIELDS (type) = (struct field *)
- TYPE_ALLOC (type, nfields * sizeof (struct field));
- memcpy (TYPE_FIELDS (type), TYPE_FIELDS (type0),
- sizeof (struct field) * nfields);
- TYPE_NAME (type) = ada_type_name (type0);
- TYPE_TAG_NAME (type) = NULL;
- TYPE_FIXED_INSTANCE (type) = 1;
- TYPE_LENGTH (type) = 0;
- }
- TYPE_FIELD_TYPE (type, f) = new_type;
- TYPE_FIELD_NAME (type, f) = TYPE_FIELD_NAME (type0, f);
+
+ if (new_type != field_type)
+ {
+ /* Clone TYPE0 only the first time we get a new field type. */
+ if (type == type0)
+ {
+ TYPE_TARGET_TYPE (type0) = type = alloc_type_copy (type0);
+ TYPE_CODE (type) = TYPE_CODE (type0);
+ INIT_NONE_SPECIFIC (type);
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, nfields * sizeof (struct field));
+ memcpy (TYPE_FIELDS (type), TYPE_FIELDS (type0),
+ sizeof (struct field) * nfields);
+ TYPE_NAME (type) = ada_type_name (type0);
+ TYPE_FIXED_INSTANCE (type) = 1;
+ TYPE_LENGTH (type) = 0;
+ }
+ TYPE_FIELD_TYPE (type, f) = new_type;
+ TYPE_FIELD_NAME (type, f) = TYPE_FIELD_NAME (type0, f);
+ }
}
+
return type;
}
return type;
if (dval0 == NULL)
- dval = value_from_contents_and_address (type, valaddr, address);
+ {
+ dval = value_from_contents_and_address (type, valaddr, address);
+ type = value_type (dval);
+ }
else
dval = dval0;
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));
memcpy (TYPE_FIELDS (rtype), TYPE_FIELDS (type),
sizeof (struct field) * nfields);
TYPE_NAME (rtype) = ada_type_name (type);
- TYPE_TAG_NAME (rtype) = NULL;
TYPE_FIXED_INSTANCE (rtype) = 1;
TYPE_LENGTH (rtype) = TYPE_LENGTH (type);
return TYPE_FIELD_TYPE (var_type, which);
}
+/* Assuming RANGE_TYPE is a TYPE_CODE_RANGE, return nonzero if
+ ENCODING_TYPE, a type following the GNAT conventions for discrete
+ type encodings, only carries redundant information. */
+
+static int
+ada_is_redundant_range_encoding (struct type *range_type,
+ struct type *encoding_type)
+{
+ const char *bounds_str;
+ int n;
+ LONGEST lo, hi;
+
+ gdb_assert (TYPE_CODE (range_type) == TYPE_CODE_RANGE);
+
+ if (TYPE_CODE (get_base_type (range_type))
+ != TYPE_CODE (get_base_type (encoding_type)))
+ {
+ /* The compiler probably used a simple base type to describe
+ the range type instead of the range's actual base type,
+ expecting us to get the real base type from the encoding
+ anyway. In this situation, the encoding cannot be ignored
+ as redundant. */
+ return 0;
+ }
+
+ if (is_dynamic_type (range_type))
+ return 0;
+
+ if (TYPE_NAME (encoding_type) == NULL)
+ return 0;
+
+ bounds_str = strstr (TYPE_NAME (encoding_type), "___XDLU_");
+ if (bounds_str == NULL)
+ return 0;
+
+ n = 8; /* Skip "___XDLU_". */
+ if (!ada_scan_number (bounds_str, n, &lo, &n))
+ return 0;
+ if (TYPE_LOW_BOUND (range_type) != lo)
+ return 0;
+
+ n += 2; /* Skip the "__" separator between the two bounds. */
+ if (!ada_scan_number (bounds_str, n, &hi, &n))
+ return 0;
+ if (TYPE_HIGH_BOUND (range_type) != hi)
+ return 0;
+
+ return 1;
+}
+
+/* Given the array type ARRAY_TYPE, return nonzero if DESC_TYPE,
+ a type following the GNAT encoding for describing array type
+ indices, only carries redundant information. */
+
+static int
+ada_is_redundant_index_type_desc (struct type *array_type,
+ struct type *desc_type)
+{
+ struct type *this_layer = check_typedef (array_type);
+ int i;
+
+ for (i = 0; i < TYPE_NFIELDS (desc_type); i++)
+ {
+ if (!ada_is_redundant_range_encoding (TYPE_INDEX_TYPE (this_layer),
+ TYPE_FIELD_TYPE (desc_type, i)))
+ return 0;
+ this_layer = check_typedef (TYPE_TARGET_TYPE (this_layer));
+ }
+
+ return 1;
+}
+
/* Assuming that TYPE0 is an array type describing the type of a value
at ADDR, and that DVAL describes a record containing any
discriminants used in TYPE0, returns a type for the value that
struct type *index_type_desc;
struct type *result;
int constrained_packed_array_p;
+ static const char *xa_suffix = "___XA";
type0 = ada_check_typedef (type0);
if (TYPE_FIXED_INSTANCE (type0))
if (constrained_packed_array_p)
type0 = decode_constrained_packed_array_type (type0);
- index_type_desc = ada_find_parallel_type (type0, "___XA");
+ index_type_desc = ada_find_parallel_type (type0, xa_suffix);
+
+ /* As mentioned in exp_dbug.ads, for non bit-packed arrays an
+ encoding suffixed with 'P' may still be generated. If so,
+ it should be used to find the XA type. */
+
+ if (index_type_desc == NULL)
+ {
+ const char *type_name = ada_type_name (type0);
+
+ if (type_name != NULL)
+ {
+ const int len = strlen (type_name);
+ char *name = (char *) alloca (len + strlen (xa_suffix));
+
+ if (type_name[len - 1] == 'P')
+ {
+ strcpy (name, type_name);
+ strcpy (name + len - 1, xa_suffix);
+ index_type_desc = ada_find_parallel_type_with_name (type0, name);
+ }
+ }
+ }
+
ada_fixup_array_indexes_type (index_type_desc);
+ if (index_type_desc != NULL
+ && ada_is_redundant_index_type_desc (type0, index_type_desc))
+ {
+ /* Ignore this ___XA parallel type, as it does not bring any
+ useful information. This allows us to avoid creating fixed
+ versions of the array's index types, which would be identical
+ to the original ones. This, in turn, can also help avoid
+ the creation of fixed versions of the array itself. */
+ index_type_desc = NULL;
+ }
+
if (index_type_desc == NULL)
{
struct type *elt_type0 = ada_check_typedef (TYPE_TARGET_TYPE (type0));
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:
value_from_contents_and_address (fixed_record_type,
valaddr,
address);
+ fixed_record_type = value_type (obj);
if (real_type != NULL)
return to_fixed_record_type
(real_type, NULL,
else if (ada_type_name (fixed_record_type) != NULL)
{
const char *name = ada_type_name (fixed_record_type);
- char *xvz_name = alloca (strlen (name) + 7 /* "___XVZ\0" */);
- int xvz_found = 0;
+ char *xvz_name
+ = (char *) alloca (strlen (name) + 7 /* "___XVZ\0" */);
+ bool xvz_found = false;
LONGEST size;
xsnprintf (xvz_name, strlen (name) + 7, "%s___XVZ", name);
- size = get_int_var_value (xvz_name, &xvz_found);
+ try
+ {
+ xvz_found = get_int_var_value (xvz_name, size);
+ }
+ 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
+ bit more information, to help the user understand
+ what went wrong (Eg: the variable might have been
+ optimized out). */
+ throw_error (except.error,
+ _("unable to read value of %s (%s)"),
+ xvz_name, except.what ());
+ }
+
if (xvz_found && TYPE_LENGTH (fixed_record_type) != size)
{
fixed_record_type = copy_type (fixed_record_type);
brobecker/2010-11-19: It seems to me that the only case where it is
useful to preserve the typedef layer is when dealing with fat pointers.
Perhaps, we could add a check for that and preserve the typedef layer
- only in that situation. But this seems unecessary so far, probably
+ only in that situation. But this seems unnecessary so far, probably
because we call check_typedef/ada_check_typedef pretty much everywhere.
*/
if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
if (type == NULL)
return NULL;
- /* If our type is a typedef type of a fat pointer, then we're done.
+ /* If our type is an access to an unconstrained array, which is encoded
+ as a TYPE_CODE_TYPEDEF of a fat pointer, then we're done.
We don't want to strip the TYPE_CODE_TYPDEF layer, because this is
what allows us to distinguish between fat pointers that represent
array types, and fat pointers that represent array access types
(in both cases, the compiler implements them as fat pointers). */
- if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
- && is_thick_pntr (ada_typedef_target_type (type)))
+ if (ada_is_access_to_unconstrained_array (type))
return type;
- CHECK_TYPEDEF (type);
+ type = check_typedef (type);
if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM
|| !TYPE_STUB (type)
- || TYPE_TAG_NAME (type) == NULL)
+ || TYPE_NAME (type) == NULL)
return type;
else
{
- const char *name = TYPE_TAG_NAME (type);
+ const char *name = TYPE_NAME (type);
struct type *type1 = ada_find_any_type (name);
if (type1 == NULL)
if (type == type0 && val0 != NULL)
return val0;
- else
- return value_from_contents_and_address (type, 0, address);
+
+ if (VALUE_LVAL (val0) != lval_memory)
+ {
+ /* Our value does not live in memory; it could be a convenience
+ variable, for instance. Create a not_lval value using val0's
+ contents. */
+ return value_from_contents (type, value_contents (val0));
+ }
+
+ return value_from_contents_and_address (type, 0, address);
}
/* A value representing VAL, but with a standard (static-sized) type
ada_to_fixed_value (struct value *val)
{
val = unwrap_value (val);
- val = ada_to_fixed_value_create (value_type (val),
- value_address (val),
- val);
+ val = ada_to_fixed_value_create (value_type (val), value_address (val), val);
return val;
}
\f
0
};
-const char *
+static const char *
ada_attribute_name (enum exp_opcode n)
{
if (n >= OP_ATR_FIRST && n <= (int) OP_ATR_VAL)
{
struct value *val = coerce_ref (arg);
struct type *type = value_type (val);
+ LONGEST result;
if (!discrete_type_p (type))
error (_("'POS only defined on discrete types"));
- if (TYPE_CODE (type) == TYPE_CODE_ENUM)
- {
- int i;
- LONGEST v = value_as_long (val);
+ if (!discrete_position (type, value_as_long (val), &result))
+ error (_("enumeration value is invalid: can't find 'POS"));
- for (i = 0; i < TYPE_NFIELDS (type); i += 1)
- {
- if (v == TYPE_FIELD_ENUMVAL (type, i))
- return i;
- }
- error (_("enumeration value is invalid: can't find 'POS"));
- }
- else
- return value_as_long (val);
+ return result;
}
static struct value *
[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
Set to True if the debugger should trust the contents of PAD types.
Otherwise, ignore the PAD type if there is a parallel XVS type. */
-static int trust_pad_over_xvs = 1;
+static bool trust_pad_over_xvs = true;
/* True if TYPE is a struct type introduced by the compiler to force the
alignment of a value. Such types have a single field with a
if (TYPE_CODE (TYPE_FIELD_TYPE (real_type_namer, 0)) != TYPE_CODE_REF)
{
/* This is an older encoding form where the base type needs to be
- looked up by name. We prefer the newer enconding because it is
+ looked up by name. We prefer the newer encoding because it is
more efficient. */
raw_real_type = ada_find_any_type (TYPE_FIELD_NAME (real_type_namer, 0));
if (raw_real_type == NULL)
{
static char *result;
static size_t result_len = 0;
- char *tmp;
+ const char *tmp;
/* First, unqualify the enumeration name:
1. Search for the last '.' character. If we find one, then skip
if (sscanf (name + 2, "%x", &v) != 1)
return name;
}
+ else if (((name[1] >= '0' && name[1] <= '9')
+ || (name[1] >= 'a' && name[1] <= 'z'))
+ && name[2] == '\0')
+ {
+ GROW_VECT (result, result_len, 4);
+ xsnprintf (result, result_len, "'%c'", name[1]);
+ return result;
+ }
else
return name;
}
static struct value *
-cast_to_fixed (struct type *type, struct value *arg)
+cast_from_fixed (struct type *type, struct value *arg)
{
- LONGEST val;
-
- if (type == value_type (arg))
- return arg;
- else if (ada_is_fixed_point_type (value_type (arg)))
- val = ada_float_to_fixed (type,
- ada_fixed_to_float (value_type (arg),
- value_as_long (arg)));
- else
- {
- DOUBLEST argd = value_as_double (arg);
-
- val = ada_float_to_fixed (type, argd);
- }
+ struct value *scale = ada_scaling_factor (value_type (arg));
+ arg = value_cast (value_type (scale), arg);
- return value_from_longest (type, val);
+ arg = value_binop (arg, scale, BINOP_MUL);
+ return value_cast (type, arg);
}
static struct value *
-cast_from_fixed (struct type *type, struct value *arg)
+cast_to_fixed (struct type *type, struct value *arg)
{
- DOUBLEST val = ada_fixed_to_float (value_type (arg),
- value_as_long (arg));
+ if (type == value_type (arg))
+ return arg;
- return value_from_double (type, val);
+ struct value *scale = ada_scaling_factor (type);
+ if (ada_is_fixed_point_type (value_type (arg)))
+ arg = cast_from_fixed (value_type (scale), arg);
+ else
+ arg = value_cast (value_type (scale), arg);
+
+ arg = value_binop (arg, scale, BINOP_DIV);
+ return value_cast (type, arg);
}
/* Given two array types T1 and T2, return nonzero iff both arrays
val = allocate_value (type1);
store_unsigned_integer (value_contents_raw (val),
TYPE_LENGTH (value_type (val)),
- gdbarch_byte_order (get_type_arch (type1)), v);
+ type_byte_order (type1), v);
return val;
}
if (ada_is_direct_array_type (value_type (arg1))
|| ada_is_direct_array_type (value_type (arg2)))
{
+ struct type *arg1_type, *arg2_type;
+
/* Automatically dereference any array reference before
we attempt to perform the comparison. */
arg1 = ada_coerce_ref (arg1);
arg2 = ada_coerce_ref (arg2);
-
+
arg1 = ada_coerce_to_simple_array (arg1);
arg2 = ada_coerce_to_simple_array (arg2);
- if (TYPE_CODE (value_type (arg1)) != TYPE_CODE_ARRAY
- || TYPE_CODE (value_type (arg2)) != TYPE_CODE_ARRAY)
+
+ arg1_type = ada_check_typedef (value_type (arg1));
+ arg2_type = ada_check_typedef (value_type (arg2));
+
+ if (TYPE_CODE (arg1_type) != TYPE_CODE_ARRAY
+ || TYPE_CODE (arg2_type) != TYPE_CODE_ARRAY)
error (_("Attempt to compare array with non-array"));
/* FIXME: The following works only for types whose
representations use all bits (no padding or undefined bits)
and do not have user-defined equality. */
- return
- TYPE_LENGTH (value_type (arg1)) == TYPE_LENGTH (value_type (arg2))
- && memcmp (value_contents (arg1), value_contents (arg2),
- TYPE_LENGTH (value_type (arg1))) == 0;
+ return (TYPE_LENGTH (arg1_type) == TYPE_LENGTH (arg2_type)
+ && memcmp (value_contents (arg1), value_contents (arg2),
+ TYPE_LENGTH (arg1_type)) == 0);
}
return value_equal (arg1, arg2);
}
{
struct value *mark = value_mark ();
struct value *elt;
+ struct type *lhs_type = check_typedef (value_type (lhs));
- if (TYPE_CODE (value_type (lhs)) == TYPE_CODE_ARRAY)
+ if (TYPE_CODE (lhs_type) == TYPE_CODE_ARRAY)
{
struct type *index_type = builtin_type (exp->gdbarch)->builtin_int;
struct value *index_val = value_from_longest (index_type, index);
if (!deprecated_value_modifiable (lhs))
error (_("Left operand of assignment is not a modifiable lvalue."));
- lhs_type = value_type (lhs);
+ lhs_type = check_typedef (value_type (lhs));
if (ada_is_direct_array_type (lhs_type))
{
lhs = ada_coerce_to_simple_array (lhs);
- lhs_type = value_type (lhs);
+ lhs_type = check_typedef (value_type (lhs));
low_index = TYPE_ARRAY_LOWER_BOUND_VALUE (lhs_type);
high_index = TYPE_ARRAY_UPPER_BOUND_VALUE (lhs_type);
}
num_specs = num_component_specs (exp, *pos - 3);
max_indices = 4 * num_specs + 4;
- indices = alloca (max_indices * sizeof (indices[0]));
+ indices = XALLOCAVEC (LONGEST, max_indices);
indices[0] = indices[1] = low_index - 1;
indices[2] = indices[3] = high_index + 1;
num_indices = 4;
name = &exp->elts[choice_pos + 2].string;
break;
case OP_VAR_VALUE:
- name = SYMBOL_NATURAL_NAME (exp->elts[choice_pos + 2].symbol);
+ name = exp->elts[choice_pos + 2].symbol->natural_name ();
break;
default:
error (_("Invalid record component association."));
is different. */
static struct value *
-ada_value_cast (struct type *type, struct value *arg2, enum noside noside)
+ada_value_cast (struct type *type, struct value *arg2)
{
if (type == ada_check_typedef (value_type (arg2)))
return arg2;
if (ada_is_fixed_point_type (type))
- return (cast_to_fixed (type, arg2));
+ return cast_to_fixed (type, arg2);
if (ada_is_fixed_point_type (value_type (arg2)))
return cast_from_fixed (type, arg2);
information nor the associated type structure in GDB are able to
express such dynamic types. So what the debugger does is to create
"fixed" versions of the type that applies to the specific object.
- We also informally refer to this opperation as "fixing" an object,
+ We also informally refer to this operation as "fixing" an object,
which means creating its associated fixed type.
Example: when printing the value of variable "Yes" above, its fixed
one element out of that array. On the other hand, fixing should
not be performed on the elements when taking a slice of an array!
- Note that one of the side-effects of miscomputing the offset and
+ Note that one of the side effects of miscomputing the offset and
size of each field is that we end up also miscomputing the size
of the containing type. This can have adverse results when computing
the value of an entity. GDB fetches the value of an entity based
on the size of its type, and thus a wrong size causes GDB to fetch
the wrong amount of memory. In the case where the computed size is
too small, GDB fetches too little data to print the value of our
- entiry. Results in this case as unpredicatble, as we usually read
+ entity. Results in this case are unpredictable, as we usually read
past the buffer containing the data =:-o. */
+/* Evaluate a subexpression of EXP, at index *POS, and return a value
+ for that subexpression cast to TO_TYPE. Advance *POS over the
+ subexpression. */
+
+static value *
+ada_evaluate_subexp_for_cast (expression *exp, int *pos,
+ enum noside noside, struct type *to_type)
+{
+ int pc = *pos;
+
+ if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE
+ || exp->elts[pc].opcode == OP_VAR_VALUE)
+ {
+ (*pos) += 4;
+
+ value *val;
+ if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE)
+ {
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (to_type, not_lval);
+
+ val = evaluate_var_msym_value (noside,
+ exp->elts[pc + 1].objfile,
+ exp->elts[pc + 2].msymbol);
+ }
+ else
+ val = evaluate_var_value (noside,
+ exp->elts[pc + 1].block,
+ exp->elts[pc + 2].symbol);
+
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+
+ val = ada_value_cast (to_type, val);
+
+ /* Follow the Ada language semantics that do not allow taking
+ an address of the result of a cast (view conversion in Ada). */
+ if (VALUE_LVAL (val) == lval_memory)
+ {
+ if (value_lazy (val))
+ value_fetch_lazy (val);
+ VALUE_LVAL (val) = not_lval;
+ }
+ return val;
+ }
+
+ value *val = evaluate_subexp (to_type, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+ return ada_value_cast (to_type, val);
+}
+
/* Implement the evaluate_exp routine in the exp_descriptor structure
for the Ada language. */
if (noside == EVAL_NORMAL)
arg1 = unwrap_value (arg1);
- /* If evaluating an OP_DOUBLE and an EXPECT_TYPE was provided,
+ /* If evaluating an OP_FLOAT and an EXPECT_TYPE was provided,
then we need to perform the conversion manually, because
evaluate_subexp_standard doesn't do it. This conversion is
necessary in Ada because the different kinds of float/fixed
Similarly, we need to perform the conversion from OP_LONG
ourselves. */
- if ((op == OP_DOUBLE || op == OP_LONG) && expect_type != NULL)
- arg1 = ada_value_cast (expect_type, arg1, noside);
+ if ((op == OP_FLOAT || op == OP_LONG) && expect_type != NULL)
+ arg1 = ada_value_cast (expect_type, arg1);
return arg1;
case UNOP_CAST:
(*pos) += 2;
type = exp->elts[pc + 1].type;
- arg1 = evaluate_subexp (type, exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- arg1 = ada_value_cast (type, arg1, noside);
- return arg1;
+ return ada_evaluate_subexp_for_cast (exp, pos, noside, type);
case UNOP_QUAL:
(*pos) += 2;
arg2 = evaluate_subexp (type, exp, pos, noside);
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
return arg1;
- if (ada_is_fixed_point_type (value_type (arg1)))
+ if (VALUE_LVAL (arg1) == lval_internalvar)
+ {
+ /* Nothing. */
+ }
+ else if (ada_is_fixed_point_type (value_type (arg1)))
arg2 = cast_to_fixed (value_type (arg1), arg2);
else if (ada_is_fixed_point_type (value_type (arg2)))
error
return (value_from_longest
(value_type (arg1),
value_as_long (arg1) + value_as_long (arg2)));
+ if (TYPE_CODE (value_type (arg2)) == TYPE_CODE_PTR)
+ return (value_from_longest
+ (value_type (arg2),
+ value_as_long (arg1) + value_as_long (arg2)));
if ((ada_is_fixed_point_type (value_type (arg1))
|| ada_is_fixed_point_type (value_type (arg2)))
&& value_type (arg1) != value_type (arg2))
return (value_from_longest
(value_type (arg1),
value_as_long (arg1) - value_as_long (arg2)));
+ if (TYPE_CODE (value_type (arg2)) == TYPE_CODE_PTR)
+ return (value_from_longest
+ (value_type (arg2),
+ value_as_long (arg1) - value_as_long (arg2)));
if ((ada_is_fixed_point_type (value_type (arg1))
|| ada_is_fixed_point_type (value_type (arg2)))
&& value_type (arg1) != value_type (arg2))
*pos += 4;
goto nosideret;
}
- else if (SYMBOL_DOMAIN (exp->elts[pc + 2].symbol) == UNDEF_DOMAIN)
+
+ if (SYMBOL_DOMAIN (exp->elts[pc + 2].symbol) == UNDEF_DOMAIN)
/* Only encountered when an unresolved symbol occurs in a
context other than a function call, in which case, it is
invalid. */
error (_("Unexpected unresolved symbol, %s, during evaluation"),
- SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol));
- else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ exp->elts[pc + 2].symbol->print_name ());
+
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
type = static_unwrap_type (SYMBOL_TYPE (exp->elts[pc + 2].symbol));
/* Check to see if this is a tagged type. We also need to handle
The latter should be shown as usual (as a pointer), whereas
a reference should mostly be transparent to the user. */
if (ada_is_tagged_type (type, 0)
- || (TYPE_CODE(type) == TYPE_CODE_REF
+ || (TYPE_CODE (type) == TYPE_CODE_REF
&& ada_is_tagged_type (TYPE_TARGET_TYPE (type), 0)))
- {
- /* Tagged types are a little special in the fact that the real
- type is dynamic and can only be determined by inspecting the
- object's tag. This means that we need to get the object's
- value first (EVAL_NORMAL) and then extract the actual object
- type from its tag.
-
- Note that we cannot skip the final step where we extract
- the object type from its tag, because the EVAL_NORMAL phase
- results in dynamic components being resolved into fixed ones.
- This can cause problems when trying to print the type
- description of tagged types whose parent has a dynamic size:
- We use the type name of the "_parent" component in order
- to print the name of the ancestor type in the type description.
- If that component had a dynamic size, the resolution into
- 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. */
- arg1 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
-
- 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);
- }
- }
+ {
+ /* Tagged types are a little special in the fact that the real
+ type is dynamic and can only be determined by inspecting the
+ object's tag. This means that we need to get the object's
+ value first (EVAL_NORMAL) and then extract the actual object
+ type from its tag.
+
+ Note that we cannot skip the final step where we extract
+ the object type from its tag, because the EVAL_NORMAL phase
+ results in dynamic components being resolved into fixed ones.
+ This can cause problems when trying to print the type
+ description of tagged types whose parent has a dynamic size:
+ We use the type name of the "_parent" component in order
+ to print the name of the ancestor type in the type description.
+ If that component had a dynamic size, the resolution into
+ 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. */
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
+
+ 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, TYPE_CODE_REF);
+ }
+ }
- *pos += 4;
- return value_zero
- (to_static_fixed_type
- (static_unwrap_type (SYMBOL_TYPE (exp->elts[pc + 2].symbol))),
- not_lval);
- }
- else
- {
- arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
- return ada_to_fixed_value (arg1);
+ /* Records and unions for which GNAT encodings have been
+ generated need to be statically fixed as well.
+ Otherwise, non-static fixing produces a type where
+ all dynamic properties are removed, which prevents "ptype"
+ from being able to completely describe the type.
+ For instance, a case statement in a variant record would be
+ replaced by the relevant components based on the actual
+ value of the discriminants. */
+ if ((TYPE_CODE (type) == TYPE_CODE_STRUCT
+ && dynamic_template_type (type) != NULL)
+ || (TYPE_CODE (type) == TYPE_CODE_UNION
+ && ada_find_parallel_type (type, "___XVU") != NULL))
+ {
+ *pos += 4;
+ return value_zero (to_static_fixed_type (type), not_lval);
+ }
}
+ arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
+ return ada_to_fixed_value (arg1);
+
case OP_FUNCALL:
(*pos) += 2;
/* Allocate arg vector, including space for the function to be
called in argvec[0] and a terminating NULL. */
nargs = longest_to_int (exp->elts[pc + 1].longconst);
- argvec =
- (struct value **) alloca (sizeof (struct value *) * (nargs + 2));
+ argvec = XALLOCAVEC (struct value *, nargs + 2);
if (exp->elts[*pos].opcode == OP_VAR_VALUE
&& SYMBOL_DOMAIN (exp->elts[pc + 5].symbol) == UNDEF_DOMAIN)
error (_("Unexpected unresolved symbol, %s, during evaluation"),
- SYMBOL_PRINT_NAME (exp->elts[pc + 5].symbol));
+ exp->elts[pc + 5].symbol->print_name ());
else
{
for (tem = 0; tem <= nargs; tem += 1)
therefore already coerced to a simple array. Nothing further
to do. */
;
- else if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_REF
- || (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_ARRAY
- && VALUE_LVAL (argvec[0]) == lval_memory))
- argvec[0] = value_addr (argvec[0]);
+ else if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_REF)
+ {
+ /* Make sure we dereference references so that all the code below
+ feels like it's really handling the referenced value. Wrapping
+ types (for alignment) may be there, so make sure we strip them as
+ well. */
+ argvec[0] = ada_to_fixed_value (coerce_ref (argvec[0]));
+ }
+ else if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_ARRAY
+ && VALUE_LVAL (argvec[0]) == lval_memory)
+ argvec[0] = value_addr (argvec[0]);
type = ada_check_typedef (value_type (argvec[0]));
case TYPE_CODE_FUNC:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
- struct type *rtype = TYPE_TARGET_TYPE (type);
-
- if (TYPE_GNU_IFUNC (type))
- return allocate_value (TYPE_TARGET_TYPE (rtype));
- return allocate_value (rtype);
+ if (TYPE_TARGET_TYPE (type) == NULL)
+ error_call_unknown_return_type (NULL);
+ return allocate_value (TYPE_TARGET_TYPE (type));
}
- return call_function_by_hand (argvec[0], 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
(ada_coerce_to_simple_array (argvec[0]),
nargs, argvec + 1));
case TYPE_CODE_PTR: /* Pointer to array */
- type = to_fixed_array_type (TYPE_TARGET_TYPE (type), NULL, 1);
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
+ type = to_fixed_array_type (TYPE_TARGET_TYPE (type), NULL, 1);
type = ada_array_element_type (type, nargs);
if (type == NULL)
error (_("element type of array unknown"));
return value_zero (ada_aligned_type (type), lval_memory);
}
return
- unwrap_value (ada_value_ptr_subscript (argvec[0], type,
- nargs, argvec + 1));
+ unwrap_value (ada_value_ptr_subscript (argvec[0],
+ nargs, argvec + 1));
default:
error (_("Attempt to index or call something other than an "
low_bound_val = coerce_ref (low_bound_val);
high_bound_val = coerce_ref (high_bound_val);
- low_bound = pos_atr (low_bound_val);
- high_bound = pos_atr (high_bound_val);
+ low_bound = value_as_long (low_bound_val);
+ high_bound = value_as_long (high_bound_val);
if (noside == EVAL_SKIP)
goto nosideret;
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));
if (noside == EVAL_SKIP)
goto nosideret;
+ else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ if (type_arg == NULL)
+ type_arg = value_type (arg1);
+
+ if (ada_is_constrained_packed_array_type (type_arg))
+ type_arg = decode_constrained_packed_array_type (type_arg);
+
+ if (!discrete_type_p (type_arg))
+ {
+ switch (op)
+ {
+ default: /* Should never happen. */
+ error (_("unexpected attribute encountered"));
+ case OP_ATR_FIRST:
+ case OP_ATR_LAST:
+ type_arg = ada_index_type (type_arg, tem,
+ ada_attribute_name (op));
+ break;
+ case OP_ATR_LENGTH:
+ type_arg = builtin_type (exp->gdbarch)->builtin_int;
+ break;
+ }
+ }
- if (type_arg == NULL)
+ return value_zero (type_arg, not_lval);
+ }
+ else if (type_arg == NULL)
{
arg1 = ada_coerce_ref (arg1);
type = builtin_type (exp->gdbarch)->builtin_int;
}
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return allocate_value (type);
-
switch (op)
{
default: /* Should never happen. */
type = builtin_type (exp->gdbarch)->builtin_int;
}
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return allocate_value (type);
-
switch (op)
{
default:
This means that we need to evaluate completely the
expression in order to get its type. */
- if ((TYPE_CODE(type) == TYPE_CODE_REF
- || TYPE_CODE(type) == TYPE_CODE_PTR)
+ if ((TYPE_CODE (type) == TYPE_CODE_REF
+ || TYPE_CODE (type) == TYPE_CODE_PTR)
&& ada_is_tagged_type (TYPE_TARGET_TYPE (type), 0))
{
arg1 = evaluate_subexp (NULL_TYPE, exp, &preeval_pos,
(ada_aligned_type
(ada_check_typedef (TYPE_TARGET_TYPE (type))));
}
- check_size (type);
+ ada_ensure_varsize_limit (type);
return value_zero (type, lval_memory);
}
else if (TYPE_CODE (type) == TYPE_CODE_INT)
{
type = ada_lookup_struct_elt_type (type1,
&exp->elts[pc + 2].string,
- 1, 1, NULL);
+ 1, 1);
/* If the field is not found, check if it exists in the
extension of this object's type. This means that we
else
type =
ada_lookup_struct_elt_type (type1, &exp->elts[pc + 2].string, 1,
- 0, NULL);
+ 0);
return value_zero (ada_aligned_type (type), lval_memory);
}
else
- arg1 = ada_value_struct_elt (arg1, &exp->elts[pc + 2].string, 0);
- arg1 = unwrap_value (arg1);
- return ada_to_fixed_value (arg1);
+ {
+ arg1 = ada_value_struct_elt (arg1, &exp->elts[pc + 2].string, 0);
+ arg1 = unwrap_value (arg1);
+ return ada_to_fixed_value (arg1);
+ }
case OP_TYPE:
/* The value is not supposed to be used. This is here to make it
}
nosideret:
- return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1);
+ return eval_skip_value (exp);
}
\f
}
/* Assuming that TYPE is the representation of an Ada fixed-point
- type, return its delta, or -1 if the type is malformed and the
- delta cannot be determined. */
+ type, return the target floating-point type to be used to represent
+ of this type during internal computation. */
-DOUBLEST
-ada_delta (struct type *type)
+static struct type *
+ada_scaling_type (struct type *type)
{
- const char *encoding = fixed_type_info (type);
- DOUBLEST num, den;
-
- /* Strictly speaking, num and den are encoded as integer. However,
- they may not fit into a long, and they will have to be converted
- to DOUBLEST anyway. So scan them as DOUBLEST. */
- if (sscanf (encoding, "_%" DOUBLEST_SCAN_FORMAT "_%" DOUBLEST_SCAN_FORMAT,
- &num, &den) < 2)
- return -1.0;
- else
- return num / den;
+ return builtin_type (get_type_arch (type))->builtin_long_double;
}
-/* Assuming that ada_is_fixed_point_type (TYPE), return the scaling
- factor ('SMALL value) associated with the type. */
+/* Assuming that TYPE is the representation of an Ada fixed-point
+ type, return its delta, or NULL if the type is malformed and the
+ delta cannot be determined. */
-static DOUBLEST
-scaling_factor (struct type *type)
+struct value *
+ada_delta (struct type *type)
{
const char *encoding = fixed_type_info (type);
- DOUBLEST num0, den0, num1, den1;
- int n;
+ struct type *scale_type = ada_scaling_type (type);
- /* Strictly speaking, num's and den's are encoded as integer. However,
- they may not fit into a long, and they will have to be converted
- to DOUBLEST anyway. So scan them as DOUBLEST. */
- n = sscanf (encoding,
- "_%" DOUBLEST_SCAN_FORMAT "_%" DOUBLEST_SCAN_FORMAT
- "_%" DOUBLEST_SCAN_FORMAT "_%" DOUBLEST_SCAN_FORMAT,
- &num0, &den0, &num1, &den1);
+ long long num, den;
- if (n < 2)
- return 1.0;
- else if (n == 4)
- return num1 / den1;
+ if (sscanf (encoding, "_%lld_%lld", &num, &den) < 2)
+ return nullptr;
else
- return num0 / den0;
+ return value_binop (value_from_longest (scale_type, num),
+ value_from_longest (scale_type, den), BINOP_DIV);
}
+/* Assuming that ada_is_fixed_point_type (TYPE), return the scaling
+ factor ('SMALL value) associated with the type. */
-/* Assuming that X is the representation of a value of fixed-point
- type TYPE, return its floating-point equivalent. */
-
-DOUBLEST
-ada_fixed_to_float (struct type *type, LONGEST x)
+struct value *
+ada_scaling_factor (struct type *type)
{
- return (DOUBLEST) x *scaling_factor (type);
-}
+ const char *encoding = fixed_type_info (type);
+ struct type *scale_type = ada_scaling_type (type);
-/* The representation of a fixed-point value of type TYPE
- corresponding to the value X. */
+ long long num0, den0, num1, den1;
+ int n;
-LONGEST
-ada_float_to_fixed (struct type *type, DOUBLEST x)
-{
- return (LONGEST) (x / scaling_factor (type) + 0.5);
+ n = sscanf (encoding, "_%lld_%lld_%lld_%lld",
+ &num0, &den0, &num1, &den1);
+
+ if (n < 2)
+ return value_from_longest (scale_type, 1);
+ else if (n == 4)
+ return value_binop (value_from_longest (scale_type, num1),
+ value_from_longest (scale_type, den1), BINOP_DIV);
+ else
+ return value_binop (value_from_longest (scale_type, num0),
+ value_from_longest (scale_type, den0), BINOP_DIV);
}
\f
not alter *PX and *PNEW_K if unsuccessful. */
static int
-scan_discrim_bound (char *str, int k, struct value *dval, LONGEST * px,
+scan_discrim_bound (const char *str, int k, struct value *dval, LONGEST * px,
int *pnew_k)
{
static char *bound_buffer = NULL;
static size_t bound_buffer_len = 0;
- char *bound;
- char *pend;
+ const char *pstart, *pend, *bound;
struct value *bound_val;
if (dval == NULL || str == NULL || str[k] == '\0')
return 0;
- pend = strstr (str + k, "__");
+ pstart = str + k;
+ pend = strstr (pstart, "__");
if (pend == NULL)
{
- bound = str + k;
+ bound = pstart;
k += strlen (bound);
}
else
{
- GROW_VECT (bound_buffer, bound_buffer_len, pend - (str + k) + 1);
+ int len = pend - pstart;
+
+ /* Strip __ and beyond. */
+ GROW_VECT (bound_buffer, bound_buffer_len, len + 1);
+ strncpy (bound_buffer, pstart, len);
+ bound_buffer[len] = '\0';
+
bound = bound_buffer;
- strncpy (bound_buffer, str + k, pend - (str + k));
- bound[pend - (str + k)] = '\0';
k = pend - str;
}
otherwise causes an error with message ERR_MSG. */
static struct value *
-get_var_value (char *name, char *err_msg)
+get_var_value (const char *name, const char *err_msg)
{
- struct ada_symbol_info *syms;
- int nsyms;
+ lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
- nsyms = ada_lookup_symbol_list (name, get_selected_block (0), VAR_DOMAIN,
- &syms);
+ std::vector<struct block_symbol> syms;
+ int nsyms = ada_lookup_symbol_list_worker (lookup_name,
+ get_selected_block (0),
+ VAR_DOMAIN, &syms, 1);
if (nsyms != 1)
{
error (("%s"), err_msg);
}
- return value_of_variable (syms[0].sym, syms[0].block);
+ return value_of_variable (syms[0].symbol, syms[0].block);
}
-/* Value of integer variable named NAME in the current environment. If
- no such variable found, returns 0, and sets *FLAG to 0. If
- successful, sets *FLAG to 1. */
+/* Value of integer variable named NAME in the current environment.
+ If no such variable is found, returns false. Otherwise, sets VALUE
+ to the variable's value and returns true. */
-LONGEST
-get_int_var_value (char *name, int *flag)
+bool
+get_int_var_value (const char *name, LONGEST &value)
{
struct value *var_val = get_var_value (name, 0);
if (var_val == 0)
- {
- if (flag != NULL)
- *flag = 0;
- return 0;
- }
- else
- {
- if (flag != NULL)
- *flag = 1;
- return value_as_long (var_val);
- }
+ return false;
+
+ value = value_as_long (var_val);
+ return true;
}
{
const char *name;
struct type *base_type;
- char *subtype_info;
+ const char *subtype_info;
gdb_assert (raw_type != NULL);
gdb_assert (TYPE_NAME (raw_type) != NULL);
if (L < INT_MIN || U > INT_MAX)
return raw_type;
else
- return create_range_type (alloc_type_copy (raw_type), raw_type,
- ada_discrete_type_low_bound (raw_type),
- ada_discrete_type_high_bound (raw_type));
+ return create_static_range_type (alloc_type_copy (raw_type), raw_type,
+ L, U);
}
else
{
int prefix_len = subtype_info - name;
LONGEST L, U;
struct type *type;
- char *bounds_str;
+ const char *bounds_str;
int n;
GROW_VECT (name_buf, name_len, prefix_len + 5);
}
else
{
- int ok;
-
strcpy (name_buf + prefix_len, "___L");
- L = get_int_var_value (name_buf, &ok);
- if (!ok)
+ if (!get_int_var_value (name_buf, L))
{
lim_warning (_("Unknown lower bound, using 1."));
L = 1;
}
else
{
- int ok;
-
strcpy (name_buf + prefix_len, "___U");
- U = get_int_var_value (name_buf, &ok);
- if (!ok)
+ if (!get_int_var_value (name_buf, U))
{
lim_warning (_("Unknown upper bound, using %ld."), (long) L);
U = L;
}
}
- type = create_range_type (alloc_type_copy (raw_type), base_type, L, U);
+ type = create_static_range_type (alloc_type_copy (raw_type),
+ base_type, L, U);
+ /* create_static_range_type alters the resulting type's length
+ to match the size of the base_type, which is not what we want.
+ Set it back to the original range type's length. */
+ TYPE_LENGTH (type) = TYPE_LENGTH (raw_type);
TYPE_NAME (type) = name;
return type;
}
variants of the runtime, we use a sniffer that will determine
the runtime variant used by the program being debugged. */
-/* Ada's standard exceptions. */
-
-static char *standard_exc[] = {
+/* Ada's standard exceptions.
+
+ The Ada 83 standard also defined Numeric_Error. But there so many
+ situations where it was unclear from the Ada 83 Reference Manual
+ (RM) whether Constraint_Error or Numeric_Error should be raised,
+ that the ARG (Ada Rapporteur Group) eventually issued a Binding
+ Interpretation saying that anytime the RM says that Numeric_Error
+ should be raised, the implementation may raise Constraint_Error.
+ Ada 95 went one step further and pretty much removed Numeric_Error
+ from the list of standard exceptions (it made it a renaming of
+ Constraint_Error, to help preserve compatibility when compiling
+ an Ada83 compiler). As such, we do not include Numeric_Error from
+ this list of standard exceptions. */
+
+static const char *standard_exc[] = {
"constraint_error",
"program_error",
"storage_error",
a catchpoint on failed assertions. */
const char *catch_assert_sym;
+ /* The name of the symbol to break on in order to insert
+ a catchpoint on exception handling. */
+ const char *catch_handlers_sym;
+
/* Assuming that the inferior just triggered an unhandled exception
catchpoint, this function is responsible for returning the address
in inferior memory where the name of that exception is stored.
/* The following exception support info structure describes how to
implement exception catchpoints with the latest version of the
- Ada runtime (as of 2007-03-06). */
+ Ada runtime (as of 2019-08-??). */
static const struct exception_support_info default_exception_support_info =
{
"__gnat_debug_raise_exception", /* catch_exception_sym */
"__gnat_unhandled_exception", /* catch_exception_unhandled_sym */
"__gnat_debug_raise_assert_failure", /* catch_assert_sym */
+ "__gnat_begin_handler_v1", /* catch_handlers_sym */
+ ada_unhandled_exception_name_addr
+};
+
+/* The following exception support info structure describes how to
+ implement exception catchpoints with an earlier version of the
+ Ada runtime (as of 2007-03-06) using v0 of the EH ABI. */
+
+static const struct exception_support_info exception_support_info_v0 =
+{
+ "__gnat_debug_raise_exception", /* catch_exception_sym */
+ "__gnat_unhandled_exception", /* catch_exception_unhandled_sym */
+ "__gnat_debug_raise_assert_failure", /* catch_assert_sym */
+ "__gnat_begin_handler", /* catch_handlers_sym */
ada_unhandled_exception_name_addr
};
"__gnat_raise_nodefer_with_msg", /* catch_exception_sym */
"__gnat_unhandled_exception", /* catch_exception_unhandled_sym */
"system__assertions__raise_assert_failure", /* catch_assert_sym */
+ "__gnat_begin_handler", /* catch_handlers_sym */
ada_unhandled_exception_name_addr_from_raise
};
/* Make sure that the symbol we found corresponds to a function. */
if (SYMBOL_CLASS (sym) != LOC_BLOCK)
- error (_("Symbol \"%s\" is not a function (class = %d)"),
- SYMBOL_LINKAGE_NAME (sym), SYMBOL_CLASS (sym));
+ {
+ error (_("Symbol \"%s\" is not a function (class = %d)"),
+ sym->linkage_name (), SYMBOL_CLASS (sym));
+ return 0;
+ }
+
+ sym = standard_lookup (einfo->catch_handlers_sym, NULL, VAR_DOMAIN);
+ if (sym == NULL)
+ {
+ struct bound_minimal_symbol msym
+ = lookup_minimal_symbol (einfo->catch_handlers_sym, NULL, NULL);
+
+ if (msym.minsym && MSYMBOL_TYPE (msym.minsym) != mst_solib_trampoline)
+ error (_("Your Ada runtime appears to be missing some debugging "
+ "information.\nCannot insert Ada exception catchpoint "
+ "in this configuration."));
+
+ return 0;
+ }
+
+ /* Make sure that the symbol we found corresponds to a function. */
+
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ {
+ error (_("Symbol \"%s\" is not a function (class = %d)"),
+ sym->linkage_name (), SYMBOL_CLASS (sym));
+ return 0;
+ }
return 1;
}
return;
}
+ /* Try the v0 exception suport info. */
+ if (ada_has_this_exception_support (&exception_support_info_v0))
+ {
+ data->exception_info = &exception_support_info_v0;
+ return;
+ }
+
/* Try our fallback exception suport info. */
if (ada_has_this_exception_support (&exception_support_info_fallback))
{
loaded. If it is not started, this may mean that the symbol is
in a shared library. */
- if (ptid_get_pid (inferior_ptid) == 0)
+ if (inferior_ptid.pid () == 0)
error (_("Unable to insert catchpoint. Try to start the program first."));
/* At this point, we know that we are debugging an Ada program and
static int
is_known_support_routine (struct frame_info *frame)
{
- struct symtab_and_line sal;
- 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. */
- find_frame_sal (frame, &sal);
+ symtab_and_line sal = find_frame_sal (frame);
if (sal.symtab == NULL)
return 1;
if (access (fullname, R_OK) != 0)
return 1;
- /* Check the unit filename againt the Ada runtime file naming.
+ /* Check the unit filename against the Ada runtime file naming.
We also check the name of the objfile against the name of some
known system libraries that sometimes come with debugging info
too. */
re_comp (known_runtime_file_name_patterns[i]);
if (re_exec (lbasename (sal.symtab->filename)))
return 1;
- if (sal.symtab->objfile != NULL
- && re_exec (objfile_name (sal.symtab->objfile)))
+ if (SYMTAB_OBJFILE (sal.symtab) != NULL
+ && re_exec (objfile_name (SYMTAB_OBJFILE (sal.symtab))))
return 1;
}
/* Check whether the function is a GNAT-generated entity. */
- find_frame_funname (frame, &func_name, &func_lang, NULL);
+ gdb::unique_xmalloc_ptr<char> func_name
+ = find_frame_funname (frame, &func_lang, NULL);
if (func_name == NULL)
return 1;
for (i = 0; known_auxiliary_function_name_patterns[i] != NULL; i += 1)
{
re_comp (known_auxiliary_function_name_patterns[i]);
- if (re_exec (func_name))
- {
- xfree (func_name);
- return 1;
- }
+ if (re_exec (func_name.get ()))
+ return 1;
}
- xfree (func_name);
return 0;
}
int frame_level;
struct frame_info *fi;
struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ());
- struct cleanup *old_chain;
/* To determine the name of this exception, we need to select
the frame corresponding to RAISE_SYM_NAME. This frame is
if (fi != NULL)
fi = get_prev_frame (fi);
- old_chain = make_cleanup (null_cleanup, NULL);
while (fi != NULL)
{
- char *func_name;
enum language func_lang;
- find_frame_funname (fi, &func_name, &func_lang, NULL);
+ gdb::unique_xmalloc_ptr<char> func_name
+ = find_frame_funname (fi, &func_lang, NULL);
if (func_name != NULL)
{
- make_cleanup (xfree, func_name);
-
- if (strcmp (func_name,
+ if (strcmp (func_name.get (),
data->exception_info->catch_exception_sym) == 0)
break; /* We found the frame we were looking for... */
- fi = get_prev_frame (fi);
}
+ fi = get_prev_frame (fi);
}
- do_cleanups (old_chain);
if (fi == NULL)
return 0;
(of any type), return the address in inferior memory where the name
of the exception is stored, if applicable.
+ Assumes the selected frame is the current frame.
+
Return zero if the address could not be computed, or if not relevant. */
static CORE_ADDR
case ada_catch_exception_unhandled:
return data->exception_info->unhandled_exception_name_addr ();
break;
-
+
+ case ada_catch_handlers:
+ return 0; /* The runtimes does not provide access to the exception
+ name. */
+ break;
+
case ada_catch_assert:
return 0; /* Exception name is not relevant in this case. */
break;
return 0; /* Should never be reached. */
}
+/* Assuming the inferior is stopped at an exception catchpoint,
+ return the message which was associated to the exception, if
+ available. Return NULL if the message could not be retrieved.
+
+ Note: The exception message can be associated to an exception
+ either through the use of the Raise_Exception function, or
+ more simply (Ada 2005 and later), via:
+
+ raise Exception_Name with "exception message";
+
+ */
+
+static gdb::unique_xmalloc_ptr<char>
+ada_exception_message_1 (void)
+{
+ struct value *e_msg_val;
+ int e_msg_len;
+
+ /* For runtimes that support this feature, the exception message
+ is passed as an unbounded string argument called "message". */
+ e_msg_val = parse_and_eval ("message");
+ if (e_msg_val == NULL)
+ return NULL; /* Exception message not supported. */
+
+ e_msg_val = ada_coerce_to_simple_array (e_msg_val);
+ gdb_assert (e_msg_val != NULL);
+ e_msg_len = TYPE_LENGTH (value_type (e_msg_val));
+
+ /* If the message string is empty, then treat it as if there was
+ no exception message. */
+ if (e_msg_len <= 0)
+ return NULL;
+
+ gdb::unique_xmalloc_ptr<char> e_msg ((char *) xmalloc (e_msg_len + 1));
+ read_memory_string (value_address (e_msg_val), e_msg.get (), e_msg_len + 1);
+ e_msg.get ()[e_msg_len] = '\0';
+
+ return e_msg;
+}
+
+/* Same as ada_exception_message_1, except that all exceptions are
+ contained here (returning NULL instead). */
+
+static gdb::unique_xmalloc_ptr<char>
+ada_exception_message (void)
+{
+ gdb::unique_xmalloc_ptr<char> e_msg;
+
+ try
+ {
+ e_msg = ada_exception_message_1 ();
+ }
+ catch (const gdb_exception_error &e)
+ {
+ e_msg.reset (nullptr);
+ }
+
+ return e_msg;
+}
+
/* Same as ada_exception_name_addr_1, except that it intercepts and contains
any error that ada_exception_name_addr_1 might cause to be thrown.
When an error is intercepted, a warning with the error message is printed,
ada_exception_name_addr (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b)
{
- volatile struct gdb_exception e;
CORE_ADDR result = 0;
- TRY_CATCH (e, RETURN_MASK_ERROR)
+ try
{
result = ada_exception_name_addr_1 (ex, b);
}
- if (e.reason < 0)
+ 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;
}
return result;
}
-static char *ada_exception_catchpoint_cond_string (const char *excep_string);
+static std::string ada_exception_catchpoint_cond_string
+ (const char *excep_string,
+ enum ada_exception_catchpoint_kind ex);
/* Ada catchpoints.
when symbols change. */
/* An instance of this type is used to represent an Ada catchpoint
- breakpoint location. It includes a "struct bp_location" as a kind
- of base class; users downcast to "struct bp_location *" when
- needed. */
+ breakpoint location. */
-struct ada_catchpoint_location
+class ada_catchpoint_location : public bp_location
{
- /* The base class. */
- struct bp_location base;
+public:
+ ada_catchpoint_location (breakpoint *owner)
+ : bp_location (owner, bp_loc_software_breakpoint)
+ {}
/* The condition that checks whether the exception that was raised
is the specific exception the user specified on catchpoint
creation. */
- struct expression *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;
-
- xfree (al->excep_cond_expr);
-}
-
-/* The vtable to be used in Ada catchpoint locations. */
-
-static const struct bp_location_ops ada_catchpoint_location_ops =
-{
- ada_catchpoint_location_dtor
+ expression_up excep_cond_expr;
};
-/* An instance of this type is used to represent an Ada catchpoint.
- It includes a "struct breakpoint" as a kind of base class; users
- downcast to "struct breakpoint *" when needed. */
+/* An instance of this type is used to represent an Ada catchpoint. */
-struct ada_catchpoint
+struct ada_catchpoint : public breakpoint
{
- /* The base class. */
- struct breakpoint base;
+ explicit ada_catchpoint (enum ada_exception_catchpoint_kind kind)
+ : m_kind (kind)
+ {
+ }
/* The name of the specific exception the user specified. */
- char *excep_string;
+ std::string excep_string;
+
+ /* What kind of catchpoint this is. */
+ enum ada_exception_catchpoint_kind m_kind;
};
/* Parse the exception condition string in the context of each of the
catchpoint's locations, and store them for later evaluation. */
static void
-create_excep_cond_exprs (struct ada_catchpoint *c)
+create_excep_cond_exprs (struct ada_catchpoint *c,
+ enum ada_exception_catchpoint_kind ex)
{
- struct cleanup *old_chain;
struct bp_location *bl;
- char *cond_string;
/* Nothing to do if there's no specific exception to catch. */
- if (c->excep_string == NULL)
+ if (c->excep_string.empty ())
return;
/* Same if there are no locations... */
- if (c->base.loc == NULL)
+ if (c->loc == NULL)
return;
/* Compute the condition expression in text form, from the specific
expection we want to catch. */
- cond_string = ada_exception_catchpoint_cond_string (c->excep_string);
- old_chain = make_cleanup (xfree, cond_string);
+ std::string cond_string
+ = ada_exception_catchpoint_cond_string (c->excep_string.c_str (), ex);
/* Iterate over all the catchpoint's locations, and parse an
expression for each. */
- for (bl = c->base.loc; bl != NULL; bl = bl->next)
+ for (bl = c->loc; bl != NULL; bl = bl->next)
{
struct ada_catchpoint_location *ada_loc
= (struct ada_catchpoint_location *) bl;
- struct expression *exp = NULL;
+ expression_up exp;
if (!bl->shlib_disabled)
{
- volatile struct gdb_exception e;
const char *s;
- s = cond_string;
- TRY_CATCH (e, RETURN_MASK_ERROR)
+ s = cond_string.c_str ();
+ try
{
exp = parse_exp_1 (&s, bl->address,
- block_for_pc (bl->address), 0);
+ block_for_pc (bl->address),
+ 0);
}
- if (e.reason < 0)
+ catch (const gdb_exception_error &e)
{
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;
+ c->number, e.what ());
}
}
- ada_loc->excep_cond_expr = exp;
+ ada_loc->excep_cond_expr = std::move (exp);
}
-
- do_cleanups (old_chain);
-}
-
-/* Implement the DTOR method in the breakpoint_ops structure for all
- exception catchpoint kinds. */
-
-static void
-dtor_exception (enum ada_exception_catchpoint_kind ex, struct breakpoint *b)
-{
- struct ada_catchpoint *c = (struct ada_catchpoint *) b;
-
- xfree (c->excep_string);
-
- bkpt_breakpoint_ops.dtor (b);
}
/* Implement the ALLOCATE_LOCATION method in the breakpoint_ops
structure for all exception catchpoint kinds. */
static struct bp_location *
-allocate_location_exception (enum ada_exception_catchpoint_kind ex,
- struct breakpoint *self)
+allocate_location_exception (struct breakpoint *self)
{
- struct ada_catchpoint_location *loc;
-
- loc = XNEW (struct ada_catchpoint_location);
- init_bp_location (&loc->base, &ada_catchpoint_location_ops, self);
- loc->excep_cond_expr = NULL;
- return &loc->base;
+ return new ada_catchpoint_location (self);
}
/* Implement the RE_SET method in the breakpoint_ops structure for all
exception catchpoint kinds. */
static void
-re_set_exception (enum ada_exception_catchpoint_kind ex, struct breakpoint *b)
+re_set_exception (struct breakpoint *b)
{
struct ada_catchpoint *c = (struct ada_catchpoint *) b;
/* Reparse the exception conditional expressions. One for each
location. */
- create_excep_cond_exprs (c);
+ create_excep_cond_exprs (c, c->m_kind);
}
/* Returns true if we should stop for this breakpoint hit. If the
struct ada_catchpoint *c = (struct ada_catchpoint *) bl->owner;
const struct ada_catchpoint_location *ada_loc
= (const struct ada_catchpoint_location *) bl;
- volatile struct gdb_exception ex;
int stop;
+ struct internalvar *var = lookup_internalvar ("_ada_exception");
+ if (c->m_kind == ada_catch_assert)
+ clear_internalvar (var);
+ else
+ {
+ try
+ {
+ const char *expr;
+
+ if (c->m_kind == ada_catch_handlers)
+ expr = ("GNAT_GCC_exception_Access(gcc_exception)"
+ ".all.occurrence.id");
+ else
+ expr = "e";
+
+ struct value *exc = parse_and_eval (expr);
+ set_internalvar (var, exc);
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ clear_internalvar (var);
+ }
+ }
+
/* With no specific exception, should always stop. */
- if (c->excep_string == NULL)
+ if (c->excep_string.empty ())
return 1;
if (ada_loc->excep_cond_expr == NULL)
}
stop = 1;
- TRY_CATCH (ex, RETURN_MASK_ALL)
+ try
{
struct value *mark;
mark = value_mark ();
- stop = value_true (evaluate_expression (ada_loc->excep_cond_expr));
+ stop = value_true (evaluate_expression (ada_loc->excep_cond_expr.get ()));
value_free_to_mark (mark);
}
- if (ex.reason < 0)
- exception_fprintf (gdb_stderr, ex,
- _("Error in testing exception condition:\n"));
+ catch (const gdb_exception &ex)
+ {
+ exception_fprintf (gdb_stderr, ex,
+ _("Error in testing exception condition:\n"));
+ }
+
return stop;
}
for all exception catchpoint kinds. */
static void
-check_status_exception (enum ada_exception_catchpoint_kind ex, bpstat bs)
+check_status_exception (bpstat bs)
{
bs->stop = should_stop_exception (bs->bp_location_at);
}
for all exception catchpoint kinds. */
static enum print_stop_action
-print_it_exception (enum ada_exception_catchpoint_kind ex, bpstat bs)
+print_it_exception (bpstat bs)
{
struct ui_out *uiout = current_uiout;
struct breakpoint *b = bs->breakpoint_at;
annotate_catchpoint (b->number);
- if (ui_out_is_mi_like_p (uiout))
+ if (uiout->is_mi_like_p ())
{
- ui_out_field_string (uiout, "reason",
+ uiout->field_string ("reason",
async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
- ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
+ uiout->field_string ("disp", bpdisp_text (b->disposition));
}
- ui_out_text (uiout,
- b->disposition == disp_del ? "\nTemporary catchpoint "
- : "\nCatchpoint ");
- ui_out_field_int (uiout, "bkptno", b->number);
- ui_out_text (uiout, ", ");
+ uiout->text (b->disposition == disp_del
+ ? "\nTemporary catchpoint " : "\nCatchpoint ");
+ uiout->field_signed ("bkptno", b->number);
+ uiout->text (", ");
- switch (ex)
+ /* ada_exception_name_addr relies on the selected frame being the
+ current frame. Need to do this here because this function may be
+ called more than once when printing a stop, and below, we'll
+ select the first frame past the Ada run-time (see
+ ada_find_printable_frame). */
+ select_frame (get_current_frame ());
+
+ struct ada_catchpoint *c = (struct ada_catchpoint *) b;
+ switch (c->m_kind)
{
case ada_catch_exception:
case ada_catch_exception_unhandled:
+ case ada_catch_handlers:
{
- const CORE_ADDR addr = ada_exception_name_addr (ex, b);
+ const CORE_ADDR addr = ada_exception_name_addr (c->m_kind, b);
char exception_name[256];
if (addr != 0)
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 == ada_catch_exception_unhandled)
- ui_out_text (uiout, "unhandled ");
- ui_out_field_string (uiout, "exception-name", exception_name);
+ if (c->m_kind == ada_catch_exception_unhandled)
+ uiout->text ("unhandled ");
+ uiout->field_string ("exception-name", exception_name);
}
break;
case ada_catch_assert:
that his program just hit an assertion-failure catchpoint.
We used ui_out_text because this info does not belong in
the MI output. */
- ui_out_text (uiout, "failed assertion");
+ uiout->text ("failed assertion");
break;
}
- ui_out_text (uiout, " at ");
+
+ gdb::unique_xmalloc_ptr<char> exception_message = ada_exception_message ();
+ if (exception_message != NULL)
+ {
+ uiout->text (" (");
+ uiout->field_string ("exception-message", exception_message.get ());
+ uiout->text (")");
+ }
+
+ uiout->text (" at ");
ada_find_printable_frame (get_current_frame ());
return PRINT_SRC_AND_LOC;
for all exception catchpoint kinds. */
static void
-print_one_exception (enum ada_exception_catchpoint_kind ex,
- struct breakpoint *b, struct bp_location **last_loc)
+print_one_exception (struct breakpoint *b, struct bp_location **last_loc)
{
struct ui_out *uiout = current_uiout;
struct ada_catchpoint *c = (struct ada_catchpoint *) b;
struct value_print_options opts;
get_user_print_options (&opts);
+
if (opts.addressprint)
- {
- annotate_field (4);
- ui_out_field_core_addr (uiout, "addr", b->loc->gdbarch, b->loc->address);
- }
+ uiout->field_skip ("addr");
annotate_field (5);
- *last_loc = b->loc;
- switch (ex)
+ switch (c->m_kind)
{
case ada_catch_exception:
- if (c->excep_string != NULL)
+ if (!c->excep_string.empty ())
{
- char *msg = xstrprintf (_("`%s' Ada exception"), c->excep_string);
+ std::string msg = string_printf (_("`%s' Ada exception"),
+ c->excep_string.c_str ());
- ui_out_field_string (uiout, "what", msg);
- xfree (msg);
+ uiout->field_string ("what", msg);
}
else
- ui_out_field_string (uiout, "what", "all Ada exceptions");
+ uiout->field_string ("what", "all Ada exceptions");
break;
case ada_catch_exception_unhandled:
- ui_out_field_string (uiout, "what", "unhandled Ada exceptions");
+ uiout->field_string ("what", "unhandled Ada exceptions");
break;
- case ada_catch_assert:
- ui_out_field_string (uiout, "what", "failed Ada assertions");
- break;
-
- default:
- internal_error (__FILE__, __LINE__, _("unexpected catchpoint type"));
- break;
- }
-}
-
-/* Implement the PRINT_MENTION method in the breakpoint_ops structure
- for all exception catchpoint kinds. */
-
-static void
-print_mention_exception (enum ada_exception_catchpoint_kind ex,
- struct breakpoint *b)
-{
- struct ada_catchpoint *c = (struct ada_catchpoint *) b;
- struct ui_out *uiout = current_uiout;
-
- ui_out_text (uiout, b->disposition == disp_del ? _("Temporary catchpoint ")
- : _("Catchpoint "));
- ui_out_field_int (uiout, "bkptno", b->number);
- ui_out_text (uiout, ": ");
-
- switch (ex)
- {
- case ada_catch_exception:
- if (c->excep_string != NULL)
- {
- char *info = xstrprintf (_("`%s' Ada exception"), c->excep_string);
- struct cleanup *old_chain = make_cleanup (xfree, info);
-
- ui_out_text (uiout, info);
- do_cleanups (old_chain);
- }
+ case ada_catch_handlers:
+ if (!c->excep_string.empty ())
+ {
+ uiout->field_fmt ("what",
+ _("`%s' Ada exception handlers"),
+ c->excep_string.c_str ());
+ }
else
- ui_out_text (uiout, _("all Ada exceptions"));
- break;
-
- case ada_catch_exception_unhandled:
- ui_out_text (uiout, _("unhandled Ada exceptions"));
- break;
-
- case ada_catch_assert:
- ui_out_text (uiout, _("failed Ada assertions"));
- break;
-
- default:
- internal_error (__FILE__, __LINE__, _("unexpected catchpoint type"));
+ uiout->field_string ("what", "all Ada exceptions handlers");
break;
- }
-}
-
-/* Implement the PRINT_RECREATE method in the breakpoint_ops structure
- for all exception catchpoint kinds. */
-
-static void
-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 ada_catch_exception:
- fprintf_filtered (fp, "catch exception");
- if (c->excep_string != NULL)
- fprintf_filtered (fp, " %s", c->excep_string);
- break;
-
- case ada_catch_exception_unhandled:
- fprintf_filtered (fp, "catch exception unhandled");
- break;
case ada_catch_assert:
- fprintf_filtered (fp, "catch assert");
- break;
-
- default:
- internal_error (__FILE__, __LINE__, _("unexpected catchpoint type"));
- }
- print_recreate_thread (b, fp);
-}
-
-/* Virtual table for "catch exception" breakpoints. */
-
-static void
-dtor_catch_exception (struct breakpoint *b)
-{
- dtor_exception (ada_catch_exception, b);
-}
-
-static struct bp_location *
-allocate_location_catch_exception (struct breakpoint *self)
-{
- return allocate_location_exception (ada_catch_exception, self);
-}
-
-static void
-re_set_catch_exception (struct breakpoint *b)
-{
- re_set_exception (ada_catch_exception, b);
-}
-
-static void
-check_status_catch_exception (bpstat bs)
-{
- check_status_exception (ada_catch_exception, bs);
-}
-
-static enum print_stop_action
-print_it_catch_exception (bpstat 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 (ada_catch_exception, b, last_loc);
-}
-
-static void
-print_mention_catch_exception (struct breakpoint *b)
-{
- print_mention_exception (ada_catch_exception, b);
-}
-
-static void
-print_recreate_catch_exception (struct breakpoint *b, struct ui_file *fp)
-{
- print_recreate_exception (ada_catch_exception, b, fp);
-}
-
-static struct breakpoint_ops catch_exception_breakpoint_ops;
-
-/* Virtual table for "catch exception unhandled" breakpoints. */
-
-static void
-dtor_catch_exception_unhandled (struct breakpoint *b)
-{
- dtor_exception (ada_catch_exception_unhandled, b);
-}
-
-static struct bp_location *
-allocate_location_catch_exception_unhandled (struct breakpoint *self)
-{
- return allocate_location_exception (ada_catch_exception_unhandled, self);
-}
-
-static void
-re_set_catch_exception_unhandled (struct breakpoint *b)
-{
- re_set_exception (ada_catch_exception_unhandled, b);
-}
-
-static void
-check_status_catch_exception_unhandled (bpstat bs)
-{
- check_status_exception (ada_catch_exception_unhandled, bs);
-}
+ uiout->field_string ("what", "failed Ada assertions");
+ break;
-static enum print_stop_action
-print_it_catch_exception_unhandled (bpstat bs)
-{
- return print_it_exception (ada_catch_exception_unhandled, bs);
+ default:
+ internal_error (__FILE__, __LINE__, _("unexpected catchpoint type"));
+ break;
+ }
}
-static void
-print_one_catch_exception_unhandled (struct breakpoint *b,
- struct bp_location **last_loc)
-{
- print_one_exception (ada_catch_exception_unhandled, b, last_loc);
-}
+/* Implement the PRINT_MENTION method in the breakpoint_ops structure
+ for all exception catchpoint kinds. */
static void
-print_mention_catch_exception_unhandled (struct breakpoint *b)
+print_mention_exception (struct breakpoint *b)
{
- print_mention_exception (ada_catch_exception_unhandled, b);
-}
+ struct ada_catchpoint *c = (struct ada_catchpoint *) b;
+ struct ui_out *uiout = current_uiout;
-static void
-print_recreate_catch_exception_unhandled (struct breakpoint *b,
- struct ui_file *fp)
-{
- print_recreate_exception (ada_catch_exception_unhandled, b, fp);
-}
+ uiout->text (b->disposition == disp_del ? _("Temporary catchpoint ")
+ : _("Catchpoint "));
+ uiout->field_signed ("bkptno", b->number);
+ uiout->text (": ");
-static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops;
+ switch (c->m_kind)
+ {
+ case ada_catch_exception:
+ if (!c->excep_string.empty ())
+ {
+ std::string info = string_printf (_("`%s' Ada exception"),
+ c->excep_string.c_str ());
+ uiout->text (info.c_str ());
+ }
+ else
+ uiout->text (_("all Ada exceptions"));
+ break;
-/* Virtual table for "catch assert" breakpoints. */
+ case ada_catch_exception_unhandled:
+ uiout->text (_("unhandled Ada exceptions"));
+ break;
-static void
-dtor_catch_assert (struct breakpoint *b)
-{
- dtor_exception (ada_catch_assert, b);
-}
+ case ada_catch_handlers:
+ if (!c->excep_string.empty ())
+ {
+ std::string info
+ = string_printf (_("`%s' Ada exception handlers"),
+ c->excep_string.c_str ());
+ uiout->text (info.c_str ());
+ }
+ else
+ uiout->text (_("all Ada exceptions handlers"));
+ break;
-static struct bp_location *
-allocate_location_catch_assert (struct breakpoint *self)
-{
- return allocate_location_exception (ada_catch_assert, self);
-}
+ case ada_catch_assert:
+ uiout->text (_("failed Ada assertions"));
+ break;
-static void
-re_set_catch_assert (struct breakpoint *b)
-{
- re_set_exception (ada_catch_assert, b);
+ default:
+ internal_error (__FILE__, __LINE__, _("unexpected catchpoint type"));
+ break;
+ }
}
+/* Implement the PRINT_RECREATE method in the breakpoint_ops structure
+ for all exception catchpoint kinds. */
+
static void
-check_status_catch_assert (bpstat bs)
+print_recreate_exception (struct breakpoint *b, struct ui_file *fp)
{
- check_status_exception (ada_catch_assert, bs);
-}
+ struct ada_catchpoint *c = (struct ada_catchpoint *) b;
-static enum print_stop_action
-print_it_catch_assert (bpstat bs)
-{
- return print_it_exception (ada_catch_assert, bs);
-}
+ switch (c->m_kind)
+ {
+ case ada_catch_exception:
+ fprintf_filtered (fp, "catch exception");
+ if (!c->excep_string.empty ())
+ fprintf_filtered (fp, " %s", c->excep_string.c_str ());
+ break;
-static void
-print_one_catch_assert (struct breakpoint *b, struct bp_location **last_loc)
-{
- print_one_exception (ada_catch_assert, b, last_loc);
-}
+ case ada_catch_exception_unhandled:
+ fprintf_filtered (fp, "catch exception unhandled");
+ break;
-static void
-print_mention_catch_assert (struct breakpoint *b)
-{
- print_mention_exception (ada_catch_assert, b);
-}
+ case ada_catch_handlers:
+ fprintf_filtered (fp, "catch handlers");
+ break;
-static void
-print_recreate_catch_assert (struct breakpoint *b, struct ui_file *fp)
-{
- print_recreate_exception (ada_catch_assert, b, fp);
+ case ada_catch_assert:
+ fprintf_filtered (fp, "catch assert");
+ break;
+
+ default:
+ internal_error (__FILE__, __LINE__, _("unexpected catchpoint type"));
+ }
+ print_recreate_thread (b, fp);
}
+/* Virtual tables for various breakpoint types. */
+static struct breakpoint_ops catch_exception_breakpoint_ops;
+static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops;
static struct breakpoint_ops catch_assert_breakpoint_ops;
+static struct breakpoint_ops catch_handlers_breakpoint_ops;
-/* Return a newly allocated copy of the first space-separated token
- in ARGSP, and then adjust ARGSP to point immediately after that
- token.
+/* See ada-lang.h. */
- Return NULL if ARGPS does not contain any more tokens. */
-
-static char *
-ada_get_next_arg (char **argsp)
+bool
+is_ada_exception_catchpoint (breakpoint *bp)
{
- char *args = *argsp;
- char *end;
- char *result;
-
- args = skip_spaces (args);
- if (args[0] == '\0')
- return NULL; /* No more arguments. */
-
- /* Find the end of the current argument. */
-
- end = skip_to_space (args);
-
- /* Adjust ARGSP to point to the start of the next argument. */
-
- *argsp = end;
-
- /* Make a copy of the current argument and return it. */
-
- result = xmalloc (end - args + 1);
- strncpy (result, args, end - args);
- result[end - args] = '\0';
-
- return result;
+ return (bp->ops == &catch_exception_breakpoint_ops
+ || bp->ops == &catch_exception_unhandled_breakpoint_ops
+ || bp->ops == &catch_assert_breakpoint_ops
+ || bp->ops == &catch_handlers_breakpoint_ops);
}
/* Split the arguments specified in a "catch exception" command.
Set EX to the appropriate catchpoint type.
Set EXCEP_STRING to the name of the specific exception if
specified by the user.
+ IS_CATCH_HANDLERS_CMD: True if the arguments are for a
+ "catch handlers" command. False otherwise.
If a condition is found at the end of the arguments, the condition
expression is stored in COND_STRING (memory must be deallocated
after use). Otherwise COND_STRING is set to NULL. */
static void
-catch_ada_exception_command_split (char *args,
+catch_ada_exception_command_split (const char *args,
+ bool is_catch_handlers_cmd,
enum ada_exception_catchpoint_kind *ex,
- char **excep_string,
- char **cond_string)
+ std::string *excep_string,
+ std::string *cond_string)
{
- struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
- char *exception_name;
- char *cond = NULL;
+ std::string exception_name;
- exception_name = ada_get_next_arg (&args);
- if (exception_name != NULL && strcmp (exception_name, "if") == 0)
+ exception_name = extract_arg (&args);
+ if (exception_name == "if")
{
/* This is not an exception name; this is the start of a condition
expression for a catchpoint on all exceptions. So, "un-get"
this token, and set exception_name to NULL. */
- xfree (exception_name);
- exception_name = NULL;
+ exception_name.clear ();
args -= 2;
}
- make_cleanup (xfree, exception_name);
/* Check to see if we have a condition. */
args = skip_spaces (args);
- if (strncmp (args, "if", 2) == 0
+ if (startswith (args, "if")
&& (isspace (args[2]) || args[2] == '\0'))
{
args += 2;
if (args[0] == '\0')
error (_("Condition missing after `if' keyword"));
- cond = xstrdup (args);
- make_cleanup (xfree, cond);
+ *cond_string = args;
args += strlen (args);
}
if (args[0] != '\0')
error (_("Junk at end of expression"));
- discard_cleanups (old_chain);
-
- if (exception_name == NULL)
+ if (is_catch_handlers_cmd)
+ {
+ /* Catch handling of exceptions. */
+ *ex = ada_catch_handlers;
+ *excep_string = exception_name;
+ }
+ else if (exception_name.empty ())
{
/* Catch all exceptions. */
*ex = ada_catch_exception;
- *excep_string = NULL;
+ excep_string->clear ();
}
- else if (strcmp (exception_name, "unhandled") == 0)
+ else if (exception_name == "unhandled")
{
/* Catch unhandled exceptions. */
*ex = ada_catch_exception_unhandled;
- *excep_string = NULL;
+ excep_string->clear ();
}
else
{
*ex = ada_catch_exception;
*excep_string = exception_name;
}
- *cond_string = cond;
}
/* Return the name of the symbol on which we should break in order to
case ada_catch_assert:
return (data->exception_info->catch_assert_sym);
break;
+ case ada_catch_handlers:
+ return (data->exception_info->catch_handlers_sym);
+ break;
default:
internal_error (__FILE__, __LINE__,
_("unexpected catchpoint kind (%d)"), ex);
case ada_catch_assert:
return (&catch_assert_breakpoint_ops);
break;
+ case ada_catch_handlers:
+ return (&catch_handlers_breakpoint_ops);
+ break;
default:
internal_error (__FILE__, __LINE__,
_("unexpected catchpoint kind (%d)"), ex);
being raised with the exception that the user wants to catch. This
assumes that this condition is used when the inferior just triggered
an exception catchpoint.
-
- The string returned is a newly allocated string that needs to be
- deallocated later. */
+ EX: the type of catchpoints used for catching Ada exceptions. */
-static char *
-ada_exception_catchpoint_cond_string (const char *excep_string)
+static std::string
+ada_exception_catchpoint_cond_string (const char *excep_string,
+ enum ada_exception_catchpoint_kind ex)
{
int i;
+ bool is_standard_exc = false;
+ std::string result;
+
+ if (ex == ada_catch_handlers)
+ {
+ /* For exception handlers catchpoints, the condition string does
+ not use the same parameter as for the other exceptions. */
+ result = ("long_integer (GNAT_GCC_exception_Access"
+ "(gcc_exception).all.occurrence.id)");
+ }
+ else
+ result = "long_integer (e)";
/* The standard exceptions are a special case. They are defined in
runtime units that have been compiled without debugging info; if
exception constraint_error" is rewritten into "catch exception
standard.constraint_error".
- If an exception named contraint_error is defined in another package of
+ If an exception named constraint_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. */
{
if (strcmp (standard_exc [i], excep_string) == 0)
{
- return xstrprintf ("long_integer (e) = long_integer (&standard.%s)",
- excep_string);
+ is_standard_exc = true;
+ break;
}
}
- return xstrprintf ("long_integer (e) = long_integer (&%s)", excep_string);
+
+ result += " = ";
+
+ if (is_standard_exc)
+ string_appendf (result, "long_integer (&standard.%s)", excep_string);
+ else
+ string_appendf (result, "long_integer (&%s)", excep_string);
+
+ return result;
}
/* Return the symtab_and_line that should be used to insert an exception
catchpoint of the TYPE kind.
- EXCEP_STRING should contain the name of a specific exception that
- the catchpoint should catch, or NULL otherwise.
-
ADDR_STRING returns the name of the function where the real
breakpoint that implements the catchpoints is set, depending on the
type of catchpoint we need to create. */
static struct symtab_and_line
-ada_exception_sal (enum ada_exception_catchpoint_kind ex, char *excep_string,
- char **addr_string, const struct breakpoint_ops **ops)
+ada_exception_sal (enum ada_exception_catchpoint_kind ex,
+ std::string *addr_string, const struct breakpoint_ops **ops)
{
const char *sym_name;
struct symbol *sym;
sym_name = ada_exception_sym_name (ex);
sym = standard_lookup (sym_name, NULL, VAR_DOMAIN);
- /* We can assume that SYM is not NULL at this stage. If the symbol
- did not exist, ada_exception_support_info_sniffer would have
- raised an exception.
+ if (sym == NULL)
+ error (_("Catchpoint symbol not found: %s"), sym_name);
- Also, ada_exception_support_info_sniffer should have already
- verified that SYM is a function symbol. */
- gdb_assert (sym != NULL);
- gdb_assert (SYMBOL_CLASS (sym) == LOC_BLOCK);
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ error (_("Unable to insert catchpoint. %s is not a function."), sym_name);
/* Set ADDR_STRING. */
- *addr_string = xstrdup (sym_name);
+ *addr_string = sym_name;
/* Set OPS. */
*ops = ada_exception_breakpoint_ops (ex);
EX_KIND is the kind of exception catchpoint to be created.
- If EXCEPT_STRING is NULL, this catchpoint is expected to trigger
+ If EXCEPT_STRING is empty, this catchpoint is expected to trigger
for all exceptions. Otherwise, EXCEPT_STRING indicates the name
- of the exception to which this catchpoint applies. When not NULL,
- the string must be allocated on the heap, and its deallocation
- is no longer the responsibility of the caller.
+ of the exception to which this catchpoint applies.
- COND_STRING, if not NULL, is the catchpoint condition. This string
- must be allocated on the heap, and its deallocation is no longer
- the responsibility of the caller.
+ COND_STRING, if not empty, is the catchpoint condition.
TEMPFLAG, if nonzero, means that the underlying breakpoint
should be temporary.
void
create_ada_exception_catchpoint (struct gdbarch *gdbarch,
enum ada_exception_catchpoint_kind ex_kind,
- char *excep_string,
- char *cond_string,
+ const std::string &excep_string,
+ const std::string &cond_string,
int tempflag,
int disabled,
int from_tty)
{
- struct ada_catchpoint *c;
- char *addr_string = NULL;
+ std::string addr_string;
const struct breakpoint_ops *ops = NULL;
- struct symtab_and_line sal
- = ada_exception_sal (ex_kind, excep_string, &addr_string, &ops);
+ struct symtab_and_line sal = ada_exception_sal (ex_kind, &addr_string, &ops);
- c = XNEW (struct ada_catchpoint);
- init_ada_exception_breakpoint (&c->base, gdbarch, sal, addr_string,
+ std::unique_ptr<ada_catchpoint> c (new ada_catchpoint (ex_kind));
+ 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);
- if (cond_string != NULL)
- set_breakpoint_condition (&c->base, cond_string, from_tty);
- install_breakpoint (0, &c->base, 1);
+ create_excep_cond_exprs (c.get (), ex_kind);
+ if (!cond_string.empty ())
+ set_breakpoint_condition (c.get (), cond_string.c_str (), from_tty);
+ install_breakpoint (0, std::move (c), 1);
}
/* Implement the "catch exception" command. */
static void
-catch_ada_exception_command (char *arg, int from_tty,
+catch_ada_exception_command (const char *arg_entry, int from_tty,
struct cmd_list_element *command)
{
+ const char *arg = arg_entry;
+ struct gdbarch *gdbarch = get_current_arch ();
+ int tempflag;
+ enum ada_exception_catchpoint_kind ex_kind;
+ std::string excep_string;
+ std::string cond_string;
+
+ tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+ if (!arg)
+ arg = "";
+ catch_ada_exception_command_split (arg, false, &ex_kind, &excep_string,
+ &cond_string);
+ create_ada_exception_catchpoint (gdbarch, ex_kind,
+ excep_string, cond_string,
+ tempflag, 1 /* enabled */,
+ from_tty);
+}
+
+/* Implement the "catch handlers" command. */
+
+static void
+catch_ada_handlers_command (const char *arg_entry, int from_tty,
+ struct cmd_list_element *command)
+{
+ const char *arg = arg_entry;
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
enum ada_exception_catchpoint_kind ex_kind;
- char *excep_string = NULL;
- char *cond_string = NULL;
+ std::string excep_string;
+ std::string cond_string;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
if (!arg)
arg = "";
- catch_ada_exception_command_split (arg, &ex_kind, &excep_string,
+ catch_ada_exception_command_split (arg, true, &ex_kind, &excep_string,
&cond_string);
create_ada_exception_catchpoint (gdbarch, ex_kind,
excep_string, cond_string,
from_tty);
}
+/* Completion function for the Ada "catch" commands. */
+
+static void
+catch_ada_completer (struct cmd_list_element *cmd, completion_tracker &tracker,
+ const char *text, const char *word)
+{
+ std::vector<ada_exc_info> exceptions = ada_exceptions_list (NULL);
+
+ for (const ada_exc_info &info : exceptions)
+ {
+ if (startswith (info.name, word))
+ tracker.add_completion (make_unique_xstrdup (info.name));
+ }
+}
+
/* Split the arguments specified in a "catch assert" command.
ARGS contains the command's arguments (or the empty string if
(the memory needs to be deallocated after use). */
static void
-catch_ada_assert_command_split (char *args, char **cond_string)
+catch_ada_assert_command_split (const char *args, std::string &cond_string)
{
args = skip_spaces (args);
/* Check whether a condition was provided. */
- if (strncmp (args, "if", 2) == 0
+ if (startswith (args, "if")
&& (isspace (args[2]) || args[2] == '\0'))
{
args += 2;
args = skip_spaces (args);
if (args[0] == '\0')
error (_("condition missing after `if' keyword"));
- *cond_string = xstrdup (args);
+ cond_string.assign (args);
}
/* Otherwise, there should be no other argument at the end of
/* Implement the "catch assert" command. */
static void
-catch_assert_command (char *arg, int from_tty,
+catch_assert_command (const char *arg_entry, int from_tty,
struct cmd_list_element *command)
{
+ const char *arg = arg_entry;
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
- char *cond_string = NULL;
+ std::string cond_string;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
if (!arg)
arg = "";
- catch_ada_assert_command_split (arg, &cond_string);
+ catch_ada_assert_command_split (arg, cond_string);
create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
- NULL, cond_string,
+ "", cond_string,
tempflag, 1 /* enabled */,
from_tty);
}
static int
ada_is_exception_sym (struct symbol *sym)
{
- const char *type_name = type_name_no_tag (SYMBOL_TYPE (sym));
+ const char *type_name = TYPE_NAME (SYMBOL_TYPE (sym));
return (SYMBOL_CLASS (sym) != LOC_TYPEDEF
&& SYMBOL_CLASS (sym) != LOC_BLOCK
return 0;
for (i = 0; i < ARRAY_SIZE (standard_exc); i++)
- if (strcmp (SYMBOL_LINKAGE_NAME (sym), standard_exc[i]) == 0)
+ if (strcmp (sym->linkage_name (), 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)
+ if (strcmp (sym->linkage_name (), "numeric_error") == 0)
return 0;
return 1;
}
-/* A helper function for qsort, comparing two struct ada_exc_info
+/* A helper function for std::sort, 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)
+bool
+ada_exc_info::operator< (const ada_exc_info &other) const
{
- 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;
+ result = strcmp (name, other.name);
+ if (result < 0)
+ return true;
+ if (result == 0 && addr < other.addr)
+ return true;
+ return false;
+}
- return 0;
+bool
+ada_exc_info::operator== (const ada_exc_info &other) const
+{
+ return addr == other.addr && strcmp (name, other.name) == 0;
}
/* Sort EXCEPTIONS using compare_ada_exception_info as the comparison
All duplicates are also removed. */
static void
-sort_remove_dups_ada_exceptions_list (VEC(ada_exc_info) **exceptions,
+sort_remove_dups_ada_exceptions_list (std::vector<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);
+ std::sort (exceptions->begin () + skip, exceptions->end ());
+ exceptions->erase (std::unique (exceptions->begin () + skip, exceptions->end ()),
+ exceptions->end ());
}
/* Add all exceptions defined by the Ada standard whose name match
gets pushed. */
static void
-ada_add_standard_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
+ada_add_standard_exceptions (compiled_regex *preg,
+ std::vector<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)
+ || preg->exec (standard_exc[i], 0, NULL, 0) == 0)
{
struct bound_minimal_symbol msymbol
= ada_lookup_simple_minsym (standard_exc[i]);
struct ada_exc_info info
= {standard_exc[i], BMSYMBOL_VALUE_ADDRESS (msymbol)};
- VEC_safe_push (ada_exc_info, *exceptions, &info);
+ exceptions->push_back (info);
}
}
}
gets pushed. */
static void
-ada_add_exceptions_from_frame (regex_t *preg, struct frame_info *frame,
- VEC(ada_exc_info) **exceptions)
+ada_add_exceptions_from_frame (compiled_regex *preg,
+ struct frame_info *frame,
+ std::vector<ada_exc_info> *exceptions)
{
- struct block *block = get_frame_block (frame, 0);
+ const struct block *block = get_frame_block (frame, 0);
while (block != 0)
{
default:
if (ada_is_exception_sym (sym))
{
- struct ada_exc_info info = {SYMBOL_PRINT_NAME (sym),
+ struct ada_exc_info info = {sym->print_name (),
SYMBOL_VALUE_ADDRESS (sym)};
- VEC_safe_push (ada_exc_info, *exceptions, &info);
+ exceptions->push_back (info);
}
}
}
}
}
+/* Return true if NAME matches PREG or if PREG is NULL. */
+
+static bool
+name_matches_regex (const char *name, compiled_regex *preg)
+{
+ return (preg == NULL
+ || preg->exec (ada_decode (name).c_str (), 0, NULL, 0) == 0);
+}
+
/* Add all exceptions defined globally whose name name match
a regular expression, excluding standard exceptions.
gets pushed. */
static void
-ada_add_global_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
-{
- struct objfile *objfile;
- struct symtab *s;
-
- expand_symtabs_matching (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++)
+ada_add_global_exceptions (compiled_regex *preg,
+ std::vector<ada_exc_info> *exceptions)
+{
+ /* 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. */
+ expand_symtabs_matching (NULL,
+ lookup_name_info::match_any (),
+ [&] (const char *search_name)
+ {
+ std::string decoded = ada_decode (search_name);
+ return name_matches_regex (decoded.c_str (), preg);
+ },
+ NULL,
+ VARIABLES_DOMAIN);
+
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ 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)
- && (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)};
+ for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+ {
+ const struct block *b = BLOCKVECTOR_BLOCK (bv, i);
+ struct block_iterator iter;
+ struct symbol *sym;
- VEC_safe_push (ada_exc_info, *exceptions, &info);
- }
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ if (ada_is_non_standard_exception_sym (sym)
+ && name_matches_regex (sym->natural_name (), preg))
+ {
+ struct ada_exc_info info
+ = {sym->print_name (), SYMBOL_VALUE_ADDRESS (sym)};
+
+ exceptions->push_back (info);
+ }
+ }
}
}
}
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)
+static std::vector<ada_exc_info>
+ada_exceptions_list_1 (compiled_regex *preg)
{
- VEC(ada_exc_info) *result = NULL;
- struct cleanup *old_chain
- = make_cleanup (VEC_cleanup (ada_exc_info), &result);
+ std::vector<ada_exc_info> result;
int prev_len;
/* First, list the known standard exceptions. These exceptions
if (has_stack_frames ())
{
- prev_len = VEC_length (ada_exc_info, result);
+ prev_len = result.size ();
ada_add_exceptions_from_frame (preg, get_selected_frame (NULL),
&result);
- if (VEC_length (ada_exc_info, result) > prev_len)
+ if (result.size () > 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);
+ prev_len = result.size ();
ada_add_global_exceptions (preg, &result);
- if (VEC_length (ada_exc_info, result) > prev_len)
+ if (result.size () > prev_len)
sort_remove_dups_ada_exceptions_list (&result, prev_len);
- discard_cleanups (old_chain);
return result;
}
alphabetical order;
- Exceptions whose scope is global, in alphabetical order. */
-VEC(ada_exc_info) *
+std::vector<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"));
+ if (regexp == NULL)
+ return ada_exceptions_list_1 (NULL);
- result = ada_exceptions_list_1 (regexp != NULL ? ® : NULL);
-
- if (old_chain != NULL)
- do_cleanups (old_chain);
- return result;
+ compiled_regex reg (regexp, REG_NOSUB, _("invalid regular expression"));
+ return ada_exceptions_list_1 (®);
}
/* Implement the "info exceptions" command. */
static void
-info_exceptions_command (char *regexp, int from_tty)
+info_exceptions_command (const 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);
+ std::vector<ada_exc_info> exceptions = ada_exceptions_list (regexp);
if (regexp != NULL)
printf_filtered
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);
+ for (const ada_exc_info &info : exceptions)
+ printf_filtered ("%s: %s\n", info.name, paddress (gdbarch, info.addr));
}
/* Operators */
return 0;
}
-static char *
+static const char *
ada_op_name (enum exp_opcode opcode)
{
switch (opcode)
return;
case OP_VAR_VALUE:
- fputs_filtered (SYMBOL_NATURAL_NAME (exp->elts[pc + 2].symbol), stream);
+ fputs_filtered (exp->elts[pc + 2].symbol->natural_name (), stream);
return;
case BINOP_IN_BOUNDS:
{".all", UNOP_IND, PREC_SUFFIX, 1},
{"'access", UNOP_ADDR, PREC_SUFFIX, 1},
{"'size", OP_ATR_SIZE, PREC_SUFFIX, 1},
- {NULL, 0, 0, 0}
+ {NULL, OP_NULL, PREC_SUFFIX, 0}
};
\f
enum ada_primitive_types {
ada_primitive_type_natural,
ada_primitive_type_positive,
ada_primitive_type_system_address,
+ ada_primitive_type_storage_offset,
nr_ada_primitive_types
};
0, "short_integer");
lai->string_char_type
= lai->primitive_type_vector [ada_primitive_type_char]
- = arch_integer_type (gdbarch, TARGET_CHAR_BIT, 0, "character");
+ = arch_character_type (gdbarch, TARGET_CHAR_BIT, 0, "character");
lai->primitive_type_vector [ada_primitive_type_float]
= arch_float_type (gdbarch, gdbarch_float_bit (gdbarch),
- "float", NULL);
+ "float", gdbarch_float_format (gdbarch));
lai->primitive_type_vector [ada_primitive_type_double]
= arch_float_type (gdbarch, gdbarch_double_bit (gdbarch),
- "long_float", NULL);
+ "long_float", gdbarch_double_format (gdbarch));
lai->primitive_type_vector [ada_primitive_type_long_long]
= arch_integer_type (gdbarch, gdbarch_long_long_bit (gdbarch),
0, "long_long_integer");
lai->primitive_type_vector [ada_primitive_type_long_double]
- = arch_float_type (gdbarch, gdbarch_double_bit (gdbarch),
- "long_long_float", NULL);
+ = arch_float_type (gdbarch, gdbarch_long_double_bit (gdbarch),
+ "long_long_float", gdbarch_long_double_format (gdbarch));
lai->primitive_type_vector [ada_primitive_type_natural]
= arch_integer_type (gdbarch, gdbarch_int_bit (gdbarch),
0, "natural");
= builtin->builtin_void;
lai->primitive_type_vector [ada_primitive_type_system_address]
- = lookup_pointer_type (arch_type (gdbarch, TYPE_CODE_VOID, 1, "void"));
+ = lookup_pointer_type (arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT,
+ "void"));
TYPE_NAME (lai->primitive_type_vector [ada_primitive_type_system_address])
= "system__address";
+ /* Create the equivalent of the System.Storage_Elements.Storage_Offset
+ type. This is a signed integral type whose size is the same as
+ the size of addresses. */
+ {
+ unsigned int addr_length = TYPE_LENGTH
+ (lai->primitive_type_vector [ada_primitive_type_system_address]);
+
+ lai->primitive_type_vector [ada_primitive_type_storage_offset]
+ = arch_integer_type (gdbarch, addr_length * HOST_CHAR_BIT, 0,
+ "storage_offset");
+ }
+
lai->bool_type_symbol = NULL;
lai->bool_type_default = builtin->builtin_bool;
}
}
static int
-parse (void)
+parse (struct parser_state *ps)
{
warnings_issued = 0;
- return ada_parse ();
+ return ada_parse (ps);
}
static const struct exp_descriptor ada_exp_descriptor = {
ada_evaluate_subexp
};
-/* Implement the "la_get_symbol_name_cmp" language_defn method
- for Ada. */
+/* symbol_name_matcher_ftype adapter for wild_match. */
+
+static bool
+do_wild_match (const char *symbol_search_name,
+ const lookup_name_info &lookup_name,
+ completion_match_result *comp_match_res)
+{
+ return wild_match (symbol_search_name, ada_lookup_name (lookup_name));
+}
+
+/* symbol_name_matcher_ftype adapter for full_match. */
+
+static bool
+do_full_match (const char *symbol_search_name,
+ const lookup_name_info &lookup_name,
+ completion_match_result *comp_match_res)
+{
+ 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)
+{
+ const std::string &user_name = lookup_name.name ();
+
+ if (user_name[0] == '<')
+ {
+ if (user_name.back () == '>')
+ m_encoded_name = user_name.substr (1, user_name.size () - 2);
+ else
+ m_encoded_name = user_name.substr (1, user_name.size () - 1);
+ m_encoded_p = true;
+ m_verbatim_p = true;
+ m_wild_match_p = false;
+ m_standard_p = false;
+ }
+ else
+ {
+ m_verbatim_p = false;
+
+ m_encoded_p = user_name.find ("__") != std::string::npos;
+
+ if (!m_encoded_p)
+ {
+ const char *folded = ada_fold_name (user_name.c_str ());
+ const char *encoded = ada_encode_1 (folded, false);
+ if (encoded != NULL)
+ m_encoded_name = encoded;
+ else
+ m_encoded_name = user_name;
+ }
+ else
+ m_encoded_name = user_name;
+
+ /* Handle the 'package Standard' special case. See description
+ of m_standard_p. */
+ if (startswith (m_encoded_name.c_str (), "standard__"))
+ {
+ m_encoded_name = m_encoded_name.substr (sizeof ("standard__") - 1);
+ m_standard_p = true;
+ }
+ else
+ m_standard_p = false;
+
+ /* If the name contains a ".", then the user is entering a fully
+ qualified entity name, and the match must not be done in wild
+ mode. Similarly, if the user wants to complete what looks
+ like an encoded name, the match must not be done in wild
+ mode. Also, in the standard__ special case always do
+ non-wild matching. */
+ m_wild_match_p
+ = (lookup_name.match_type () != symbol_name_match_type::FULL
+ && !m_encoded_p
+ && !m_standard_p
+ && user_name.find ('.') == std::string::npos);
+ }
+}
+
+/* symbol_name_matcher_ftype method for Ada. This only handles
+ completion mode. */
+
+static bool
+ada_symbol_name_matches (const char *symbol_search_name,
+ const lookup_name_info &lookup_name,
+ completion_match_result *comp_match_res)
+{
+ return lookup_name.ada ().matches (symbol_search_name,
+ lookup_name.match_type (),
+ comp_match_res);
+}
+
+/* A name matcher that matches the symbol name exactly, with
+ strcmp. */
+
+static bool
+literal_symbol_name_matcher (const char *symbol_search_name,
+ const lookup_name_info &lookup_name,
+ completion_match_result *comp_match_res)
+{
+ const std::string &name = lookup_name.name ();
+
+ int cmp = (lookup_name.completion_mode ()
+ ? strncmp (symbol_search_name, name.c_str (), name.size ())
+ : strcmp (symbol_search_name, name.c_str ()));
+ if (cmp == 0)
+ {
+ if (comp_match_res != NULL)
+ comp_match_res->set_match (symbol_search_name);
+ return true;
+ }
+ else
+ return false;
+}
-static symbol_name_cmp_ftype
-ada_get_symbol_name_cmp (const char *lookup_name)
+/* Implement the "la_get_symbol_name_matcher" language_defn method for
+ Ada. */
+
+static symbol_name_matcher_ftype *
+ada_get_symbol_name_matcher (const lookup_name_info &lookup_name)
{
- if (should_use_wild_match (lookup_name))
- return wild_match;
+ if (lookup_name.match_type () == symbol_name_match_type::SEARCH_NAME)
+ return literal_symbol_name_matcher;
+
+ if (lookup_name.completion_mode ())
+ return ada_symbol_name_matches;
else
- return compare_names;
+ {
+ 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;
+ }
}
/* Implement the "la_read_var_value" language_defn method for Ada. */
static struct value *
-ada_read_var_value (struct symbol *var, struct frame_info *frame)
+ada_read_var_value (struct symbol *var, const struct block *var_block,
+ struct frame_info *frame)
{
- struct block *frame_block = NULL;
- struct symbol *renaming_sym = NULL;
-
/* The only case where default_read_var_value is not sufficient
is when VAR is a renaming... */
- if (frame)
- frame_block = get_frame_block (frame, NULL);
- if (frame_block)
- renaming_sym = ada_find_renaming_symbol (var, frame_block);
- if (renaming_sym != NULL)
- return ada_read_renaming_var_value (renaming_sym, frame_block);
+ if (frame != nullptr)
+ {
+ const struct block *frame_block = get_frame_block (frame, NULL);
+ if (frame_block != nullptr && ada_is_renaming_symbol (var))
+ return ada_read_renaming_var_value (var, frame_block);
+ }
/* This is a typical case where we expect the default_read_var_value
function to work. */
- return default_read_var_value (var, frame);
+ return default_read_var_value (var, var_block, frame);
}
-const struct language_defn ada_language_defn = {
+static const char *ada_extensions[] =
+{
+ ".adb", ".ads", ".a", ".ada", ".dg", NULL
+};
+
+extern const struct language_defn ada_language_defn = {
"ada", /* Language name */
"Ada",
language_ada,
that's not quite what this means. */
array_row_major,
macro_expansion_no,
+ ada_extensions,
&ada_exp_descriptor,
parse,
- ada_error,
resolve,
ada_printchar, /* Print a character constant */
ada_printstr, /* Function to print string constant */
ada_read_var_value, /* la_read_var_value */
NULL, /* Language specific skip_trampoline */
NULL, /* name_of_this */
+ true, /* la_store_sym_names_in_linkage_form_p */
ada_lookup_symbol_nonlocal, /* Looking up non-local symbols. */
basic_lookup_transparent_type, /* lookup_transparent_type */
ada_la_decode, /* Language specific symbol demangler */
+ ada_sniff_from_mangled_name,
NULL, /* Language specific
class_name_from_physname */
ada_op_print_tab, /* expression operators for printing */
0, /* c-style arrays */
1, /* String lower bound */
ada_get_gdb_completer_word_break_characters,
- ada_make_symbol_completion_list,
+ ada_collect_symbol_completion_matches,
ada_language_arch_info,
ada_print_array_index,
default_pass_by_reference,
- c_get_string,
- ada_get_symbol_name_cmp, /* la_get_symbol_name_cmp */
+ ada_watch_location_expression,
+ ada_get_symbol_name_matcher, /* la_get_symbol_name_matcher */
ada_iterate_over_symbols,
+ default_search_name_hash,
&ada_varobj_ops,
- LANG_MAGIC
+ NULL,
+ NULL,
+ ada_is_string_type,
+ "(...)" /* la_struct_too_deep_ellipsis */
};
-/* Provide a prototype to silence -Wmissing-prototypes. */
-extern initialize_file_ftype _initialize_ada_language;
-
/* Command-list for the "set/show ada" prefix command. */
static struct cmd_list_element *set_ada_list;
static struct cmd_list_element *show_ada_list;
/* Implement the "set ada" prefix command. */
static void
-set_ada_command (char *arg, int from_tty)
+set_ada_command (const char *arg, int from_tty)
{
printf_unfiltered (_(\
"\"set ada\" must be followed by the name of a setting.\n"));
- help_list (set_ada_list, "set ada ", -1, gdb_stdout);
+ help_list (set_ada_list, "set ada ", all_commands, gdb_stdout);
}
/* Implement the "show ada" prefix command. */
static void
-show_ada_command (char *args, int from_tty)
+show_ada_command (const char *args, int from_tty)
{
cmd_show_list (show_ada_list, from_tty, "");
}
ops = &catch_exception_breakpoint_ops;
*ops = bkpt_breakpoint_ops;
- ops->dtor = dtor_catch_exception;
- ops->allocate_location = allocate_location_catch_exception;
- ops->re_set = re_set_catch_exception;
- ops->check_status = check_status_catch_exception;
- ops->print_it = print_it_catch_exception;
- ops->print_one = print_one_catch_exception;
- ops->print_mention = print_mention_catch_exception;
- ops->print_recreate = print_recreate_catch_exception;
+ ops->allocate_location = allocate_location_exception;
+ ops->re_set = re_set_exception;
+ ops->check_status = check_status_exception;
+ ops->print_it = print_it_exception;
+ ops->print_one = print_one_exception;
+ ops->print_mention = print_mention_exception;
+ ops->print_recreate = print_recreate_exception;
ops = &catch_exception_unhandled_breakpoint_ops;
*ops = bkpt_breakpoint_ops;
- ops->dtor = dtor_catch_exception_unhandled;
- ops->allocate_location = allocate_location_catch_exception_unhandled;
- ops->re_set = re_set_catch_exception_unhandled;
- ops->check_status = check_status_catch_exception_unhandled;
- ops->print_it = print_it_catch_exception_unhandled;
- ops->print_one = print_one_catch_exception_unhandled;
- ops->print_mention = print_mention_catch_exception_unhandled;
- ops->print_recreate = print_recreate_catch_exception_unhandled;
+ ops->allocate_location = allocate_location_exception;
+ ops->re_set = re_set_exception;
+ ops->check_status = check_status_exception;
+ ops->print_it = print_it_exception;
+ ops->print_one = print_one_exception;
+ ops->print_mention = print_mention_exception;
+ ops->print_recreate = print_recreate_exception;
ops = &catch_assert_breakpoint_ops;
*ops = bkpt_breakpoint_ops;
- ops->dtor = dtor_catch_assert;
- ops->allocate_location = allocate_location_catch_assert;
- ops->re_set = re_set_catch_assert;
- ops->check_status = check_status_catch_assert;
- ops->print_it = print_it_catch_assert;
- ops->print_one = print_one_catch_assert;
- ops->print_mention = print_mention_catch_assert;
- ops->print_recreate = print_recreate_catch_assert;
+ ops->allocate_location = allocate_location_exception;
+ ops->re_set = re_set_exception;
+ ops->check_status = check_status_exception;
+ ops->print_it = print_it_exception;
+ ops->print_one = print_one_exception;
+ ops->print_mention = print_mention_exception;
+ ops->print_recreate = print_recreate_exception;
+
+ ops = &catch_handlers_breakpoint_ops;
+ *ops = bkpt_breakpoint_ops;
+ ops->allocate_location = allocate_location_exception;
+ ops->re_set = re_set_exception;
+ ops->check_status = check_status_exception;
+ ops->print_it = print_it_exception;
+ ops->print_one = print_one_exception;
+ ops->print_mention = print_mention_exception;
+ ops->print_recreate = print_recreate_exception;
}
/* This module's 'new_objfile' observer. */
void
_initialize_ada_language (void)
{
- add_language (&ada_language_defn);
-
initialize_ada_catchpoint_ops ();
add_prefix_cmd ("ada", no_class, set_ada_command,
- _("Prefix command for changing Ada-specfic settings"),
+ _("Prefix command for changing Ada-specific settings."),
&set_ada_list, "set ada ", 0, &setlist);
add_prefix_cmd ("ada", no_class, show_ada_command,
add_setshow_boolean_cmd ("trust-PAD-over-XVS", class_obscure,
&trust_pad_over_xvs, _("\
-Enable or disable an optimization trusting PAD types over XVS types"), _("\
-Show whether an optimization trusting PAD types over XVS types is activated"),
+Enable or disable an optimization trusting PAD types over XVS types."), _("\
+Show whether an optimization trusting PAD types over XVS types is activated."),
_("\
This is related to the encoding used by the GNAT compiler. The debugger\n\
should normally trust the contents of PAD types, but certain older versions\n\
this option to \"off\" unless necessary."),
NULL, NULL, &set_ada_list, &show_ada_list);
+ add_setshow_boolean_cmd ("print-signatures", class_vars,
+ &print_signatures, _("\
+Enable or disable the output of formal and return types for functions in the \
+overloads selection menu."), _("\
+Show whether the output of formal and return types for functions in the \
+overloads selection menu is activated."),
+ NULL, NULL, NULL, &set_ada_list, &show_ada_list);
+
add_catch_command ("exception", _("\
Catch Ada exceptions, when raised.\n\
-With an argument, catch only exceptions with the given name."),
+Usage: catch exception [ARG] [if CONDITION]\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.\n\
+CONDITION is a boolean expression that is evaluated to see whether the\n\
+exception should cause a stop."),
catch_ada_exception_command,
- NULL,
+ catch_ada_completer,
+ CATCH_PERMANENT,
+ CATCH_TEMPORARY);
+
+ add_catch_command ("handlers", _("\
+Catch Ada exceptions, when handled.\n\
+Usage: catch handlers [ARG] [if CONDITION]\n\
+Without any argument, stop when any Ada exception is handled.\n\
+With an argument, catch only exceptions with the given name.\n\
+CONDITION is a boolean expression that is evaluated to see whether the\n\
+exception should cause a stop."),
+ catch_ada_handlers_command,
+ catch_ada_completer,
CATCH_PERMANENT,
CATCH_TEMPORARY);
add_catch_command ("assert", _("\
Catch failed Ada assertions, when raised.\n\
-With an argument, catch only exceptions with the given name."),
+Usage: catch assert [if CONDITION]\n\
+CONDITION is a boolean expression that is evaluated to see whether the\n\
+exception should cause a stop."),
catch_assert_command,
NULL,
CATCH_PERMANENT,
CATCH_TEMPORARY);
varsize_limit = 65536;
+ add_setshow_uinteger_cmd ("varsize-limit", class_support,
+ &varsize_limit, _("\
+Set the maximum number of bytes allowed in a variable-size object."), _("\
+Show the maximum number of bytes allowed in a variable-size object."), _("\
+Attempts to access an object whose size is not a compile-time constant\n\
+and exceeds this limit will cause an error."),
+ NULL, NULL, &setlist, &showlist);
add_info ("exceptions", info_exceptions_command,
_("\
List all Ada exception names.\n\
+Usage: info exceptions [REGEXP]\n\
If a regular expression is passed as an argument, only those matching\n\
the regular expression are listed."));
0/*allow-unknown*/, &maintenance_set_cmdlist);
add_prefix_cmd ("ada", class_maintenance, maint_show_ada_cmd,
- _("Show Ada maintenance-related variables"),
+ _("Show Ada maintenance-related variables."),
&maint_show_ada_cmdlist, "maintenance show ada ",
0/*allow-unknown*/, &maintenance_show_cmdlist);
DWARF attribute."),
NULL, NULL, &maint_set_ada_cmdlist, &maint_show_ada_cmdlist);
- obstack_init (&symbol_list_obstack);
-
- decoded_names_store = htab_create_alloc
- (256, htab_hash_string, (int (*)(const void *, const void *)) streq,
- NULL, xcalloc, xfree);
+ decoded_names_store = htab_create_alloc (256, htab_hash_string, streq_hash,
+ NULL, xcalloc, xfree);
/* The ada-lang observers. */
- observer_attach_new_objfile (ada_new_objfile_observer);
- observer_attach_free_objfile (ada_free_objfile_observer);
- observer_attach_inferior_exit (ada_inferior_exit);
-
- /* Setup various context-specific data. */
- ada_inferior_data
- = register_inferior_data_with_cleanup (NULL, ada_inferior_data_cleanup);
- ada_pspace_data_handle
- = register_program_space_data_with_cleanup (NULL, ada_pspace_data_cleanup);
+ gdb::observers::new_objfile.attach (ada_new_objfile_observer);
+ gdb::observers::free_objfile.attach (ada_free_objfile_observer);
+ gdb::observers::inferior_exit.attach (ada_inferior_exit);
}