Implement Ada min and max operations
[deliverable/binutils-gdb.git] / gdb / ada-lang.c
index ca66642dee02d039e360f912d3ffa4092f99153a..418cc04cce1dd195d57940bb1f76dc874f500bd1 100644 (file)
@@ -1,6 +1,6 @@
 /* Ada language support routines for GDB, the GNU debugger.
 
 /* Ada language support routines for GDB, the GNU debugger.
 
-   Copyright (C) 1992-2020 Free Software Foundation, Inc.
+   Copyright (C) 1992-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
    This file is part of GDB.
 
@@ -57,6 +57,7 @@
 #include "gdbsupport/function-view.h"
 #include "gdbsupport/byte-vector.h"
 #include <algorithm>
 #include "gdbsupport/function-view.h"
 #include "gdbsupport/byte-vector.h"
 #include <algorithm>
+#include "ada-exp.h"
 
 /* Define whether or not the C operator '/' truncates towards zero for
    differently signed operands (truncation direction is undefined in C).
 
 /* Define whether or not the C operator '/' truncates towards zero for
    differently signed operands (truncation direction is undefined in C).
@@ -100,24 +101,22 @@ static int ada_args_match (struct symbol *, struct value **, int);
 
 static struct value *make_array_descriptor (struct type *, struct value *);
 
 
 static struct value *make_array_descriptor (struct type *, struct value *);
 
-static void ada_add_block_symbols (struct obstack *,
+static void ada_add_block_symbols (std::vector<struct block_symbol> &,
                                   const struct block *,
                                   const lookup_name_info &lookup_name,
                                   domain_enum, struct objfile *);
 
                                   const struct block *,
                                   const lookup_name_info &lookup_name,
                                   domain_enum, struct objfile *);
 
-static void ada_add_all_symbols (struct obstack *, const struct block *,
+static void ada_add_all_symbols (std::vector<struct block_symbol> &,
+                                const struct block *,
                                 const lookup_name_info &lookup_name,
                                 domain_enum, int, int *);
 
                                 const lookup_name_info &lookup_name,
                                 domain_enum, int, int *);
 
-static int is_nonfunction (struct block_symbol *, int);
+static int is_nonfunction (const std::vector<struct block_symbol> &);
 
 
-static void add_defn_to_vec (struct obstack *, struct symbol *,
+static void add_defn_to_vec (std::vector<struct block_symbol> &,
+                            struct symbol *,
                             const struct block *);
 
                             const struct block *);
 
-static int num_defns_collected (struct obstack *);
-
-static struct block_symbol *defns_collected (struct obstack *, int);
-
 static struct value *resolve_subexp (expression_up *, int *, int,
                                     struct type *, int,
                                     innermost_block_tracker *);
 static struct value *resolve_subexp (expression_up *, int *, int,
                                     struct type *, int,
                                     innermost_block_tracker *);
@@ -194,8 +193,6 @@ static struct value *value_pos_atr (struct type *, struct value *);
 
 static struct value *val_atr (struct type *, LONGEST);
 
 
 static struct value *val_atr (struct type *, LONGEST);
 
-static struct value *value_val_atr (struct type *, struct value *);
-
 static struct symbol *standard_lookup (const char *, const struct block *,
                                       domain_enum);
 
 static struct symbol *standard_lookup (const char *, const struct block *,
                                       domain_enum);
 
@@ -205,7 +202,7 @@ static struct value *ada_search_struct_field (const char *, struct value *, int,
 static int find_struct_field (const char *, struct type *, int,
                              struct type **, int *, int *, int *, int *);
 
 static int find_struct_field (const char *, struct type *, int,
                              struct type **, int *, int *, int *, int *);
 
-static int ada_resolve_function (struct block_symbol *, int,
+static int ada_resolve_function (std::vector<struct block_symbol> &,
                                 struct value **, int, const char *,
                                 struct type *, int);
 
                                 struct value **, int, const char *,
                                 struct type *, int);
 
@@ -218,23 +215,24 @@ static struct value *assign_aggregate (struct value *, struct value *,
                                       struct expression *,
                                       int *, enum noside);
 
                                       struct expression *,
                                       int *, enum noside);
 
-static void aggregate_assign_from_choices (struct value *, struct value *, 
+static void aggregate_assign_from_choices (struct value *, struct value *,
                                           struct expression *,
                                           struct expression *,
-                                          int *, LONGEST *, int *,
-                                          int, LONGEST, LONGEST);
+                                          int *, std::vector<LONGEST> &,
+                                          LONGEST, LONGEST);
 
 static void aggregate_assign_positional (struct value *, struct value *,
                                         struct expression *,
 
 static void aggregate_assign_positional (struct value *, struct value *,
                                         struct expression *,
-                                        int *, LONGEST *, int *, int,
+                                        int *, std::vector<LONGEST> &,
                                         LONGEST, LONGEST);
 
 
 static void aggregate_assign_others (struct value *, struct value *,
                                     struct expression *,
                                         LONGEST, LONGEST);
 
 
 static void aggregate_assign_others (struct value *, struct value *,
                                     struct expression *,
-                                    int *, LONGEST *, int, LONGEST, LONGEST);
+                                    int *, std::vector<LONGEST> &,
+                                    LONGEST, LONGEST);
 
 
 
 
-static void add_component_interval (LONGEST, LONGEST, LONGEST *, int *, int);
+static void add_component_interval (LONGEST, LONGEST, std::vector<LONGEST> &);
 
 
 static struct value *ada_evaluate_subexp (struct type *, struct expression *,
 
 
 static struct value *ada_evaluate_subexp (struct type *, struct expression *,
@@ -282,14 +280,12 @@ struct cache_entry
 struct ada_symbol_cache
 {
   /* An obstack used to store the entries in our cache.  */
 struct ada_symbol_cache
 {
   /* An obstack used to store the entries in our cache.  */
-  struct obstack cache_space;
+  struct auto_obstack cache_space;
 
   /* The root of the hash table used to implement our symbol cache.  */
 
   /* The root of the hash table used to implement our symbol cache.  */
-  struct cache_entry *root[HASH_SIZE];
+  struct cache_entry *root[HASH_SIZE] {};
 };
 
 };
 
-static void ada_free_symbol_cache (struct ada_symbol_cache *sym_cache);
-
 /* Maximum-sized dynamic type.  */
 static unsigned int varsize_limit;
 
 /* Maximum-sized dynamic type.  */
 static unsigned int varsize_limit;
 
@@ -384,14 +380,8 @@ ada_inferior_exit (struct inferior *inf)
 /* This module's per-program-space data.  */
 struct ada_pspace_data
 {
 /* This module's per-program-space data.  */
 struct ada_pspace_data
 {
-  ~ada_pspace_data ()
-  {
-    if (sym_cache != NULL)
-      ada_free_symbol_cache (sym_cache);
-  }
-
   /* The Ada symbol cache.  */
   /* The Ada symbol cache.  */
-  struct ada_symbol_cache *sym_cache = nullptr;
+  std::unique_ptr<ada_symbol_cache> sym_cache;
 };
 
 /* Key to our per-program-space data.  */
 };
 
 /* Key to our per-program-space data.  */
@@ -484,29 +474,6 @@ add_angle_brackets (const char *str)
   return string_printf ("<%s>", str);
 }
 
   return string_printf ("<%s>", str);
 }
 
-/* Assuming V points to an array of S objects,  make sure that it contains at
-   least M objects, updating V and S as necessary.  */
-
-#define GROW_VECT(v, s, m)                                    \
-   if ((s) < (m)) (v) = (char *) grow_vect (v, &(s), m, sizeof *(v));
-
-/* Assuming VECT points to an array of *SIZE objects of size
-   ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
-   updating *SIZE as necessary and returning the (new) array.  */
-
-static void *
-grow_vect (void *vect, size_t *size, size_t min_size, int element_size)
-{
-  if (*size < min_size)
-    {
-      *size *= 2;
-      if (*size < min_size)
-       *size = min_size;
-      vect = xrealloc (vect, *size * element_size);
-    }
-  return vect;
-}
-
 /* True (non-zero) iff TARGET matches FIELD_NAME up to any trailing
    suffix of FIELD_NAME beginning "___".  */
 
 /* True (non-zero) iff TARGET matches FIELD_NAME up to any trailing
    suffix of FIELD_NAME beginning "___".  */
 
@@ -600,13 +567,17 @@ coerce_unspec_val_to_type (struct value *val, struct type *type)
         trying to allocate some memory for it.  */
       ada_ensure_varsize_limit (type);
 
         trying to allocate some memory for it.  */
       ada_ensure_varsize_limit (type);
 
-      if (value_lazy (val)
-         || TYPE_LENGTH (type) > TYPE_LENGTH (value_type (val)))
+      if (value_optimized_out (val))
+       result = allocate_optimized_out_value (type);
+      else if (value_lazy (val)
+              /* Be careful not to make a lazy not_lval value.  */
+              || (VALUE_LVAL (val) != not_lval
+                  && TYPE_LENGTH (type) > TYPE_LENGTH (value_type (val))))
        result = allocate_value_lazy (type);
       else
        {
          result = allocate_value (type);
        result = allocate_value_lazy (type);
       else
        {
          result = allocate_value (type);
-         value_contents_copy_raw (result, 0, val, 0, TYPE_LENGTH (type));
+         value_contents_copy (result, 0, val, 0, TYPE_LENGTH (type));
        }
       set_value_component_location (result, val);
       set_value_bitsize (result, value_bitsize (val));
        }
       set_value_component_location (result, val);
       set_value_bitsize (result, value_bitsize (val));
@@ -966,30 +937,21 @@ ada_encode (const char *decoded)
    quotes, unfolded, but with the quotes stripped away.  Result good
    to next call.  */
 
    quotes, unfolded, but with the quotes stripped away.  Result good
    to next call.  */
 
-static char *
+static const char *
 ada_fold_name (gdb::string_view name)
 {
 ada_fold_name (gdb::string_view name)
 {
-  static char *fold_buffer = NULL;
-  static size_t fold_buffer_size = 0;
-
-  int len = name.size ();
-  GROW_VECT (fold_buffer, fold_buffer_size, len + 1);
+  static std::string fold_storage;
 
 
-  if (name[0] == '\'')
-    {
-      strncpy (fold_buffer, name.data () + 1, len - 2);
-      fold_buffer[len - 2] = '\000';
-    }
+  if (!name.empty () && name[0] == '\'')
+    fold_storage = gdb::to_string (name.substr (1, name.size () - 2));
   else
     {
   else
     {
-      int i;
-
-      for (i = 0; i < len; i += 1)
-       fold_buffer[i] = tolower (name[i]);
-      fold_buffer[i] = '\0';
+      fold_storage = gdb::to_string (name);
+      for (int i = 0; i < name.size (); i += 1)
+       fold_storage[i] = tolower (fold_storage[i]);
     }
 
     }
 
-  return fold_buffer;
+  return fold_storage.c_str ();
 }
 
 /* Return nonzero if C is either a digit or a lowercase alphabet character.  */
 }
 
 /* Return nonzero if C is either a digit or a lowercase alphabet character.  */
@@ -3452,6 +3414,126 @@ See set/show multiple-symbol."));
   return n_chosen;
 }
 
   return n_chosen;
 }
 
+/* See ada-lang.h.  */
+
+block_symbol
+ada_find_operator_symbol (enum exp_opcode op, int parse_completion,
+                         int nargs, value *argvec[])
+{
+  if (possible_user_operator_p (op, argvec))
+    {
+      std::vector<struct block_symbol> candidates
+       = ada_lookup_symbol_list (ada_decoded_op_name (op),
+                                 NULL, VAR_DOMAIN);
+
+      int i = ada_resolve_function (candidates, argvec,
+                                   nargs, ada_decoded_op_name (op), NULL,
+                                   parse_completion);
+      if (i >= 0)
+       return candidates[i];
+    }
+  return {};
+}
+
+/* See ada-lang.h.  */
+
+block_symbol
+ada_resolve_funcall (struct symbol *sym, const struct block *block,
+                    struct type *context_type,
+                    int parse_completion,
+                    int nargs, value *argvec[],
+                    innermost_block_tracker *tracker)
+{
+  std::vector<struct block_symbol> candidates
+    = ada_lookup_symbol_list (sym->linkage_name (), block, VAR_DOMAIN);
+
+  int i;
+  if (candidates.size () == 1)
+    i = 0;
+  else
+    {
+      i = ada_resolve_function
+       (candidates,
+        argvec, nargs,
+        sym->linkage_name (),
+        context_type, parse_completion);
+      if (i < 0)
+       error (_("Could not find a match for %s"), sym->print_name ());
+    }
+
+  tracker->update (candidates[i]);
+  return candidates[i];
+}
+
+/* See ada-lang.h.  */
+
+block_symbol
+ada_resolve_variable (struct symbol *sym, const struct block *block,
+                     struct type *context_type,
+                     int parse_completion,
+                     int deprocedure_p,
+                     innermost_block_tracker *tracker)
+{
+  std::vector<struct block_symbol> candidates
+    = ada_lookup_symbol_list (sym->linkage_name (), block, VAR_DOMAIN);
+
+  if (std::any_of (candidates.begin (),
+                  candidates.end (),
+                  [] (block_symbol &bsym)
+                  {
+                    switch (SYMBOL_CLASS (bsym.symbol))
+                      {
+                      case LOC_REGISTER:
+                      case LOC_ARG:
+                      case LOC_REF_ARG:
+                      case LOC_REGPARM_ADDR:
+                      case LOC_LOCAL:
+                      case LOC_COMPUTED:
+                        return true;
+                      default:
+                        return false;
+                      }
+                  }))
+    {
+      /* Types tend to get re-introduced locally, so if there
+        are any local symbols that are not types, first filter
+        out all types.  */
+      candidates.erase
+       (std::remove_if
+        (candidates.begin (),
+         candidates.end (),
+         [] (block_symbol &bsym)
+         {
+           return SYMBOL_CLASS (bsym.symbol) == LOC_TYPEDEF;
+         }),
+        candidates.end ());
+    }
+
+  int i;
+  if (candidates.empty ())
+    error (_("No definition found for %s"), sym->print_name ());
+  else if (candidates.size () == 1)
+    i = 0;
+  else if (deprocedure_p && !is_nonfunction (candidates))
+    {
+      i = ada_resolve_function
+       (candidates, NULL, 0,
+        sym->linkage_name (),
+        context_type, parse_completion);
+      if (i < 0)
+       error (_("Could not find a match for %s"), sym->print_name ());
+    }
+  else
+    {
+      printf_filtered (_("Multiple matches for %s\n"), sym->print_name ());
+      user_select_syms (candidates.data (), candidates.size (), 1);
+      i = 0;
+    }
+
+  tracker->update (candidates[i]);
+  return candidates[i];
+}
+
 /* Resolve the operator of the subexpression beginning at
    position *POS of *EXPP.  "Resolving" consists of replacing
    the symbols that have undefined namespaces in OP_VAR_VALUE nodes
 /* Resolve the operator of the subexpression beginning at
    position *POS of *EXPP.  "Resolving" consists of replacing
    the symbols that have undefined namespaces in OP_VAR_VALUE nodes
@@ -3473,6 +3555,12 @@ resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
   struct value **argvec;        /* Vector of operand types (alloca'ed).  */
   int nargs;                    /* Number of operands.  */
   int oplen;
   struct value **argvec;        /* Vector of operand types (alloca'ed).  */
   int nargs;                    /* Number of operands.  */
   int oplen;
+  /* If we're resolving an expression like ARRAY(ARG...), then we set
+     this to the type of the array, so we can use the index types as
+     the expected types for resolution.  */
+  struct type *array_type = nullptr;
+  /* The arity of ARRAY_TYPE.  */
+  int array_arity = 0;
 
   argvec = NULL;
   nargs = 0;
 
   argvec = NULL;
   nargs = 0;
@@ -3489,7 +3577,12 @@ resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
       else
        {
          *pos += 3;
       else
        {
          *pos += 3;
-         resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
+         struct value *lhs = resolve_subexp (expp, pos, 0, NULL,
+                                             parse_completion, tracker);
+         struct type *lhstype = ada_check_typedef (value_type (lhs));
+         array_arity = ada_array_arity (lhstype);
+         if (array_arity > 0)
+           array_type = lhstype;
        }
       nargs = longest_to_int (exp->elts[pc + 1].longconst);
       break;
        }
       nargs = longest_to_int (exp->elts[pc + 1].longconst);
       break;
@@ -3626,8 +3719,13 @@ resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
 
   argvec = XALLOCAVEC (struct value *, nargs + 1);
   for (i = 0; i < nargs; i += 1)
 
   argvec = XALLOCAVEC (struct value *, nargs + 1);
   for (i = 0; i < nargs; i += 1)
-    argvec[i] = resolve_subexp (expp, pos, 1, NULL, parse_completion,
-                               tracker);
+    {
+      struct type *subtype = nullptr;
+      if (i < array_arity)
+       subtype = ada_index_type (array_type, i + 1, "array type");
+      argvec[i] = resolve_subexp (expp, pos, 1, subtype, parse_completion,
+                                 tracker);
+    }
   argvec[i] = NULL;
   exp = expp->get ();
 
   argvec[i] = NULL;
   exp = expp->get ();
 
