-/* Ada language support routines for GDB, the GNU debugger. Copyright
+/* Ada language support routines for GDB, the GNU debugger. Copyright (C)
- 1992, 1993, 1994, 1997, 1998, 1999, 2000, 2003, 2004, 2005 Free
- Software Foundation, Inc.
+ 1992, 1993, 1994, 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2007
+ Free Software Foundation, Inc.
-This file is part of GDB.
+ This file is part of GDB.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "infcall.h"
#include "dictionary.h"
#include "exceptions.h"
+#include "annotate.h"
+#include "valprint.h"
+#include "source.h"
+#include "observer.h"
#ifndef ADA_RETAIN_DOTS
#define ADA_RETAIN_DOTS 0
static void extract_string (CORE_ADDR addr, char *buf);
-static struct type *ada_create_fundamental_type (struct objfile *, int);
-
static void modify_general_field (char *, LONGEST, int, int);
static struct type *desc_base_type (struct type *);
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 *,
+ struct block *);
+
static struct type *ada_lookup_struct_elt_type (struct type *, char *,
int, int, int *);
struct objfile *);
static struct type *to_static_fixed_type (struct type *);
+static struct type *static_unwrap_type (struct type *type);
static struct value *unwrap_value (struct value *);
static struct value *value_subscript_packed (struct value *, int,
struct value **);
+static void move_bits (gdb_byte *, int, const gdb_byte *, int, int);
+
static struct value *coerce_unspec_val_to_type (struct value *,
struct type *);
struct type *);
static int find_struct_field (char *, struct type *, int,
- struct type **, int *, int *, int *);
+ struct type **, int *, int *, int *, int *);
static struct value *ada_to_fixed_value_create (struct type *, CORE_ADDR,
struct value *);
struct language_arch_info *);
static void check_size (const struct type *);
+
+static struct value *ada_index_struct_field (int, struct value *, int,
+ struct type *);
+
+static struct value *assign_aggregate (struct value *, struct value *,
+ struct expression *, int *, enum noside);
+
+static void aggregate_assign_from_choices (struct value *, struct value *,
+ struct expression *,
+ int *, LONGEST *, int *,
+ int, LONGEST, LONGEST);
+
+static void aggregate_assign_positional (struct value *, struct value *,
+ struct expression *,
+ int *, LONGEST *, int *, int,
+ LONGEST, LONGEST);
+
+
+static void aggregate_assign_others (struct value *, struct value *,
+ struct expression *,
+ int *, LONGEST *, int, LONGEST, LONGEST);
+
+
+static void add_component_interval (LONGEST, LONGEST, LONGEST *, int *, int);
+
+
+static struct value *ada_evaluate_subexp (struct type *, struct expression *,
+ int *, enum noside);
+
+static void ada_forward_operator_length (struct expression *, int, int *,
+ int *);
\f
static const char ADA_MAIN_PROGRAM_SYMBOL_NAME[]
= "__gnat_ada_main_program_name";
-/* The name of the runtime function called when an exception is raised. */
-static const char raise_sym_name[] = "__gnat_raise_nodefer_with_msg";
-
-/* The name of the runtime function called when an unhandled exception
- is raised. */
-static const char raise_unhandled_sym_name[] = "__gnat_unhandled_exception";
-
-/* The name of the runtime function called when an assert failure is
- raised. */
-static const char raise_assert_sym_name[] =
- "system__assertions__raise_assert_failure";
-
-/* When GDB stops on an unhandled exception, GDB will go up the stack until
- if finds a frame corresponding to this function, in order to extract the
- name of the exception that has been raised from one of the parameters. */
-static const char process_raise_exception_name[] =
- "ada__exceptions__process_raise_exception";
-
-/* A string that reflects the longest exception expression rewrite,
- aside from the exception name. */
-static const char longest_exception_template[] =
- "'__gnat_raise_nodefer_with_msg' if long_integer(e) = long_integer(&)";
-
/* Limit on the number of warnings to raise per expression evaluation. */
static int warning_limit = 2;
return ada_completer_word_break_characters;
}
+/* Print an array element index using the Ada syntax. */
+
+static void
+ada_print_array_index (struct value *index_value, struct ui_file *stream,
+ int format, enum val_prettyprint pretty)
+{
+ LA_VALUE_PRINT (index_value, stream, format, pretty);
+ fprintf_filtered (stream, " => ");
+}
+
/* Read the string located at ADDR from the inferior and store the
result into BUF. */
return fold_buffer;
}
-/* decode:
- 0. Discard trailing .{DIGIT}+ or trailing ___{DIGIT}+
- These are suffixes introduced by GNAT5 to nested subprogram
- names, and do not serve any purpose for the debugger.
- 1. Discard final __{DIGIT}+ or $({DIGIT}+(__{DIGIT}+)*)
- 2. Convert other instances of embedded "__" to `.'.
- 3. Discard leading _ada_.
- 4. Convert operator names to the appropriate quoted symbols.
- 5. Remove everything after first ___ if it is followed by
- 'X'.
- 6. Replace TK__ with __, and a trailing B or TKB with nothing.
- 7. Put symbols that should be suppressed in <...> brackets.
- 8. Remove trailing X[bn]* suffix (indicating names in package bodies).
+/* Return nonzero if C is either a digit or a lowercase alphabet character. */
+
+static int
+is_lower_alphanum (const char c)
+{
+ return (isdigit (c) || (isalpha (c) && islower (c)));
+}
+
+/* Remove either of these suffixes:
+ . .{DIGIT}+
+ . ${DIGIT}+
+ . ___{DIGIT}+
+ . __{DIGIT}+.
+ These are suffixes introduced by the compiler for entities such as
+ nested subprogram for instance, in order to avoid name clashes.
+ They do not serve any purpose for the debugger. */
+
+static void
+ada_remove_trailing_digits (const char *encoded, int *len)
+{
+ if (*len > 1 && isdigit (encoded[*len - 1]))
+ {
+ int i = *len - 2;
+ while (i > 0 && isdigit (encoded[i]))
+ i--;
+ if (i >= 0 && encoded[i] == '.')
+ *len = i;
+ else if (i >= 0 && encoded[i] == '$')
+ *len = i;
+ else if (i >= 2 && strncmp (encoded + i - 2, "___", 3) == 0)
+ *len = i - 2;
+ else if (i >= 1 && strncmp (encoded + i - 1, "__", 2) == 0)
+ *len = i - 1;
+ }
+}
+
+/* Remove the suffix introduced by the compiler for protected object
+ subprograms. */
+
+static void
+ada_remove_po_subprogram_suffix (const char *encoded, int *len)
+{
+ /* Remove trailing N. */
+
+ /* Protected entry subprograms are broken into two
+ separate subprograms: The first one is unprotected, and has
+ a 'N' suffix; the second is the protected version, and has
+ the 'P' suffix. The second calls the first one after handling
+ the protection. Since the P subprograms are internally generated,
+ we leave these names undecoded, giving the user a clue that this
+ entity is internal. */
+
+ if (*len > 1
+ && encoded[*len - 1] == 'N'
+ && (isdigit (encoded[*len - 2]) || islower (encoded[*len - 2])))
+ *len = *len - 1;
+}
+
+/* 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 demangling, the original string pointer
+ If the string is unchanged by decoding, the original string pointer
is returned. */
const char *
static char *decoding_buffer = NULL;
static size_t decoding_buffer_size = 0;
+ /* 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)
encoded += 5;
+ /* If the name starts with '_', then it is not a properly encoded
+ name, so do not attempt to decode it. Similarly, if the name
+ starts with '<', the name should not be decoded. */
if (encoded[0] == '_' || encoded[0] == '<')
goto Suppress;
- /* Remove trailing .{DIGIT}+ or ___{DIGIT}+. */
len0 = strlen (encoded);
- if (len0 > 1 && isdigit (encoded[len0 - 1]))
- {
- i = len0 - 2;
- while (i > 0 && isdigit (encoded[i]))
- i--;
- if (i >= 0 && encoded[i] == '.')
- len0 = i;
- else if (i >= 2 && strncmp (encoded + i - 2, "___", 3) == 0)
- len0 = i - 2;
- }
+
+ ada_remove_trailing_digits (encoded, &len0);
+ ada_remove_po_subprogram_suffix (encoded, &len0);
/* Remove the ___X.* suffix if present. Do not forget to verify that
the suffix is located before the current "end" of ENCODED. We want
goto Suppress;
}
+ /* Remove any trailing TKB suffix. It tells us that this symbol
+ 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)
len0 -= 3;
+ /* 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)
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;
+ /* Remove trailing __{digit}+ or trailing ${digit}+. */
+
if (len0 > 1 && isdigit (encoded[len0 - 1]))
{
i = len0 - 2;
len0 = i;
}
+ /* The first few characters that are not alphabetic are not part
+ of any encoding we use, so we can copy them over verbatim. */
+
for (i = 0, j = 0; i < len0 && !isalpha (encoded[i]); i += 1, j += 1)
decoded[j] = encoded[i];
at_start_name = 1;
while (i < len0)
{
+ /* Is this a symbol function? */
if (at_start_name && encoded[i] == 'O')
{
int k;
}
at_start_name = 0;
+ /* Replace "TK__" with "__", which will eventually be translated
+ into "." (just below). */
+
if (i < len0 - 4 && strncmp (encoded + i, "TK__", 4) == 0)
i += 2;
+
+ /* Replace "__B_{DIGITS}+__" sequences by "__", which will eventually
+ be translated into "." (just below). These are internal names
+ generated for anonymous blocks inside which our symbol is nested. */
+
+ if (len0 - i > 5 && encoded [i] == '_' && encoded [i+1] == '_'
+ && encoded [i+2] == 'B' && encoded [i+3] == '_'
+ && isdigit (encoded [i+4]))
+ {
+ int k = i + 5;
+
+ while (k < len0 && isdigit (encoded[k]))
+ k++; /* Skip any extra digit. */
+
+ /* Double-check that the "__B_{DIGITS}+" sequence we found
+ is indeed followed by "__". */
+ if (len0 - k > 2 && encoded [k] == '_' && encoded [k+1] == '_')
+ i = k;
+ }
+
+ /* Remove _E{DIGITS}+[sb] */
+
+ /* Just as for protected object subprograms, there are 2 categories
+ of subprograms created by the compiler for each entry. The first
+ one implements the actual entry code, and has a suffix following
+ the convention above; the second one implements the barrier and
+ uses the same convention as above, except that the 'E' is replaced
+ by a 'B'.
+
+ Just as above, we do not decode the name of barrier functions
+ to give the user a clue that the code he is debugging has been
+ internally generated. */
+
+ if (len0 - i > 3 && encoded [i] == '_' && encoded[i+1] == 'E'
+ && isdigit (encoded[i+2]))
+ {
+ int k = i + 3;
+
+ while (k < len0 && isdigit (encoded[k]))
+ k++;
+
+ if (k < len0
+ && (encoded[k] == 'b' || encoded[k] == 's'))
+ {
+ k++;
+ /* Just as an extra precaution, make sure that if this
+ suffix is followed by anything else, it is a '_'.
+ Otherwise, we matched this sequence by accident. */
+ if (k == len0
+ || (k < len0 && encoded[k] == '_'))
+ i = k;
+ }
+ }
+
+ /* Remove trailing "N" in [a-z0-9]+N__. The N is added by
+ the GNAT front-end in protected object subprograms. */
+
+ if (i < len0 + 3
+ && encoded[i] == 'N' && encoded[i+1] == '_' && encoded[i+2] == '_')
+ {
+ /* Backtrack a bit up until we reach either the begining of
+ the encoded name, or "__". Make sure that we only find
+ digits or lowercase characters. */
+ const char *ptr = encoded + i - 1;
+
+ while (ptr >= encoded && is_lower_alphanum (ptr[0]))
+ ptr--;
+ if (ptr < encoded
+ || (ptr > encoded && ptr[0] == '_' && ptr[-1] == '_'))
+ i++;
+ }
+
if (encoded[i] == 'X' && i != 0 && isalnum (encoded[i - 1]))
{
+ /* This is a X[bn]* sequence not separated from the previous
+ part of the name with a non-alpha-numeric character (in other
+ words, immediately following an alpha-numeric character), then
+ verify that it is placed at the end of the encoded name. If
+ not, then the encoding is not valid and we should abort the
+ decoding. Otherwise, just skip it, it is used in body-nested
+ package names. */
do
i += 1;
while (i < len0 && (encoded[i] == 'b' || encoded[i] == 'n'));
else if (!ADA_RETAIN_DOTS
&& i < len0 - 2 && encoded[i] == '_' && encoded[i + 1] == '_')
{
+ /* Replace '__' by '.'. */
decoded[j] = '.';
at_start_name = 1;
i += 2;
}
else
{
+ /* It's a character part of the decoded name, so just copy it
+ over. */
decoded[j] = encoded[i];
i += 1;
j += 1;
}
decoded[j] = '\000';
+ /* 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)
if (isupper (decoded[i]) || decoded[i] == ' ')
goto Suppress;
desc_bounds_type (thin_descriptor_type (type));
LONGEST addr;
- if (desc_bounds_type == NULL)
+ if (bounds_type == NULL)
error (_("Bad GNAT array descriptor"));
/* NOTE: The following calculation is not really kosher, but
|| ada_is_array_descriptor_type (type));
}
+/* Non-zero iff TYPE represents any kind of array in Ada, or a pointer
+ * to one. */
+
+int
+ada_is_array_type (struct type *type)
+{
+ while (type != NULL
+ && (TYPE_CODE (type) == TYPE_CODE_PTR
+ || TYPE_CODE (type) == TYPE_CODE_REF))
+ type = TYPE_TARGET_TYPE (type);
+ return ada_is_direct_array_type (type);
+}
+
/* Non-zero iff TYPE is a simple array type or pointer to one. */
int
arity -= 1;
create_range_type (range_type, value_type (low),
- (int) value_as_long (low),
- (int) value_as_long (high));
+ 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);
}
struct value *arrVal = ada_coerce_to_simple_array_ptr (arr);
if (arrVal == NULL)
error (_("Bounds unavailable for null array pointer."));
+ check_size (TYPE_TARGET_TYPE (value_type (arrVal)));
return value_ind (arrVal);
}
else if (ada_is_packed_array_type (value_type (arr)))
{
struct symbol *sym;
struct block **blocks;
- const char *raw_name = ada_type_name (ada_check_typedef (type));
- char *name = (char *) alloca (strlen (raw_name) + 1);
- char *tail = strstr (raw_name, "___XP");
+ char *raw_name = ada_type_name (ada_check_typedef (type));
+ char *name;
+ char *tail;
struct type *shadow_type;
long bits;
int i, n;
+ if (!raw_name)
+ raw_name = ada_type_name (desc_base_type (type));
+
+ if (!raw_name)
+ return NULL;
+
+ name = (char *) alloca (strlen (raw_name) + 1);
+ tail = strstr (raw_name, "___XP");
type = desc_base_type (type);
memcpy (name, raw_name, tail - raw_name);
v = ada_value_primitive_packed_val (arr, NULL, elt_off, bit_off,
bits, elt_type);
- if (VALUE_LVAL (arr) == lval_internalvar)
- VALUE_LVAL (v) = lval_internalvar_component;
- else
- VALUE_LVAL (v) = VALUE_LVAL (arr);
return v;
}
(HOST_CHAR_BIT - bit_size % HOST_CHAR_BIT) % HOST_CHAR_BIT;
/* ... And are placed at the beginning (most-significant) bytes
of the target. */
- targ = src;
+ targ = (bit_size + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT - 1;
break;
default:
accumSize = 0;
}
}
-
/* Store the contents of FROMVAL into the location of TOVAL.
Return a new value with the location of TOVAL and contents of
FROMVAL. Handles assignment into packed fields that have
struct type *type = value_type (toval);
int bits = value_bitsize (toval);
+ toval = ada_coerce_ref (toval);
+ fromval = ada_coerce_ref (fromval);
+
+ if (ada_is_direct_array_type (value_type (toval)))
+ toval = ada_coerce_to_simple_array (toval);
+ if (ada_is_direct_array_type (value_type (fromval)))
+ fromval = ada_coerce_to_simple_array (fromval);
+
if (!deprecated_value_modifiable (toval))
error (_("Left operand of assignment is not a modifiable lvalue."));
- toval = coerce_ref (toval);
-
if (VALUE_LVAL (toval) == lval_memory
&& bits > 0
&& (TYPE_CODE (type) == TYPE_CODE_FLT
+ bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
char *buffer = (char *) alloca (len);
struct value *val;
+ CORE_ADDR to_addr = VALUE_ADDRESS (toval) + value_offset (toval);
if (TYPE_CODE (type) == TYPE_CODE_FLT)
fromval = value_cast (type, fromval);
- read_memory (VALUE_ADDRESS (toval) + value_offset (toval), buffer, len);
+ read_memory (to_addr, buffer, len);
if (BITS_BIG_ENDIAN)
move_bits (buffer, value_bitpos (toval),
value_contents (fromval),
else
move_bits (buffer, value_bitpos (toval), value_contents (fromval),
0, bits);
- write_memory (VALUE_ADDRESS (toval) + value_offset (toval), buffer,
- len);
-
+ write_memory (to_addr, buffer, len);
+ if (deprecated_memory_changed_hook)
+ deprecated_memory_changed_hook (to_addr, len);
+
val = value_copy (toval);
memcpy (value_contents_raw (val), value_contents (fromval),
TYPE_LENGTH (type));
}
+/* 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. */
+static void
+value_assign_to_component (struct value *container, struct value *component,
+ struct value *val)
+{
+ LONGEST offset_in_container =
+ (LONGEST) (VALUE_ADDRESS (component) + value_offset (component)
+ - VALUE_ADDRESS (container) - value_offset (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)
+ bits = TARGET_CHAR_BIT * TYPE_LENGTH (value_type (component));
+ else
+ bits = value_bitsize (component);
+
+ if (BITS_BIG_ENDIAN)
+ 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);
+ else
+ move_bits (value_contents_writeable (container) + offset_in_container,
+ value_bitpos (container) + bit_offset_in_container,
+ value_contents (val), 0, bits);
+}
+
/* 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. */
bounds type. It works for other arrays with bounds supplied by
run-time quantities other than discriminants. */
-LONGEST
+static LONGEST
ada_array_bound_from_type (struct type * arr_type, int n, int which,
struct type ** typep)
{
index_type_desc = ada_find_parallel_type (type, "___XA");
if (index_type_desc == NULL)
{
- struct type *range_type;
struct type *index_type;
while (n > 1)
n -= 1;
}
- range_type = TYPE_INDEX_TYPE (type);
- index_type = TYPE_TARGET_TYPE (range_type);
- if (TYPE_CODE (index_type) == TYPE_CODE_UNDEF)
- index_type = builtin_type_long;
+ index_type = TYPE_INDEX_TYPE (type);
if (typep != NULL)
*typep = index_type;
+
+ /* The index type is either a range type or an enumerated type.
+ For the range type, we have some macros that allow us to
+ extract the value of the low and high bounds. But they
+ do now work for enumerated types. The expressions used
+ below work for both range and enum types. */
return
(LONGEST) (which == 0
- ? TYPE_LOW_BOUND (range_type)
- : TYPE_HIGH_BOUND (range_type));
+ ? TYPE_FIELD_BITPOS (index_type, 0)
+ : TYPE_FIELD_BITPOS (index_type,
+ TYPE_NFIELDS (index_type) - 1));
}
else
{
struct type *index_type =
to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, n - 1),
NULL, TYPE_OBJFILE (arr_type));
+
if (typep != NULL)
- *typep = TYPE_TARGET_TYPE (index_type);
+ *typep = index_type;
+
return
(LONGEST) (which == 0
? TYPE_LOW_BOUND (index_type)
}
/* Given that arr is an array value, returns the lower bound of the
- nth index (numbering from 1) if which is 0, and the upper bound if
- which is 1. This routine will also work for arrays with bounds
+ nth index (numbering from 1) if WHICH is 0, and the upper bound if
+ WHICH is 1. This routine will also work for arrays with bounds
supplied by run-time quantities other than discriminants. */
struct value *
enum exp_opcode op = (*expp)->elts[pc].opcode;
struct value **argvec; /* Vector of operand types (alloca'ed). */
int nargs; /* Number of operands. */
+ int oplen;
argvec = NULL;
nargs = 0;
exp = *expp;
- /* Pass one: resolve operands, saving their types and updating *pos. */
+ /* Pass one: resolve operands, saving their types and updating *pos,
+ if needed. */
switch (op)
{
case OP_FUNCALL:
nargs = longest_to_int (exp->elts[pc + 1].longconst);
break;
- case UNOP_QUAL:
- *pos += 3;
- resolve_subexp (expp, pos, 1, exp->elts[pc + 1].type);
- break;
-
case UNOP_ADDR:
*pos += 1;
resolve_subexp (expp, pos, 0, NULL);
break;
- case OP_ATR_MODULUS:
- *pos += 4;
+ case UNOP_QUAL:
+ *pos += 3;
+ resolve_subexp (expp, pos, 1, exp->elts[pc + 1].type);
break;
+ case OP_ATR_MODULUS:
case OP_ATR_SIZE:
case OP_ATR_TAG:
- *pos += 1;
- nargs = 1;
- break;
-
case OP_ATR_FIRST:
case OP_ATR_LAST:
case OP_ATR_LENGTH:
case OP_ATR_POS:
case OP_ATR_VAL:
- *pos += 1;
- nargs = 2;
- break;
-
case OP_ATR_MIN:
case OP_ATR_MAX:
- *pos += 1;
- nargs = 3;
+ case TERNOP_IN_RANGE:
+ case BINOP_IN_BOUNDS:
+ case UNOP_IN_RANGE:
+ case OP_AGGREGATE:
+ case OP_OTHERS:
+ case OP_CHOICES:
+ case OP_POSITIONAL:
+ case OP_DISCRETE_RANGE:
+ case OP_NAME:
+ ada_forward_operator_length (exp, pc, &oplen, &nargs);
+ *pos += oplen;
break;
case BINOP_ASSIGN:
}
case UNOP_CAST:
- case UNOP_IN_RANGE:
*pos += 3;
nargs = 1;
break;
case OP_TYPE:
case OP_BOOL:
case OP_LAST:
- case OP_REGISTER:
case OP_INTERNALVAR:
*pos += 3;
break;
nargs = 1;
break;
- case STRUCTOP_STRUCT:
+ case OP_REGISTER:
*pos += 4 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1);
- nargs = 1;
break;
- case OP_STRING:
- (*pos) += 3
- + BYTES_TO_EXP_ELEM (longest_to_int (exp->elts[pc + 1].longconst)
- + 1);
+ case STRUCTOP_STRUCT:
+ *pos += 4 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1);
+ nargs = 1;
break;
case TERNOP_SLICE:
- case TERNOP_IN_RANGE:
*pos += 1;
nargs = 3;
break;
- case BINOP_IN_BOUNDS:
- *pos += 3;
- nargs = 2;
+ case OP_STRING:
break;
default:
break;
case OP_TYPE:
+ case OP_REGISTER:
return NULL;
}
return (!(scalar_type_p (type0) && scalar_type_p (type1)));
case BINOP_CONCAT:
- return
- ((TYPE_CODE (type0) != TYPE_CODE_ARRAY
- && (TYPE_CODE (type0) != TYPE_CODE_PTR
- || TYPE_CODE (TYPE_TARGET_TYPE (type0)) != TYPE_CODE_ARRAY))
- || (TYPE_CODE (type1) != TYPE_CODE_ARRAY
- && (TYPE_CODE (type1) != TYPE_CODE_PTR
- || (TYPE_CODE (TYPE_TARGET_TYPE (type1))
- != TYPE_CODE_ARRAY))));
+ return !ada_is_array_type (type0) || !ada_is_array_type (type1);
case BINOP_EXP:
return (!(numeric_type_p (type0) && integer_type_p (type1)));
\f
/* Renaming */
-/* NOTE: In the following, we assume that a renaming type's name may
- have an ___XD suffix. It would be nice if this went away at some
- point. */
-
-/* If TYPE encodes a renaming, returns the renaming suffix, which
- is XR for an object renaming, XRP for a procedure renaming, XRE for
- an exception renaming, and XRS for a subprogram renaming. Returns
- NULL if NAME encodes none of these. */
-
-const char *
-ada_renaming_type (struct type *type)
-{
- if (type != NULL && TYPE_CODE (type) == TYPE_CODE_ENUM)
+/* NOTES:
+
+ 1. In the following, we assume that a renaming type's name may
+ have an ___XD suffix. It would be nice if this went away at some
+ point.
+ 2. We handle both the (old) purely type-based representation of
+ renamings and the (new) variable-based encoding. At some point,
+ it is devoutly to be hoped that the former goes away
+ (FIXME: hilfinger-2007-07-09).
+ 3. Subprogram renamings are not implemented, although the XRS
+ suffix is recognized (FIXME: hilfinger-2007-07-09). */
+
+/* If SYM encodes a renaming,
+
+ <renaming> renames <renamed entity>,
+
+ sets *LEN to the length of the renamed entity's name,
+ *RENAMED_ENTITY to that name (not null-terminated), and *RENAMING_EXPR to
+ the string describing the subcomponent selected from the renamed
+ entity. Returns ADA_NOT_RENAMING if SYM does not encode a renaming
+ (in which case, the values of *RENAMED_ENTITY, *LEN, and *RENAMING_EXPR
+ are undefined). Otherwise, returns a value indicating the category
+ of entity renamed: an object (ADA_OBJECT_RENAMING), exception
+ (ADA_EXCEPTION_RENAMING), package (ADA_PACKAGE_RENAMING), or
+ subprogram (ADA_SUBPROGRAM_RENAMING). Does no allocation; the
+ strings returned in *RENAMED_ENTITY and *RENAMING_EXPR should not be
+ deallocated. The values of RENAMED_ENTITY, LEN, or RENAMING_EXPR
+ may be NULL, in which case they are not assigned.
+
+ [Currently, however, GCC does not generate subprogram renamings.] */
+
+enum ada_renaming_category
+ada_parse_renaming (struct symbol *sym,
+ const char **renamed_entity, int *len,
+ const char **renaming_expr)
+{
+ enum ada_renaming_category kind;
+ const char *info;
+ const char *suffix;
+
+ if (sym == NULL)
+ return ADA_NOT_RENAMING;
+ switch (SYMBOL_CLASS (sym))
{
- const char *name = type_name_no_tag (type);
- const char *suffix = (name == NULL) ? NULL : strstr (name, "___XR");
- if (suffix == NULL
- || (suffix[5] != '\000' && strchr ("PES_", suffix[5]) == NULL))
- return NULL;
- else
- return suffix + 3;
+ 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");
+ if (info == NULL)
+ return ADA_NOT_RENAMING;
+ switch (info[5])
+ {
+ case '_':
+ kind = ADA_OBJECT_RENAMING;
+ info += 6;
+ break;
+ case 'E':
+ kind = ADA_EXCEPTION_RENAMING;
+ info += 7;
+ break;
+ case 'P':
+ kind = ADA_PACKAGE_RENAMING;
+ info += 7;
+ break;
+ case 'S':
+ kind = ADA_SUBPROGRAM_RENAMING;
+ info += 7;
+ break;
+ default:
+ return ADA_NOT_RENAMING;
+ }
}
- else
- return NULL;
-}
-
-/* Return non-zero iff SYM encodes an object renaming. */
-
-int
-ada_is_object_renaming (struct symbol *sym)
-{
- const char *renaming_type = ada_renaming_type (SYMBOL_TYPE (sym));
- return renaming_type != NULL
- && (renaming_type[2] == '\0' || renaming_type[2] == '_');
-}
-
-/* Assuming that SYM encodes a non-object renaming, returns the original
- name of the renamed entity. The name is good until the end of
- parsing. */
-char *
-ada_simple_renamed_entity (struct symbol *sym)
-{
- struct type *type;
- const char *raw_name;
- int len;
- char *result;
+ if (renamed_entity != NULL)
+ *renamed_entity = info;
+ suffix = strstr (info, "___XE");
+ if (suffix == NULL || suffix == info)
+ return ADA_NOT_RENAMING;
+ if (len != NULL)
+ *len = strlen (info) - strlen (suffix);
+ suffix += 5;
+ if (renaming_expr != NULL)
+ *renaming_expr = suffix;
+ 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)
+{
+ enum ada_renaming_category kind;
+ const char *name;
+ const char *info;
+ const char *suffix;
- type = SYMBOL_TYPE (sym);
- if (type == NULL || TYPE_NFIELDS (type) < 1)
- error (_("Improperly encoded renaming."));
+ if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM
+ || TYPE_NFIELDS (type) != 1)
+ return ADA_NOT_RENAMING;
- raw_name = TYPE_FIELD_NAME (type, 0);
- len = (raw_name == NULL ? 0 : strlen (raw_name)) - 5;
- if (len <= 0)
- error (_("Improperly encoded renaming."));
+ 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])
+ {
+ 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;
+ }
+
+ 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;
+}
- result = xmalloc (len + 1);
- strncpy (result, raw_name, len);
- result[len] = '\000';
- return result;
-}
\f
/* Evaluation: Function Calls */
/* The following is taken from the structure-return code in
call_function_by_hand. FIXME: Therefore, some refactoring seems
indicated. */
- if (INNER_THAN (1, 2))
+ if (gdbarch_inner_than (current_gdbarch, 1, 2))
{
/* Stack grows downward. Align SP and VALUE_ADDRESS (val) after
reserving sufficient space. */
if (gdbarch_frame_align_p (current_gdbarch))
*sp = gdbarch_frame_align (current_gdbarch, *sp);
}
+ VALUE_LVAL (val) = lval_memory;
write_memory (VALUE_ADDRESS (val), value_contents_raw (val), len);
}
allocating any necessary descriptors (fat pointers), or copies of
values not residing in memory, updating it as needed. */
-static struct value *
-convert_actual (struct value *actual, struct type *formal_type0,
- CORE_ADDR *sp)
+struct value *
+ada_convert_actual (struct value *actual, struct type *formal_type0,
+ CORE_ADDR *sp)
{
struct type *actual_type = ada_check_typedef (value_type (actual));
struct type *formal_type = ada_check_typedef (formal_type0);
if (ada_is_array_descriptor_type (formal_target)
&& TYPE_CODE (actual_target) == TYPE_CODE_ARRAY)
return make_array_descriptor (formal_type, actual, sp);
- else if (TYPE_CODE (formal_type) == TYPE_CODE_PTR)
+ else if (TYPE_CODE (formal_type) == TYPE_CODE_PTR
+ || TYPE_CODE (formal_type) == TYPE_CODE_REF)
{
+ struct value *result;
if (TYPE_CODE (formal_target) == TYPE_CODE_ARRAY
&& ada_is_array_descriptor_type (actual_target))
- return desc_data (actual);
+ result = desc_data (actual);
else if (TYPE_CODE (actual_type) != TYPE_CODE_PTR)
{
if (VALUE_LVAL (actual) != lval_memory)
TYPE_LENGTH (actual_type));
actual = ensure_lval (val, sp);
}
- return value_addr (actual);
+ result = value_addr (actual);
}
+ else
+ return actual;
+ return value_cast_pointers (formal_type, result);
}
else if (TYPE_CODE (actual_type) == TYPE_CODE_PTR)
return ada_value_ind (actual);
else
return descriptor;
}
-
-
-/* Assuming a dummy frame has been established on the target, perform any
- conversions needed for calling function FUNC on the NARGS actual
- parameters in ARGS, other than standard C conversions. Does
- nothing if FUNC does not have Ada-style prototype data, or if NARGS
- does not match the number of arguments expected. Use *SP as a
- stack pointer for additional data that must be pushed, updating its
- value as needed. */
-
-void
-ada_convert_actuals (struct value *func, int nargs, struct value *args[],
- CORE_ADDR *sp)
-{
- int i;
-
- if (TYPE_NFIELDS (value_type (func)) == 0
- || nargs != TYPE_NFIELDS (value_type (func)))
- return;
-
- for (i = 0; i < nargs; i += 1)
- args[i] =
- convert_actual (args[i], TYPE_FIELD_TYPE (value_type (func), i), sp);
-}
\f
/* Dummy definitions for an experimental caching module that is not
* used in the public sources. */
size_t tmp;
struct ada_symbol_info *prevDefns = defns_collected (obstackp, 0);
- if (SYMBOL_TYPE (sym) != NULL)
- SYMBOL_TYPE (sym) = ada_check_typedef (SYMBOL_TYPE (sym));
+ /* Do not try to complete stub types, as the debugger is probably
+ already scanning all symbols matching a certain name at the
+ time when this function is called. Trying to replace the stub
+ type by its associated full type will cause us to restart a scan
+ which may lead to an infinite recursion. Instead, the client
+ collecting the matching symbols will end up collecting several
+ matches, with at least one of them complete. It can then filter
+ out the stub ones if needed. */
+
for (i = num_defns_collected (obstackp) - 1; i >= 0; i -= 1)
{
if (lesseq_defined_than (sym, prevDefns[i].sym))
struct dict_iterator iter;
int j;
- ALL_SYMTABS (objfile, s)
+ ALL_PRIMARY_SYMTABS (objfile, s)
{
switch (SYMBOL_CLASS (sym))
{
{
}
-/* FIXME: The next two routines belong in symtab.c */
-
-static void
-restore_language (void *lang)
-{
- set_language ((enum language) lang);
-}
-
-/* As for lookup_symbol, but performed as if the current language
- were LANG. */
-
-struct symbol *
-lookup_symbol_in_language (const char *name, const struct block *block,
- domain_enum domain, enum language lang,
- int *is_a_field_of_this, struct symtab **symtab)
-{
- struct cleanup *old_chain
- = make_cleanup (restore_language, (void *) current_language->la_language);
- struct symbol *result;
- set_language (lang);
- result = lookup_symbol (name, block, domain, is_a_field_of_this, symtab);
- do_cleanups (old_chain);
- return result;
-}
-
/* True if TYPE is definitely an artificial type supplied to a symbol
for which no debugging information was given in the symbol file. */
"_ada_" followed by NAME can be found. */
/* Do a quick check that NAME does not contain "__", since library-level
- functions names can not contain "__" in them. */
+ functions names cannot contain "__" in them. */
if (strstr (name, "__") != NULL)
return 0;
}
/* Return nonzero if SYM corresponds to a renaming entity that is
- visible from FUNCTION_NAME. */
+ not visible from FUNCTION_NAME. */
static int
-renaming_is_visible (const struct symbol *sym, char *function_name)
+old_renaming_is_invisible (const struct symbol *sym, char *function_name)
{
- char *scope = xget_renaming_scope (SYMBOL_TYPE (sym));
+ char *scope;
+
+ if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+ return 0;
+
+ scope = xget_renaming_scope (SYMBOL_TYPE (sym));
make_cleanup (xfree, scope);
/* If the rename has been defined in a package, then it is visible. */
if (is_package_name (scope))
- return 1;
+ return 0;
/* Check that the rename is in the current function scope by checking
that its name starts with SCOPE. */
if (strncmp (function_name, "_ada_", 5) == 0)
function_name += 5;
- return (strncmp (function_name, scope, strlen (scope)) == 0);
+ return (strncmp (function_name, scope, strlen (scope)) != 0);
}
-/* Iterates over the SYMS list and remove any entry that corresponds to
- a renaming entity that is not visible from the function associated
- with CURRENT_BLOCK.
+/* Remove entries from SYMS that corresponds to a renaming entity that
+ is not visible from the function associated with CURRENT_BLOCK or
+ that is superfluous due to the presence of more specific renaming
+ information. Places surviving symbols in the initial entries of
+ SYMS and returns the number of surviving symbols.
Rationale:
- GNAT emits a type following a specified encoding for each renaming
+ First, in cases where an object renaming is implemented as a
+ reference variable, GNAT may produce both the actual reference
+ variable and the renaming encoding. In this case, we discard the
+ latter.
+
+ Second, GNAT emits a type following a specified encoding for each renaming
entity. Unfortunately, STABS currently does not support the definition
of types that are local to a given lexical block, so all renamings types
are emitted at library level. As a consequence, if an application
the user will be unable to print such rename entities. */
static int
-remove_out_of_scope_renamings (struct ada_symbol_info *syms,
- int nsyms, struct block *current_block)
+remove_irrelevant_renamings (struct ada_symbol_info *syms,
+ int nsyms, const struct block *current_block)
{
struct symbol *current_function;
char *current_function_name;
int i;
+ int is_new_style_renaming;
+
+ /* If there is both a renaming foo___XR... encoded as a variable and
+ 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)
+ {
+ struct symbol *sym = syms[i].sym;
+ 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);
+ suffix = strstr (name, "___XR");
+
+ if (suffix != NULL)
+ {
+ int name_len = suffix - name;
+ 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),
+ name_len) == 0
+ && block == syms[j].block)
+ syms[j].sym = NULL;
+ }
+ }
+ if (is_new_style_renaming)
+ {
+ int j, k;
+
+ for (j = k = 0; j < nsyms; j += 1)
+ if (syms[j].sym != NULL)
+ {
+ syms[k] = syms[j];
+ k += 1;
+ }
+ return k;
+ }
/* Extract the function name associated to CURRENT_BLOCK.
Abort if unable to do so. */
i = 0;
while (i < nsyms)
{
- if (ada_is_object_renaming (syms[i].sym)
- && !renaming_is_visible (syms[i].sym, current_function_name))
+ if (ada_parse_renaming (syms[i].sym, 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++)
+ for (j = i + 1; j < nsyms; j += 1)
syms[j - 1] = syms[j];
nsyms -= 1;
}
/* Now add symbols from all global blocks: symbol tables, minimal symbol
tables, and psymtab's. */
- ALL_SYMTABS (objfile, s)
+ ALL_PRIMARY_SYMTABS (objfile, s)
{
QUIT;
- if (!s->primary)
- continue;
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
ada_add_block_symbols (&symbol_list_obstack, block, name, namespace,
if (num_defns_collected (&symbol_list_obstack) == 0)
{
- ALL_SYMTABS (objfile, s)
+ ALL_PRIMARY_SYMTABS (objfile, s)
{
QUIT;
- if (!s->primary)
- continue;
bv = BLOCKVECTOR (s);
block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
ada_add_block_symbols (&symbol_list_obstack, block, name, namespace,
cache_symbol (name0, namespace, (*results)[0].sym, (*results)[0].block,
(*results)[0].symtab);
- ndefns = remove_out_of_scope_renamings (*results, ndefns,
- (struct block *) block0);
+ ndefns = remove_irrelevant_renamings (*results, ndefns, block0);
return ndefns;
}
-/* Return a symbol in DOMAIN matching NAME, in BLOCK0 and enclosing
- scope and in global scopes, or NULL if none. NAME is folded and
- encoded first. Otherwise, the result is as for ada_lookup_symbol_list,
- choosing the first symbol if there are multiple choices.
- *IS_A_FIELD_OF_THIS is set to 0 and *SYMTAB is set to the symbol
- table in which the symbol was found (in both cases, these
- assignments occur only if the pointers are non-null). */
-
struct symbol *
-ada_lookup_symbol (const char *name, const struct block *block0,
- domain_enum namespace, int *is_a_field_of_this,
- struct symtab **symtab)
+ada_lookup_encoded_symbol (const char *name, const struct block *block0,
+ domain_enum namespace,
+ struct block **block_found, struct symtab **symtab)
{
struct ada_symbol_info *candidates;
int n_candidates;
- n_candidates = ada_lookup_symbol_list (ada_encode (ada_fold_name (name)),
- block0, namespace, &candidates);
+ n_candidates = ada_lookup_symbol_list (name, block0, namespace, &candidates);
if (n_candidates == 0)
return NULL;
- if (is_a_field_of_this != NULL)
- *is_a_field_of_this = 0;
+ if (block_found != NULL)
+ *block_found = candidates[0].block;
if (symtab != NULL)
{
/* Search the list of symtabs for one which contains the
address of the start of this block. */
- ALL_SYMTABS (objfile, s)
+ ALL_PRIMARY_SYMTABS (objfile, s)
{
bv = BLOCKVECTOR (s);
b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
*symtab = s;
return fixup_symbol_section (candidates[0].sym, objfile);
}
- return fixup_symbol_section (candidates[0].sym, NULL);
}
+ /* FIXME: brobecker/2004-11-12: I think that we should never
+ reach this point. I don't see a reason why we would not
+ find a symtab for a given block, so I suggest raising an
+ internal_error exception here. Otherwise, we end up
+ returning a symbol but no symtab, which certain parts of
+ the code that rely (indirectly) on this function do not
+ expect, eventually causing a SEGV. */
+ return fixup_symbol_section (candidates[0].sym, NULL);
}
}
return candidates[0].sym;
-}
+}
-static struct symbol *
-ada_lookup_symbol_nonlocal (const char *name,
- const char *linkage_name,
- const struct block *block,
- const domain_enum domain, struct symtab **symtab)
-{
- if (linkage_name == NULL)
- linkage_name = name;
+/* Return a symbol in DOMAIN matching NAME, in BLOCK0 and enclosing
+ scope and in global scopes, or NULL if none. NAME is folded and
+ encoded first. Otherwise, the result is as for ada_lookup_symbol_list,
+ choosing the first symbol if there are multiple choices.
+ *IS_A_FIELD_OF_THIS is set to 0 and *SYMTAB is set to the symbol
+ table in which the symbol was found (in both cases, these
+ assignments occur only if the pointers are non-null). */
+struct symbol *
+ada_lookup_symbol (const char *name, const struct block *block0,
+ domain_enum namespace, int *is_a_field_of_this,
+ struct symtab **symtab)
+{
+ if (is_a_field_of_this != NULL)
+ *is_a_field_of_this = 0;
+
+ return
+ ada_lookup_encoded_symbol (ada_encode (ada_fold_name (name)),
+ block0, namespace, NULL, symtab);
+}
+
+static struct symbol *
+ada_lookup_symbol_nonlocal (const char *name,
+ const char *linkage_name,
+ const struct block *block,
+ const domain_enum domain, struct symtab **symtab)
+{
+ if (linkage_name == NULL)
+ linkage_name = name;
return ada_lookup_symbol (linkage_name, block_static_block (block), domain,
NULL, symtab);
}
names (e.g., XVE) are not included here. Currently, the possible suffixes
are given by either of the regular expression:
- (__[0-9]+)?\.[0-9]+ [nested subprogram suffix, on platforms such
- as GNU/Linux]
- ___[0-9]+ [nested subprogram suffix, on platforms such as HP/UX]
+ [.$][0-9]+ [nested subprogram suffix, on platforms such as GNU/Linux]
+ ___[0-9]+ [nested subprogram suffix, on platforms such as HP/UX]
+ _E[0-9]+[bs]$ [protected object entry suffixes]
(X[nb]*)?((\$|__)[0-9](_?[0-9]+)|___(JM|LJM|X([FDBUP].*|R[^T]?)))?$
- */
+
+ Also, any leading "__[0-9]+" sequence is skipped before the suffix
+ match is performed. This sequence is used to differentiate homonyms,
+ is an optional part of a valid name suffix. */
static int
is_name_suffix (const char *str)
const char *matching;
const int len = strlen (str);
- /* (__[0-9]+)?\.[0-9]+ */
- matching = str;
+ /* Skip optional leading __[0-9]+. */
+
if (len > 3 && str[0] == '_' && str[1] == '_' && isdigit (str[2]))
{
- matching += 3;
+ str += 3;
+ while (isdigit (str[0]))
+ str += 1;
+ }
+
+ /* [.$][0-9]+ */
+
+ if (str[0] == '.' || str[0] == '$')
+ {
+ matching = str + 1;
while (isdigit (matching[0]))
matching += 1;
if (matching[0] == '\0')
return 1;
}
- if (matching[0] == '.')
+ /* ___[0-9]+ */
+
+ if (len > 3 && str[0] == '_' && str[1] == '_' && str[2] == '_')
{
- matching += 1;
+ matching = str + 3;
while (isdigit (matching[0]))
matching += 1;
if (matching[0] == '\0')
return 1;
}
- /* ___[0-9]+ */
- if (len > 3 && str[0] == '_' && str[1] == '_' && str[2] == '_')
+#if 0
+ /* FIXME: brobecker/2005-09-23: Protected Object subprograms end
+ with a N at the end. Unfortunately, the compiler uses the same
+ convention for other internal types it creates. So treating
+ all entity names that end with an "N" as a name suffix causes
+ some regressions. For instance, consider the case of an enumerated
+ type. To support the 'Image attribute, it creates an array whose
+ name ends with N.
+ Having a single character like this as a suffix carrying some
+ information is a bit risky. Perhaps we should change the encoding
+ to be something like "_N" instead. In the meantime, do not do
+ the following check. */
+ /* Protected Object Subprograms */
+ if (len == 1 && str [0] == 'N')
+ return 1;
+#endif
+
+ /* _E[0-9]+[bs]$ */
+ if (len > 3 && str[0] == '_' && str [1] == 'E' && isdigit (str[2]))
{
matching = str + 3;
while (isdigit (matching[0]))
matching += 1;
- if (matching[0] == '\0')
+ if ((matching[0] == 'b' || matching[0] == 's')
+ && matching [1] == '\0')
return 1;
}
str += 1;
}
}
+
if (str[0] == '\000')
return 1;
+
if (str[0] == '_')
{
if (str[1] != '_' || str[2] == '\000')
return (str[0] == '\0');
}
+/* Return non-zero if the string starting at NAME and ending before
+ NAME_END contains no capital letters. */
+
+static int
+is_valid_name_for_wild_match (const char *name0)
+{
+ const char *decoded_name = ada_decode (name0);
+ int i;
+
+ for (i=0; decoded_name[i] != '\0'; i++)
+ if (isalpha (decoded_name[i]) && !islower (decoded_name[i]))
+ return 0;
+
+ return 1;
+}
+
/* True if NAME represents a name of the form A1.A2....An, n>=1 and
PATN[0..PATN_LEN-1] = Ak.Ak+1.....An for some k >= 1. Ignores
informational suffixes of NAME (i.e., for which is_name_suffix is
{
int name_len;
char *name;
+ char *name_start;
char *patn;
/* FIXME: brobecker/2003-11-10: For some reason, the symbol name
char *dot;
name_len = strlen (name0);
- name = (char *) alloca ((name_len + 1) * sizeof (char));
+ name = name_start = (char *) alloca ((name_len + 1) * sizeof (char));
strcpy (name, name0);
dot = strrchr (name, '.');
if (dot != NULL && is_dot_digits_suffix (dot))
{
if (strncmp (patn, name, patn_len) == 0
&& is_name_suffix (name + patn_len))
- return 1;
+ return (name == name_start || is_valid_name_for_wild_match (name0));
do
{
name += 1;
\f
/* Field Access */
+/* Return non-zero if TYPE is a pointer to the GNAT dispatch table used
+ for tagged types. */
+
+static int
+ada_is_dispatch_table_ptr_type (struct type *type)
+{
+ char *name;
+
+ if (TYPE_CODE (type) != TYPE_CODE_PTR)
+ return 0;
+
+ name = TYPE_NAME (TYPE_TARGET_TYPE (type));
+ if (name == NULL)
+ return 0;
+
+ return (strcmp (name, "ada__tags__dispatch_table") == 0);
+}
+
/* True if field number FIELD_NUM in struct or union type TYPE is supposed
to be invisible to users. */
{
if (field_num < 0 || field_num > TYPE_NFIELDS (type))
return 1;
- else
- {
- const char *name = TYPE_FIELD_NAME (type, field_num);
- return (name == NULL
- || (name[0] == '_' && strncmp (name, "_parent", 7) != 0));
- }
+
+ /* Check the name of that field. */
+ {
+ const char *name = TYPE_FIELD_NAME (type, field_num);
+
+ /* 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. */
+ if (name == NULL)
+ return 1;
+
+ /* A field named "_parent" is internally generated by GNAT for
+ tagged types, and should not be printed either. */
+ if (name[0] == '_' && strncmp (name, "_parent", 7) != 0)
+ return 1;
+ }
+
+ /* If this is the dispatch table of a tagged type, then ignore. */
+ if (ada_is_tagged_type (type, 1)
+ && ada_is_dispatch_table_ptr_type (TYPE_FIELD_TYPE (type, field_num)))
+ return 1;
+
+ /* Not a special field, so it should not be ignored. */
+ return 0;
}
/* True iff TYPE has a tag field. If REFOK, then TYPE may also be a
struct value *
ada_value_tag (struct value *val)
{
- return ada_value_struct_elt (val, "_tag", "record");
+ return ada_value_struct_elt (val, "_tag", 0);
}
/* The value of the tag on the object of type TYPE whose contents are
int tag_byte_offset, dummy1, dummy2;
struct type *tag_type;
if (find_struct_field ("_tag", type, 0, &tag_type, &tag_byte_offset,
- &dummy1, &dummy2))
+ NULL, NULL, NULL))
{
const gdb_byte *valaddr1 = ((valaddr == NULL)
? NULL
char *name;
};
+
+static int ada_tag_name_1 (void *);
+static int ada_tag_name_2 (struct tag_args *);
+
/* Wrapper function used by ada_tag_name. Given a struct tag_args*
value ARGS, sets ARGS->name to the tag name of ARGS->tag.
The value stored in ARGS->name is valid until the next call to
char *p;
struct value *val;
args->name = NULL;
- val = ada_value_struct_elt (args->tag, "tsd", NULL);
+ val = ada_value_struct_elt (args->tag, "tsd", 1);
+ if (val == NULL)
+ return ada_tag_name_2 (args);
+ val = ada_value_struct_elt (val, "expanded_name", 1);
+ if (val == NULL)
+ return 0;
+ read_memory_string (value_as_address (val), name, sizeof (name) - 1);
+ for (p = name; *p != '\0'; p += 1)
+ if (isalpha (*p))
+ *p = tolower (*p);
+ args->name = name;
+ return 0;
+}
+
+/* Utility function for ada_tag_name_1 that tries the second
+ representation for the dispatch table (in which there is no
+ explicit 'tsd' field in the referent of the tag pointer, and instead
+ the tsd pointer is stored just before the dispatch table. */
+
+static int
+ada_tag_name_2 (struct tag_args *args)
+{
+ struct type *info_type;
+ static char name[1024];
+ char *p;
+ struct value *val, *valp;
+
+ args->name = NULL;
+ info_type = ada_find_any_type ("ada__tags__type_specific_data");
+ if (info_type == NULL)
+ return 0;
+ info_type = lookup_pointer_type (lookup_pointer_type (info_type));
+ valp = value_cast (info_type, args->tag);
+ if (valp == NULL)
+ return 0;
+ val = value_ind (value_add (valp, value_from_longest (builtin_type_int, -1)));
if (val == NULL)
return 0;
- val = ada_value_struct_elt (val, "expanded_name", NULL);
+ val = ada_value_struct_elt (val, "expanded_name", 1);
if (val == NULL)
return 0;
read_memory_string (value_as_address (val), name, sizeof (name) - 1);
return value_primitive_field (arg1, offset, fieldno, arg_type);
}
-/* Find field with name NAME in object of type TYPE. If found, return 1
- after setting *FIELD_TYPE_P to the field's type, *BYTE_OFFSET_P to
- OFFSET + the byte offset of the field within an object of that type,
- *BIT_OFFSET_P to the bit offset modulo byte size of the field, and
- *BIT_SIZE_P to its size in bits if the field is packed, and 0 otherwise.
- Looks inside wrappers for the field. Returns 0 if field not
- found. */
+/* Find field with name NAME in object of type TYPE. If found,
+ set the following for each argument that is non-null:
+ - *FIELD_TYPE_P to the field's type;
+ - *BYTE_OFFSET_P to OFFSET + the byte offset of the field within
+ an object of that type;
+ - *BIT_OFFSET_P to the bit offset modulo byte size of the field;
+ - *BIT_SIZE_P to its size in bits if the field is packed, and
+ 0 otherwise;
+ If INDEX_P is non-null, increment *INDEX_P by the number of source-visible
+ fields up to but not including the desired field, or by the total
+ number of fields if not found. A NULL value of NAME never
+ matches; the function just counts visible fields in this case.
+
+ Returns 1 if found, 0 otherwise. */
+
static int
find_struct_field (char *name, struct type *type, int offset,
struct type **field_type_p,
- int *byte_offset_p, int *bit_offset_p, int *bit_size_p)
+ int *byte_offset_p, int *bit_offset_p, int *bit_size_p,
+ int *index_p)
{
int i;
type = ada_check_typedef (type);
- *field_type_p = NULL;
- *byte_offset_p = *bit_offset_p = *bit_size_p = 0;
- for (i = TYPE_NFIELDS (type) - 1; i >= 0; i -= 1)
+ if (field_type_p != NULL)
+ *field_type_p = NULL;
+ if (byte_offset_p != NULL)
+ *byte_offset_p = 0;
+ if (bit_offset_p != NULL)
+ *bit_offset_p = 0;
+ if (bit_size_p != NULL)
+ *bit_size_p = 0;
+
+ for (i = 0; i < TYPE_NFIELDS (type); i += 1)
{
int bit_pos = TYPE_FIELD_BITPOS (type, i);
int fld_offset = offset + bit_pos / 8;
if (t_field_name == NULL)
continue;
- else if (field_name_match (t_field_name, name))
+ else if (name != NULL && field_name_match (t_field_name, name))
{
int bit_size = TYPE_FIELD_BITSIZE (type, i);
- *field_type_p = TYPE_FIELD_TYPE (type, i);
- *byte_offset_p = fld_offset;
- *bit_offset_p = bit_pos % 8;
- *bit_size_p = bit_size;
+ if (field_type_p != NULL)
+ *field_type_p = TYPE_FIELD_TYPE (type, i);
+ if (byte_offset_p != NULL)
+ *byte_offset_p = fld_offset;
+ if (bit_offset_p != NULL)
+ *bit_offset_p = bit_pos % 8;
+ if (bit_size_p != NULL)
+ *bit_size_p = bit_size;
return 1;
}
else if (ada_is_wrapper_field (type, i))
{
- if (find_struct_field (name, TYPE_FIELD_TYPE (type, i), fld_offset,
- field_type_p, byte_offset_p, bit_offset_p,
- bit_size_p))
+ if (find_struct_field (name, TYPE_FIELD_TYPE (type, i), fld_offset,
+ field_type_p, byte_offset_p, bit_offset_p,
+ bit_size_p, index_p))
return 1;
}
else if (ada_is_variant_part (type, i))
{
+ /* PNH: Wait. Do we ever execute this section, or is ARG always of
+ fixed type?? */
int j;
- struct type *field_type = ada_check_typedef (TYPE_FIELD_TYPE (type, i));
+ struct type *field_type
+ = ada_check_typedef (TYPE_FIELD_TYPE (type, i));
- for (j = TYPE_NFIELDS (field_type) - 1; j >= 0; j -= 1)
+ for (j = 0; j < TYPE_NFIELDS (field_type); j += 1)
{
if (find_struct_field (name, TYPE_FIELD_TYPE (field_type, j),
fld_offset
+ TYPE_FIELD_BITPOS (field_type, j) / 8,
field_type_p, byte_offset_p,
- bit_offset_p, bit_size_p))
+ bit_offset_p, bit_size_p, index_p))
return 1;
}
}
+ else if (index_p != NULL)
+ *index_p += 1;
}
return 0;
}
+/* Number of user-visible fields in record type TYPE. */
+static int
+num_visible_fields (struct type *type)
+{
+ int n;
+ n = 0;
+ find_struct_field (NULL, type, 0, NULL, NULL, NULL, NULL, &n);
+ return n;
+}
/* Look for a field NAME in ARG. Adjust the address of ARG by OFFSET bytes,
and search in it assuming it has (class) type TYPE.
int i;
type = ada_check_typedef (type);
- for (i = TYPE_NFIELDS (type) - 1; i >= 0; i -= 1)
+ for (i = 0; i < TYPE_NFIELDS (type); i += 1)
{
char *t_field_name = TYPE_FIELD_NAME (type, i);
else if (ada_is_variant_part (type, i))
{
+ /* PNH: Do we ever get here? See find_struct_field. */
int j;
struct type *field_type = ada_check_typedef (TYPE_FIELD_TYPE (type, i));
int var_offset = offset + TYPE_FIELD_BITPOS (type, i) / 8;
- for (j = TYPE_NFIELDS (field_type) - 1; j >= 0; j -= 1)
+ for (j = 0; j < TYPE_NFIELDS (field_type); j += 1)
{
struct value *v = ada_search_struct_field /* Force line break. */
(name, arg,
return NULL;
}
+static struct value *ada_index_struct_field_1 (int *, struct value *,
+ int, struct type *);
+
+
+/* Return field #INDEX in ARG, where the index is that returned by
+ * find_struct_field through its INDEX_P argument. Adjust the address
+ * of ARG by OFFSET bytes, and search in it assuming it has (class) type TYPE.
+ * If found, return value, else return NULL. */
+
+static struct value *
+ada_index_struct_field (int index, struct value *arg, int offset,
+ struct type *type)
+{
+ return ada_index_struct_field_1 (&index, arg, offset, type);
+}
+
+
+/* Auxiliary function for ada_index_struct_field. Like
+ * ada_index_struct_field, but takes index from *INDEX_P and modifies
+ * *INDEX_P. */
+
+static struct value *
+ada_index_struct_field_1 (int *index_p, struct value *arg, int offset,
+ struct type *type)
+{
+ int i;
+ type = ada_check_typedef (type);
+
+ for (i = 0; i < TYPE_NFIELDS (type); i += 1)
+ {
+ if (TYPE_FIELD_NAME (type, i) == NULL)
+ continue;
+ else if (ada_is_wrapper_field (type, i))
+ {
+ struct value *v = /* Do not let indent join lines here. */
+ ada_index_struct_field_1 (index_p, arg,
+ offset + TYPE_FIELD_BITPOS (type, i) / 8,
+ TYPE_FIELD_TYPE (type, i));
+ if (v != NULL)
+ return v;
+ }
+
+ else if (ada_is_variant_part (type, i))
+ {
+ /* PNH: Do we ever get here? See ada_search_struct_field,
+ find_struct_field. */
+ error (_("Cannot assign this kind of variant record"));
+ }
+ else if (*index_p == 0)
+ return ada_value_primitive_field (arg, offset, i, type);
+ else
+ *index_p -= 1;
+ }
+ 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
and (recursively) among all members of any wrapper members
(e.g., '_parent').
- ERR is a name (for use in error messages) that identifies the class
- of entity that ARG is supposed to be. ERR may be null, indicating
- that on error, the function simply returns NULL, and does not
- throw an error. (FIXME: True only if ARG is a pointer or reference
- at the moment). */
+ If NO_ERR, then simply return NULL in case of error, rather than
+ calling error. */
struct value *
-ada_value_struct_elt (struct value *arg, char *name, char *err)
+ada_value_struct_elt (struct value *arg, char *name, int no_err)
{
struct type *t, *t1;
struct value *v;
{
t1 = TYPE_TARGET_TYPE (t);
if (t1 == NULL)
- {
- if (err == NULL)
- return NULL;
- else
- error (_("Bad value type in a %s."), err);
- }
+ goto BadValue;
t1 = ada_check_typedef (t1);
if (TYPE_CODE (t1) == TYPE_CODE_PTR)
{
{
t1 = TYPE_TARGET_TYPE (t);
if (t1 == NULL)
- {
- if (err == NULL)
- return NULL;
- else
- error (_("Bad value type in a %s."), err);
- }
+ goto BadValue;
t1 = ada_check_typedef (t1);
if (TYPE_CODE (t1) == TYPE_CODE_PTR)
{
}
if (TYPE_CODE (t1) != TYPE_CODE_STRUCT && TYPE_CODE (t1) != TYPE_CODE_UNION)
- {
- if (err == NULL)
- return NULL;
- else
- error (_("Attempt to extract a component of a value that is not a %s."),
- err);
- }
+ goto BadValue;
if (t1 == t)
v = ada_search_struct_field (name, arg, 0, t);
else
address = unpack_pointer (t, value_contents (arg));
- t1 = ada_to_fixed_type (ada_get_base_type (t1), NULL, address, NULL);
+ 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))
+ &bit_size, NULL))
{
if (bit_size != 0)
{
}
}
- if (v == NULL && err != NULL)
+ if (v != NULL || no_err)
+ return v;
+ else
error (_("There is no member named %s."), name);
- return v;
+ BadValue:
+ if (no_err)
+ return NULL;
+ else
+ error (_("Attempt to extract a component of a value that is not a record."));
}
/* Given a type TYPE, look up the type of the component of type named NAME.
{
int others_clause;
int i;
- int disp;
- struct type *discrim_type;
char *discrim_name = ada_variant_discrim_name (var_type);
+ struct value *outer;
+ struct value *discrim;
LONGEST discrim_val;
- disp = 0;
- discrim_type =
- ada_lookup_struct_elt_type (outer_type, discrim_name, 1, 1, &disp);
- if (discrim_type == NULL)
+ outer = value_from_contents_and_address (outer_type, outer_valaddr, 0);
+ discrim = ada_value_struct_elt (outer, discrim_name, 1);
+ if (discrim == NULL)
return -1;
- discrim_val = unpack_long (discrim_type, outer_valaddr + disp);
+ discrim_val = value_as_long (discrim);
others_clause = -1;
for (i = 0; i < TYPE_NFIELDS (var_type); i += 1)
field_alignment (struct type *type, int f)
{
const char *name = TYPE_FIELD_NAME (type, f);
- int len = (name == NULL) ? 0 : strlen (name);
+ int len;
int align_offset;
+ /* The field name should never be null, unless the debugging information
+ is somehow malformed. In this case, we assume the field does not
+ require any alignment. */
+ if (name == NULL)
+ return 1;
+
+ len = strlen (name);
+
if (!isdigit (name[len - 1]))
return 1;
return NULL;
}
-/* Given a symbol NAME and its associated BLOCK, search all symbols
- for its ___XR counterpart, which is the ``renaming'' symbol
+/* Given NAME and an associated BLOCK, search all symbols for
+ NAME suffixed with "___XR", which is the ``renaming'' symbol
associated to NAME. Return this symbol if found, return
NULL otherwise. */
struct symbol *
ada_find_renaming_symbol (const char *name, struct block *block)
+{
+ struct symbol *sym;
+
+ sym = find_old_style_renaming_symbol (name, block);
+
+ if (sym != NULL)
+ return sym;
+
+ /* Not right yet. FIXME pnh 7/20/2007. */
+ sym = ada_find_any_symbol (name);
+ 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, struct block *block)
{
const struct symbol *function_sym = block_function (block);
char *rename;
as well as adding the ``___XR'' suffix to build the name of
the associated renaming symbol. */
char *function_name = SYMBOL_LINKAGE_NAME (function_sym);
- const int function_name_len = strlen (function_name);
+ /* 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. */
+ const 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. */
+ function_name[function_name_len] = '\0';
+
/* Library-level functions are a special case, as GNAT adds
a ``_ada_'' prefix to the function name to avoid namespace
- pollution. However, the renaming symbol themselves do not
+ 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)
else if (ada_is_array_descriptor_type (type0)
&& !ada_is_array_descriptor_type (type1))
return 1;
- else if (ada_renaming_type (type0) != NULL
- && ada_renaming_type (type1) == NULL)
- return 1;
+ else
+ {
+ const char *type0_name = type_name_no_tag (type0);
+ const char *type1_name = type_name_no_tag (type1);
+
+ if (type0_name != NULL && strstr (type0_name, "___XR") != NULL
+ && (type1_name == NULL || strstr (type1_name, "___XR") == NULL))
+ return 1;
+ }
return 0;
}
else
dval = dval0;
+ /* Get the fixed type of the field. Note that, in this case, we
+ do not want to get the real type out of the tag: if the current
+ field is the parent part of a tagged record, we will get the
+ tag of the object. Clearly wrong: the real type of the parent
+ is not the real type of the child. We would end up in an infinite
+ loop. */
TYPE_FIELD_TYPE (rtype, f) =
ada_to_fixed_type
(ada_get_base_type
(TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, f))),
cond_offset_host (valaddr, off / TARGET_CHAR_BIT),
- cond_offset_target (address, off / TARGET_CHAR_BIT), dval);
+ cond_offset_target (address, off / TARGET_CHAR_BIT), dval, 0);
TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f);
bit_incr = fld_bit_len =
TYPE_LENGTH (TYPE_FIELD_TYPE (rtype, f)) * TARGET_CHAR_BIT;
if (is_dynamic_field (type0, f))
new_type = to_static_fixed_type (TYPE_TARGET_TYPE (field_type));
else
- new_type = to_static_fixed_type (field_type);
+ new_type = static_unwrap_type (field_type);
if (type == type0 && new_type != field_type)
{
TYPE_TARGET_TYPE (type0) = type = alloc_type (TYPE_OBJFILE (type0));
/* NOTE: elt_type---the fixed version of elt_type0---should never
depend on the contents of the array in properly constructed
debugging data. */
- struct type *elt_type = ada_to_fixed_type (elt_type0, 0, 0, dval);
+ /* Create a fixed version of the array element type.
+ We're not providing the address of an element here,
+ and thus the actual object value cannot be inspected to do
+ the conversion. This should not be a problem, since arrays of
+ unconstrained objects are not allowed. In particular, all
+ the elements of an array of a tagged type should all be of
+ the same type specified in the debugging info. No need to
+ consult the object tag. */
+ struct type *elt_type = ada_to_fixed_type (elt_type0, 0, 0, dval, 1);
if (elt_type0 == elt_type)
result = type0;
/* NOTE: result---the fixed version of elt_type0---should never
depend on the contents of the array in properly constructed
debugging data. */
- result = ada_to_fixed_type (ada_check_typedef (elt_type0), 0, 0, dval);
+ /* Create a fixed version of the array element type.
+ We're not providing the address of an element here,
+ and thus the actual object value cannot be inspected to do
+ the conversion. This should not be a problem, since arrays of
+ unconstrained objects are not allowed. In particular, all
+ the elements of an array of a tagged type should all be of
+ the same type specified in the debugging info. No need to
+ consult the object tag. */
+ result =
+ ada_to_fixed_type (ada_check_typedef (elt_type0), 0, 0, dval, 1);
for (i = TYPE_NFIELDS (index_type_desc) - 1; i >= 0; i -= 1)
{
struct type *range_type =
corresponding to TYPE for the value (TYPE, VALADDR, ADDRESS)
DVAL describes a record containing any discriminants used in TYPE0,
and may be NULL if there are none, or if the object of type TYPE at
- ADDRESS or in VALADDR contains these discriminants. */
-
-struct type *
-ada_to_fixed_type (struct type *type, const gdb_byte *valaddr,
- CORE_ADDR address, struct value *dval)
+ ADDRESS or in VALADDR contains these discriminants.
+
+ If CHECK_TAG is not null, in the case of tagged types, this function
+ attempts to locate the object's tag and use it to compute the actual
+ type. However, when ADDRESS is null, we cannot use it to determine the
+ location of the tag, and therefore compute the tagged type's actual type.
+ So we return the tagged type without consulting the tag. */
+
+static struct type *
+ada_to_fixed_type_1 (struct type *type, const gdb_byte *valaddr,
+ CORE_ADDR address, struct value *dval, int check_tag)
{
type = ada_check_typedef (type);
switch (TYPE_CODE (type))
case TYPE_CODE_STRUCT:
{
struct type *static_type = to_static_fixed_type (type);
- if (ada_is_tagged_type (static_type, 0))
+ struct type *fixed_record_type =
+ to_fixed_record_type (type, valaddr, address, NULL);
+ /* If STATIC_TYPE is a tagged type and we know the object's address,
+ then we can determine its tag, and compute the object's actual
+ type from there. Note that we have to use the fixed record
+ type (the parent part of the record may have dynamic fields
+ and the way the location of _tag is expressed may depend on
+ them). */
+
+ if (check_tag && address != 0 && ada_is_tagged_type (static_type, 0))
{
struct type *real_type =
- type_from_tag (value_tag_from_contents_and_address (static_type,
- valaddr,
- address));
+ type_from_tag (value_tag_from_contents_and_address
+ (fixed_record_type,
+ valaddr,
+ address));
if (real_type != NULL)
- type = real_type;
+ return to_fixed_record_type (real_type, valaddr, address, NULL);
}
- return to_fixed_record_type (type, valaddr, address, NULL);
+ return fixed_record_type;
}
case TYPE_CODE_ARRAY:
return to_fixed_array_type (type, dval, 1);
}
}
+/* The same as ada_to_fixed_type_1, except that it preserves the type
+ if it is a TYPE_CODE_TYPEDEF of a type that is already fixed.
+ ada_to_fixed_type_1 would return the type referenced by TYPE. */
+
+struct type *
+ada_to_fixed_type (struct type *type, const gdb_byte *valaddr,
+ CORE_ADDR address, struct value *dval, int check_tag)
+
+{
+ struct type *fixed_type =
+ ada_to_fixed_type_1 (type, valaddr, address, dval, check_tag);
+
+ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
+ && TYPE_TARGET_TYPE (type) == fixed_type)
+ return type;
+
+ return fixed_type;
+}
+
/* A standard (static-sized) type corresponding as well as possible to
TYPE0, but based on no runtime data. */
struct type *
ada_check_typedef (struct type *type)
{
+ if (type == NULL)
+ return NULL;
+
CHECK_TYPEDEF (type);
if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM
- || (TYPE_FLAGS (type) & TYPE_FLAG_STUB) == 0
+ || !TYPE_STUB (type)
|| TYPE_TAG_NAME (type) == NULL)
return type;
else
ada_to_fixed_value_create (struct type *type0, CORE_ADDR address,
struct value *val0)
{
- struct type *type = ada_to_fixed_type (type0, 0, address, NULL);
+ struct type *type = ada_to_fixed_type (type0, 0, address, NULL, 1);
if (type == type0 && val0 != NULL)
return val0;
else
int
ada_is_character_type (struct type *type)
{
- const char *name = ada_type_name (type);
- return
- name != NULL
- && (TYPE_CODE (type) == TYPE_CODE_CHAR
- || TYPE_CODE (type) == TYPE_CODE_INT
- || TYPE_CODE (type) == TYPE_CODE_RANGE)
- && (strcmp (name, "character") == 0
- || strcmp (name, "wide_character") == 0
- || strcmp (name, "unsigned char") == 0);
+ 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;
+
+ /* Otherwise, assume it's a character type iff it is a discrete type
+ with a known character type name. */
+ name = ada_type_name (type);
+ return (name != NULL
+ && (TYPE_CODE (type) == TYPE_CODE_INT
+ || TYPE_CODE (type) == TYPE_CODE_RANGE)
+ && (strcmp (name, "character") == 0
+ || strcmp (name, "wide_character") == 0
+ || strcmp (name, "wide_wide_character") == 0
+ || strcmp (name, "unsigned char") == 0));
}
/* True if TYPE appears to be an Ada string type. */
coerce_unspec_val_to_type
(val, ada_to_fixed_type (raw_real_type, 0,
VALUE_ADDRESS (val) + value_offset (val),
- NULL));
+ NULL, 1));
}
}
if (ada_is_direct_array_type (value_type (arg1))
|| ada_is_direct_array_type (value_type (arg2)))
{
+ /* 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
return value_equal (arg1, arg2);
}
-struct value *
-ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
- int *pos, enum noside noside)
+/* Total number of component associations in the aggregate starting at
+ index PC in EXP. Assumes that index PC is the start of an
+ OP_AGGREGATE. */
+
+static int
+num_component_specs (struct expression *exp, int pc)
{
- enum exp_opcode op;
- int tem, tem2, tem3;
- int pc;
- struct value *arg1 = NULL, *arg2 = NULL, *arg3;
- struct type *type;
- int nargs;
- struct value **argvec;
+ int n, m, i;
+ m = exp->elts[pc + 1].longconst;
+ pc += 3;
+ n = 0;
+ for (i = 0; i < m; i += 1)
+ {
+ switch (exp->elts[pc].opcode)
+ {
+ default:
+ n += 1;
+ break;
+ case OP_CHOICES:
+ n += exp->elts[pc + 1].longconst;
+ break;
+ }
+ ada_evaluate_subexp (NULL, exp, &pc, EVAL_SKIP);
+ }
+ return n;
+}
- pc = *pos;
- *pos += 1;
- op = exp->elts[pc].opcode;
+/* Assign the result of evaluating EXP starting at *POS to the INDEXth
+ component of LHS (a simple array or a record), updating *POS past
+ the expression, assuming that LHS is contained in CONTAINER. Does
+ not modify the inferior's memory, nor does it modify LHS (unless
+ LHS == CONTAINER). */
- switch (op)
+static void
+assign_component (struct value *container, struct value *lhs, LONGEST index,
+ struct expression *exp, int *pos)
+{
+ struct value *mark = value_mark ();
+ struct value *elt;
+ if (TYPE_CODE (value_type (lhs)) == TYPE_CODE_ARRAY)
{
- default:
- *pos -= 1;
- return
- unwrap_value (evaluate_subexp_standard
- (expect_type, exp, pos, noside));
+ struct value *index_val = value_from_longest (builtin_type_int, index);
+ elt = unwrap_value (ada_value_subscript (lhs, 1, &index_val));
+ }
+ else
+ {
+ elt = ada_index_struct_field (index, lhs, 0, value_type (lhs));
+ elt = ada_to_fixed_value (unwrap_value (elt));
+ }
- case OP_STRING:
- {
- struct value *result;
- *pos -= 1;
- result = evaluate_subexp_standard (expect_type, exp, pos, noside);
- /* The result type will have code OP_STRING, bashed there from
- OP_ARRAY. Bash it back. */
- if (TYPE_CODE (value_type (result)) == TYPE_CODE_STRING)
- TYPE_CODE (value_type (result)) = TYPE_CODE_ARRAY;
- return result;
- }
+ if (exp->elts[*pos].opcode == OP_AGGREGATE)
+ assign_aggregate (container, elt, exp, pos, EVAL_NORMAL);
+ else
+ value_assign_to_component (container, elt,
+ ada_evaluate_subexp (NULL, exp, pos,
+ EVAL_NORMAL));
+
+ value_free_to_mark (mark);
+}
+
+/* Assuming that LHS represents an lvalue having a record or array
+ type, and EXP->ELTS[*POS] is an OP_AGGREGATE, evaluate an assignment
+ of that aggregate's value to LHS, advancing *POS past the
+ aggregate. NOSIDE is as for evaluate_subexp. CONTAINER is an
+ lvalue containing LHS (possibly LHS itself). Does not modify
+ the inferior's memory, nor does it modify the contents of
+ LHS (unless == CONTAINER). Returns the modified CONTAINER. */
+
+static struct value *
+assign_aggregate (struct value *container,
+ struct value *lhs, struct expression *exp,
+ int *pos, enum noside noside)
+{
+ struct type *lhs_type;
+ int n = exp->elts[*pos+1].longconst;
+ LONGEST low_index, high_index;
+ int num_specs;
+ LONGEST *indices;
+ int max_indices, num_indices;
+ int is_array_aggregate;
+ int i;
+ struct value *mark = value_mark ();
+
+ *pos += 3;
+ if (noside != EVAL_NORMAL)
+ {
+ int i;
+ for (i = 0; i < n; i += 1)
+ ada_evaluate_subexp (NULL, exp, pos, noside);
+ return container;
+ }
+
+ container = ada_coerce_ref (container);
+ if (ada_is_direct_array_type (value_type (container)))
+ container = ada_coerce_to_simple_array (container);
+ lhs = ada_coerce_ref (lhs);
+ if (!deprecated_value_modifiable (lhs))
+ error (_("Left operand of assignment is not a modifiable lvalue."));
+
+ lhs_type = value_type (lhs);
+ if (ada_is_direct_array_type (lhs_type))
+ {
+ lhs = ada_coerce_to_simple_array (lhs);
+ lhs_type = value_type (lhs);
+ low_index = TYPE_ARRAY_LOWER_BOUND_VALUE (lhs_type);
+ high_index = TYPE_ARRAY_UPPER_BOUND_VALUE (lhs_type);
+ is_array_aggregate = 1;
+ }
+ else if (TYPE_CODE (lhs_type) == TYPE_CODE_STRUCT)
+ {
+ low_index = 0;
+ high_index = num_visible_fields (lhs_type) - 1;
+ is_array_aggregate = 0;
+ }
+ else
+ error (_("Left-hand side must be array or record."));
+
+ num_specs = num_component_specs (exp, *pos - 3);
+ max_indices = 4 * num_specs + 4;
+ indices = alloca (max_indices * sizeof (indices[0]));
+ indices[0] = indices[1] = low_index - 1;
+ indices[2] = indices[3] = high_index + 1;
+ num_indices = 4;
+
+ for (i = 0; i < n; i += 1)
+ {
+ switch (exp->elts[*pos].opcode)
+ {
+ case OP_CHOICES:
+ aggregate_assign_from_choices (container, lhs, exp, pos, indices,
+ &num_indices, max_indices,
+ low_index, high_index);
+ break;
+ case OP_POSITIONAL:
+ aggregate_assign_positional (container, lhs, exp, pos, indices,
+ &num_indices, max_indices,
+ low_index, high_index);
+ break;
+ case OP_OTHERS:
+ if (i != n-1)
+ error (_("Misplaced 'others' clause"));
+ aggregate_assign_others (container, lhs, exp, pos, indices,
+ num_indices, low_index, high_index);
+ break;
+ default:
+ error (_("Internal error: bad aggregate clause"));
+ }
+ }
+
+ return container;
+}
+
+/* Assign into the component of LHS indexed by the OP_POSITIONAL
+ construct at *POS, updating *POS past the construct, given that
+ the positions are relative to lower bound LOW, where HIGH is the
+ upper bound. Record the position in INDICES[0 .. MAX_INDICES-1]
+ updating *NUM_INDICES as needed. CONTAINER is as for
+ assign_aggregate. */
+static void
+aggregate_assign_positional (struct value *container,
+ struct value *lhs, struct expression *exp,
+ int *pos, LONGEST *indices, int *num_indices,
+ int max_indices, LONGEST low, LONGEST high)
+{
+ LONGEST ind = longest_to_int (exp->elts[*pos + 1].longconst) + low;
+
+ if (ind - 1 == high)
+ warning (_("Extra components in aggregate ignored."));
+ if (ind <= high)
+ {
+ add_component_interval (ind, ind, indices, num_indices, max_indices);
+ *pos += 3;
+ assign_component (container, lhs, ind, exp, pos);
+ }
+ else
+ ada_evaluate_subexp (NULL, exp, pos, EVAL_SKIP);
+}
+
+/* Assign into the components of LHS indexed by the OP_CHOICES
+ construct at *POS, updating *POS past the construct, given that
+ the allowable indices are LOW..HIGH. Record the indices assigned
+ to in INDICES[0 .. MAX_INDICES-1], updating *NUM_INDICES as
+ needed. CONTAINER is as for assign_aggregate. */
+static void
+aggregate_assign_from_choices (struct value *container,
+ struct value *lhs, struct expression *exp,
+ int *pos, LONGEST *indices, int *num_indices,
+ int max_indices, LONGEST low, LONGEST high)
+{
+ int j;
+ int n_choices = longest_to_int (exp->elts[*pos+1].longconst);
+ int choice_pos, expr_pc;
+ int is_array = ada_is_direct_array_type (value_type (lhs));
+
+ choice_pos = *pos += 3;
+
+ for (j = 0; j < n_choices; j += 1)
+ ada_evaluate_subexp (NULL, exp, pos, EVAL_SKIP);
+ expr_pc = *pos;
+ ada_evaluate_subexp (NULL, exp, pos, EVAL_SKIP);
+
+ for (j = 0; j < n_choices; j += 1)
+ {
+ LONGEST lower, upper;
+ enum exp_opcode op = exp->elts[choice_pos].opcode;
+ if (op == OP_DISCRETE_RANGE)
+ {
+ choice_pos += 1;
+ lower = value_as_long (ada_evaluate_subexp (NULL, exp, pos,
+ EVAL_NORMAL));
+ upper = value_as_long (ada_evaluate_subexp (NULL, exp, pos,
+ EVAL_NORMAL));
+ }
+ else if (is_array)
+ {
+ lower = value_as_long (ada_evaluate_subexp (NULL, exp, &choice_pos,
+ EVAL_NORMAL));
+ upper = lower;
+ }
+ else
+ {
+ int ind;
+ char *name;
+ switch (op)
+ {
+ case OP_NAME:
+ name = &exp->elts[choice_pos + 2].string;
+ break;
+ case OP_VAR_VALUE:
+ name = SYMBOL_NATURAL_NAME (exp->elts[choice_pos + 2].symbol);
+ break;
+ default:
+ error (_("Invalid record component association."));
+ }
+ ada_evaluate_subexp (NULL, exp, &choice_pos, EVAL_SKIP);
+ ind = 0;
+ if (! find_struct_field (name, value_type (lhs), 0,
+ NULL, NULL, NULL, NULL, &ind))
+ error (_("Unknown component name: %s."), name);
+ lower = upper = ind;
+ }
+
+ if (lower <= upper && (lower < low || upper > high))
+ error (_("Index in component association out of bounds."));
+
+ add_component_interval (lower, upper, indices, num_indices,
+ max_indices);
+ while (lower <= upper)
+ {
+ int pos1;
+ pos1 = expr_pc;
+ assign_component (container, lhs, lower, exp, &pos1);
+ lower += 1;
+ }
+ }
+}
+
+/* Assign the value of the expression in the OP_OTHERS construct in
+ EXP at *POS into the components of LHS indexed from LOW .. HIGH that
+ have not been previously assigned. The index intervals already assigned
+ are in INDICES[0 .. NUM_INDICES-1]. Updates *POS to after the
+ OP_OTHERS clause. CONTAINER is as for assign_aggregate*/
+static void
+aggregate_assign_others (struct value *container,
+ struct value *lhs, struct expression *exp,
+ int *pos, LONGEST *indices, int num_indices,
+ LONGEST low, LONGEST high)
+{
+ int i;
+ int expr_pc = *pos+1;
+
+ for (i = 0; i < num_indices - 2; i += 2)
+ {
+ LONGEST ind;
+ for (ind = indices[i + 1] + 1; ind < indices[i + 2]; ind += 1)
+ {
+ int pos;
+ pos = expr_pc;
+ assign_component (container, lhs, ind, exp, &pos);
+ }
+ }
+ ada_evaluate_subexp (NULL, exp, pos, EVAL_SKIP);
+}
+
+/* Add the interval [LOW .. HIGH] to the sorted set of intervals
+ [ INDICES[0] .. INDICES[1] ],..., [ INDICES[*SIZE-2] .. INDICES[*SIZE-1] ],
+ modifying *SIZE as needed. It is an error if *SIZE exceeds
+ MAX_SIZE. The resulting intervals do not overlap. */
+static void
+add_component_interval (LONGEST low, LONGEST high,
+ LONGEST* indices, int *size, int max_size)
+{
+ int i, j;
+ for (i = 0; i < *size; i += 2) {
+ if (high >= indices[i] && low <= indices[i + 1])
+ {
+ int kh;
+ for (kh = i + 2; kh < *size; kh += 2)
+ if (high < indices[kh])
+ break;
+ if (low < indices[i])
+ indices[i] = low;
+ indices[i + 1] = indices[kh - 1];
+ if (high > indices[i + 1])
+ indices[i + 1] = high;
+ memcpy (indices + i + 2, indices + kh, *size - kh);
+ *size -= kh - i - 2;
+ return;
+ }
+ else if (high < indices[i])
+ break;
+ }
+
+ if (*size == max_size)
+ error (_("Internal error: miscounted aggregate components."));
+ *size += 2;
+ for (j = *size-1; j >= i+2; j -= 1)
+ indices[j] = indices[j - 2];
+ indices[i] = low;
+ indices[i + 1] = high;
+}
+
+/* Perform and Ada cast of ARG2 to type TYPE if the type of ARG2
+ is different. */
+
+static struct value *
+ada_value_cast (struct type *type, struct value *arg2, enum noside noside)
+{
+ if (type == ada_check_typedef (value_type (arg2)))
+ return arg2;
+
+ if (ada_is_fixed_point_type (type))
+ return (cast_to_fixed (type, arg2));
+
+ if (ada_is_fixed_point_type (value_type (arg2)))
+ return value_cast (type, cast_from_fixed_to_double (arg2));
+
+ return value_cast (type, arg2);
+}
+
+static struct value *
+ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
+ int *pos, enum noside noside)
+{
+ enum exp_opcode op;
+ int tem, tem2, tem3;
+ int pc;
+ struct value *arg1 = NULL, *arg2 = NULL, *arg3;
+ struct type *type;
+ int nargs, oplen;
+ struct value **argvec;
+
+ pc = *pos;
+ *pos += 1;
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ default:
+ *pos -= 1;
+ arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
+ arg1 = unwrap_value (arg1);
+
+ /* If evaluating an OP_DOUBLE 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
+ types in Ada have different representations.
+
+ 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);
+
+ return arg1;
+
+ case OP_STRING:
+ {
+ struct value *result;
+ *pos -= 1;
+ result = evaluate_subexp_standard (expect_type, exp, pos, noside);
+ /* The result type will have code OP_STRING, bashed there from
+ OP_ARRAY. Bash it back. */
+ if (TYPE_CODE (value_type (result)) == TYPE_CODE_STRING)
+ TYPE_CODE (value_type (result)) = TYPE_CODE_ARRAY;
+ return result;
+ }
case UNOP_CAST:
(*pos) += 2;
arg1 = evaluate_subexp (type, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
- if (type != ada_check_typedef (value_type (arg1)))
- {
- if (ada_is_fixed_point_type (type))
- arg1 = cast_to_fixed (type, arg1);
- else if (ada_is_fixed_point_type (value_type (arg1)))
- arg1 = value_cast (type, cast_from_fixed_to_double (arg1));
- else if (VALUE_LVAL (arg1) == lval_memory)
- {
- /* This is in case of the really obscure (and undocumented,
- but apparently expected) case of (Foo) Bar.all, where Bar
- is an integer constant and Foo is a dynamic-sized type.
- If we don't do this, ARG1 will simply be relabeled with
- TYPE. */
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return value_zero (to_static_fixed_type (type), not_lval);
- arg1 =
- ada_to_fixed_value_create
- (type, VALUE_ADDRESS (arg1) + value_offset (arg1), 0);
- }
- else
- arg1 = value_cast (type, arg1);
- }
+ arg1 = ada_value_cast (type, arg1, noside);
return arg1;
case UNOP_QUAL:
case BINOP_ASSIGN:
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (exp->elts[*pos].opcode == OP_AGGREGATE)
+ {
+ arg1 = assign_aggregate (arg1, arg1, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ return ada_value_assign (arg1, arg1);
+ }
arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
return arg1;
|| ada_is_fixed_point_type (value_type (arg2)))
&& value_type (arg1) != value_type (arg2))
error (_("Operands of fixed-point addition must have the same type"));
- return value_cast (value_type (arg1), value_add (arg1, arg2));
+ /* Do the addition, and cast the result to the type of the first
+ argument. We cannot cast the result to a reference type, so if
+ ARG1 is a reference type, find its underlying type. */
+ type = value_type (arg1);
+ while (TYPE_CODE (type) == TYPE_CODE_REF)
+ type = TYPE_TARGET_TYPE (type);
+ return value_cast (type, value_add (arg1, arg2));
case BINOP_SUB:
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
|| ada_is_fixed_point_type (value_type (arg2)))
&& value_type (arg1) != value_type (arg2))
error (_("Operands of fixed-point subtraction must have the same type"));
- return value_cast (value_type (arg1), value_sub (arg1, arg2));
+ /* Do the substraction, and cast the result to the type of the first
+ argument. We cannot cast the result to a reference type, so if
+ ARG1 is a reference type, find its underlying type. */
+ type = value_type (arg1);
+ while (TYPE_CODE (type) == TYPE_CODE_REF)
+ type = TYPE_TARGET_TYPE (type);
+ return value_cast (type, value_sub (arg1, arg2));
case BINOP_MUL:
case BINOP_DIV:
else
return value_neg (arg1);
+ case BINOP_LOGICAL_AND:
+ case BINOP_LOGICAL_OR:
+ case UNOP_LOGICAL_NOT:
+ {
+ struct value *val;
+
+ *pos -= 1;
+ val = evaluate_subexp_standard (expect_type, exp, pos, noside);
+ return value_cast (LA_BOOL_TYPE, val);
+ }
+
+ case BINOP_BITWISE_AND:
+ case BINOP_BITWISE_IOR:
+ case BINOP_BITWISE_XOR:
+ {
+ struct value *val;
+
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ *pos = pc;
+ val = evaluate_subexp_standard (expect_type, exp, pos, noside);
+
+ return value_cast (value_type (arg1), val);
+ }
+
case OP_VAR_VALUE:
*pos -= 1;
+
+ /* Tagged types are a little special in the fact that the real type
+ is dynamic and can only be determined by inspecting the object
+ value. So even if we're support to do an EVAL_AVOID_SIDE_EFFECTS
+ evaluation, we force an EVAL_NORMAL evaluation for tagged types. */
+ if (noside == EVAL_AVOID_SIDE_EFFECTS
+ && ada_is_tagged_type (SYMBOL_TYPE (exp->elts[pc + 2].symbol), 1))
+ noside = EVAL_NORMAL;
+
if (noside == EVAL_SKIP)
{
*pos += 4;
else 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
- illegal. */
+ invalid. */
error (_("Unexpected unresolved symbol, %s, during evaluation"),
SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol));
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
if (arity != nargs)
error (_("wrong number of subscripts; expecting %d"), arity);
if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return allocate_value (ada_aligned_type (type));
+ return value_zero (ada_aligned_type (type), lval_memory);
return
unwrap_value (ada_value_subscript
(argvec[0], nargs, argvec + 1));
if (type == NULL)
error (_("element type of array unknown"));
else
- return allocate_value (ada_aligned_type (type));
+ return value_zero (ada_aligned_type (type), lval_memory);
}
return
unwrap_value (ada_value_subscript
if (type == NULL)
error (_("element type of array unknown"));
else
- return allocate_value (ada_aligned_type (type));
+ return value_zero (ada_aligned_type (type), lval_memory);
}
return
unwrap_value (ada_value_ptr_subscript (argvec[0], type,
nargs, argvec + 1));
default:
- error (_("Attempt to index or call something other than an \
-array or function"));
+ error (_("Attempt to index or call something other than an "
+ "array or function"));
}
case TERNOP_SLICE:
to_fixed_array_type (TYPE_TARGET_TYPE (value_type (array)),
NULL, 1);
return ada_value_slice_ptr (array, arr_type0,
- (int) low_bound,
- (int) high_bound);
+ longest_to_int (low_bound),
+ longest_to_int (high_bound));
}
}
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
else if (high_bound < low_bound)
return empty_array (value_type (array), low_bound);
else
- return ada_value_slice (array, (int) low_bound, (int) high_bound);
+ return ada_value_slice (array, longest_to_int (low_bound),
+ longest_to_int (high_bound));
}
case UNOP_IN_RANGE:
switch (TYPE_CODE (type))
{
default:
- lim_warning (_("Membership test incompletely implemented; \
-always returns true"));
+ lim_warning (_("Membership test incompletely implemented; "
+ "always returns true"));
return value_from_longest (builtin_type_int, (LONGEST) 1);
case TYPE_CODE_RANGE:
return
ada_to_fixed_value (unwrap_value
(ada_value_struct_elt
- (arg1, &exp->elts[pc + 2].string, "record")));
+ (arg1, &exp->elts[pc + 2].string, 0)));
case OP_TYPE:
/* The value is not supposed to be used. This is here to make it
easier to accommodate expressions that contain types. */
if (noside == EVAL_SKIP)
goto nosideret;
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return allocate_value (builtin_type_void);
+ return allocate_value (exp->elts[pc + 1].type);
else
error (_("Attempt to use a type name as an expression"));
+
+ case OP_AGGREGATE:
+ case OP_CHOICES:
+ case OP_OTHERS:
+ case OP_DISCRETE_RANGE:
+ case OP_POSITIONAL:
+ case OP_NAME:
+ if (noside == EVAL_NORMAL)
+ switch (op)
+ {
+ case OP_NAME:
+ error (_("Undefined name, ambiguous name, or renaming used in "
+ "component association: %s."), &exp->elts[pc+2].string);
+ case OP_AGGREGATE:
+ error (_("Aggregates only allowed on the right of an assignment"));
+ default:
+ internal_error (__FILE__, __LINE__, _("aggregate apparently mangled"));
+ }
+
+ ada_forward_operator_length (exp, pc, &oplen, &nargs);
+ *pos += oplen - 1;
+ for (tem = 0; tem < nargs; tem += 1)
+ ada_evaluate_subexp (NULL, exp, pos, noside);
+ goto nosideret;
}
nosideret:
return (ULONGEST) TYPE_HIGH_BOUND (type) + 1;
}
\f
- /* Operators */
-/* Information about operators given special treatment in functions
- below. */
-/* Format: OP_DEFN (<operator>, <operator length>, <# args>, <binop>). */
-#define ADA_OPERATORS \
- OP_DEFN (OP_VAR_VALUE, 4, 0, 0) \
- OP_DEFN (BINOP_IN_BOUNDS, 3, 2, 0) \
- OP_DEFN (TERNOP_IN_RANGE, 1, 3, 0) \
- OP_DEFN (OP_ATR_FIRST, 1, 2, 0) \
- OP_DEFN (OP_ATR_LAST, 1, 2, 0) \
- OP_DEFN (OP_ATR_LENGTH, 1, 2, 0) \
- OP_DEFN (OP_ATR_IMAGE, 1, 2, 0) \
- OP_DEFN (OP_ATR_MAX, 1, 3, 0) \
- OP_DEFN (OP_ATR_MIN, 1, 3, 0) \
- OP_DEFN (OP_ATR_MODULUS, 1, 1, 0) \
- OP_DEFN (OP_ATR_POS, 1, 2, 0) \
- OP_DEFN (OP_ATR_SIZE, 1, 1, 0) \
- OP_DEFN (OP_ATR_TAG, 1, 1, 0) \
- OP_DEFN (OP_ATR_VAL, 1, 2, 0) \
- OP_DEFN (UNOP_QUAL, 3, 1, 0) \
- OP_DEFN (UNOP_IN_RANGE, 3, 1, 0)
+/* Ada exception catchpoint support:
+ ---------------------------------
+
+ We support 3 kinds of exception catchpoints:
+ . catchpoints on Ada exceptions
+ . catchpoints on unhandled Ada exceptions
+ . catchpoints on failed assertions
+
+ Exceptions raised during failed assertions, or unhandled exceptions
+ could perfectly be caught with the general catchpoint on Ada exceptions.
+ However, we can easily differentiate these two special cases, and having
+ the option to distinguish these two cases from the rest can be useful
+ to zero-in on certain situations.
+
+ Exception catchpoints are a specialized form of breakpoint,
+ since they rely on inserting breakpoints inside known routines
+ of the GNAT runtime. The implementation therefore uses a standard
+ breakpoint structure of the BP_BREAKPOINT type, but with its own set
+ of breakpoint_ops.
+
+ Support in the runtime for exception catchpoints have been changed
+ a few times already, and these changes affect the implementation
+ of these catchpoints. In order to be able to support several
+ variants of the runtime, we use a sniffer that will determine
+ the runtime variant used by the program being debugged.
+
+ At this time, we do not support the use of conditions on Ada exception
+ catchpoints. The COND and COND_STRING fields are therefore set
+ to NULL (most of the time, see below).
+
+ Conditions where EXP_STRING, COND, and COND_STRING are used:
+
+ When a user specifies the name of a specific exception in the case
+ of catchpoints on Ada exceptions, we store the name of that exception
+ in the EXP_STRING. We then translate this request into an actual
+ condition stored in COND_STRING, and then parse it into an expression
+ stored in COND. */
+
+/* The different types of catchpoints that we introduced for catching
+ Ada exceptions. */
+
+enum exception_catchpoint_kind
+{
+ ex_catch_exception,
+ ex_catch_exception_unhandled,
+ ex_catch_assert
+};
+
+typedef CORE_ADDR (ada_unhandled_exception_name_addr_ftype) (void);
+
+/* A structure that describes how to support exception catchpoints
+ for a given executable. */
+
+struct exception_support_info
+{
+ /* The name of the symbol to break on in order to insert
+ a catchpoint on exceptions. */
+ const char *catch_exception_sym;
+
+ /* The name of the symbol to break on in order to insert
+ a catchpoint on unhandled exceptions. */
+ const char *catch_exception_unhandled_sym;
+
+ /* The name of the symbol to break on in order to insert
+ a catchpoint on failed assertions. */
+ const char *catch_assert_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.
+ Return zero if the address could not be computed. */
+ ada_unhandled_exception_name_addr_ftype *unhandled_exception_name_addr;
+};
+
+static CORE_ADDR ada_unhandled_exception_name_addr (void);
+static CORE_ADDR ada_unhandled_exception_name_addr_from_raise (void);
+
+/* 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). */
+
+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 */
+ ada_unhandled_exception_name_addr
+};
+
+/* The following exception support info structure describes how to
+ implement exception catchpoints with a slightly older version
+ of the Ada runtime. */
+
+static const struct exception_support_info exception_support_info_fallback =
+{
+ "__gnat_raise_nodefer_with_msg", /* catch_exception_sym */
+ "__gnat_unhandled_exception", /* catch_exception_unhandled_sym */
+ "system__assertions__raise_assert_failure", /* catch_assert_sym */
+ ada_unhandled_exception_name_addr_from_raise
+};
+
+/* For each executable, we sniff which exception info structure to use
+ and cache it in the following global variable. */
+
+static const struct exception_support_info *exception_info = NULL;
+
+/* Inspect the Ada runtime and determine which exception info structure
+ should be used to provide support for exception catchpoints.
+
+ This function will always set exception_info, or raise an error. */
static void
-ada_operator_length (struct expression *exp, int pc, int *oplenp, int *argsp)
+ada_exception_support_info_sniffer (void)
{
- switch (exp->elts[pc - 1].opcode)
- {
- default:
- operator_length_standard (exp, pc, oplenp, argsp);
- break;
+ struct symbol *sym;
-#define OP_DEFN(op, len, args, binop) \
- case op: *oplenp = len; *argsp = args; break;
- ADA_OPERATORS;
-#undef OP_DEFN
+ /* If the exception info is already known, then no need to recompute it. */
+ if (exception_info != NULL)
+ return;
+
+ /* Check the latest (default) exception support info. */
+ sym = standard_lookup (default_exception_support_info.catch_exception_sym,
+ NULL, VAR_DOMAIN);
+ if (sym != NULL)
+ {
+ exception_info = &default_exception_support_info;
+ return;
}
-}
-static char *
-ada_op_name (enum exp_opcode opcode)
-{
- switch (opcode)
+ /* Try our fallback exception suport info. */
+ sym = standard_lookup (exception_support_info_fallback.catch_exception_sym,
+ NULL, VAR_DOMAIN);
+ if (sym != NULL)
{
- default:
- return op_name_standard (opcode);
-#define OP_DEFN(op, len, args, binop) case op: return #op;
- ADA_OPERATORS;
-#undef OP_DEFN
+ exception_info = &exception_support_info_fallback;
+ return;
}
+
+ /* Sometimes, it is normal for us to not be able to find the routine
+ we are looking for. This happens when the program is linked with
+ the shared version of the GNAT runtime, and the program has not been
+ started yet. Inform the user of these two possible causes if
+ applicable. */
+
+ if (ada_update_initial_language (language_unknown, NULL) != language_ada)
+ error (_("Unable to insert catchpoint. Is this an Ada main program?"));
+
+ /* If the symbol does not exist, then check that the program is
+ already started, to make sure that shared libraries have been
+ loaded. If it is not started, this may mean that the symbol is
+ in a shared library. */
+
+ if (ptid_get_pid (inferior_ptid) == 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
+ that the inferior has been started, but we still are not able to
+ find the run-time symbols. That can mean that we are in
+ configurable run time mode, or that a-except as been optimized
+ out by the linker... In any case, at this point it is not worth
+ supporting this feature. */
+
+ error (_("Cannot insert catchpoints in this configuration."));
}
-/* As for operator_length, but assumes PC is pointing at the first
- element of the operator, and gives meaningful results only for the
- Ada-specific operators. */
+/* An observer of "executable_changed" events.
+ Its role is to clear certain cached values that need to be recomputed
+ each time a new executable is loaded by GDB. */
static void
-ada_forward_operator_length (struct expression *exp, int pc,
- int *oplenp, int *argsp)
+ada_executable_changed_observer (void *unused)
{
- switch (exp->elts[pc].opcode)
- {
- default:
- *oplenp = *argsp = 0;
- break;
-#define OP_DEFN(op, len, args, binop) \
- case op: *oplenp = len; *argsp = args; break;
- ADA_OPERATORS;
-#undef OP_DEFN
- }
+ /* If the executable changed, then it is possible that the Ada runtime
+ is different. So we need to invalidate the exception support info
+ cache. */
+ exception_info = NULL;
+}
+
+/* Return the name of the function at PC, NULL if could not find it.
+ This function only checks the debugging information, not the symbol
+ table. */
+
+static char *
+function_name_from_pc (CORE_ADDR pc)
+{
+ char *func_name;
+
+ if (!find_pc_partial_function (pc, &func_name, NULL, NULL))
+ return NULL;
+
+ return func_name;
}
+/* True iff FRAME is very likely to be that of a function that is
+ part of the runtime system. This is all very heuristic, but is
+ intended to be used as advice as to what frames are uninteresting
+ to most users. */
+
static int
-ada_dump_subexp_body (struct expression *exp, struct ui_file *stream, int elt)
+is_known_support_routine (struct frame_info *frame)
{
- enum exp_opcode op = exp->elts[elt].opcode;
- int oplen, nargs;
- int pc = elt;
+ struct symtab_and_line sal;
+ char *func_name;
int i;
- ada_forward_operator_length (exp, elt, &oplen, &nargs);
+ /* If this code does not have any debugging information (no symtab),
+ This cannot be any user code. */
- switch (op)
- {
- /* Ada attributes ('Foo). */
- case OP_ATR_FIRST:
+ find_frame_sal (frame, &sal);
+ if (sal.symtab == NULL)
+ return 1;
+
+ /* If there is a symtab, but the associated source file cannot be
+ located, then assume this is not user code: Selecting a frame
+ for which we cannot display the code would not be very helpful
+ for the user. This should also take care of case such as VxWorks
+ where the kernel has some debugging info provided for a few units. */
+
+ if (symtab_to_fullname (sal.symtab) == NULL)
+ return 1;
+
+ /* Check the unit filename againt 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. */
+
+ for (i = 0; known_runtime_file_name_patterns[i] != NULL; i += 1)
+ {
+ re_comp (known_runtime_file_name_patterns[i]);
+ if (re_exec (sal.symtab->filename))
+ return 1;
+ if (sal.symtab->objfile != NULL
+ && re_exec (sal.symtab->objfile->name))
+ return 1;
+ }
+
+ /* Check whether the function is a GNAT-generated entity. */
+
+ func_name = function_name_from_pc (get_frame_address_in_block (frame));
+ 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))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Find the first frame that contains debugging information and that is not
+ part of the Ada run-time, starting from FI and moving upward. */
+
+static void
+ada_find_printable_frame (struct frame_info *fi)
+{
+ for (; fi != NULL; fi = get_prev_frame (fi))
+ {
+ if (!is_known_support_routine (fi))
+ {
+ select_frame (fi);
+ break;
+ }
+ }
+
+}
+
+/* Assuming that the inferior just triggered an unhandled exception
+ catchpoint, return the address in inferior memory where the name
+ of the exception is stored.
+
+ Return zero if the address could not be computed. */
+
+static CORE_ADDR
+ada_unhandled_exception_name_addr (void)
+{
+ return parse_and_eval_address ("e.full_name");
+}
+
+/* Same as ada_unhandled_exception_name_addr, except that this function
+ should be used when the inferior uses an older version of the runtime,
+ where the exception name needs to be extracted from a specific frame
+ several frames up in the callstack. */
+
+static CORE_ADDR
+ada_unhandled_exception_name_addr_from_raise (void)
+{
+ int frame_level;
+ struct frame_info *fi;
+
+ /* To determine the name of this exception, we need to select
+ the frame corresponding to RAISE_SYM_NAME. This frame is
+ at least 3 levels up, so we simply skip the first 3 frames
+ without checking the name of their associated function. */
+ fi = get_current_frame ();
+ for (frame_level = 0; frame_level < 3; frame_level += 1)
+ if (fi != NULL)
+ fi = get_prev_frame (fi);
+
+ while (fi != NULL)
+ {
+ const char *func_name =
+ function_name_from_pc (get_frame_address_in_block (fi));
+ if (func_name != NULL
+ && strcmp (func_name, exception_info->catch_exception_sym) == 0)
+ break; /* We found the frame we were looking for... */
+ fi = get_prev_frame (fi);
+ }
+
+ if (fi == NULL)
+ return 0;
+
+ select_frame (fi);
+ return parse_and_eval_address ("id.full_name");
+}
+
+/* Assuming the inferior just triggered an Ada exception catchpoint
+ (of any type), return the address in inferior memory where the name
+ of the exception is stored, if applicable.
+
+ Return zero if the address could not be computed, or if not relevant. */
+
+static CORE_ADDR
+ada_exception_name_addr_1 (enum exception_catchpoint_kind ex,
+ struct breakpoint *b)
+{
+ switch (ex)
+ {
+ case ex_catch_exception:
+ return (parse_and_eval_address ("e.full_name"));
+ break;
+
+ case ex_catch_exception_unhandled:
+ return exception_info->unhandled_exception_name_addr ();
+ break;
+
+ case ex_catch_assert:
+ return 0; /* Exception name is not relevant in this case. */
+ break;
+
+ default:
+ internal_error (__FILE__, __LINE__, _("unexpected catchpoint type"));
+ break;
+ }
+
+ return 0; /* Should never be reached. */
+}
+
+/* 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,
+ and zero is returned. */
+
+static CORE_ADDR
+ada_exception_name_addr (enum exception_catchpoint_kind ex,
+ struct breakpoint *b)
+{
+ struct gdb_exception e;
+ CORE_ADDR result = 0;
+
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ result = ada_exception_name_addr_1 (ex, b);
+ }
+
+ if (e.reason < 0)
+ {
+ warning (_("failed to get exception name: %s"), e.message);
+ return 0;
+ }
+
+ return result;
+}
+
+/* Implement the PRINT_IT method in the breakpoint_ops structure
+ for all exception catchpoint kinds. */
+
+static enum print_stop_action
+print_it_exception (enum exception_catchpoint_kind ex, struct breakpoint *b)
+{
+ const CORE_ADDR addr = ada_exception_name_addr (ex, b);
+ char exception_name[256];
+
+ if (addr != 0)
+ {
+ read_memory (addr, exception_name, sizeof (exception_name) - 1);
+ exception_name [sizeof (exception_name) - 1] = '\0';
+ }
+
+ ada_find_printable_frame (get_current_frame ());
+
+ annotate_catchpoint (b->number);
+ switch (ex)
+ {
+ case ex_catch_exception:
+ if (addr != 0)
+ printf_filtered (_("\nCatchpoint %d, %s at "),
+ b->number, exception_name);
+ else
+ printf_filtered (_("\nCatchpoint %d, exception at "), b->number);
+ break;
+ case ex_catch_exception_unhandled:
+ if (addr != 0)
+ printf_filtered (_("\nCatchpoint %d, unhandled %s at "),
+ b->number, exception_name);
+ else
+ printf_filtered (_("\nCatchpoint %d, unhandled exception at "),
+ b->number);
+ break;
+ case ex_catch_assert:
+ printf_filtered (_("\nCatchpoint %d, failed assertion at "),
+ b->number);
+ break;
+ }
+
+ return PRINT_SRC_AND_LOC;
+}
+
+/* Implement the PRINT_ONE method in the breakpoint_ops structure
+ for all exception catchpoint kinds. */
+
+static void
+print_one_exception (enum exception_catchpoint_kind ex,
+ struct breakpoint *b, CORE_ADDR *last_addr)
+{
+ if (addressprint)
+ {
+ annotate_field (4);
+ ui_out_field_core_addr (uiout, "addr", b->loc->address);
+ }
+
+ annotate_field (5);
+ *last_addr = b->loc->address;
+ switch (ex)
+ {
+ case ex_catch_exception:
+ if (b->exp_string != NULL)
+ {
+ char *msg = xstrprintf (_("`%s' Ada exception"), b->exp_string);
+
+ ui_out_field_string (uiout, "what", msg);
+ xfree (msg);
+ }
+ else
+ ui_out_field_string (uiout, "what", "all Ada exceptions");
+
+ break;
+
+ case ex_catch_exception_unhandled:
+ ui_out_field_string (uiout, "what", "unhandled Ada exceptions");
+ break;
+
+ case ex_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 exception_catchpoint_kind ex,
+ struct breakpoint *b)
+{
+ switch (ex)
+ {
+ case ex_catch_exception:
+ if (b->exp_string != NULL)
+ printf_filtered (_("Catchpoint %d: `%s' Ada exception"),
+ b->number, b->exp_string);
+ else
+ printf_filtered (_("Catchpoint %d: all Ada exceptions"), b->number);
+
+ break;
+
+ case ex_catch_exception_unhandled:
+ printf_filtered (_("Catchpoint %d: unhandled Ada exceptions"),
+ b->number);
+ break;
+
+ case ex_catch_assert:
+ printf_filtered (_("Catchpoint %d: failed Ada assertions"), b->number);
+ break;
+
+ default:
+ internal_error (__FILE__, __LINE__, _("unexpected catchpoint type"));
+ break;
+ }
+}
+
+/* Virtual table for "catch exception" breakpoints. */
+
+static enum print_stop_action
+print_it_catch_exception (struct breakpoint *b)
+{
+ return print_it_exception (ex_catch_exception, b);
+}
+
+static void
+print_one_catch_exception (struct breakpoint *b, CORE_ADDR *last_addr)
+{
+ print_one_exception (ex_catch_exception, b, last_addr);
+}
+
+static void
+print_mention_catch_exception (struct breakpoint *b)
+{
+ print_mention_exception (ex_catch_exception, b);
+}
+
+static struct breakpoint_ops catch_exception_breakpoint_ops =
+{
+ print_it_catch_exception,
+ print_one_catch_exception,
+ print_mention_catch_exception
+};
+
+/* Virtual table for "catch exception unhandled" breakpoints. */
+
+static enum print_stop_action
+print_it_catch_exception_unhandled (struct breakpoint *b)
+{
+ return print_it_exception (ex_catch_exception_unhandled, b);
+}
+
+static void
+print_one_catch_exception_unhandled (struct breakpoint *b, CORE_ADDR *last_addr)
+{
+ print_one_exception (ex_catch_exception_unhandled, b, last_addr);
+}
+
+static void
+print_mention_catch_exception_unhandled (struct breakpoint *b)
+{
+ print_mention_exception (ex_catch_exception_unhandled, b);
+}
+
+static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops = {
+ print_it_catch_exception_unhandled,
+ print_one_catch_exception_unhandled,
+ print_mention_catch_exception_unhandled
+};
+
+/* Virtual table for "catch assert" breakpoints. */
+
+static enum print_stop_action
+print_it_catch_assert (struct breakpoint *b)
+{
+ return print_it_exception (ex_catch_assert, b);
+}
+
+static void
+print_one_catch_assert (struct breakpoint *b, CORE_ADDR *last_addr)
+{
+ print_one_exception (ex_catch_assert, b, last_addr);
+}
+
+static void
+print_mention_catch_assert (struct breakpoint *b)
+{
+ print_mention_exception (ex_catch_assert, b);
+}
+
+static struct breakpoint_ops catch_assert_breakpoint_ops = {
+ print_it_catch_assert,
+ print_one_catch_assert,
+ print_mention_catch_assert
+};
+
+/* Return non-zero if B is an Ada exception catchpoint. */
+
+int
+ada_exception_catchpoint_p (struct breakpoint *b)
+{
+ return (b->ops == &catch_exception_breakpoint_ops
+ || b->ops == &catch_exception_unhandled_breakpoint_ops
+ || b->ops == &catch_assert_breakpoint_ops);
+}
+
+/* Return a newly allocated copy of the first space-separated token
+ in ARGSP, and then adjust ARGSP to point immediately after that
+ token.
+
+ Return NULL if ARGPS does not contain any more tokens. */
+
+static char *
+ada_get_next_arg (char **argsp)
+{
+ char *args = *argsp;
+ char *end;
+ char *result;
+
+ /* Skip any leading white space. */
+
+ while (isspace (*args))
+ args++;
+
+ if (args[0] == '\0')
+ return NULL; /* No more arguments. */
+
+ /* Find the end of the current argument. */
+
+ end = args;
+ while (*end != '\0' && !isspace (*end))
+ end++;
+
+ /* 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;
+}
+
+/* Split the arguments specified in a "catch exception" command.
+ Set EX to the appropriate catchpoint type.
+ Set EXP_STRING to the name of the specific exception if
+ specified by the user. */
+
+static void
+catch_ada_exception_command_split (char *args,
+ enum exception_catchpoint_kind *ex,
+ char **exp_string)
+{
+ struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+ char *exception_name;
+
+ exception_name = ada_get_next_arg (&args);
+ make_cleanup (xfree, exception_name);
+
+ /* Check that we do not have any more arguments. Anything else
+ is unexpected. */
+
+ while (isspace (*args))
+ args++;
+
+ if (args[0] != '\0')
+ error (_("Junk at end of expression"));
+
+ discard_cleanups (old_chain);
+
+ if (exception_name == NULL)
+ {
+ /* Catch all exceptions. */
+ *ex = ex_catch_exception;
+ *exp_string = NULL;
+ }
+ else if (strcmp (exception_name, "unhandled") == 0)
+ {
+ /* Catch unhandled exceptions. */
+ *ex = ex_catch_exception_unhandled;
+ *exp_string = NULL;
+ }
+ else
+ {
+ /* Catch a specific exception. */
+ *ex = ex_catch_exception;
+ *exp_string = exception_name;
+ }
+}
+
+/* Return the name of the symbol on which we should break in order to
+ implement a catchpoint of the EX kind. */
+
+static const char *
+ada_exception_sym_name (enum exception_catchpoint_kind ex)
+{
+ gdb_assert (exception_info != NULL);
+
+ switch (ex)
+ {
+ case ex_catch_exception:
+ return (exception_info->catch_exception_sym);
+ break;
+ case ex_catch_exception_unhandled:
+ return (exception_info->catch_exception_unhandled_sym);
+ break;
+ case ex_catch_assert:
+ return (exception_info->catch_assert_sym);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ _("unexpected catchpoint kind (%d)"), ex);
+ }
+}
+
+/* Return the breakpoint ops "virtual table" used for catchpoints
+ of the EX kind. */
+
+static struct breakpoint_ops *
+ada_exception_breakpoint_ops (enum exception_catchpoint_kind ex)
+{
+ switch (ex)
+ {
+ case ex_catch_exception:
+ return (&catch_exception_breakpoint_ops);
+ break;
+ case ex_catch_exception_unhandled:
+ return (&catch_exception_unhandled_breakpoint_ops);
+ break;
+ case ex_catch_assert:
+ return (&catch_assert_breakpoint_ops);
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ _("unexpected catchpoint kind (%d)"), ex);
+ }
+}
+
+/* Return the condition that will be used to match the current exception
+ 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. */
+
+static char *
+ada_exception_catchpoint_cond_string (const char *exp_string)
+{
+ return xstrprintf ("long_integer (e) = long_integer (&%s)", exp_string);
+}
+
+/* Return the expression corresponding to COND_STRING evaluated at SAL. */
+
+static struct expression *
+ada_parse_catchpoint_condition (char *cond_string,
+ struct symtab_and_line sal)
+{
+ return (parse_exp_1 (&cond_string, block_for_pc (sal.pc), 0));
+}
+
+/* Return the symtab_and_line that should be used to insert an exception
+ catchpoint of the TYPE kind.
+
+ EX_STRING should contain the name of a specific exception
+ that the catchpoint should catch, or NULL otherwise.
+
+ The idea behind all the remaining parameters is that their names match
+ the name of certain fields in the breakpoint structure that are used to
+ handle exception catchpoints. This function returns the value to which
+ these fields should be set, depending on the type of catchpoint we need
+ to create.
+
+ If COND and COND_STRING are both non-NULL, any value they might
+ hold will be free'ed, and then replaced by newly allocated ones.
+ These parameters are left untouched otherwise. */
+
+static struct symtab_and_line
+ada_exception_sal (enum exception_catchpoint_kind ex, char *exp_string,
+ char **addr_string, char **cond_string,
+ struct expression **cond, struct breakpoint_ops **ops)
+{
+ const char *sym_name;
+ struct symbol *sym;
+ struct symtab_and_line sal;
+
+ /* First, find out which exception support info to use. */
+ ada_exception_support_info_sniffer ();
+
+ /* Then lookup the function on which we will break in order to catch
+ the Ada exceptions requested by the user. */
+
+ sym_name = ada_exception_sym_name (ex);
+ sym = standard_lookup (sym_name, NULL, VAR_DOMAIN);
+
+ /* The symbol we're looking up is provided by a unit in the GNAT runtime
+ that should be compiled with debugging information. As a result, we
+ expect to find that symbol in the symtabs. If we don't find it, then
+ the target most likely does not support Ada exceptions, or we cannot
+ insert exception breakpoints yet, because the GNAT runtime hasn't been
+ loaded yet. */
+
+ /* brobecker/2006-12-26: It is conceivable that the runtime was compiled
+ in such a way that no debugging information is produced for the symbol
+ we are looking for. In this case, we could search the minimal symbols
+ as a fall-back mechanism. This would still be operating in degraded
+ mode, however, as we would still be missing the debugging information
+ that is needed in order to extract the name of the exception being
+ raised (this name is printed in the catchpoint message, and is also
+ used when trying to catch a specific exception). We do not handle
+ this case for now. */
+
+ if (sym == NULL)
+ error (_("Unable to break on '%s' in this configuration."), sym_name);
+
+ /* 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_name, SYMBOL_CLASS (sym));
+
+ sal = find_function_start_sal (sym, 1);
+
+ /* Set ADDR_STRING. */
+
+ *addr_string = xstrdup (sym_name);
+
+ /* Set the COND and COND_STRING (if not NULL). */
+
+ if (cond_string != NULL && cond != NULL)
+ {
+ if (*cond_string != NULL)
+ {
+ xfree (*cond_string);
+ *cond_string = NULL;
+ }
+ if (*cond != NULL)
+ {
+ xfree (*cond);
+ *cond = NULL;
+ }
+ if (exp_string != NULL)
+ {
+ *cond_string = ada_exception_catchpoint_cond_string (exp_string);
+ *cond = ada_parse_catchpoint_condition (*cond_string, sal);
+ }
+ }
+
+ /* Set OPS. */
+ *ops = ada_exception_breakpoint_ops (ex);
+
+ return sal;
+}
+
+/* Parse the arguments (ARGS) of the "catch exception" command.
+
+ Set TYPE to the appropriate exception catchpoint type.
+ If the user asked the catchpoint to catch only a specific
+ exception, then save the exception name in ADDR_STRING.
+
+ See ada_exception_sal for a description of all the remaining
+ function arguments of this function. */
+
+struct symtab_and_line
+ada_decode_exception_location (char *args, char **addr_string,
+ char **exp_string, char **cond_string,
+ struct expression **cond,
+ struct breakpoint_ops **ops)
+{
+ enum exception_catchpoint_kind ex;
+
+ catch_ada_exception_command_split (args, &ex, exp_string);
+ return ada_exception_sal (ex, *exp_string, addr_string, cond_string,
+ cond, ops);
+}
+
+struct symtab_and_line
+ada_decode_assert_location (char *args, char **addr_string,
+ struct breakpoint_ops **ops)
+{
+ /* Check that no argument where provided at the end of the command. */
+
+ if (args != NULL)
+ {
+ while (isspace (*args))
+ args++;
+ if (*args != '\0')
+ error (_("Junk at end of arguments."));
+ }
+
+ return ada_exception_sal (ex_catch_assert, NULL, addr_string, NULL, NULL,
+ ops);
+}
+
+ /* Operators */
+/* Information about operators given special treatment in functions
+ below. */
+/* Format: OP_DEFN (<operator>, <operator length>, <# args>, <binop>). */
+
+#define ADA_OPERATORS \
+ OP_DEFN (OP_VAR_VALUE, 4, 0, 0) \
+ OP_DEFN (BINOP_IN_BOUNDS, 3, 2, 0) \
+ OP_DEFN (TERNOP_IN_RANGE, 1, 3, 0) \
+ OP_DEFN (OP_ATR_FIRST, 1, 2, 0) \
+ OP_DEFN (OP_ATR_LAST, 1, 2, 0) \
+ OP_DEFN (OP_ATR_LENGTH, 1, 2, 0) \
+ OP_DEFN (OP_ATR_IMAGE, 1, 2, 0) \
+ OP_DEFN (OP_ATR_MAX, 1, 3, 0) \
+ OP_DEFN (OP_ATR_MIN, 1, 3, 0) \
+ OP_DEFN (OP_ATR_MODULUS, 1, 1, 0) \
+ OP_DEFN (OP_ATR_POS, 1, 2, 0) \
+ OP_DEFN (OP_ATR_SIZE, 1, 1, 0) \
+ OP_DEFN (OP_ATR_TAG, 1, 1, 0) \
+ OP_DEFN (OP_ATR_VAL, 1, 2, 0) \
+ OP_DEFN (UNOP_QUAL, 3, 1, 0) \
+ OP_DEFN (UNOP_IN_RANGE, 3, 1, 0) \
+ OP_DEFN (OP_OTHERS, 1, 1, 0) \
+ OP_DEFN (OP_POSITIONAL, 3, 1, 0) \
+ OP_DEFN (OP_DISCRETE_RANGE, 1, 2, 0)
+
+static void
+ada_operator_length (struct expression *exp, int pc, int *oplenp, int *argsp)
+{
+ switch (exp->elts[pc - 1].opcode)
+ {
+ default:
+ operator_length_standard (exp, pc, oplenp, argsp);
+ break;
+
+#define OP_DEFN(op, len, args, binop) \
+ case op: *oplenp = len; *argsp = args; break;
+ ADA_OPERATORS;
+#undef OP_DEFN
+
+ case OP_AGGREGATE:
+ *oplenp = 3;
+ *argsp = longest_to_int (exp->elts[pc - 2].longconst);
+ break;
+
+ case OP_CHOICES:
+ *oplenp = 3;
+ *argsp = longest_to_int (exp->elts[pc - 2].longconst) + 1;
+ break;
+ }
+}
+
+static char *
+ada_op_name (enum exp_opcode opcode)
+{
+ switch (opcode)
+ {
+ default:
+ return op_name_standard (opcode);
+
+#define OP_DEFN(op, len, args, binop) case op: return #op;
+ ADA_OPERATORS;
+#undef OP_DEFN
+
+ case OP_AGGREGATE:
+ return "OP_AGGREGATE";
+ case OP_CHOICES:
+ return "OP_CHOICES";
+ case OP_NAME:
+ return "OP_NAME";
+ }
+}
+
+/* As for operator_length, but assumes PC is pointing at the first
+ element of the operator, and gives meaningful results only for the
+ Ada-specific operators, returning 0 for *OPLENP and *ARGSP otherwise. */
+
+static void
+ada_forward_operator_length (struct expression *exp, int pc,
+ int *oplenp, int *argsp)
+{
+ switch (exp->elts[pc].opcode)
+ {
+ default:
+ *oplenp = *argsp = 0;
+ break;
+
+#define OP_DEFN(op, len, args, binop) \
+ case op: *oplenp = len; *argsp = args; break;
+ ADA_OPERATORS;
+#undef OP_DEFN
+
+ case OP_AGGREGATE:
+ *oplenp = 3;
+ *argsp = longest_to_int (exp->elts[pc + 1].longconst);
+ break;
+
+ case OP_CHOICES:
+ *oplenp = 3;
+ *argsp = longest_to_int (exp->elts[pc + 1].longconst) + 1;
+ break;
+
+ case OP_STRING:
+ case OP_NAME:
+ {
+ int len = longest_to_int (exp->elts[pc + 1].longconst);
+ *oplenp = 4 + BYTES_TO_EXP_ELEM (len + 1);
+ *argsp = 0;
+ break;
+ }
+ }
+}
+
+static int
+ada_dump_subexp_body (struct expression *exp, struct ui_file *stream, int elt)
+{
+ enum exp_opcode op = exp->elts[elt].opcode;
+ int oplen, nargs;
+ int pc = elt;
+ int i;
+
+ ada_forward_operator_length (exp, elt, &oplen, &nargs);
+
+ switch (op)
+ {
+ /* Ada attributes ('Foo). */
+ case OP_ATR_FIRST:
case OP_ATR_LAST:
case OP_ATR_LENGTH:
case OP_ATR_IMAGE:
fprintf_filtered (stream, ")");
break;
case BINOP_IN_BOUNDS:
- fprintf_filtered (stream, " (%d)", (int) exp->elts[pc + 2].longconst);
+ fprintf_filtered (stream, " (%d)",
+ longest_to_int (exp->elts[pc + 2].longconst));
break;
case TERNOP_IN_RANGE:
break;
+ case OP_AGGREGATE:
+ case OP_OTHERS:
+ case OP_DISCRETE_RANGE:
+ case OP_POSITIONAL:
+ case OP_CHOICES:
+ break;
+
+ case OP_NAME:
+ case OP_STRING:
+ {
+ char *name = &exp->elts[elt + 2].string;
+ int len = longest_to_int (exp->elts[elt + 1].longconst);
+ fprintf_filtered (stream, "Text: `%.*s'", len, name);
+ break;
+ }
+
default:
return dump_subexp_body_standard (exp, stream, elt);
}
ada_print_subexp (struct expression *exp, int *pos,
struct ui_file *stream, enum precedence prec)
{
- int oplen, nargs;
+ int oplen, nargs, i;
int pc = *pos;
enum exp_opcode op = exp->elts[pc].opcode;
ada_forward_operator_length (exp, pc, &oplen, &nargs);
+ *pos += oplen;
switch (op)
{
default:
+ *pos -= oplen;
print_subexp_standard (exp, pos, stream, prec);
return;
case OP_VAR_VALUE:
- *pos += oplen;
fputs_filtered (SYMBOL_NATURAL_NAME (exp->elts[pc + 2].symbol), stream);
return;
case BINOP_IN_BOUNDS:
/* XXX: sprint_subexp */
- *pos += oplen;
print_subexp (exp, pos, stream, PREC_SUFFIX);
fputs_filtered (" in ", stream);
print_subexp (exp, pos, stream, PREC_SUFFIX);
return;
case TERNOP_IN_RANGE:
- *pos += oplen;
if (prec >= PREC_EQUAL)
fputs_filtered ("(", stream);
/* XXX: sprint_subexp */
case OP_ATR_SIZE:
case OP_ATR_TAG:
case OP_ATR_VAL:
- *pos += oplen;
if (exp->elts[*pos].opcode == OP_TYPE)
{
if (TYPE_CODE (exp->elts[*pos + 1].type) != TYPE_CODE_VOID)
return;
case UNOP_QUAL:
- *pos += oplen;
type_print (exp->elts[pc + 1].type, "", stream, 0);
fputs_filtered ("'(", stream);
print_subexp (exp, pos, stream, PREC_PREFIX);
return;
case UNOP_IN_RANGE:
- *pos += oplen;
/* XXX: sprint_subexp */
print_subexp (exp, pos, stream, PREC_SUFFIX);
fputs_filtered (" in ", stream);
LA_PRINT_TYPE (exp->elts[pc + 1].type, "", stream, 1, 0);
return;
+
+ case OP_DISCRETE_RANGE:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("..", stream);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ return;
+
+ case OP_OTHERS:
+ fputs_filtered ("others => ", stream);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ return;
+
+ case OP_CHOICES:
+ for (i = 0; i < nargs-1; i += 1)
+ {
+ if (i > 0)
+ fputs_filtered ("|", stream);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ }
+ fputs_filtered (" => ", stream);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ return;
+
+ case OP_POSITIONAL:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ return;
+
+ case OP_AGGREGATE:
+ fputs_filtered ("(", stream);
+ for (i = 0; i < nargs; i += 1)
+ {
+ if (i > 0)
+ fputs_filtered (", ", stream);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ }
+ fputs_filtered (")", stream);
+ return;
}
}
{NULL, 0, 0, 0}
};
\f
- /* Fundamental Ada Types */
-
-/* Create a fundamental Ada type using default reasonable for the current
- target machine.
-
- Some object/debugging file formats (DWARF version 1, COFF, etc) do not
- define fundamental types such as "int" or "double". Others (stabs or
- DWARF version 2, etc) do define fundamental types. For the formats which
- don't provide fundamental types, gdb can create such types using this
- function.
-
- FIXME: Some compilers distinguish explicitly signed integral types
- (signed short, signed int, signed long) from "regular" integral types
- (short, int, long) in the debugging information. There is some dis-
- agreement as to how useful this feature is. In particular, gcc does
- not support this. Also, only some debugging formats allow the
- distinction to be passed on to a debugger. For now, we always just
- use "short", "int", or "long" as the type name, for both the implicit
- and explicitly signed types. This also makes life easier for the
- gdb test suite since we don't have to account for the differences
- in output depending upon what the compiler and debugging format
- support. We will probably have to re-examine the issue when gdb
- starts taking it's fundamental type information directly from the
- debugging information supplied by the compiler. fnf@cygnus.com */
-
-static struct type *
-ada_create_fundamental_type (struct objfile *objfile, int typeid)
-{
- struct type *type = NULL;
-
- switch (typeid)
- {
- default:
- /* FIXME: For now, if we are asked to produce a type not in this
- language, create the equivalent of a C integer type with the
- name "<?type?>". When all the dust settles from the type
- reconstruction work, this should probably become an error. */
- type = init_type (TYPE_CODE_INT,
- TARGET_INT_BIT / TARGET_CHAR_BIT,
- 0, "<?type?>", objfile);
- warning (_("internal error: no Ada fundamental type %d"), typeid);
- break;
- case FT_VOID:
- type = init_type (TYPE_CODE_VOID,
- TARGET_CHAR_BIT / TARGET_CHAR_BIT,
- 0, "void", objfile);
- break;
- case FT_CHAR:
- type = init_type (TYPE_CODE_INT,
- TARGET_CHAR_BIT / TARGET_CHAR_BIT,
- 0, "character", objfile);
- break;
- case FT_SIGNED_CHAR:
- type = init_type (TYPE_CODE_INT,
- TARGET_CHAR_BIT / TARGET_CHAR_BIT,
- 0, "signed char", objfile);
- break;
- case FT_UNSIGNED_CHAR:
- type = init_type (TYPE_CODE_INT,
- TARGET_CHAR_BIT / TARGET_CHAR_BIT,
- TYPE_FLAG_UNSIGNED, "unsigned char", objfile);
- break;
- case FT_SHORT:
- type = init_type (TYPE_CODE_INT,
- TARGET_SHORT_BIT / TARGET_CHAR_BIT,
- 0, "short_integer", objfile);
- break;
- case FT_SIGNED_SHORT:
- type = init_type (TYPE_CODE_INT,
- TARGET_SHORT_BIT / TARGET_CHAR_BIT,
- 0, "short_integer", objfile);
- break;
- case FT_UNSIGNED_SHORT:
- type = init_type (TYPE_CODE_INT,
- TARGET_SHORT_BIT / TARGET_CHAR_BIT,
- TYPE_FLAG_UNSIGNED, "unsigned short", objfile);
- break;
- case FT_INTEGER:
- type = init_type (TYPE_CODE_INT,
- TARGET_INT_BIT / TARGET_CHAR_BIT,
- 0, "integer", objfile);
- break;
- case FT_SIGNED_INTEGER:
- type = init_type (TYPE_CODE_INT, TARGET_INT_BIT /
- TARGET_CHAR_BIT,
- 0, "integer", objfile); /* FIXME -fnf */
- break;
- case FT_UNSIGNED_INTEGER:
- type = init_type (TYPE_CODE_INT,
- TARGET_INT_BIT / TARGET_CHAR_BIT,
- TYPE_FLAG_UNSIGNED, "unsigned int", objfile);
- break;
- case FT_LONG:
- type = init_type (TYPE_CODE_INT,
- TARGET_LONG_BIT / TARGET_CHAR_BIT,
- 0, "long_integer", objfile);
- break;
- case FT_SIGNED_LONG:
- type = init_type (TYPE_CODE_INT,
- TARGET_LONG_BIT / TARGET_CHAR_BIT,
- 0, "long_integer", objfile);
- break;
- case FT_UNSIGNED_LONG:
- type = init_type (TYPE_CODE_INT,
- TARGET_LONG_BIT / TARGET_CHAR_BIT,
- TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
- break;
- case FT_LONG_LONG:
- type = init_type (TYPE_CODE_INT,
- TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
- 0, "long_long_integer", objfile);
- break;
- case FT_SIGNED_LONG_LONG:
- type = init_type (TYPE_CODE_INT,
- TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
- 0, "long_long_integer", objfile);
- break;
- case FT_UNSIGNED_LONG_LONG:
- type = init_type (TYPE_CODE_INT,
- TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
- TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
- break;
- case FT_FLOAT:
- type = init_type (TYPE_CODE_FLT,
- TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
- 0, "float", objfile);
- break;
- case FT_DBL_PREC_FLOAT:
- type = init_type (TYPE_CODE_FLT,
- TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
- 0, "long_float", objfile);
- break;
- case FT_EXT_PREC_FLOAT:
- type = init_type (TYPE_CODE_FLT,
- TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
- 0, "long_long_float", objfile);
- break;
- }
- return (type);
-}
-
enum ada_primitive_types {
ada_primitive_type_int,
ada_primitive_type_long,
};
static void
-ada_language_arch_info (struct gdbarch *current_gdbarch,
+ada_language_arch_info (struct gdbarch *gdbarch,
struct language_arch_info *lai)
{
- const struct builtin_type *builtin = builtin_type (current_gdbarch);
+ const struct builtin_type *builtin = builtin_type (gdbarch);
lai->primitive_type_vector
- = GDBARCH_OBSTACK_CALLOC (current_gdbarch, nr_ada_primitive_types + 1,
+ = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_ada_primitive_types + 1,
struct type *);
lai->primitive_type_vector [ada_primitive_type_int] =
- init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
- 0, "integer", (struct objfile *) NULL);
+ init_type (TYPE_CODE_INT,
+ gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT,
+ 0, "integer", (struct objfile *) NULL);
lai->primitive_type_vector [ada_primitive_type_long] =
- init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
- 0, "long_integer", (struct objfile *) NULL);
+ init_type (TYPE_CODE_INT,
+ gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT,
+ 0, "long_integer", (struct objfile *) NULL);
lai->primitive_type_vector [ada_primitive_type_short] =
- init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
- 0, "short_integer", (struct objfile *) NULL);
+ init_type (TYPE_CODE_INT,
+ gdbarch_short_bit (gdbarch) / TARGET_CHAR_BIT,
+ 0, "short_integer", (struct objfile *) NULL);
lai->string_char_type =
lai->primitive_type_vector [ada_primitive_type_char] =
init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
0, "character", (struct objfile *) NULL);
lai->primitive_type_vector [ada_primitive_type_float] =
- init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ init_type (TYPE_CODE_FLT,
+ gdbarch_float_bit (gdbarch)/ TARGET_CHAR_BIT,
0, "float", (struct objfile *) NULL);
lai->primitive_type_vector [ada_primitive_type_double] =
- init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ init_type (TYPE_CODE_FLT,
+ gdbarch_double_bit (gdbarch) / TARGET_CHAR_BIT,
0, "long_float", (struct objfile *) NULL);
lai->primitive_type_vector [ada_primitive_type_long_long] =
- init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ init_type (TYPE_CODE_INT,
+ gdbarch_long_long_bit (gdbarch) / TARGET_CHAR_BIT,
0, "long_long_integer", (struct objfile *) NULL);
lai->primitive_type_vector [ada_primitive_type_long_double] =
- init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ init_type (TYPE_CODE_FLT,
+ gdbarch_double_bit (gdbarch) / TARGET_CHAR_BIT,
0, "long_long_float", (struct objfile *) NULL);
lai->primitive_type_vector [ada_primitive_type_natural] =
- init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
- 0, "natural", (struct objfile *) NULL);
+ init_type (TYPE_CODE_INT,
+ gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT,
+ 0, "natural", (struct objfile *) NULL);
lai->primitive_type_vector [ada_primitive_type_positive] =
- init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
- 0, "positive", (struct objfile *) NULL);
+ init_type (TYPE_CODE_INT,
+ gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT,
+ 0, "positive", (struct objfile *) NULL);
lai->primitive_type_vector [ada_primitive_type_void] = builtin->builtin_void;
lai->primitive_type_vector [ada_primitive_type_system_address] =
const struct language_defn ada_language_defn = {
"ada", /* Language name */
language_ada,
- NULL,
range_check_off,
type_check_off,
case_sensitive_on, /* Yes, Ada is case-insensitive, but
ada_printchar, /* Print a character constant */
ada_printstr, /* Function to print string constant */
emit_char, /* Function to print single char (not used) */
- ada_create_fundamental_type, /* Create fundamental type in this language */
ada_print_type, /* Print a type using appropriate syntax */
ada_val_print, /* Print a value using appropriate syntax */
ada_value_print, /* Print a top-level value */
ada_op_print_tab, /* expression operators for printing */
0, /* c-style arrays */
1, /* String lower bound */
- NULL,
ada_get_gdb_completer_word_break_characters,
ada_language_arch_info,
+ ada_print_array_index,
+ default_pass_by_reference,
LANG_MAGIC
};
decoded_names_store = htab_create_alloc
(256, htab_hash_string, (int (*)(const void *, const void *)) streq,
NULL, xcalloc, xfree);
+
+ observer_attach_executable_changed (ada_executable_changed_observer);
}