@@ -3640,77 +3738,13 @@ resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
     case OP_VAR_VALUE:
       if (SYMBOL_DOMAIN (exp->elts[pc + 2].symbol) == UNDEF_DOMAIN)
        {
     case OP_VAR_VALUE:
       if (SYMBOL_DOMAIN (exp->elts[pc + 2].symbol) == UNDEF_DOMAIN)
        {
-         std::vector<struct block_symbol> candidates;
-         int n_candidates;
-
-         n_candidates =
-           ada_lookup_symbol_list (exp->elts[pc + 2].symbol->linkage_name (),
-                                   exp->elts[pc + 1].block, VAR_DOMAIN,
-                                   &candidates);
-
-         if (n_candidates > 1)
-           {
-             /* Types tend to get re-introduced locally, so if there
-                are any local symbols that are not types, first filter
-                out all types.  */
-             int j;
-             for (j = 0; j < n_candidates; j += 1)
-               switch (SYMBOL_CLASS (candidates[j].symbol))
-                 {
-                 case LOC_REGISTER:
-                 case LOC_ARG:
-                 case LOC_REF_ARG:
-                 case LOC_REGPARM_ADDR:
-                 case LOC_LOCAL:
-                 case LOC_COMPUTED:
-                   goto FoundNonType;
-                 default:
-                   break;
-                 }
-           FoundNonType:
-             if (j < n_candidates)
-               {
-                 j = 0;
-                 while (j < n_candidates)
-                   {
-                     if (SYMBOL_CLASS (candidates[j].symbol) == LOC_TYPEDEF)
-                       {
-                         candidates[j] = candidates[n_candidates - 1];
-                         n_candidates -= 1;
-                       }
-                     else
-                       j += 1;
-                   }
-               }
-           }
-
-         if (n_candidates == 0)
-           error (_("No definition found for %s"),
-                  exp->elts[pc + 2].symbol->print_name ());
-         else if (n_candidates == 1)
-           i = 0;
-         else if (deprocedure_p
-                  && !is_nonfunction (candidates.data (), n_candidates))
-           {
-             i = ada_resolve_function
-               (candidates.data (), n_candidates, NULL, 0,
-                exp->elts[pc + 2].symbol->linkage_name (),
-                context_type, parse_completion);
-             if (i < 0)
-               error (_("Could not find a match for %s"),
-                      exp->elts[pc + 2].symbol->print_name ());
-           }
-         else
-           {
-             printf_filtered (_("Multiple matches for %s\n"),
-                              exp->elts[pc + 2].symbol->print_name ());
-             user_select_syms (candidates.data (), n_candidates, 1);
-             i = 0;
-           }
-
-         exp->elts[pc + 1].block = candidates[i].block;
-         exp->elts[pc + 2].symbol = candidates[i].symbol;
-         tracker->update (candidates[i]);
+         block_symbol resolved
+           = ada_resolve_variable (exp->elts[pc + 2].symbol,
+                                   exp->elts[pc + 1].block,
+                                   context_type, parse_completion,
+                                   deprocedure_p, tracker);
+         exp->elts[pc + 1].block = resolved.block;
+         exp->elts[pc + 2].symbol = resolved.symbol;
        }
 
       if (deprocedure_p
        }
 
       if (deprocedure_p
@@ -3729,31 +3763,14 @@ resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
        if (exp->elts[pc + 3].opcode == OP_VAR_VALUE
            && SYMBOL_DOMAIN (exp->elts[pc + 5].symbol) == UNDEF_DOMAIN)
          {
        if (exp->elts[pc + 3].opcode == OP_VAR_VALUE
            && SYMBOL_DOMAIN (exp->elts[pc + 5].symbol) == UNDEF_DOMAIN)
          {
-           std::vector<struct block_symbol> candidates;
-           int n_candidates;
-
-           n_candidates =
-             ada_lookup_symbol_list (exp->elts[pc + 5].symbol->linkage_name (),
-                                     exp->elts[pc + 4].block, VAR_DOMAIN,
-                                     &candidates);
-
-           if (n_candidates == 1)
-             i = 0;
-           else
-             {
-               i = ada_resolve_function
-                 (candidates.data (), n_candidates,
-                  argvec, nargs,
-                  exp->elts[pc + 5].symbol->linkage_name (),
-                  context_type, parse_completion);
-               if (i < 0)
-                 error (_("Could not find a match for %s"),
-                        exp->elts[pc + 5].symbol->print_name ());
-             }
-
-           exp->elts[pc + 4].block = candidates[i].block;
-           exp->elts[pc + 5].symbol = candidates[i].symbol;
-           tracker->update (candidates[i]);
+           block_symbol resolved
+             = ada_resolve_funcall (exp->elts[pc + 5].symbol,
+                                    exp->elts[pc + 4].block,
+                                    context_type, parse_completion,
+                                    nargs, argvec,
+                                    tracker);
+           exp->elts[pc + 4].block = resolved.block;
+           exp->elts[pc + 5].symbol = resolved.symbol;
          }
       }
       break;
          }
       }
       break;
@@ -3778,27 +3795,16 @@ resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
     case UNOP_PLUS:
     case UNOP_LOGICAL_NOT:
     case UNOP_ABS:
     case UNOP_PLUS:
     case UNOP_LOGICAL_NOT:
     case UNOP_ABS:
-      if (possible_user_operator_p (op, argvec))
-       {
-         std::vector<struct block_symbol> candidates;
-         int n_candidates;
-
-         n_candidates =
-           ada_lookup_symbol_list (ada_decoded_op_name (op),
-                                   NULL, VAR_DOMAIN,
-                                   &candidates);
-
-         i = ada_resolve_function (candidates.data (), n_candidates, argvec,
-                                   nargs, ada_decoded_op_name (op), NULL,
-                                   parse_completion);
-         if (i < 0)
-           break;
+      {
+       block_symbol found = ada_find_operator_symbol (op, parse_completion,
+                                                      nargs, argvec);
+       if (found.symbol == nullptr)
+         break;
 
 
-         replace_operator_with_call (expp, pc, nargs, 1,
-                                     candidates[i].symbol,
-                                     candidates[i].block);
-         exp = expp->get ();
-       }
+       replace_operator_with_call (expp, pc, nargs, 1,
+                                   found.symbol, found.block);
+       exp = expp->get ();
+      }
       break;
 
     case OP_TYPE:
       break;
 
     case OP_TYPE:
@@ -3941,7 +3947,7 @@ return_match (struct type *func_type, struct type *context_type)
 }
 
 
 }
 
 
-/* Returns the index in SYMS[0..NSYMS-1] that contains  the symbol for the
+/* Returns the index in SYMS that contains the symbol for the
    function (if any) that matches the types of the NARGS arguments in
    ARGS.  If CONTEXT_TYPE is non-null and there is at least one match
    that returns that type, then eliminate matches that don't.  If
    function (if any) that matches the types of the NARGS arguments in
    ARGS.  If CONTEXT_TYPE is non-null and there is at least one match
    that returns that type, then eliminate matches that don't.  If
@@ -3954,8 +3960,8 @@ return_match (struct type *func_type, struct type *context_type)
    the process; the index returned is for the modified vector.  */
 
 static int
    the process; the index returned is for the modified vector.  */
 
 static int
-ada_resolve_function (struct block_symbol syms[],
-                     int nsyms, struct value **args, int nargs,
+ada_resolve_function (std::vector<struct block_symbol> &syms,
+                     struct value **args, int nargs,
                      const char *name, struct type *context_type,
                      int parse_completion)
 {
                      const char *name, struct type *context_type,
                      int parse_completion)
 {
@@ -3969,7 +3975,7 @@ ada_resolve_function (struct block_symbol syms[],
      where every function is accepted.  */
   for (fallback = 0; m == 0 && fallback < 2; fallback++)
     {
      where every function is accepted.  */
   for (fallback = 0; m == 0 && fallback < 2; fallback++)
     {
-      for (k = 0; k < nsyms; k += 1)
+      for (k = 0; k < syms.size (); k += 1)
        {
          struct type *type = ada_check_typedef (SYMBOL_TYPE (syms[k].symbol));
 
        {
          struct type *type = ada_check_typedef (SYMBOL_TYPE (syms[k].symbol));
 
@@ -3991,7 +3997,7 @@ ada_resolve_function (struct block_symbol syms[],
   else if (m > 1 && !parse_completion)
     {
       printf_filtered (_("Multiple matches for %s\n"), name);
   else if (m > 1 && !parse_completion)
     {
       printf_filtered (_("Multiple matches for %s\n"), name);
-      user_select_syms (syms, m, 1);
+      user_select_syms (syms.data (), m, 1);
       return 0;
     }
   return 0;
       return 0;
     }
   return 0;
@@ -4508,13 +4514,12 @@ ada_convert_actual (struct value *actual, struct type *formal_type0)
 static CORE_ADDR
 value_pointer (struct value *value, struct type *type)
 {
 static CORE_ADDR
 value_pointer (struct value *value, struct type *type)
 {
-  struct gdbarch *gdbarch = get_type_arch (type);
   unsigned len = TYPE_LENGTH (type);
   gdb_byte *buf = (gdb_byte *) alloca (len);
   CORE_ADDR addr;
 
   addr = value_address (value);
   unsigned len = TYPE_LENGTH (type);
   gdb_byte *buf = (gdb_byte *) alloca (len);
   CORE_ADDR addr;
 
   addr = value_address (value);
-  gdbarch_address_to_pointer (gdbarch, type, buf, addr);
+  gdbarch_address_to_pointer (type->arch (), type, buf, addr);
   addr = extract_unsigned_integer (buf, len, type_byte_order (type));
   return addr;
 }
   addr = extract_unsigned_integer (buf, len, type_byte_order (type));
   return addr;
 }
@@ -4584,24 +4589,6 @@ make_array_descriptor (struct type *type, struct value *arr)
    even in this case, some expensive name-based symbol searches are still
    sometimes necessary - to find an XVZ variable, mostly.  */
 
    even in this case, some expensive name-based symbol searches are still
    sometimes necessary - to find an XVZ variable, mostly.  */
 
-/* Initialize the contents of SYM_CACHE.  */
-
-static void
-ada_init_symbol_cache (struct ada_symbol_cache *sym_cache)
-{
-  obstack_init (&sym_cache->cache_space);
-  memset (sym_cache->root, '\000', sizeof (sym_cache->root));
-}
-
-/* Free the memory used by SYM_CACHE.  */
-
-static void
-ada_free_symbol_cache (struct ada_symbol_cache *sym_cache)
-{
-  obstack_free (&sym_cache->cache_space, NULL);
-  xfree (sym_cache);
-}
-
 /* Return the symbol cache associated to the given program space PSPACE.
    If not allocated for this PSPACE yet, allocate and initialize one.  */
 
 /* Return the symbol cache associated to the given program space PSPACE.
    If not allocated for this PSPACE yet, allocate and initialize one.  */
 
@@ -4610,25 +4597,22 @@ ada_get_symbol_cache (struct program_space *pspace)
 {
   struct ada_pspace_data *pspace_data = get_ada_pspace_data (pspace);
 
 {
   struct ada_pspace_data *pspace_data = get_ada_pspace_data (pspace);
 
-  if (pspace_data->sym_cache == NULL)
-    {
-      pspace_data->sym_cache = XCNEW (struct ada_symbol_cache);
-      ada_init_symbol_cache (pspace_data->sym_cache);
-    }
+  if (pspace_data->sym_cache == nullptr)
+    pspace_data->sym_cache.reset (new ada_symbol_cache);
 
 
-  return pspace_data->sym_cache;
+  return pspace_data->sym_cache.get ();
 }
 
 /* Clear all entries from the symbol cache.  */
 
 static void
 }
 
 /* Clear all entries from the symbol cache.  */
 
 static void
-ada_clear_symbol_cache (void)
+ada_clear_symbol_cache ()
 {
 {
-  struct ada_symbol_cache *sym_cache
-    = ada_get_symbol_cache (current_program_space);
+  struct ada_pspace_data *pspace_data
+    = get_ada_pspace_data (current_program_space);
 
 
-  obstack_free (&sym_cache->cache_space, NULL);
-  ada_init_symbol_cache (sym_cache);
+  if (pspace_data->sym_cache != nullptr)
+    pspace_data->sym_cache.reset ();
 }
 
 /* Search our cache for an entry matching NAME and DOMAIN.
 }
 
 /* Search our cache for an entry matching NAME and DOMAIN.
@@ -4744,17 +4728,15 @@ standard_lookup (const char *name, const struct block *block,
 
 
 /* Non-zero iff there is at least one non-function/non-enumeral symbol
 
 
 /* Non-zero iff there is at least one non-function/non-enumeral symbol
-   in the symbol fields of SYMS[0..N-1].  We treat enumerals as functions, 
+   in the symbol fields of SYMS.  We treat enumerals as functions, 
    since they contend in overloading in the same way.  */
 static int
    since they contend in overloading in the same way.  */
 static int
-is_nonfunction (struct block_symbol syms[], int n)
+is_nonfunction (const std::vector<struct block_symbol> &syms)
 {
 {
-  int i;
-
-  for (i = 0; i < n; i += 1)
-    if (SYMBOL_TYPE (syms[i].symbol)->code () != TYPE_CODE_FUNC
-       && (SYMBOL_TYPE (syms[i].symbol)->code () != TYPE_CODE_ENUM
-           || SYMBOL_CLASS (syms[i].symbol) != LOC_CONST))
+  for (const block_symbol &sym : syms)
+    if (SYMBOL_TYPE (sym.symbol)->code () != TYPE_CODE_FUNC
+       && (SYMBOL_TYPE (sym.symbol)->code () != TYPE_CODE_ENUM
+           || SYMBOL_CLASS (sym.symbol) != LOC_CONST))
       return 1;
 
   return 0;
       return 1;
 
   return 0;
@@ -4827,17 +4809,14 @@ lesseq_defined_than (struct symbol *sym0, struct symbol *sym1)
     }
 }
 
     }
 }
 
-/* Append (SYM,BLOCK,SYMTAB) to the end of the array of struct block_symbol
-   records in OBSTACKP.  Do nothing if SYM is a duplicate.  */
+/* Append (SYM,BLOCK) to the end of the array of struct block_symbol
+   records in RESULT.  Do nothing if SYM is a duplicate.  */
 
 static void
 
 static void
-add_defn_to_vec (struct obstack *obstackp,
+add_defn_to_vec (std::vector<struct block_symbol> &result,
                 struct symbol *sym,
                 const struct block *block)
 {
                 struct symbol *sym,
                 const struct block *block)
 {
-  int i;
-  struct block_symbol *prevDefns = defns_collected (obstackp, 0);
-
   /* Do not try to complete stub types, as the debugger is probably
      already scanning all symbols matching a certain name at the
      time when this function is called.  Trying to replace the stub
   /* 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
@@ -4847,46 +4826,22 @@ add_defn_to_vec (struct obstack *obstackp,
      matches, with at least one of them complete.  It can then filter
      out the stub ones if needed.  */
 
      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)
+  for (int i = result.size () - 1; i >= 0; i -= 1)
     {
     {
-      if (lesseq_defined_than (sym, prevDefns[i].symbol))
+      if (lesseq_defined_than (sym, result[i].symbol))
        return;
        return;
-      else if (lesseq_defined_than (prevDefns[i].symbol, sym))
+      else if (lesseq_defined_than (result[i].symbol, sym))
        {
        {
-         prevDefns[i].symbol = sym;
-         prevDefns[i].block = block;
+         result[i].symbol = sym;
+         result[i].block = block;
          return;
        }
     }
 
          return;
        }
     }
 
-  {
-    struct block_symbol info;
-
-    info.symbol = sym;
-    info.block = block;
-    obstack_grow (obstackp, &info, sizeof (struct block_symbol));
-  }
-}
-
-/* Number of block_symbol structures currently collected in current vector in
-   OBSTACKP.  */
-
-static int
-num_defns_collected (struct obstack *obstackp)
-{
-  return obstack_object_size (obstackp) / sizeof (struct block_symbol);
-}
-
-/* Vector of block_symbol structures currently collected in current vector in
-   OBSTACKP.  If FINISH, close off the vector and return its final address.  */
-
-static struct block_symbol *
-defns_collected (struct obstack *obstackp, int finish)
-{
-  if (finish)
-    return (struct block_symbol *) obstack_finish (obstackp);
-  else
-    return (struct block_symbol *) obstack_base (obstackp);
+  struct block_symbol info;
+  info.symbol = sym;
+  info.block = block;
+  result.push_back (info);
 }
 
 /* Return a bound minimal symbol matching NAME according to Ada
 }
 
 /* Return a bound minimal symbol matching NAME according to Ada
@@ -4927,12 +4882,12 @@ ada_lookup_simple_minsym (const char *name)
 
 /* For all subprograms that statically enclose the subprogram of the
    selected frame, add symbols matching identifier NAME in DOMAIN
 
 /* For all subprograms that statically enclose the subprogram of the
    selected frame, add symbols matching identifier NAME in DOMAIN
-   and their blocks to the list of data in OBSTACKP, as for
+   and their blocks to the list of data in RESULT, as for
    ada_add_block_symbols (q.v.).   If WILD_MATCH_P, treat as NAME
    with a wildcard prefix.  */
 
 static void
    ada_add_block_symbols (q.v.).   If WILD_MATCH_P, treat as NAME
    with a wildcard prefix.  */
 
 static void
-add_symbols_from_enclosing_procs (struct obstack *obstackp,
+add_symbols_from_enclosing_procs (std::vector<struct block_symbol> &result,
                                  const lookup_name_info &lookup_name,
                                  domain_enum domain)
 {
                                  const lookup_name_info &lookup_name,
                                  domain_enum domain)
 {
@@ -5055,10 +5010,9 @@ symbols_are_identical_enums (const std::vector<struct block_symbol> &syms)
    duplicate other symbols in the list (The only case I know of where
    this happens is when object files containing stabs-in-ecoff are
    linked with files containing ordinary ecoff debugging symbols (or no
    duplicate other symbols in the list (The only case I know of where
    this happens is when object files containing stabs-in-ecoff are
    linked with files containing ordinary ecoff debugging symbols (or no
-   debugging symbols)).  Modifies SYMS to squeeze out deleted entries.
-   Returns the number of items in the modified list.  */
+   debugging symbols)).  Modifies SYMS to squeeze out deleted entries.  */
 
 
-static int
+static void
 remove_extra_symbols (std::vector<struct block_symbol> *syms)
 {
   int i, j;
 remove_extra_symbols (std::vector<struct block_symbol> *syms)
 {
   int i, j;
@@ -5067,7 +5021,7 @@ remove_extra_symbols (std::vector<struct block_symbol> *syms)
      cannot be any extra symbol in that case.  But it's easy to
      handle, since we have nothing to do in that case.  */
   if (syms->size () < 2)
      cannot be any extra symbol in that case.  But it's easy to
      handle, since we have nothing to do in that case.  */
   if (syms->size () < 2)
-    return syms->size ();
+    return;
 
   i = 0;
   while (i < syms->size ())
 
   i = 0;
   while (i < syms->size ())
@@ -5132,8 +5086,6 @@ remove_extra_symbols (std::vector<struct block_symbol> *syms)
      isn't missing some choices that were identical and yet distinct.  */
   if (symbols_are_identical_enums (*syms))
     syms->resize (1);
      isn't missing some choices that were identical and yet distinct.  */
   if (symbols_are_identical_enums (*syms))
     syms->resize (1);
-
-  return syms->size ();
 }
 
 /* Given a type that corresponds to a renaming entity, use the type name
 }
 
 /* Given a type that corresponds to a renaming entity, use the type name
@@ -5225,8 +5177,8 @@ old_renaming_is_invisible (const struct symbol *sym, const char *function_name)
    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
    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.
-   
+   SYMS.
+
    Rationale:
    First, in cases where an object renaming is implemented as a
    reference variable, GNAT may produce both the actual reference
    Rationale:
    First, in cases where an object renaming is implemented as a
    reference variable, GNAT may produce both the actual reference
@@ -5258,7 +5210,7 @@ old_renaming_is_invisible (const struct symbol *sym, const char *function_name)
        has been changed by an "Export" pragma.  As a consequence,
        the user will be unable to print such rename entities.  */
 
        has been changed by an "Export" pragma.  As a consequence,
        the user will be unable to print such rename entities.  */
 
-static int
+static void
 remove_irrelevant_renamings (std::vector<struct block_symbol> *syms,
                             const struct block *current_block)
 {
 remove_irrelevant_renamings (std::vector<struct block_symbol> *syms,
                             const struct block *current_block)
 {
@@ -5307,22 +5259,23 @@ remove_irrelevant_renamings (std::vector<struct block_symbol> *syms,
              (*syms)[k] = (*syms)[j];
              k += 1;
            }
              (*syms)[k] = (*syms)[j];
              k += 1;
            }
-      return k;
+      syms->resize (k);
+      return;
     }
 
   /* Extract the function name associated to CURRENT_BLOCK.
      Abort if unable to do so.  */
 
   if (current_block == NULL)
     }
 
   /* Extract the function name associated to CURRENT_BLOCK.
      Abort if unable to do so.  */
 
   if (current_block == NULL)
-    return syms->size ();
+    return;
 
   current_function = block_linkage_function (current_block);
   if (current_function == NULL)
 
   current_function = block_linkage_function (current_block);
   if (current_function == NULL)
-    return syms->size ();
+    return;
 
   current_function_name = current_function->linkage_name ();
   if (current_function_name == NULL)
 
   current_function_name = current_function->linkage_name ();
   if (current_function_name == NULL)
-    return syms->size ();
+    return;
 
   /* Check each of the symbols, and remove it from the list if it is
      a type corresponding to a renaming that is out of the scope of
 
   /* Check each of the symbols, and remove it from the list if it is
      a type corresponding to a renaming that is out of the scope of
@@ -5339,11 +5292,9 @@ remove_irrelevant_renamings (std::vector<struct block_symbol> *syms,
       else
        i += 1;
     }
       else
        i += 1;
     }
-
-  return syms->size ();
 }
 
 }
 
-/* Add to OBSTACKP all symbols from BLOCK (and its super-blocks)
+/* Add to RESULT all symbols from BLOCK (and its super-blocks)
    whose name and domain match NAME and DOMAIN respectively.
    If no match was found, then extend the search to "enclosing"
    routines (in other words, if we're inside a nested function,
    whose name and domain match NAME and DOMAIN respectively.
    If no match was found, then extend the search to "enclosing"
    routines (in other words, if we're inside a nested function,
@@ -5351,10 +5302,10 @@ remove_irrelevant_renamings (std::vector<struct block_symbol> *syms,
    If WILD_MATCH_P is nonzero, perform the naming matching in
    "wild" mode (see function "wild_match" for more info).
 
    If WILD_MATCH_P is nonzero, perform the naming matching in
    "wild" mode (see function "wild_match" for more info).
 
-   Note: This function assumes that OBSTACKP has 0 (zero) element in it.  */
+   Note: This function assumes that RESULT has 0 (zero) element in it.  */
 
 static void
 
 static void
-ada_add_local_symbols (struct obstack *obstackp,
+ada_add_local_symbols (std::vector<struct block_symbol> &result,
                       const lookup_name_info &lookup_name,
                       const struct block *block, domain_enum domain)
 {
                       const lookup_name_info &lookup_name,
                       const struct block *block, domain_enum domain)
 {
@@ -5363,11 +5314,10 @@ ada_add_local_symbols (struct obstack *obstackp,
   while (block != NULL)
     {
       block_depth += 1;
   while (block != NULL)
     {
       block_depth += 1;
-      ada_add_block_symbols (obstackp, block, lookup_name, domain, NULL);
+      ada_add_block_symbols (result, block, lookup_name, domain, NULL);
 
       /* If we found a non-function match, assume that's the one.  */
 
       /* If we found a non-function match, assume that's the one.  */
-      if (is_nonfunction (defns_collected (obstackp, 0),
-                         num_defns_collected (obstackp)))
+      if (is_nonfunction (result))
        return;
 
       block = BLOCK_SUPERBLOCK (block);
        return;
 
       block = BLOCK_SUPERBLOCK (block);
@@ -5375,8 +5325,8 @@ ada_add_local_symbols (struct obstack *obstackp,
 
   /* If no luck so far, try to find NAME as a local symbol in some lexically
      enclosing subprogram.  */
 
   /* If no luck so far, try to find NAME as a local symbol in some lexically
      enclosing subprogram.  */
-  if (num_defns_collected (obstackp) == 0 && block_depth > 2)
-    add_symbols_from_enclosing_procs (obstackp, lookup_name, domain);
+  if (result.empty () && block_depth > 2)
+    add_symbols_from_enclosing_procs (result, lookup_name, domain);
 }
 
 /* An object of this type is used as the user_data argument when
 }
 
 /* An object of this type is used as the user_data argument when
@@ -5384,15 +5334,21 @@ ada_add_local_symbols (struct obstack *obstackp,
 
 struct match_data
 {
 
 struct match_data
 {
-  struct objfile *objfile;
-  struct obstack *obstackp;
-  struct symbol *arg_sym;
-  int found_sym;
+  explicit match_data (std::vector<struct block_symbol> *rp)
+    : resultp (rp)
+  {
+  }
+  DISABLE_COPY_AND_ASSIGN (match_data);
+
+  struct objfile *objfile = nullptr;
+  std::vector<struct block_symbol> *resultp;
+  struct symbol *arg_sym = nullptr;
+  bool found_sym = false;
 };
 
 /* A callback for add_nonlocal_symbols that adds symbol, found in BSYM,
    to a list of symbols.  DATA is a pointer to a struct match_data *
 };
 
 /* A callback for add_nonlocal_symbols that adds symbol, found in BSYM,
    to a list of symbols.  DATA is a pointer to a struct match_data *
-   containing the obstack that collects the symbol list, the file that SYM
+   containing the vector that collects the symbol list, the file that SYM
    must come from, a flag indicating whether a non-argument symbol has
    been found in the current block, and the last argument symbol
    passed in SYM within the current block (if any).  When SYM is null,
    must come from, a flag indicating whether a non-argument symbol has
    been found in the current block, and the last argument symbol
    passed in SYM within the current block (if any).  When SYM is null,
@@ -5409,10 +5365,10 @@ aux_add_nonlocal_symbols (struct block_symbol *bsym,
   if (sym == NULL)
     {
       if (!data->found_sym && data->arg_sym != NULL) 
   if (sym == NULL)
     {
       if (!data->found_sym && data->arg_sym != NULL) 
-       add_defn_to_vec (data->obstackp,
+       add_defn_to_vec (*data->resultp,
                         fixup_symbol_section (data->arg_sym, data->objfile),
                         block);
                         fixup_symbol_section (data->arg_sym, data->objfile),
                         block);
-      data->found_sym = 0;
+      data->found_sym = false;
       data->arg_sym = NULL;
     }
   else 
       data->arg_sym = NULL;
     }
   else 
@@ -5423,8 +5379,8 @@ aux_add_nonlocal_symbols (struct block_symbol *bsym,
        data->arg_sym = sym;
       else
        {
        data->arg_sym = sym;
       else
        {
-         data->found_sym = 1;
-         add_defn_to_vec (data->obstackp,
+         data->found_sym = true;
+         add_defn_to_vec (*data->resultp,
                           fixup_symbol_section (sym, data->objfile),
                           block);
        }
                           fixup_symbol_section (sym, data->objfile),
                           block);
        }
@@ -5434,16 +5390,16 @@ aux_add_nonlocal_symbols (struct block_symbol *bsym,
 
 /* Helper for add_nonlocal_symbols.  Find symbols in DOMAIN which are
    targeted by renamings matching LOOKUP_NAME in BLOCK.  Add these
 
 /* Helper for add_nonlocal_symbols.  Find symbols in DOMAIN which are
    targeted by renamings matching LOOKUP_NAME in BLOCK.  Add these
-   symbols to OBSTACKP.  Return whether we found such symbols.  */
+   symbols to RESULT.  Return whether we found such symbols.  */
 
 static int
 
 static int
-ada_add_block_renamings (struct obstack *obstackp,
+ada_add_block_renamings (std::vector<struct block_symbol> &result,
                         const struct block *block,
                         const lookup_name_info &lookup_name,
                         domain_enum domain)
 {
   struct using_direct *renaming;
                         const struct block *block,
                         const lookup_name_info &lookup_name,
                         domain_enum domain)
 {
   struct using_direct *renaming;
-  int defns_mark = num_defns_collected (obstackp);
+  int defns_mark = result.size ();
 
   symbol_name_matcher_ftype *name_match
     = ada_get_symbol_name_matcher (lookup_name);
 
   symbol_name_matcher_ftype *name_match
     = ada_get_symbol_name_matcher (lookup_name);
@@ -5481,12 +5437,12 @@ ada_add_block_renamings (struct obstack *obstackp,
        {
          lookup_name_info decl_lookup_name (renaming->declaration,
                                             lookup_name.match_type ());
        {
          lookup_name_info decl_lookup_name (renaming->declaration,
                                             lookup_name.match_type ());
-         ada_add_all_symbols (obstackp, block, decl_lookup_name, domain,
+         ada_add_all_symbols (result, block, decl_lookup_name, domain,
                               1, NULL);
        }
       renaming->searched = 0;
     }
                               1, NULL);
        }
       renaming->searched = 0;
     }
-  return num_defns_collected (obstackp) != defns_mark;
+  return result.size () != defns_mark;
 }
 
 /* Implements compare_names, but only applying the comparision using
 }
 
 /* Implements compare_names, but only applying the comparision using
@@ -5583,20 +5539,17 @@ ada_lookup_name (const lookup_name_info &lookup_name)
   return lookup_name.ada ().lookup_name ().c_str ();
 }
 
   return lookup_name.ada ().lookup_name ().c_str ();
 }
 
-/* Add to OBSTACKP all non-local symbols whose name and domain match
+/* Add to RESULT all non-local symbols whose name and domain match
    LOOKUP_NAME and DOMAIN respectively.  The search is performed on
    GLOBAL_BLOCK symbols if GLOBAL is non-zero, or on STATIC_BLOCK
    symbols otherwise.  */
 
 static void
    LOOKUP_NAME and DOMAIN respectively.  The search is performed on
    GLOBAL_BLOCK symbols if GLOBAL is non-zero, or on STATIC_BLOCK
    symbols otherwise.  */
 
 static void
-add_nonlocal_symbols (struct obstack *obstackp,
+add_nonlocal_symbols (std::vector<struct block_symbol> &result,
                      const lookup_name_info &lookup_name,
                      domain_enum domain, int global)
 {
                      const lookup_name_info &lookup_name,
                      domain_enum domain, int global)
 {
-  struct match_data data;
-
-  memset (&data, 0, sizeof data);
-  data.obstackp = obstackp;
+  struct match_data data (&result);
 
   bool is_wild_match = lookup_name.ada ().wild_match_p ();
 
 
   bool is_wild_match = lookup_name.ada ().wild_match_p ();
 
@@ -5609,23 +5562,24 @@ add_nonlocal_symbols (struct obstack *obstackp,
     {
       data.objfile = objfile;
 
     {
       data.objfile = objfile;
 
-      objfile->sf->qf->map_matching_symbols (objfile, lookup_name,
-                                            domain, global, callback,
-                                            (is_wild_match
-                                             ? NULL : compare_names));
+      if (objfile->sf != nullptr)
+       objfile->sf->qf->map_matching_symbols (objfile, lookup_name,
+                                              domain, global, callback,
+                                              (is_wild_match
+                                               ? NULL : compare_names));
 
       for (compunit_symtab *cu : objfile->compunits ())
        {
          const struct block *global_block
            = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cu), GLOBAL_BLOCK);
 
 
       for (compunit_symtab *cu : objfile->compunits ())
        {
          const struct block *global_block
            = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cu), GLOBAL_BLOCK);
 
-         if (ada_add_block_renamings (obstackp, global_block, lookup_name,
+         if (ada_add_block_renamings (result, global_block, lookup_name,
                                       domain))
                                       domain))
-           data.found_sym = 1;
+           data.found_sym = true;
        }
     }
 
        }
     }
 
-  if (num_defns_collected (obstackp) == 0 && global && !is_wild_match)
+  if (result.empty () && global && !is_wild_match)
     {
       const char *name = ada_lookup_name (lookup_name);
       std::string bracket_name = std::string ("<_ada_") + name + '>';
     {
       const char *name = ada_lookup_name (lookup_name);
       std::string bracket_name = std::string ("<_ada_") + name + '>';
@@ -5634,16 +5588,17 @@ add_nonlocal_symbols (struct obstack *obstackp,
       for (objfile *objfile : current_program_space->objfiles ())
        {
          data.objfile = objfile;
       for (objfile *objfile : current_program_space->objfiles ())
        {
          data.objfile = objfile;
-         objfile->sf->qf->map_matching_symbols (objfile, name1,
-                                                domain, global, callback,
-                                                compare_names);
+         if (objfile->sf != nullptr)
+           objfile->sf->qf->map_matching_symbols (objfile, name1,
+                                                  domain, global, callback,
+                                                  compare_names);
        }
     }          
 }
 
 /* Find symbols in DOMAIN matching LOOKUP_NAME, in BLOCK and, if
    FULL_SEARCH is non-zero, enclosing scope and in global scopes,
        }
     }          
 }
 
 /* Find symbols in DOMAIN matching LOOKUP_NAME, in BLOCK and, if
    FULL_SEARCH is non-zero, enclosing scope and in global scopes,
-   returning the number of matches.  Add these to OBSTACKP.
+   returning the number of matches.  Add these to RESULT.
 
    When FULL_SEARCH is non-zero, any non-function/non-enumeral
    symbol match within the nest of blocks whose innermost member is BLOCK,
 
    When FULL_SEARCH is non-zero, any non-function/non-enumeral
    symbol match within the nest of blocks whose innermost member is BLOCK,
@@ -5659,7 +5614,7 @@ add_nonlocal_symbols (struct obstack *obstackp,
    to lookup global symbols.  */
 
 static void
    to lookup global symbols.  */
 
 static void
-ada_add_all_symbols (struct obstack *obstackp,
+ada_add_all_symbols (std::vector<struct block_symbol> &result,
                     const struct block *block,
                     const lookup_name_info &lookup_name,
                     domain_enum domain,
                     const struct block *block,
                     const lookup_name_info &lookup_name,
                     domain_enum domain,
@@ -5686,15 +5641,15 @@ ada_add_all_symbols (struct obstack *obstackp,
   if (block != NULL)
     {
       if (full_search)
   if (block != NULL)
     {
       if (full_search)
-       ada_add_local_symbols (obstackp, lookup_name, block, domain);
+       ada_add_local_symbols (result, lookup_name, block, domain);
       else
        {
          /* In the !full_search case we're are being called by
             iterate_over_symbols, and we don't want to search
             superblocks.  */
       else
        {
          /* In the !full_search case we're are being called by
             iterate_over_symbols, and we don't want to search
             superblocks.  */
-         ada_add_block_symbols (obstackp, block, lookup_name, domain, NULL);
+         ada_add_block_symbols (result, block, lookup_name, domain, NULL);
        }
        }
-      if (num_defns_collected (obstackp) > 0 || !full_search)
+      if (!result.empty () || !full_search)
        return;
     }
 
        return;
     }
 
@@ -5706,7 +5661,7 @@ ada_add_all_symbols (struct obstack *obstackp,
                            domain, &sym, &block))
     {
       if (sym != NULL)
                            domain, &sym, &block))
     {
       if (sym != NULL)
-       add_defn_to_vec (obstackp, sym, block);
+       add_defn_to_vec (result, sym, block);
       return;
     }
 
       return;
     }
 
@@ -5715,21 +5670,20 @@ ada_add_all_symbols (struct obstack *obstackp,
 
   /* Search symbols from all global blocks.  */
  
 
   /* Search symbols from all global blocks.  */
  
-  add_nonlocal_symbols (obstackp, lookup_name, domain, 1);
+  add_nonlocal_symbols (result, lookup_name, domain, 1);
 
   /* Now add symbols from all per-file blocks if we've gotten no hits
      (not strictly correct, but perhaps better than an error).  */
 
 
   /* Now add symbols from all per-file blocks if we've gotten no hits
      (not strictly correct, but perhaps better than an error).  */
 
-  if (num_defns_collected (obstackp) == 0)
-    add_nonlocal_symbols (obstackp, lookup_name, domain, 0);
+  if (result.empty ())
+    add_nonlocal_symbols (result, lookup_name, domain, 0);
 }
 
 /* Find symbols in DOMAIN matching LOOKUP_NAME, in BLOCK and, if FULL_SEARCH
 }
 
 /* Find symbols in DOMAIN matching LOOKUP_NAME, in BLOCK and, if FULL_SEARCH
-   is non-zero, enclosing scope and in global scopes, returning the number of
-   matches.
-   Fills *RESULTS with (SYM,BLOCK) tuples, indicating the symbols
-   found and the blocks and symbol tables (if any) in which they were
-   found.
+   is non-zero, enclosing scope and in global scopes.
+
+   Returns (SYM,BLOCK) tuples, indicating the symbols found and the
+   blocks and symbol tables (if any) in which they were found.
 
    When full_search is non-zero, any non-function/non-enumeral
    symbol match within the nest of blocks whose innermost member is BLOCK,
 
    When full_search is non-zero, any non-function/non-enumeral
    symbol match within the nest of blocks whose innermost member is BLOCK,
@@ -5740,55 +5694,44 @@ ada_add_all_symbols (struct obstack *obstackp,
    Names prefixed with "standard__" are handled specially: "standard__"
    is first stripped off, and only static and global symbols are searched.  */
 
    Names prefixed with "standard__" are handled specially: "standard__"
    is first stripped off, and only static and global symbols are searched.  */
 
-static int
+static std::vector<struct block_symbol>
 ada_lookup_symbol_list_worker (const lookup_name_info &lookup_name,
                               const struct block *block,
                               domain_enum domain,
 ada_lookup_symbol_list_worker (const lookup_name_info &lookup_name,
                               const struct block *block,
                               domain_enum domain,
-                              std::vector<struct block_symbol> *results,
                               int full_search)
 {
   int syms_from_global_search;
                               int full_search)
 {
   int syms_from_global_search;
-  int ndefns;
-  auto_obstack obstack;
+  std::vector<struct block_symbol> results;
 
 
-  ada_add_all_symbols (&obstack, block, lookup_name,
+  ada_add_all_symbols (results, block, lookup_name,
                       domain, full_search, &syms_from_global_search);
 
                       domain, full_search, &syms_from_global_search);
 
-  ndefns = num_defns_collected (&obstack);
-
-  struct block_symbol *base = defns_collected (&obstack, 1);
-  for (int i = 0; i < ndefns; ++i)
-    results->push_back (base[i]);
+  remove_extra_symbols (&results);
 
 
-  ndefns = remove_extra_symbols (results);
-
-  if (ndefns == 0 && full_search && syms_from_global_search)
+  if (results.empty () && full_search && syms_from_global_search)
     cache_symbol (ada_lookup_name (lookup_name), domain, NULL, NULL);
 
     cache_symbol (ada_lookup_name (lookup_name), domain, NULL, NULL);
 
-  if (ndefns == 1 && full_search && syms_from_global_search)
+  if (results.size () == 1 && full_search && syms_from_global_search)
     cache_symbol (ada_lookup_name (lookup_name), domain,
     cache_symbol (ada_lookup_name (lookup_name), domain,
-                 (*results)[0].symbol, (*results)[0].block);
-
-  ndefns = remove_irrelevant_renamings (results, block);
+                 results[0].symbol, results[0].block);
 
 
-  return ndefns;
+  remove_irrelevant_renamings (&results, block);
+  return results;
 }
 
 /* Find symbols in DOMAIN matching NAME, in BLOCK and enclosing scope and
 }
 
 /* Find symbols in DOMAIN matching NAME, in BLOCK and enclosing scope and
-   in global scopes, returning the number of matches, and filling *RESULTS
-   with (SYM,BLOCK) tuples.
+   in global scopes, returning (SYM,BLOCK) tuples.
 
    See ada_lookup_symbol_list_worker for further details.  */
 
 
    See ada_lookup_symbol_list_worker for further details.  */
 
-int
+std::vector<struct block_symbol>
 ada_lookup_symbol_list (const char *name, const struct block *block,
 ada_lookup_symbol_list (const char *name, const struct block *block,
-                       domain_enum domain,
-                       std::vector<struct block_symbol> *results)
+                       domain_enum domain)
 {
   symbol_name_match_type name_match_type = name_match_type_from_name (name);
   lookup_name_info lookup_name (name, name_match_type);
 
 {
   symbol_name_match_type name_match_type = name_match_type_from_name (name);
   lookup_name_info lookup_name (name, name_match_type);
 
-  return ada_lookup_symbol_list_worker (lookup_name, block, domain, results, 1);
+  return ada_lookup_symbol_list_worker (lookup_name, block, domain, 1);
 }
 
 /* The result is as for ada_lookup_symbol_list with FULL_SEARCH set
 }
 
 /* The result is as for ada_lookup_symbol_list with FULL_SEARCH set
@@ -5824,12 +5767,10 @@ struct block_symbol
 ada_lookup_symbol (const char *name, const struct block *block0,
                   domain_enum domain)
 {
 ada_lookup_symbol (const char *name, const struct block *block0,
                   domain_enum domain)
 {
-  std::vector<struct block_symbol> candidates;
-  int n_candidates;
-
-  n_candidates = ada_lookup_symbol_list (name, block0, domain, &candidates);
+  std::vector<struct block_symbol> candidates
+    = ada_lookup_symbol_list (name, block0, domain);
 
 
-  if (n_candidates == 0)
+  if (candidates.empty ())
     return {};
 
   block_symbol info = candidates[0];
     return {};
 
   block_symbol info = candidates[0];
@@ -6037,6 +5978,13 @@ advance_wild_match (const char **namep, const char *name0, char target0)
              name += 2;
              break;
            }
              name += 2;
              break;
            }
+         else if (t1 == '_' && name[2] == 'B' && name[3] == '_')
+           {
+             /* Names like "pkg__B_N__name", where N is a number, are
+                block-local.  We can handle these by simply skipping
+                the "B_" here.  */
+             name += 4;
+           }
          else
            return 0;
        }
          else
            return 0;
        }
@@ -6081,34 +6029,11 @@ wild_match (const char *name, const char *patn)
     }
 }
 
     }
 }
 
-/* Returns true iff symbol name SYM_NAME matches SEARCH_NAME, ignoring
-   any trailing suffixes that encode debugging information or leading
-   _ada_ on SYM_NAME (see is_name_suffix commentary for the debugging
-   information that is ignored).  */
-
-static bool
-full_match (const char *sym_name, const char *search_name)
-{
-  size_t search_name_len = strlen (search_name);
-
-  if (strncmp (sym_name, search_name, search_name_len) == 0
-      && is_name_suffix (sym_name + search_name_len))
-    return true;
-
-  if (startswith (sym_name, "_ada_")
-      && strncmp (sym_name + 5, search_name, search_name_len) == 0
-      && is_name_suffix (sym_name + search_name_len + 5))
-    return true;
-
-  return false;
-}
-
-/* Add symbols from BLOCK matching LOOKUP_NAME in DOMAIN to vector
-   *defn_symbols, updating the list of symbols in OBSTACKP (if
+/* Add symbols from BLOCK matching LOOKUP_NAME in DOMAIN to RESULT (if
    necessary).  OBJFILE is the section containing BLOCK.  */
 
 static void
    necessary).  OBJFILE is the section containing BLOCK.  */
 
 static void
-ada_add_block_symbols (struct obstack *obstackp,
+ada_add_block_symbols (std::vector<struct block_symbol> &result,
                       const struct block *block,
                       const lookup_name_info &lookup_name,
                       domain_enum domain, struct objfile *objfile)
                       const struct block *block,
                       const lookup_name_info &lookup_name,
                       domain_enum domain, struct objfile *objfile)
@@ -6117,11 +6042,11 @@ ada_add_block_symbols (struct obstack *obstackp,
   /* A matching argument symbol, if any.  */
   struct symbol *arg_sym;
   /* Set true when we find a matching non-argument symbol.  */
   /* A matching argument symbol, if any.  */
   struct symbol *arg_sym;
   /* Set true when we find a matching non-argument symbol.  */
-  int found_sym;
+  bool found_sym;
   struct symbol *sym;
 
   arg_sym = NULL;
   struct symbol *sym;
 
   arg_sym = NULL;
-  found_sym = 0;
+  found_sym = false;
   for (sym = block_iter_match_first (block, lookup_name, &iter);
        sym != NULL;
        sym = block_iter_match_next (lookup_name, &iter))
   for (sym = block_iter_match_first (block, lookup_name, &iter);
        sym != NULL;
        sym = block_iter_match_next (lookup_name, &iter))
@@ -6134,8 +6059,8 @@ ada_add_block_symbols (struct obstack *obstackp,
                arg_sym = sym;
              else
                {
                arg_sym = sym;
              else
                {
-                 found_sym = 1;
-                 add_defn_to_vec (obstackp,
+                 found_sym = true;
+                 add_defn_to_vec (result,
                                   fixup_symbol_section (sym, objfile),
                                   block);
                }
                                   fixup_symbol_section (sym, objfile),
                                   block);
                }
@@ -6145,12 +6070,12 @@ ada_add_block_symbols (struct obstack *obstackp,
 
   /* Handle renamings.  */
 
 
   /* Handle renamings.  */
 
-  if (ada_add_block_renamings (obstackp, block, lookup_name, domain))
-    found_sym = 1;
+  if (ada_add_block_renamings (result, block, lookup_name, domain))
+    found_sym = true;
 
   if (!found_sym && arg_sym != NULL)
     {
 
   if (!found_sym && arg_sym != NULL)
     {
-      add_defn_to_vec (obstackp,
+      add_defn_to_vec (result,
                       fixup_symbol_section (arg_sym, objfile),
                       block);
     }
                       fixup_symbol_section (arg_sym, objfile),
                       block);
     }
@@ -6158,7 +6083,7 @@ ada_add_block_symbols (struct obstack *obstackp,
   if (!lookup_name.ada ().wild_match_p ())
     {
       arg_sym = NULL;
   if (!lookup_name.ada ().wild_match_p ())
     {
       arg_sym = NULL;
-      found_sym = 0;
+      found_sym = false;
       const std::string &ada_lookup_name = lookup_name.ada ().lookup_name ();
       const char *name = ada_lookup_name.c_str ();
       size_t name_len = ada_lookup_name.size ();
       const std::string &ada_lookup_name = lookup_name.ada ().lookup_name ();
       const char *name = ada_lookup_name.c_str ();
       size_t name_len = ada_lookup_name.size ();
@@ -6188,8 +6113,8 @@ ada_add_block_symbols (struct obstack *obstackp,
                      arg_sym = sym;
                    else
                      {
                      arg_sym = sym;
                    else
                      {
-                       found_sym = 1;
-                       add_defn_to_vec (obstackp,
+                       found_sym = true;
+                       add_defn_to_vec (result,
                                         fixup_symbol_section (sym, objfile),
                                         block);
                      }
                                         fixup_symbol_section (sym, objfile),
                                         block);
                      }
@@ -6202,7 +6127,7 @@ ada_add_block_symbols (struct obstack *obstackp,
         They aren't parameters, right?  */
       if (!found_sym && arg_sym != NULL)
        {
         They aren't parameters, right?  */
       if (!found_sym && arg_sym != NULL)
        {
-         add_defn_to_vec (obstackp,
+         add_defn_to_vec (result,
                           fixup_symbol_section (arg_sym, objfile),
                           block);
        }
                           fixup_symbol_section (arg_sym, objfile),
                           block);
        }
@@ -6784,8 +6709,7 @@ ada_is_others_clause (struct type *type, int field_num)
 const char *
 ada_variant_discrim_name (struct type *type0)
 {
 const char *
 ada_variant_discrim_name (struct type *type0)
 {
-  static char *result = NULL;
-  static size_t result_len = 0;
+  static std::string result;
   struct type *type;
   const char *name;
   const char *discrim_end;
   struct type *type;
   const char *name;
   const char *discrim_end;
@@ -6821,10 +6745,8 @@ ada_variant_discrim_name (struct type *type0)
        break;
     }
 
        break;
     }
 
-  GROW_VECT (result, result_len, discrim_end - discrim_start + 1);
-  strncpy (result, discrim_start, discrim_end - discrim_start);
-  result[discrim_end - discrim_start] = '\0';
-  return result;
+  result = std::string (discrim_start, discrim_end - discrim_start);
+  return result.c_str ();
 }
 
 /* Scan STR for a subtype-encoded number, beginning at position K.
 }
 
 /* Scan STR for a subtype-encoded number, beginning at position K.
@@ -8967,8 +8889,11 @@ val_atr (struct type *type, LONGEST val)
 }
 
 static struct value *
 }
 
 static struct value *
-value_val_atr (struct type *type, struct value *arg)
+ada_val_atr (enum noside noside, struct type *type, struct value *arg)
 {
 {
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return value_zero (type, not_lval);
+
   if (!discrete_type_p (type))
     error (_("'VAL only defined on discrete types"));
   if (!integer_type_p (value_type (arg)))
   if (!discrete_type_p (type))
     error (_("'VAL only defined on discrete types"));
   if (!integer_type_p (value_type (arg)))
@@ -9137,8 +9062,7 @@ ada_aligned_value_addr (struct type *type, const gdb_byte *valaddr)
 const char *
 ada_enum_name (const char *name)
 {
 const char *
 ada_enum_name (const char *name)
 {
-  static char *result;
-  static size_t result_len = 0;
+  static std::string storage;
   const char *tmp;
 
   /* First, unqualify the enumeration name:
   const char *tmp;
 
   /* First, unqualify the enumeration name:
@@ -9177,22 +9101,20 @@ ada_enum_name (const char *name)
                || (name[1] >= 'a' && name[1] <= 'z'))
               && name[2] == '\0')
        {
                || (name[1] >= 'a' && name[1] <= 'z'))
               && name[2] == '\0')
        {
-         GROW_VECT (result, result_len, 4);
-         xsnprintf (result, result_len, "'%c'", name[1]);
-         return result;
+         storage = string_printf ("'%c'", name[1]);
+         return storage.c_str ();
        }
       else
        return name;
 
        }
       else
        return name;
 
-      GROW_VECT (result, result_len, 16);
       if (isascii (v) && isprint (v))
       if (isascii (v) && isprint (v))
-       xsnprintf (result, result_len, "'%c'", v);
+       storage = string_printf ("'%c'", v);
       else if (name[1] == 'U')
       else if (name[1] == 'U')
-       xsnprintf (result, result_len, "[\"%02x\"]", v);
+       storage = string_printf ("[\"%02x\"]", v);
       else
       else
-       xsnprintf (result, result_len, "[\"%04x\"]", v);
+       storage = string_printf ("[\"%04x\"]", v);
 
 
-      return result;
+      return storage.c_str ();
     }
   else
     {
     }
   else
     {
@@ -9201,10 +9123,8 @@ ada_enum_name (const char *name)
        tmp = strstr (name, "$");
       if (tmp != NULL)
        {
        tmp = strstr (name, "$");
       if (tmp != NULL)
        {
-         GROW_VECT (result, result_len, tmp - name + 1);
-         strncpy (result, name, tmp - name);
-         result[tmp - name] = '\0';
-         return result;
+         storage = std::string (name, tmp - name);
+         return storage.c_str ();
        }
 
       return name;
        }
 
       return name;
@@ -9258,33 +9178,6 @@ unwrap_value (struct value *val)
     }
 }
 
     }
 }
 
-static struct value *
-cast_from_gnat_encoded_fixed_point_type (struct type *type, struct value *arg)
-{
-  struct value *scale
-    = gnat_encoded_fixed_point_scaling_factor (value_type (arg));
-  arg = value_cast (value_type (scale), arg);
-
-  arg = value_binop (arg, scale, BINOP_MUL);
-  return value_cast (type, arg);
-}
-
-static struct value *
-cast_to_gnat_encoded_fixed_point_type (struct type *type, struct value *arg)
-{
-  if (type == value_type (arg))
-    return arg;
-
-  struct value *scale = gnat_encoded_fixed_point_scaling_factor (type);
-  if (ada_is_gnat_encoded_fixed_point_type (value_type (arg)))
-    arg = cast_from_gnat_encoded_fixed_point_type (value_type (scale), arg);
-  else
-    arg = value_cast (value_type (scale), arg);
-
-  arg = value_binop (arg, scale, BINOP_DIV);
-  return value_cast (type, arg);
-}
-
 /* Given two array types T1 and T2, return nonzero iff both arrays
    contain the same number of elements.  */
 
 /* Given two array types T1 and T2, return nonzero iff both arrays
    contain the same number of elements.  */
 
@@ -9486,34 +9379,6 @@ ada_value_equal (struct value *arg1, struct value *arg2)
   return value_equal (arg1, arg2);
 }
 
   return value_equal (arg1, arg2);
 }
 
-/* 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)
-{
-  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;
-}
-
 /* 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
 /* 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
@@ -9567,9 +9432,6 @@ assign_aggregate (struct value *container,
   struct type *lhs_type;
   int n = exp->elts[*pos+1].longconst;
   LONGEST low_index, high_index;
   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 i;
 
   *pos += 3;
   int i;
 
   *pos += 3;
@@ -9603,32 +9465,27 @@ assign_aggregate (struct value *container,
   else
     error (_("Left-hand side must be array or record."));
 
   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 = XALLOCAVEC (LONGEST, max_indices);
+  std::vector<LONGEST> indices (4);
   indices[0] = indices[1] = low_index - 1;
   indices[2] = indices[3] = high_index + 1;
   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:
 
   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,
+           aggregate_assign_from_choices (container, lhs, exp, pos, indices,
                                           low_index, high_index);
            break;
          case OP_POSITIONAL:
            aggregate_assign_positional (container, lhs, exp, pos, 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"));
                                         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);
+           aggregate_assign_others (container, lhs, exp, pos, indices,
+                                    low_index, high_index);
            break;
          default:
            error (_("Internal error: bad aggregate clause"));
            break;
          default:
            error (_("Internal error: bad aggregate clause"));
@@ -9640,15 +9497,14 @@ assign_aggregate (struct value *container,
              
 /* Assign into the component of LHS indexed by the OP_POSITIONAL
    construct at *POS, updating *POS past the construct, given that
              
 /* 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
+   the positions are relative to lower bound LOW, where HIGH is the
+   upper bound.  Record the position in INDICES.  CONTAINER is as for
    assign_aggregate.  */
 static void
 aggregate_assign_positional (struct value *container,
                             struct value *lhs, struct expression *exp,
    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) 
+                            int *pos, std::vector<LONGEST> &indices,
+                            LONGEST low, LONGEST high)
 {
   LONGEST ind = longest_to_int (exp->elts[*pos + 1].longconst) + low;
   
 {
   LONGEST ind = longest_to_int (exp->elts[*pos + 1].longconst) + low;
   
@@ -9656,7 +9512,7 @@ aggregate_assign_positional (struct value *container,
     warning (_("Extra components in aggregate ignored."));
   if (ind <= high)
     {
     warning (_("Extra components in aggregate ignored."));
   if (ind <= high)
     {
-      add_component_interval (ind, ind, indices, num_indices, max_indices);
+      add_component_interval (ind, ind, indices);
       *pos += 3;
       assign_component (container, lhs, ind, exp, pos);
     }
       *pos += 3;
       assign_component (container, lhs, ind, exp, pos);
     }
@@ -9667,13 +9523,12 @@ aggregate_assign_positional (struct value *container,
 /* 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
 /* 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.  */
+   to in INDICES.  CONTAINER is as for assign_aggregate.  */
 static void
 aggregate_assign_from_choices (struct value *container,
                               struct value *lhs, struct expression *exp,
 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 *pos, std::vector<LONGEST> &indices,
+                              LONGEST low, LONGEST high)
 {
   int j;
   int n_choices = longest_to_int (exp->elts[*pos+1].longconst);
 {
   int j;
   int n_choices = longest_to_int (exp->elts[*pos+1].longconst);
@@ -9733,8 +9588,7 @@ aggregate_assign_from_choices (struct value *container,
       if (lower <= upper && (lower < low || upper > high))
        error (_("Index in component association out of bounds."));
 
       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);
+      add_component_interval (lower, upper, indices);
       while (lower <= upper)
        {
          int pos1;
       while (lower <= upper)
        {
          int pos1;
@@ -9749,17 +9603,18 @@ aggregate_assign_from_choices (struct value *container,
 /* 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
 /* 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.  */
+   are in INDICES.  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,
 static void
 aggregate_assign_others (struct value *container,
                         struct value *lhs, struct expression *exp,
-                        int *pos, LONGEST *indices, int num_indices,
+                        int *pos, std::vector<LONGEST> &indices,
                         LONGEST low, LONGEST high) 
 {
   int i;
   int expr_pc = *pos + 1;
   
                         LONGEST low, LONGEST high) 
 {
   int i;
   int expr_pc = *pos + 1;
   
+  int num_indices = indices.size ();
   for (i = 0; i < num_indices - 2; i += 2)
     {
       LONGEST ind;
   for (i = 0; i < num_indices - 2; i += 2)
     {
       LONGEST ind;
@@ -9775,22 +9630,22 @@ aggregate_assign_others (struct value *container,
   ada_evaluate_subexp (NULL, exp, pos, EVAL_SKIP);
 }
 
   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.  */
+/* Add the interval [LOW .. HIGH] to the sorted set of intervals
+   [ INDICES[0] .. INDICES[1] ],...  The resulting intervals do not
+   overlap.  */
 static void
 add_component_interval (LONGEST low, LONGEST high, 
 static void
 add_component_interval (LONGEST low, LONGEST high, 
-                       LONGEST* indices, int *size, int max_size)
+                       std::vector<LONGEST> &indices)
 {
   int i, j;
 
 {
   int i, j;
 
-  for (i = 0; i < *size; i += 2) {
+  int size = indices.size ();
+  for (i = 0; i < size; i += 2) {
     if (high >= indices[i] && low <= indices[i + 1])
       {
        int kh;
 
     if (high >= indices[i] && low <= indices[i + 1])
       {
        int kh;
 
-       for (kh = i + 2; kh < *size; kh += 2)
+       for (kh = i + 2; kh < size; kh += 2)
          if (high < indices[kh])
            break;
        if (low < indices[i])
          if (high < indices[kh])
            break;
        if (low < indices[i])
@@ -9798,18 +9653,16 @@ add_component_interval (LONGEST low, LONGEST high,
        indices[i + 1] = indices[kh - 1];
        if (high > indices[i + 1])
          indices[i + 1] = high;
        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;
+       memcpy (indices.data () + i + 2, indices.data () + kh, size - kh);
+       indices.resize (kh - i - 2);
        return;
       }
     else if (high < indices[i])
       break;
   }
        
        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.resize (indices.size () + 2);
+  for (j = indices.size () - 1; j >= i + 2; j -= 1)
     indices[j] = indices[j - 2];
   indices[i] = low;
   indices[i + 1] = high;
     indices[j] = indices[j - 2];
   indices[i] = low;
   indices[i + 1] = high;
@@ -9824,12 +9677,6 @@ ada_value_cast (struct type *type, struct value *arg2)
   if (type == ada_check_typedef (value_type (arg2)))
     return arg2;
 
   if (type == ada_check_typedef (value_type (arg2)))
     return arg2;
 
-  if (ada_is_gnat_encoded_fixed_point_type (type))
-    return cast_to_gnat_encoded_fixed_point_type (type, arg2);
-
-  if (ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-    return cast_from_gnat_encoded_fixed_point_type (type, arg2);
-
   return value_cast (type, arg2);
 }
 
   return value_cast (type, arg2);
 }
 
@@ -10139,50 +9986,756 @@ ada_evaluate_subexp_for_cast (expression *exp, int *pos,
   return ada_value_cast (to_type, val);
 }
 
   return ada_value_cast (to_type, val);
 }
 
-/* Implement the evaluate_exp routine in the exp_descriptor structure
-   for the Ada language.  */
+/* A helper function for TERNOP_IN_RANGE.  */
 
 
-static struct value *
-ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
-                    int *pos, enum noside noside)
+static value *
+eval_ternop_in_range (struct type *expect_type, struct expression *exp,
+                     enum noside noside,
+                     value *arg1, value *arg2, value *arg3)
 {
 {
-  enum exp_opcode op;
-  int tem;
-  int pc;
-  int preeval_pos;
-  struct value *arg1 = NULL, *arg2 = NULL, *arg3;
-  struct type *type;
-  int nargs, oplen;
-  struct value **argvec;
+  if (noside == EVAL_SKIP)
+    return eval_skip_value (exp);
 
 
-  pc = *pos;
-  *pos += 1;
-  op = exp->elts[pc].opcode;
+  binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+  binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg3);
+  struct type *type = language_bool_type (exp->language_defn, exp->gdbarch);
+  return
+    value_from_longest (type,
+                       (value_less (arg1, arg3)
+                        || value_equal (arg1, arg3))
+                       && (value_less (arg2, arg1)
+                           || value_equal (arg2, arg1)));
+}
 
 
-  switch (op)
+/* A helper function for UNOP_NEG.  */
+
+value *
+ada_unop_neg (struct type *expect_type,
+             struct expression *exp,
+             enum noside noside, enum exp_opcode op,
+             struct value *arg1)
+{
+  if (noside == EVAL_SKIP)
+    return eval_skip_value (exp);
+  unop_promote (exp->language_defn, exp->gdbarch, &arg1);
+  return value_neg (arg1);
+}
+
+/* A helper function for UNOP_IN_RANGE.  */
+
+value *
+ada_unop_in_range (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside, enum exp_opcode op,
+                  struct value *arg1, struct type *type)
+{
+  if (noside == EVAL_SKIP)
+    return eval_skip_value (exp);
+
+  struct value *arg2, *arg3;
+  switch (type->code ())
     {
     default:
     {
     default:
-      *pos -= 1;
-      arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
+      lim_warning (_("Membership test incompletely implemented; "
+                    "always returns true"));
+      type = language_bool_type (exp->language_defn, exp->gdbarch);
+      return value_from_longest (type, (LONGEST) 1);
 
 
-      if (noside == EVAL_NORMAL)
-       arg1 = unwrap_value (arg1);
+    case TYPE_CODE_RANGE:
+      arg2 = value_from_longest (type,
+                                type->bounds ()->low.const_val ());
+      arg3 = value_from_longest (type,
+                                type->bounds ()->high.const_val ());
+      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg3);
+      type = language_bool_type (exp->language_defn, exp->gdbarch);
+      return
+       value_from_longest (type,
+                           (value_less (arg1, arg3)
+                            || value_equal (arg1, arg3))
+                           && (value_less (arg2, arg1)
+                               || value_equal (arg2, arg1)));
+    }
+}
 
 
-      /* If evaluating an OP_FLOAT and an EXPECT_TYPE was provided,
-        then we need to perform the conversion manually, because
-        evaluate_subexp_standard doesn't do it.  This conversion is
-        necessary in Ada because the different kinds of float/fixed
-        types in Ada have different representations.
+/* A helper function for OP_ATR_TAG.  */
 
 
-        Similarly, we need to perform the conversion from OP_LONG
-        ourselves.  */
-      if ((op == OP_FLOAT || op == OP_LONG) && expect_type != NULL)
-       arg1 = ada_value_cast (expect_type, arg1);
+value *
+ada_atr_tag (struct type *expect_type,
+            struct expression *exp,
+            enum noside noside, enum exp_opcode op,
+            struct value *arg1)
+{
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return value_zero (ada_tag_type (arg1), not_lval);
 
 
-      return arg1;
+  return ada_value_tag (arg1);
+}
 
 
-    case OP_STRING:
-      {
+/* A helper function for OP_ATR_SIZE.  */
+
+value *
+ada_atr_size (struct type *expect_type,
+             struct expression *exp,
+             enum noside noside, enum exp_opcode op,
+             struct value *arg1)
+{
+  struct type *type = value_type (arg1);
+
+  /* If the argument is a reference, then dereference its type, since
+     the user is really asking for the size of the actual object,
+     not the size of the pointer.  */
+  if (type->code () == TYPE_CODE_REF)
+    type = TYPE_TARGET_TYPE (type);
+
+  if (noside == EVAL_SKIP)
+    return eval_skip_value (exp);
+  else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return value_zero (builtin_type (exp->gdbarch)->builtin_int, not_lval);
+  else
+    return value_from_longest (builtin_type (exp->gdbarch)->builtin_int,
+                              TARGET_CHAR_BIT * TYPE_LENGTH (type));
+}
+
+/* A helper function for UNOP_ABS.  */
+
+value *
+ada_abs (struct type *expect_type,
+        struct expression *exp,
+        enum noside noside, enum exp_opcode op,
+        struct value *arg1)
+{
+  unop_promote (exp->language_defn, exp->gdbarch, &arg1);
+  if (value_less (arg1, value_zero (value_type (arg1), not_lval)))
+    return value_neg (arg1);
+  else
+    return arg1;
+}
+
+/* A helper function for BINOP_MUL.  */
+
+value *
+ada_mult_binop (struct type *expect_type,
+               struct expression *exp,
+               enum noside noside, enum exp_opcode op,
+               struct value *arg1, struct value *arg2)
+{
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    {
+      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+      return value_zero (value_type (arg1), not_lval);
+    }
+  else
+    {
+      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+      return ada_value_binop (arg1, arg2, op);
+    }
+}
+
+/* A helper function for BINOP_EQUAL and BINOP_NOTEQUAL.  */
+
+value *
+ada_equal_binop (struct type *expect_type,
+                struct expression *exp,
+                enum noside noside, enum exp_opcode op,
+                struct value *arg1, struct value *arg2)
+{
+  int tem;
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    tem = 0;
+  else
+    {
+      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+      tem = ada_value_equal (arg1, arg2);
+    }
+  if (op == BINOP_NOTEQUAL)
+    tem = !tem;
+  struct type *type = language_bool_type (exp->language_defn, exp->gdbarch);
+  return value_from_longest (type, (LONGEST) tem);
+}
+
+/* A helper function for TERNOP_SLICE.  */
+
+value *
+ada_ternop_slice (struct expression *exp,
+                 enum noside noside,
+                 struct value *array, struct value *low_bound_val,
+                 struct value *high_bound_val)
+{
+  LONGEST low_bound;
+  LONGEST high_bound;
+
+  low_bound_val = coerce_ref (low_bound_val);
+  high_bound_val = coerce_ref (high_bound_val);
+  low_bound = value_as_long (low_bound_val);
+  high_bound = value_as_long (high_bound_val);
+
+  /* If this is a reference to an aligner type, then remove all
+     the aligners.  */
+  if (value_type (array)->code () == TYPE_CODE_REF
+      && ada_is_aligner_type (TYPE_TARGET_TYPE (value_type (array))))
+    TYPE_TARGET_TYPE (value_type (array)) =
+      ada_aligned_type (TYPE_TARGET_TYPE (value_type (array)));
+
+  if (ada_is_any_packed_array_type (value_type (array)))
+    error (_("cannot slice a packed array"));
+
+  /* If this is a reference to an array or an array lvalue,
+     convert to a pointer.  */
+  if (value_type (array)->code () == TYPE_CODE_REF
+      || (value_type (array)->code () == TYPE_CODE_ARRAY
+         && VALUE_LVAL (array) == lval_memory))
+    array = value_addr (array);
+
+  if (noside == EVAL_AVOID_SIDE_EFFECTS
+      && ada_is_array_descriptor_type (ada_check_typedef
+                                      (value_type (array))))
+    return empty_array (ada_type_of_array (array, 0), low_bound,
+                       high_bound);
+
+  array = ada_coerce_to_simple_array_ptr (array);
+
+  /* If we have more than one level of pointer indirection,
+     dereference the value until we get only one level.  */
+  while (value_type (array)->code () == TYPE_CODE_PTR
+        && (TYPE_TARGET_TYPE (value_type (array))->code ()
+            == TYPE_CODE_PTR))
+    array = value_ind (array);
+
+  /* Make sure we really do have an array type before going further,
+     to avoid a SEGV when trying to get the index type or the target
+     type later down the road if the debug info generated by
+     the compiler is incorrect or incomplete.  */
+  if (!ada_is_simple_array_type (value_type (array)))
+    error (_("cannot take slice of non-array"));
+
+  if (ada_check_typedef (value_type (array))->code ()
+      == TYPE_CODE_PTR)
+    {
+      struct type *type0 = ada_check_typedef (value_type (array));
+
+      if (high_bound < low_bound || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return empty_array (TYPE_TARGET_TYPE (type0), low_bound, high_bound);
+      else
+       {
+         struct type *arr_type0 =
+           to_fixed_array_type (TYPE_TARGET_TYPE (type0), NULL, 1);
+
+         return ada_value_slice_from_ptr (array, arr_type0,
+                                          longest_to_int (low_bound),
+                                          longest_to_int (high_bound));
+       }
+    }
+  else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return array;
+  else if (high_bound < low_bound)
+    return empty_array (value_type (array), low_bound, high_bound);
+  else
+    return ada_value_slice (array, longest_to_int (low_bound),
+                           longest_to_int (high_bound));
+}
+
+/* A helper function for BINOP_IN_BOUNDS.  */
+
+value *
+ada_binop_in_bounds (struct expression *exp, enum noside noside,
+                    struct value *arg1, struct value *arg2, int n)
+{
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    {
+      struct type *type = language_bool_type (exp->language_defn,
+                                             exp->gdbarch);
+      return value_zero (type, not_lval);
+    }
+
+  struct type *type = ada_index_type (value_type (arg2), n, "range");
+  if (!type)
+    type = value_type (arg1);
+
+  value *arg3 = value_from_longest (type, ada_array_bound (arg2, n, 1));
+  arg2 = value_from_longest (type, ada_array_bound (arg2, n, 0));
+
+  binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+  binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg3);
+  type = language_bool_type (exp->language_defn, exp->gdbarch);
+  return value_from_longest (type,
+                            (value_less (arg1, arg3)
+                             || value_equal (arg1, arg3))
+                            && (value_less (arg2, arg1)
+                                || value_equal (arg2, arg1)));
+}
+
+/* A helper function for some attribute operations.  */
+
+static value *
+ada_unop_atr (struct expression *exp, enum noside noside, enum exp_opcode op,
+             struct value *arg1, struct type *type_arg, int tem)
+{
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    {
+      if (type_arg == NULL)
+       type_arg = value_type (arg1);
+
+      if (ada_is_constrained_packed_array_type (type_arg))
+       type_arg = decode_constrained_packed_array_type (type_arg);
+
+      if (!discrete_type_p (type_arg))
+       {
+         switch (op)
+           {
+           default:          /* Should never happen.  */
+             error (_("unexpected attribute encountered"));
+           case OP_ATR_FIRST:
+           case OP_ATR_LAST:
+             type_arg = ada_index_type (type_arg, tem,
+                                        ada_attribute_name (op));
+             break;
+           case OP_ATR_LENGTH:
+             type_arg = builtin_type (exp->gdbarch)->builtin_int;
+             break;
+           }
+       }
+
+      return value_zero (type_arg, not_lval);
+    }
+  else if (type_arg == NULL)
+    {
+      arg1 = ada_coerce_ref (arg1);
+
+      if (ada_is_constrained_packed_array_type (value_type (arg1)))
+       arg1 = ada_coerce_to_simple_array (arg1);
+
+      struct type *type;
+      if (op == OP_ATR_LENGTH)
+       type = builtin_type (exp->gdbarch)->builtin_int;
+      else
+       {
+         type = ada_index_type (value_type (arg1), tem,
+                                ada_attribute_name (op));
+         if (type == NULL)
+           type = builtin_type (exp->gdbarch)->builtin_int;
+       }
+
+      switch (op)
+       {
+       default:          /* Should never happen.  */
+         error (_("unexpected attribute encountered"));
+       case OP_ATR_FIRST:
+         return value_from_longest
+           (type, ada_array_bound (arg1, tem, 0));
+       case OP_ATR_LAST:
+         return value_from_longest
+           (type, ada_array_bound (arg1, tem, 1));
+       case OP_ATR_LENGTH:
+         return value_from_longest
+           (type, ada_array_length (arg1, tem));
+       }
+    }
+  else if (discrete_type_p (type_arg))
+    {
+      struct type *range_type;
+      const char *name = ada_type_name (type_arg);
+
+      range_type = NULL;
+      if (name != NULL && type_arg->code () != TYPE_CODE_ENUM)
+       range_type = to_fixed_range_type (type_arg, NULL);
+      if (range_type == NULL)
+       range_type = type_arg;
+      switch (op)
+       {
+       default:
+         error (_("unexpected attribute encountered"));
+       case OP_ATR_FIRST:
+         return value_from_longest 
+           (range_type, ada_discrete_type_low_bound (range_type));
+       case OP_ATR_LAST:
+         return value_from_longest
+           (range_type, ada_discrete_type_high_bound (range_type));
+       case OP_ATR_LENGTH:
+         error (_("the 'length attribute applies only to array types"));
+       }
+    }
+  else if (type_arg->code () == TYPE_CODE_FLT)
+    error (_("unimplemented type attribute"));
+  else
+    {
+      LONGEST low, high;
+
+      if (ada_is_constrained_packed_array_type (type_arg))
+       type_arg = decode_constrained_packed_array_type (type_arg);
+
+      struct type *type;
+      if (op == OP_ATR_LENGTH)
+       type = builtin_type (exp->gdbarch)->builtin_int;
+      else
+       {
+         type = ada_index_type (type_arg, tem, ada_attribute_name (op));
+         if (type == NULL)
+           type = builtin_type (exp->gdbarch)->builtin_int;
+       }
+
+      switch (op)
+       {
+       default:
+         error (_("unexpected attribute encountered"));
+       case OP_ATR_FIRST:
+         low = ada_array_bound_from_type (type_arg, tem, 0);
+         return value_from_longest (type, low);
+       case OP_ATR_LAST:
+         high = ada_array_bound_from_type (type_arg, tem, 1);
+         return value_from_longest (type, high);
+       case OP_ATR_LENGTH:
+         low = ada_array_bound_from_type (type_arg, tem, 0);
+         high = ada_array_bound_from_type (type_arg, tem, 1);
+         return value_from_longest (type, high - low + 1);
+       }
+    }
+}
+
+/* A helper function for OP_ATR_MIN and OP_ATR_MAX.  */
+
+struct value *
+ada_binop_minmax (struct type *expect_type,
+                 struct expression *exp,
+                 enum noside noside, enum exp_opcode op,
+                 struct value *arg1, struct value *arg2)
+{
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return value_zero (value_type (arg1), not_lval);
+  else
+    {
+      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+      return value_binop (arg1, arg2,
+                         op == OP_ATR_MIN ? BINOP_MIN : BINOP_MAX);
+    }
+}
+
+/* A helper function for BINOP_EXP.  */
+
+static struct value *
+ada_binop_exp (struct type *expect_type,
+              struct expression *exp,
+              enum noside noside, enum exp_opcode op,
+              struct value *arg1, struct value *arg2)
+{
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return value_zero (value_type (arg1), not_lval);
+  else
+    {
+      /* For integer exponentiation operations,
+        only promote the first argument.  */
+      if (is_integral_type (value_type (arg2)))
+       unop_promote (exp->language_defn, exp->gdbarch, &arg1);
+      else
+       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+
+      return value_binop (arg1, arg2, op);
+    }
+}
+
+namespace expr
+{
+
+value *
+ada_wrapped_operation::evaluate (struct type *expect_type,
+                                struct expression *exp,
+                                enum noside noside)
+{
+  value *result = std::get<0> (m_storage)->evaluate (expect_type, exp, noside);
+  if (noside == EVAL_NORMAL)
+    result = unwrap_value (result);
+
+  /* If evaluating an OP_FLOAT and an EXPECT_TYPE was provided,
+     then we need to perform the conversion manually, because
+     evaluate_subexp_standard doesn't do it.  This conversion is
+     necessary in Ada because the different kinds of float/fixed
+     types in Ada have different representations.
+
+     Similarly, we need to perform the conversion from OP_LONG
+     ourselves.  */
+  if ((opcode () == OP_FLOAT || opcode () == OP_LONG) && expect_type != NULL)
+    result = ada_value_cast (expect_type, result);
+
+  return result;
+}
+
+value *
+ada_string_operation::evaluate (struct type *expect_type,
+                               struct expression *exp,
+                               enum noside noside)
+{
+  value *result = string_operation::evaluate (expect_type, exp, noside);
+  /* The result type will have code OP_STRING, bashed there from 
+     OP_ARRAY.  Bash it back.  */
+  if (value_type (result)->code () == TYPE_CODE_STRING)
+    value_type (result)->set_code (TYPE_CODE_ARRAY);
+  return result;
+}
+
+value *
+ada_qual_operation::evaluate (struct type *expect_type,
+                             struct expression *exp,
+                             enum noside noside)
+{
+  struct type *type = std::get<1> (m_storage);
+  return std::get<0> (m_storage)->evaluate (type, exp, noside);
+}
+
+value *
+ada_ternop_range_operation::evaluate (struct type *expect_type,
+                                     struct expression *exp,
+                                     enum noside noside)
+{
+  value *arg0 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+  value *arg1 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+  value *arg2 = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
+  return eval_ternop_in_range (expect_type, exp, noside, arg0, arg1, arg2);
+}
+
+value *
+ada_binop_addsub_operation::evaluate (struct type *expect_type,
+                                     struct expression *exp,
+                                     enum noside noside)
+{
+  value *arg1 = std::get<1> (m_storage)->evaluate_with_coercion (exp, noside);
+  value *arg2 = std::get<2> (m_storage)->evaluate_with_coercion (exp, noside);
+
+  auto do_op = [=] (LONGEST x, LONGEST y)
+    {
+      if (std::get<0> (m_storage) == BINOP_ADD)
+       return x + y;
+      return x - y;
+    };
+
+  if (value_type (arg1)->code () == TYPE_CODE_PTR)
+    return (value_from_longest
+           (value_type (arg1),
+            do_op (value_as_long (arg1), value_as_long (arg2))));
+  if (value_type (arg2)->code () == TYPE_CODE_PTR)
+    return (value_from_longest
+           (value_type (arg2),
+            do_op (value_as_long (arg1), value_as_long (arg2))));
+  /* Preserve the original type for use by the range case below.
+     We cannot cast the result to a reference type, so if ARG1 is
+     a reference type, find its underlying type.  */
+  struct type *type = value_type (arg1);
+  while (type->code () == TYPE_CODE_REF)
+    type = TYPE_TARGET_TYPE (type);
+  binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
+  arg1 = value_binop (arg1, arg2, std::get<0> (m_storage));
+  /* We need to special-case the result with a range.
+     This is done for the benefit of "ptype".  gdb's Ada support
+     historically used the LHS to set the result type here, so
+     preserve this behavior.  */
+  if (type->code () == TYPE_CODE_RANGE)
+    arg1 = value_cast (type, arg1);
+  return arg1;
+}
+
+value *
+ada_unop_atr_operation::evaluate (struct type *expect_type,
+                                 struct expression *exp,
+                                 enum noside noside)
+{
+  struct type *type_arg = nullptr;
+  value *val = nullptr;
+
+  if (std::get<0> (m_storage)->opcode () == OP_TYPE)
+    {
+      value *tem = std::get<0> (m_storage)->evaluate (nullptr, exp,
+                                                     EVAL_AVOID_SIDE_EFFECTS);
+      type_arg = value_type (tem);
+    }
+  else
+    val = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+
+  return ada_unop_atr (exp, noside, std::get<1> (m_storage),
+                      val, type_arg, std::get<2> (m_storage));
+}
+
+value *
+ada_var_msym_value_operation::evaluate_for_cast (struct type *expect_type,
+                                                struct expression *exp,
+                                                enum noside noside)
+{
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    return value_zero (expect_type, not_lval);
+
+  value *val = evaluate_var_msym_value (noside,
+                                       std::get<1> (m_storage),
+                                       std::get<0> (m_storage));
+
+  val = ada_value_cast (expect_type, val);
+
+  /* Follow the Ada language semantics that do not allow taking
+     an address of the result of a cast (view conversion in Ada).  */
+  if (VALUE_LVAL (val) == lval_memory)
+    {
+      if (value_lazy (val))
+       value_fetch_lazy (val);
+      VALUE_LVAL (val) = not_lval;
+    }
+  return val;
+}
+
+value *
+ada_var_value_operation::evaluate_for_cast (struct type *expect_type,
+                                           struct expression *exp,
+                                           enum noside noside)
+{
+  value *val = evaluate_var_value (noside,
+                                  std::get<1> (m_storage),
+                                  std::get<0> (m_storage));
+
+  val = ada_value_cast (expect_type, val);
+
+  /* Follow the Ada language semantics that do not allow taking
+     an address of the result of a cast (view conversion in Ada).  */
+  if (VALUE_LVAL (val) == lval_memory)
+    {
+      if (value_lazy (val))
+       value_fetch_lazy (val);
+      VALUE_LVAL (val) = not_lval;
+    }
+  return val;
+}
+
+value *
+ada_var_value_operation::evaluate (struct type *expect_type,
+                                  struct expression *exp,
+                                  enum noside noside)
+{
+  symbol *sym = std::get<0> (m_storage);
+
+  if (SYMBOL_DOMAIN (sym) == UNDEF_DOMAIN)
+    /* Only encountered when an unresolved symbol occurs in a
+       context other than a function call, in which case, it is
+       invalid.  */
+    error (_("Unexpected unresolved symbol, %s, during evaluation"),
+          sym->print_name ());
+
+  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+    {
+      struct type *type = static_unwrap_type (SYMBOL_TYPE (sym));
+      /* Check to see if this is a tagged type.  We also need to handle
+        the case where the type is a reference to a tagged type, but
+        we have to be careful to exclude pointers to tagged types.
+        The latter should be shown as usual (as a pointer), whereas
+        a reference should mostly be transparent to the user.  */
+      if (ada_is_tagged_type (type, 0)
+         || (type->code () == TYPE_CODE_REF
+             && ada_is_tagged_type (TYPE_TARGET_TYPE (type), 0)))
+       {
+         /* Tagged types are a little special in the fact that the real
+            type is dynamic and can only be determined by inspecting the
+            object's tag.  This means that we need to get the object's
+            value first (EVAL_NORMAL) and then extract the actual object
+            type from its tag.
+
+            Note that we cannot skip the final step where we extract
+            the object type from its tag, because the EVAL_NORMAL phase
+            results in dynamic components being resolved into fixed ones.
+            This can cause problems when trying to print the type
+            description of tagged types whose parent has a dynamic size:
+            We use the type name of the "_parent" component in order
+            to print the name of the ancestor type in the type description.
+            If that component had a dynamic size, the resolution into
+            a fixed type would result in the loss of that type name,
+            thus preventing us from printing the name of the ancestor
+            type in the type description.  */
+         value *arg1 = var_value_operation::evaluate (nullptr, exp,
+                                                      EVAL_NORMAL);
+
+         if (type->code () != TYPE_CODE_REF)
+           {
+             struct type *actual_type;
+
+             actual_type = type_from_tag (ada_value_tag (arg1));
+             if (actual_type == NULL)
+               /* If, for some reason, we were unable to determine
+                  the actual type from the tag, then use the static
+                  approximation that we just computed as a fallback.
+                  This can happen if the debugging information is
+                  incomplete, for instance.  */
+               actual_type = type;
+             return value_zero (actual_type, not_lval);
+           }
+         else
+           {
+             /* In the case of a ref, ada_coerce_ref takes care
+                of determining the actual type.  But the evaluation
+                should return a ref as it should be valid to ask
+                for its address; so rebuild a ref after coerce.  */
+             arg1 = ada_coerce_ref (arg1);
+             return value_ref (arg1, TYPE_CODE_REF);
+           }
+       }
+
+      /* Records and unions for which GNAT encodings have been
+        generated need to be statically fixed as well.
+        Otherwise, non-static fixing produces a type where
+        all dynamic properties are removed, which prevents "ptype"
+        from being able to completely describe the type.
+        For instance, a case statement in a variant record would be
+        replaced by the relevant components based on the actual
+        value of the discriminants.  */
+      if ((type->code () == TYPE_CODE_STRUCT
+          && dynamic_template_type (type) != NULL)
+         || (type->code () == TYPE_CODE_UNION
+             && ada_find_parallel_type (type, "___XVU") != NULL))
+       return value_zero (to_static_fixed_type (type), not_lval);
+    }
+
+  value *arg1 = var_value_operation::evaluate (expect_type, exp, noside);
+  return ada_to_fixed_value (arg1);
+}
+
+}
+
+/* Implement the evaluate_exp routine in the exp_descriptor structure
+   for the Ada language.  */
+
+static struct value *
+ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
+                    int *pos, enum noside noside)
+{
+  enum exp_opcode op;
+  int tem;
+  int pc;
+  int preeval_pos;
+  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);
+
+      if (noside == EVAL_NORMAL)
+       arg1 = unwrap_value (arg1);
+
+      /* If evaluating an OP_FLOAT and an EXPECT_TYPE was provided,
+        then we need to perform the conversion manually, because
+        evaluate_subexp_standard doesn't do it.  This conversion is
+        necessary in Ada because the different kinds of float/fixed
+        types in Ada have different representations.
+
+        Similarly, we need to perform the conversion from OP_LONG
+        ourselves.  */
+      if ((op == OP_FLOAT || op == OP_LONG) && expect_type != NULL)
+       arg1 = ada_value_cast (expect_type, arg1);
+
+      return arg1;
+
+    case OP_STRING:
+      {
        struct value *result;
 
        *pos -= 1;
        struct value *result;
 
        *pos -= 1;
@@ -10227,11 +10780,6 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
        {
          /* Nothing.  */
        }
        {
          /* Nothing.  */
        }
-      else if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1)))
-       arg2 = cast_to_gnat_encoded_fixed_point_type (value_type (arg1), arg2);
-      else if (ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-       error
-         (_("Fixed-point values must be assigned to fixed-point variables"));
       else
        arg2 = coerce_for_assign (value_type (arg1), arg2);
       return ada_value_assign (arg1, arg2);
       else
        arg2 = coerce_for_assign (value_type (arg1), arg2);
       return ada_value_assign (arg1, arg2);
@@ -10249,18 +10797,21 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
        return (value_from_longest
                 (value_type (arg2),
                  value_as_long (arg1) + value_as_long (arg2)));
        return (value_from_longest
                 (value_type (arg2),
                  value_as_long (arg1) + value_as_long (arg2)));
-      if ((ada_is_gnat_encoded_fixed_point_type (value_type (arg1))
-          || ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-         && value_type (arg1) != value_type (arg2))
-       error (_("Operands of fixed-point addition must have the same type"));
-      /* 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.  */
+      /* Preserve the original type for use by the range case below.
+        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_CODE_REF)
        type = TYPE_TARGET_TYPE (type);
       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
       type = value_type (arg1);
       while (type->code () == TYPE_CODE_REF)
        type = TYPE_TARGET_TYPE (type);
       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-      return value_cast (type, value_binop (arg1, arg2, BINOP_ADD));
+      arg1 = value_binop (arg1, arg2, BINOP_ADD);
+      /* We need to special-case the result of adding to a range.
+        This is done for the benefit of "ptype".  gdb's Ada support
+        historically used the LHS to set the result type here, so
+        preserve this behavior.  */
+      if (type->code () == TYPE_CODE_RANGE)
+       arg1 = value_cast (type, arg1);
+      return arg1;
 
     case BINOP_SUB:
       arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
 
     case BINOP_SUB:
       arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
@@ -10275,19 +10826,21 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
        return (value_from_longest
                 (value_type (arg2),
                  value_as_long (arg1) - value_as_long (arg2)));
        return (value_from_longest
                 (value_type (arg2),
                  value_as_long (arg1) - value_as_long (arg2)));
-      if ((ada_is_gnat_encoded_fixed_point_type (value_type (arg1))
-          || ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-         && value_type (arg1) != value_type (arg2))
-       error (_("Operands of fixed-point subtraction "
-                "must have the same type"));
-      /* 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.  */
+      /* Preserve the original type for use by the range case below.
+        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_CODE_REF)
        type = TYPE_TARGET_TYPE (type);
       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
       type = value_type (arg1);
       while (type->code () == TYPE_CODE_REF)
        type = TYPE_TARGET_TYPE (type);
       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-      return value_cast (type, value_binop (arg1, arg2, BINOP_SUB));
+      arg1 = value_binop (arg1, arg2, BINOP_SUB);
+      /* We need to special-case the result of adding to a range.
+        This is done for the benefit of "ptype".  gdb's Ada support
+        historically used the LHS to set the result type here, so
+        preserve this behavior.  */
+      if (type->code () == TYPE_CODE_RANGE)
+       arg1 = value_cast (type, arg1);
+      return arg1;
 
     case BINOP_MUL:
     case BINOP_DIV:
 
     case BINOP_MUL:
     case BINOP_DIV:
@@ -10297,21 +10850,8 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       arg2 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
       arg2 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
-      else if (noside == EVAL_AVOID_SIDE_EFFECTS)
-       {
-         binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-         return value_zero (value_type (arg1), not_lval);
-       }
-      else
-       {
-         type = builtin_type (exp->gdbarch)->builtin_double;
-         if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1)))
-           arg1 = cast_from_gnat_encoded_fixed_point_type (type, arg1);
-         if (ada_is_gnat_encoded_fixed_point_type (value_type (arg2)))
-           arg2 = cast_from_gnat_encoded_fixed_point_type (type, arg2);
-         binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-         return ada_value_binop (arg1, arg2, op);
-       }
+      return ada_mult_binop (expect_type, exp, noside, op,
+                            arg1, arg2);
 
     case BINOP_EQUAL:
     case BINOP_NOTEQUAL:
 
     case BINOP_EQUAL:
     case BINOP_NOTEQUAL:
@@ -10319,29 +10859,11 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
       arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
-      if (noside == EVAL_AVOID_SIDE_EFFECTS)
-       tem = 0;
-      else
-       {
-         binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-         tem = ada_value_equal (arg1, arg2);
-       }
-      if (op == BINOP_NOTEQUAL)
-       tem = !tem;
-      type = language_bool_type (exp->language_defn, exp->gdbarch);
-      return value_from_longest (type, (LONGEST) tem);
+      return ada_equal_binop (expect_type, exp, noside, op, arg1, arg2);
 
     case UNOP_NEG:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
 
     case UNOP_NEG:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
-      if (noside == EVAL_SKIP)
-       goto nosideret;
-      else if (ada_is_gnat_encoded_fixed_point_type (value_type (arg1)))
-       return value_cast (value_type (arg1), value_neg (arg1));
-      else
-       {
-         unop_promote (exp->language_defn, exp->gdbarch, &arg1);
-         return value_neg (arg1);
-       }
+      return ada_unop_neg (expect_type, exp, noside, op, arg1);
 
     case BINOP_LOGICAL_AND:
     case BINOP_LOGICAL_OR:
 
     case BINOP_LOGICAL_AND:
     case BINOP_LOGICAL_OR:
@@ -10611,113 +11133,19 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
          = evaluate_subexp (nullptr, exp, pos, noside);
        struct value *high_bound_val
          = evaluate_subexp (nullptr, exp, pos, noside);
          = evaluate_subexp (nullptr, exp, pos, noside);
        struct value *high_bound_val
          = evaluate_subexp (nullptr, exp, pos, noside);
-       LONGEST low_bound;
-       LONGEST high_bound;
-
-       low_bound_val = coerce_ref (low_bound_val);
-       high_bound_val = coerce_ref (high_bound_val);
-       low_bound = value_as_long (low_bound_val);
-       high_bound = value_as_long (high_bound_val);
 
        if (noside == EVAL_SKIP)
          goto nosideret;
 
 
        if (noside == EVAL_SKIP)
          goto nosideret;
 
-       /* If this is a reference to an aligner type, then remove all
-          the aligners.  */
-       if (value_type (array)->code () == TYPE_CODE_REF
-           && ada_is_aligner_type (TYPE_TARGET_TYPE (value_type (array))))
-         TYPE_TARGET_TYPE (value_type (array)) =
-           ada_aligned_type (TYPE_TARGET_TYPE (value_type (array)));
-
-       if (ada_is_any_packed_array_type (value_type (array)))
-         error (_("cannot slice a packed array"));
-
-       /* If this is a reference to an array or an array lvalue,
-          convert to a pointer.  */
-       if (value_type (array)->code () == TYPE_CODE_REF
-           || (value_type (array)->code () == TYPE_CODE_ARRAY
-               && VALUE_LVAL (array) == lval_memory))
-         array = value_addr (array);
-
-       if (noside == EVAL_AVOID_SIDE_EFFECTS
-           && ada_is_array_descriptor_type (ada_check_typedef
-                                            (value_type (array))))
-         return empty_array (ada_type_of_array (array, 0), low_bound,
-                             high_bound);
-
-       array = ada_coerce_to_simple_array_ptr (array);
-
-       /* If we have more than one level of pointer indirection,
-          dereference the value until we get only one level.  */
-       while (value_type (array)->code () == TYPE_CODE_PTR
-              && (TYPE_TARGET_TYPE (value_type (array))->code ()
-                    == TYPE_CODE_PTR))
-         array = value_ind (array);
-
-       /* Make sure we really do have an array type before going further,
-          to avoid a SEGV when trying to get the index type or the target
-          type later down the road if the debug info generated by
-          the compiler is incorrect or incomplete.  */
-       if (!ada_is_simple_array_type (value_type (array)))
-         error (_("cannot take slice of non-array"));
-
-       if (ada_check_typedef (value_type (array))->code ()
-           == TYPE_CODE_PTR)
-         {
-           struct type *type0 = ada_check_typedef (value_type (array));
-
-           if (high_bound < low_bound || noside == EVAL_AVOID_SIDE_EFFECTS)
-             return empty_array (TYPE_TARGET_TYPE (type0), low_bound, high_bound);
-           else
-             {
-               struct type *arr_type0 =
-                 to_fixed_array_type (TYPE_TARGET_TYPE (type0), NULL, 1);
-
-               return ada_value_slice_from_ptr (array, arr_type0,
-                                                longest_to_int (low_bound),
-                                                longest_to_int (high_bound));
-             }
-         }
-       else if (noside == EVAL_AVOID_SIDE_EFFECTS)
-         return array;
-       else if (high_bound < low_bound)
-         return empty_array (value_type (array), low_bound, high_bound);
-       else
-         return ada_value_slice (array, longest_to_int (low_bound),
-                                 longest_to_int (high_bound));
+       return ada_ternop_slice (exp, noside, array, low_bound_val,
+                                high_bound_val);
       }
 
     case UNOP_IN_RANGE:
       (*pos) += 2;
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       type = check_typedef (exp->elts[pc + 1].type);
       }
 
     case UNOP_IN_RANGE:
       (*pos) += 2;
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       type = check_typedef (exp->elts[pc + 1].type);
-
-      if (noside == EVAL_SKIP)
-       goto nosideret;
-
-      switch (type->code ())
-       {
-       default:
-         lim_warning (_("Membership test incompletely implemented; "
-                        "always returns true"));
-         type = language_bool_type (exp->language_defn, exp->gdbarch);
-         return value_from_longest (type, (LONGEST) 1);
-
-       case TYPE_CODE_RANGE:
-         arg2 = value_from_longest (type,
-                                    type->bounds ()->low.const_val ());
-         arg3 = value_from_longest (type,
-                                    type->bounds ()->high.const_val ());
-         binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-         binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg3);
-         type = language_bool_type (exp->language_defn, exp->gdbarch);
-         return
-           value_from_longest (type,
-                               (value_less (arg1, arg3)
-                                || value_equal (arg1, arg3))
-                               && (value_less (arg2, arg1)
-                                   || value_equal (arg2, arg1)));
-       }
+      return ada_unop_in_range (expect_type, exp, noside, op, arg1, type);
 
     case BINOP_IN_BOUNDS:
       (*pos) += 2;
 
     case BINOP_IN_BOUNDS:
       (*pos) += 2;
@@ -10727,48 +11155,16 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       if (noside == EVAL_SKIP)
        goto nosideret;
 
       if (noside == EVAL_SKIP)
        goto nosideret;
 
-      if (noside == EVAL_AVOID_SIDE_EFFECTS)
-       {
-         type = language_bool_type (exp->language_defn, exp->gdbarch);
-         return value_zero (type, not_lval);
-       }
-
       tem = longest_to_int (exp->elts[pc + 1].longconst);
 
       tem = longest_to_int (exp->elts[pc + 1].longconst);
 
-      type = ada_index_type (value_type (arg2), tem, "range");
-      if (!type)
-       type = value_type (arg1);
-
-      arg3 = value_from_longest (type, ada_array_bound (arg2, tem, 1));
-      arg2 = value_from_longest (type, ada_array_bound (arg2, tem, 0));
-
-      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg3);
-      type = language_bool_type (exp->language_defn, exp->gdbarch);
-      return
-       value_from_longest (type,
-                           (value_less (arg1, arg3)
-                            || value_equal (arg1, arg3))
-                           && (value_less (arg2, arg1)
-                               || value_equal (arg2, arg1)));
+      return ada_binop_in_bounds (exp, noside, arg1, arg2, tem);
 
     case TERNOP_IN_RANGE:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       arg2 = evaluate_subexp (nullptr, exp, pos, noside);
       arg3 = evaluate_subexp (nullptr, exp, pos, noside);
 
 
     case TERNOP_IN_RANGE:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       arg2 = evaluate_subexp (nullptr, exp, pos, noside);
       arg3 = evaluate_subexp (nullptr, exp, pos, noside);
 
-      if (noside == EVAL_SKIP)
-       goto nosideret;
-
-      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-      binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg3);
-      type = language_bool_type (exp->language_defn, exp->gdbarch);
-      return
-       value_from_longest (type,
-                           (value_less (arg1, arg3)
-                            || value_equal (arg1, arg3))
-                           && (value_less (arg2, arg1)
-                               || value_equal (arg2, arg1)));
+      return eval_ternop_in_range (expect_type, exp, noside, arg1, arg2, arg3);
 
     case OP_ATR_FIRST:
     case OP_ATR_LAST:
 
     case OP_ATR_FIRST:
     case OP_ATR_LAST:
@@ -10795,134 +11191,15 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
 
        if (noside == EVAL_SKIP)
          goto nosideret;
 
        if (noside == EVAL_SKIP)
          goto nosideret;
-       else if (noside == EVAL_AVOID_SIDE_EFFECTS)
-         {
-           if (type_arg == NULL)
-             type_arg = value_type (arg1);
-
-           if (ada_is_constrained_packed_array_type (type_arg))
-             type_arg = decode_constrained_packed_array_type (type_arg);
-
-           if (!discrete_type_p (type_arg))
-             {
-               switch (op)
-                 {
-                 default:          /* Should never happen.  */
-                   error (_("unexpected attribute encountered"));
-                 case OP_ATR_FIRST:
-                 case OP_ATR_LAST:
-                   type_arg = ada_index_type (type_arg, tem,
-                                              ada_attribute_name (op));
-                   break;
-                 case OP_ATR_LENGTH:
-                   type_arg = builtin_type (exp->gdbarch)->builtin_int;
-                   break;
-                 }
-             }
-
-           return value_zero (type_arg, not_lval);
-         }
-       else if (type_arg == NULL)
-         {
-           arg1 = ada_coerce_ref (arg1);
 
 
-           if (ada_is_constrained_packed_array_type (value_type (arg1)))
-             arg1 = ada_coerce_to_simple_array (arg1);
-
-           if (op == OP_ATR_LENGTH)
-             type = builtin_type (exp->gdbarch)->builtin_int;
-           else
-             {
-               type = ada_index_type (value_type (arg1), tem,
-                                      ada_attribute_name (op));
-               if (type == NULL)
-                 type = builtin_type (exp->gdbarch)->builtin_int;
-             }
-
-           switch (op)
-             {
-             default:          /* Should never happen.  */
-               error (_("unexpected attribute encountered"));
-             case OP_ATR_FIRST:
-               return value_from_longest
-                       (type, ada_array_bound (arg1, tem, 0));
-             case OP_ATR_LAST:
-               return value_from_longest
-                       (type, ada_array_bound (arg1, tem, 1));
-             case OP_ATR_LENGTH:
-               return value_from_longest
-                       (type, ada_array_length (arg1, tem));
-             }
-         }
-       else if (discrete_type_p (type_arg))
-         {
-           struct type *range_type;
-           const char *name = ada_type_name (type_arg);
-
-           range_type = NULL;
-           if (name != NULL && type_arg->code () != TYPE_CODE_ENUM)
-             range_type = to_fixed_range_type (type_arg, NULL);
-           if (range_type == NULL)
-             range_type = type_arg;
-           switch (op)
-             {
-             default:
-               error (_("unexpected attribute encountered"));
-             case OP_ATR_FIRST:
-               return value_from_longest 
-                 (range_type, ada_discrete_type_low_bound (range_type));
-             case OP_ATR_LAST:
-               return value_from_longest
-                 (range_type, ada_discrete_type_high_bound (range_type));
-             case OP_ATR_LENGTH:
-               error (_("the 'length attribute applies only to array types"));
-             }
-         }
-       else if (type_arg->code () == TYPE_CODE_FLT)
-         error (_("unimplemented type attribute"));
-       else
-         {
-           LONGEST low, high;
-
-           if (ada_is_constrained_packed_array_type (type_arg))
-             type_arg = decode_constrained_packed_array_type (type_arg);
-
-           if (op == OP_ATR_LENGTH)
-             type = builtin_type (exp->gdbarch)->builtin_int;
-           else
-             {
-               type = ada_index_type (type_arg, tem, ada_attribute_name (op));
-               if (type == NULL)
-                 type = builtin_type (exp->gdbarch)->builtin_int;
-             }
-
-           switch (op)
-             {
-             default:
-               error (_("unexpected attribute encountered"));
-             case OP_ATR_FIRST:
-               low = ada_array_bound_from_type (type_arg, tem, 0);
-               return value_from_longest (type, low);
-             case OP_ATR_LAST:
-               high = ada_array_bound_from_type (type_arg, tem, 1);
-               return value_from_longest (type, high);
-             case OP_ATR_LENGTH:
-               low = ada_array_bound_from_type (type_arg, tem, 0);
-               high = ada_array_bound_from_type (type_arg, tem, 1);
-               return value_from_longest (type, high - low + 1);
-             }
-         }
+       return ada_unop_atr (exp, noside, op, arg1, type_arg, tem);
       }
 
     case OP_ATR_TAG:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
       }
 
     case OP_ATR_TAG:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
-
-      if (noside == EVAL_AVOID_SIDE_EFFECTS)
-       return value_zero (ada_tag_type (arg1), not_lval);
-
-      return ada_value_tag (arg1);
+      return ada_atr_tag (expect_type, exp, noside, op, arg1);
 
     case OP_ATR_MIN:
     case OP_ATR_MAX:
 
     case OP_ATR_MIN:
     case OP_ATR_MAX:
@@ -10931,14 +11208,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       arg2 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
       arg2 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
-      else if (noside == EVAL_AVOID_SIDE_EFFECTS)
-       return value_zero (value_type (arg1), not_lval);
-      else
-       {
-         binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-         return value_binop (arg1, arg2,
-                             op == OP_ATR_MIN ? BINOP_MIN : BINOP_MAX);
-       }
+      return ada_binop_minmax (expect_type, exp, noside, op, arg1, arg2);
 
     case OP_ATR_MODULUS:
       {
 
     case OP_ATR_MODULUS:
       {
@@ -10969,21 +11239,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
 
     case OP_ATR_SIZE:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
 
     case OP_ATR_SIZE:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
-      type = value_type (arg1);
-
-      /* If the argument is a reference, then dereference its type, since
-        the user is really asking for the size of the actual object,
-        not the size of the pointer.  */
-      if (type->code () == TYPE_CODE_REF)
-       type = TYPE_TARGET_TYPE (type);
-
-      if (noside == EVAL_SKIP)
-       goto nosideret;
-      else if (noside == EVAL_AVOID_SIDE_EFFECTS)
-       return value_zero (builtin_type (exp->gdbarch)->builtin_int, not_lval);
-      else
-       return value_from_longest (builtin_type (exp->gdbarch)->builtin_int,
-                                  TARGET_CHAR_BIT * TYPE_LENGTH (type));
+      return ada_atr_size (expect_type, exp, noside, op, arg1);
 
     case OP_ATR_VAL:
       evaluate_subexp (nullptr, exp, pos, EVAL_SKIP);
 
     case OP_ATR_VAL:
       evaluate_subexp (nullptr, exp, pos, EVAL_SKIP);
@@ -10991,29 +11247,14 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       type = exp->elts[pc + 2].type;
       if (noside == EVAL_SKIP)
        goto nosideret;
       type = exp->elts[pc + 2].type;
       if (noside == EVAL_SKIP)
        goto nosideret;
-      else if (noside == EVAL_AVOID_SIDE_EFFECTS)
-       return value_zero (type, not_lval);
-      else
-       return value_val_atr (type, arg1);
+      return ada_val_atr (noside, type, arg1);
 
     case BINOP_EXP:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       arg2 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
 
     case BINOP_EXP:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       arg2 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
-      else if (noside == EVAL_AVOID_SIDE_EFFECTS)
-       return value_zero (value_type (arg1), not_lval);
-      else
-       {
-         /* For integer exponentiation operations,
-            only promote the first argument.  */
-         if (is_integral_type (value_type (arg2)))
-           unop_promote (exp->language_defn, exp->gdbarch, &arg1);
-         else
-           binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
-
-         return value_binop (arg1, arg2, op);
-       }
+      return ada_binop_exp (expect_type, exp, noside, op, arg1, arg2);
 
     case UNOP_PLUS:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
 
     case UNOP_PLUS:
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
@@ -11026,11 +11267,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
       arg1 = evaluate_subexp (nullptr, exp, pos, noside);
       if (noside == EVAL_SKIP)
        goto nosideret;
-      unop_promote (exp->language_defn, exp->gdbarch, &arg1);
-      if (value_less (arg1, value_zero (value_type (arg1), not_lval)))
-       return value_neg (arg1);
-      else
-       return arg1;
+      return ada_abs (expect_type, exp, noside, op, arg1);
 
     case UNOP_IND:
       preeval_pos = *pos;
 
     case UNOP_IND:
       preeval_pos = *pos;
@@ -11202,41 +11439,6 @@ nosideret:
 }
 \f
 
 }
 \f
 
-                               /* Fixed point */
-
-/* If TYPE encodes an Ada fixed-point type, return the suffix of the
-   type name that encodes the 'small and 'delta information.
-   Otherwise, return NULL.  */
-
-static const char *
-gnat_encoded_fixed_point_type_info (struct type *type)
-{
-  const char *name = ada_type_name (type);
-  enum type_code code = (type == NULL) ? TYPE_CODE_UNDEF : type->code ();
-
-  if ((code == TYPE_CODE_INT || code == TYPE_CODE_RANGE) && name != NULL)
-    {
-      const char *tail = strstr (name, "___XF_");
-
-      if (tail == NULL)
-       return NULL;
-      else
-       return tail + 5;
-    }
-  else if (code == TYPE_CODE_RANGE && TYPE_TARGET_TYPE (type) != type)
-    return gnat_encoded_fixed_point_type_info (TYPE_TARGET_TYPE (type));
-  else
-    return NULL;
-}
-
-/* Returns non-zero iff TYPE represents an Ada fixed-point type.  */
-
-int
-ada_is_gnat_encoded_fixed_point_type (struct type *type)
-{
-  return gnat_encoded_fixed_point_type_info (type) != NULL;
-}
-
 /* Return non-zero iff TYPE represents a System.Address type.  */
 
 int
 /* Return non-zero iff TYPE represents a System.Address type.  */
 
 int
@@ -11245,60 +11447,6 @@ ada_is_system_address_type (struct type *type)
   return (type->name () && strcmp (type->name (), "system__address") == 0);
 }
 
   return (type->name () && strcmp (type->name (), "system__address") == 0);
 }
 
-/* Assuming that TYPE is the representation of an Ada fixed-point
-   type, return the target floating-point type to be used to represent
-   of this type during internal computation.  */
-
-static struct type *
-ada_scaling_type (struct type *type)
-{
-  return builtin_type (get_type_arch (type))->builtin_long_double;
-}
-
-/* Assuming that TYPE is the representation of an Ada fixed-point
-   type, return its delta, or NULL if the type is malformed and the
-   delta cannot be determined.  */
-
-struct value *
-gnat_encoded_fixed_point_delta (struct type *type)
-{
-  const char *encoding = gnat_encoded_fixed_point_type_info (type);
-  struct type *scale_type = ada_scaling_type (type);
-
-  long long num, den;
-
-  if (sscanf (encoding, "_%lld_%lld", &num, &den) < 2)
-    return nullptr;
-  else
-    return value_binop (value_from_longest (scale_type, num),
-                       value_from_longest (scale_type, den), BINOP_DIV);
-}
-
-/* Assuming that ada_is_gnat_encoded_fixed_point_type (TYPE), return
-   the scaling factor ('SMALL value) associated with the type.  */
-
-struct value *
-gnat_encoded_fixed_point_scaling_factor (struct type *type)
-{
-  const char *encoding = gnat_encoded_fixed_point_type_info (type);
-  struct type *scale_type = ada_scaling_type (type);
-
-  long long num0, den0, num1, den1;
-  int n;
-
-  n = sscanf (encoding, "_%lld_%lld_%lld_%lld",
-             &num0, &den0, &num1, &den1);
-
-  if (n < 2)
-    return value_from_longest (scale_type, 1);
-  else if (n == 4)
-    return value_binop (value_from_longest (scale_type, num1),
-                       value_from_longest (scale_type, den1), BINOP_DIV);
-  else
-    return value_binop (value_from_longest (scale_type, num0),
-                       value_from_longest (scale_type, den0), BINOP_DIV);
-}
-
 \f
 
                                /* Range types */
 \f
 
                                /* Range types */
@@ -11313,8 +11461,7 @@ static int
 scan_discrim_bound (const char *str, int k, struct value *dval, LONGEST * px,
                    int *pnew_k)
 {
 scan_discrim_bound (const char *str, int k, struct value *dval, LONGEST * px,
                    int *pnew_k)
 {
-  static char *bound_buffer = NULL;
-  static size_t bound_buffer_len = 0;
+  static std::string storage;
   const char *pstart, *pend, *bound;
   struct value *bound_val;
 
   const char *pstart, *pend, *bound;
   struct value *bound_val;
 
@@ -11333,11 +11480,8 @@ scan_discrim_bound (const char *str, int k, struct value *dval, LONGEST * px,
       int len = pend - pstart;
 
       /* Strip __ and beyond.  */
       int len = pend - pstart;
 
       /* Strip __ and beyond.  */
-      GROW_VECT (bound_buffer, bound_buffer_len, len + 1);
-      strncpy (bound_buffer, pstart, len);
-      bound_buffer[len] = '\0';
-
-      bound = bound_buffer;
+      storage = std::string (pstart, len);
+      bound = storage.c_str ();
       k = pend - str;
     }
 
       k = pend - str;
     }
 
@@ -11362,12 +11506,12 @@ get_var_value (const char *name, const char *err_msg)
 
   lookup_name_info lookup_name (quoted_name, symbol_name_match_type::FULL);
 
 
   lookup_name_info lookup_name (quoted_name, symbol_name_match_type::FULL);
 
-  std::vector<struct block_symbol> syms;
-  int nsyms = ada_lookup_symbol_list_worker (lookup_name,
-                                            get_selected_block (0),
-                                            VAR_DOMAIN, &syms, 1);
+  std::vector<struct block_symbol> syms
+    = ada_lookup_symbol_list_worker (lookup_name,
+                                    get_selected_block (0),
+                                    VAR_DOMAIN, 1);
 
 
-  if (nsyms != 1)
+  if (syms.size () != 1)
     {
       if (err_msg == NULL)
        return 0;
     {
       if (err_msg == NULL)
        return 0;
@@ -11434,18 +11578,12 @@ to_fixed_range_type (struct type *raw_type, struct value *dval)
     }
   else
     {
     }
   else
     {
-      static char *name_buf = NULL;
-      static size_t name_len = 0;
       int prefix_len = subtype_info - name;
       LONGEST L, U;
       struct type *type;
       const char *bounds_str;
       int n;
 
       int prefix_len = subtype_info - name;
       LONGEST L, U;
       struct type *type;
       const char *bounds_str;
       int n;
 
-      GROW_VECT (name_buf, name_len, prefix_len + 5);
-      strncpy (name_buf, name, prefix_len);
-      name_buf[prefix_len] = '\0';
-
       subtype_info += 5;
       bounds_str = strchr (subtype_info, '_');
       n = 1;
       subtype_info += 5;
       bounds_str = strchr (subtype_info, '_');
       n = 1;
@@ -11463,8 +11601,8 @@ to_fixed_range_type (struct type *raw_type, struct value *dval)
        }
       else
        {
        }
       else
        {
-         strcpy (name_buf + prefix_len, "___L");
-         if (!get_int_var_value (name_buf, L))
+         std::string name_buf = std::string (name, prefix_len) + "___L";
+         if (!get_int_var_value (name_buf.c_str (), L))
            {
              lim_warning (_("Unknown lower bound, using 1."));
              L = 1;
            {
              lim_warning (_("Unknown lower bound, using 1."));
              L = 1;
@@ -11479,8 +11617,8 @@ to_fixed_range_type (struct type *raw_type, struct value *dval)
        }
       else
        {
        }
       else
        {
-         strcpy (name_buf + prefix_len, "___U");
-         if (!get_int_var_value (name_buf, U))
+         std::string name_buf = std::string (name, prefix_len) + "___U";
+         if (!get_int_var_value (name_buf.c_str (), U))
            {
              lim_warning (_("Unknown upper bound, using %ld."), (long) L);
              U = L;
            {
              lim_warning (_("Unknown upper bound, using %ld."), (long) L);
              U = L;
@@ -13287,8 +13425,8 @@ ada_operator_check (struct expression *exp, int pos,
 
   /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL.  */
 
 
   /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL.  */
 
-  if (type && TYPE_OBJFILE (type)
-      && (*objfile_func) (TYPE_OBJFILE (type), data))
+  if (type != nullptr && type->objfile_owner () != nullptr
+      && objfile_func (type->objfile_owner (), data))
     return 1;
 
   return 0;
     return 1;
 
   return 0;
@@ -13606,7 +13744,47 @@ do_full_match (const char *symbol_search_name,
               const lookup_name_info &lookup_name,
               completion_match_result *comp_match_res)
 {
               const lookup_name_info &lookup_name,
               completion_match_result *comp_match_res)
 {
-  return full_match (symbol_search_name, ada_lookup_name (lookup_name));
+  const char *lname = lookup_name.ada ().lookup_name ().c_str ();
+
+  /* If both symbols start with "_ada_", just let the loop below
+     handle the comparison.  However, if only the symbol name starts
+     with "_ada_", skip the prefix and let the match proceed as
+     usual.  */
+  if (startswith (symbol_search_name, "_ada_")
+      && !startswith (lname, "_ada"))
+    symbol_search_name += 5;
+
+  int uscore_count = 0;
+  while (*lname != '\0')
+    {
+      if (*symbol_search_name != *lname)
+       {
+         if (*symbol_search_name == 'B' && uscore_count == 2
+             && symbol_search_name[1] == '_')
+           {
+             symbol_search_name += 2;
+             while (isdigit (*symbol_search_name))
+               ++symbol_search_name;
+             if (symbol_search_name[0] == '_'
+                 && symbol_search_name[1] == '_')
+               {
+                 symbol_search_name += 2;
+                 continue;
+               }
+           }
+         return false;
+       }
+
+      if (*symbol_search_name == '_')
+       ++uscore_count;
+      else
+       uscore_count = 0;
+
+      ++symbol_search_name;
+      ++lname;
+    }
+
+  return is_name_suffix (symbol_search_name);
 }
 
 /* symbol_name_matcher_ftype for exact (verbatim) matches.  */
 }
 
 /* symbol_name_matcher_ftype for exact (verbatim) matches.  */
@@ -13625,7 +13803,7 @@ ada_lookup_name_info::ada_lookup_name_info (const lookup_name_info &lookup_name)
 {
   gdb::string_view user_name = lookup_name.name ();
 
 {
   gdb::string_view user_name = lookup_name.name ();
 
-  if (user_name[0] == '<')
+  if (!user_name.empty () && user_name[0] == '<')
     {
       if (user_name.back () == '>')
        m_encoded_name
     {
       if (user_name.back () == '>')
        m_encoded_name
@@ -13857,9 +14035,8 @@ public:
         domain_enum domain,
         gdb::function_view<symbol_found_callback_ftype> callback) const override
   {
         domain_enum domain,
         gdb::function_view<symbol_found_callback_ftype> callback) const override
   {
-    std::vector<struct block_symbol> results;
-
-    ada_lookup_symbol_list_worker (name, block, domain, &results, 0);
+    std::vector<struct block_symbol> results
+      = ada_lookup_symbol_list_worker (name, block, domain, 0);
     for (block_symbol &sym : results)
       {
        if (!callback (&sym))
     for (block_symbol &sym : results)
       {
        if (!callback (&sym))
@@ -14144,16 +14321,17 @@ public:
      A null CONTEXT_TYPE indicates that a non-void return type is
      preferred.  May change (expand) *EXP.  */
 
      A null CONTEXT_TYPE indicates that a non-void return type is
      preferred.  May change (expand) *EXP.  */
 
-  void post_parser (expression_up *expp, int void_context_p, int completing,
-                   innermost_block_tracker *tracker) const override
+  void post_parser (expression_up *expp, struct parser_state *ps)
+    const override
   {
     struct type *context_type = NULL;
     int pc = 0;
 
   {
     struct type *context_type = NULL;
     int pc = 0;
 
-    if (void_context_p)
+    if (ps->void_context_p)
       context_type = builtin_type ((*expp)->gdbarch)->builtin_void;
 
       context_type = builtin_type ((*expp)->gdbarch)->builtin_void;
 
-    resolve_subexp (expp, &pc, 1, context_type, completing, tracker);
+    resolve_subexp (expp, &pc, 1, context_type, ps->parse_completion,
+                   ps->block_tracker);
   }
 
   /* See language.h.  */
   }
 
   /* See language.h.  */
This page took 0.066201 seconds and 4 git commands to generate.