+2019-04-04  Tom Tromey  <tom@tromey.com>
+
+       * varobj.c (varobj_create): Update.
+       * rust-exp.y (struct rust_parser) <update_innermost_block,
+       lookup_symbol>: New methods.
+       (rust_parser::update_innermost_block, rust_parser::lookup_symbol):
+       Rename.
+       (rust_parser::rust_lookup_type)
+       (rust_parser::convert_ast_to_expression, rust_lex_tests): Update.
+       * printcmd.c (display_command, do_one_display): Update.
+       * parser-defs.h (struct parser_state) <parser_state>: Add
+       "tracker" parameter.
+       (block_tracker): New member.
+       (class innermost_block_tracker) <innermost_block_tracker>: Add
+       "types" parameter.
+       <reset>: Remove method.
+       (innermost_block): Don't declare.
+       (null_post_parser): Update.
+       * parse.c (innermost_block): Remove global.
+       (write_dollar_variable): Update.
+       (parse_exp_1, parse_exp_in_context): Add "tracker" parameter.
+       Remove "tracker_types" parameter.
+       (parse_expression): Add "tracker" parameter.
+       (parse_expression_for_completion): Update.
+       (null_post_parser): Add "tracker" parameter.
+       * p-exp.y: Update rules.
+       * m2-exp.y: Update rules.
+       * language.h (struct language_defn) <la_post_parser>: Add
+       "tracker" parameter.
+       * go-exp.y: Update rules.
+       * f-exp.y: Update rules.
+       * expression.h (parse_expression, parse_exp_1): Add "tracker"
+       parameter.
+       * d-exp.y: Update rules.
+       * c-exp.y: Update rules.
+       * breakpoint.c (set_breakpoint_condition): Create an
+       innermost_block_tracker.
+       (watch_command_1): Likewise.
+       * ada-lang.c (resolve): Add "tracker" parameter.
+       (resolve_subexp): Likewise.
+       * ada-exp.y (write_var_from_sym): Update.
+
 2019-04-04  Tom Tromey  <tom@tromey.com>
 
        * type-stack.h: New file.
 
                    struct symbol *sym)
 {
   if (symbol_read_needs_frame (sym))
-    innermost_block.update (block, INNERMOST_BLOCK_FOR_SYMBOLS);
+    par_state->block_tracker->update (block, INNERMOST_BLOCK_FOR_SYMBOLS);
 
   write_exp_elt_opcode (par_state, OP_VAR_VALUE);
   write_exp_elt_block (par_state, block);
 
 static struct block_symbol *defns_collected (struct obstack *, int);
 
 static struct value *resolve_subexp (expression_up *, int *, int,
-                                     struct type *, int);
+                                     struct type *, int,
+                                    innermost_block_tracker *);
 
 static void replace_operator_with_call (expression_up *, int, int, int,
                                         struct symbol *, const struct block *);
    return type is preferred.  May change (expand) *EXP.  */
 
 static void
-resolve (expression_up *expp, int void_context_p, int parse_completion)
+resolve (expression_up *expp, int void_context_p, int parse_completion,
+        innermost_block_tracker *tracker)
 {
   struct type *context_type = NULL;
   int pc = 0;
   if (void_context_p)
     context_type = builtin_type ((*expp)->gdbarch)->builtin_void;
 
-  resolve_subexp (expp, &pc, 1, context_type, parse_completion);
+  resolve_subexp (expp, &pc, 1, context_type, parse_completion, tracker);
 }
 
 /* Resolve the operator of the subexpression beginning at
 
 static struct value *
 resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
-                struct type *context_type, int parse_completion)
+                struct type *context_type, int parse_completion,
+               innermost_block_tracker *tracker)
 {
   int pc = *pos;
   int i;
       else
         {
           *pos += 3;
-          resolve_subexp (expp, pos, 0, NULL, parse_completion);
+          resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
         }
       nargs = longest_to_int (exp->elts[pc + 1].longconst);
       break;
 
     case UNOP_ADDR:
       *pos += 1;
-      resolve_subexp (expp, pos, 0, NULL, parse_completion);
+      resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
       break;
 
     case UNOP_QUAL:
       *pos += 3;
       resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type),
-                     parse_completion);
+                     parse_completion, tracker);
       break;
 
     case OP_ATR_MODULUS:
         struct value *arg1;
 
         *pos += 1;
-        arg1 = resolve_subexp (expp, pos, 0, NULL, parse_completion);
+        arg1 = resolve_subexp (expp, pos, 0, NULL, parse_completion, tracker);
         if (arg1 == NULL)
-          resolve_subexp (expp, pos, 1, NULL, parse_completion);
+          resolve_subexp (expp, pos, 1, NULL, parse_completion, tracker);
         else
-          resolve_subexp (expp, pos, 1, value_type (arg1), parse_completion);
+          resolve_subexp (expp, pos, 1, value_type (arg1), parse_completion,
+                         tracker);
         break;
       }
 
 
   argvec = XALLOCAVEC (struct value *, nargs + 1);
   for (i = 0; i < nargs; i += 1)
-    argvec[i] = resolve_subexp (expp, pos, 1, NULL, parse_completion);
+    argvec[i] = resolve_subexp (expp, pos, 1, NULL, parse_completion,
+                               tracker);
   argvec[i] = NULL;
   exp = expp->get ();
 
 
           exp->elts[pc + 1].block = candidates[i].block;
           exp->elts[pc + 2].symbol = candidates[i].symbol;
-         innermost_block.update (candidates[i]);
+         tracker->update (candidates[i]);
         }
 
       if (deprocedure_p
 
             exp->elts[pc + 4].block = candidates[i].block;
             exp->elts[pc + 5].symbol = candidates[i].symbol;
-           innermost_block.update (candidates[i]);
+           tracker->update (candidates[i]);
           }
       }
       break;
 
        {
          struct watchpoint *w = (struct watchpoint *) b;
 
+         innermost_block_tracker tracker;
          arg = exp;
-         w->cond_exp = parse_exp_1 (&arg, 0, 0, 0);
+         w->cond_exp = parse_exp_1 (&arg, 0, 0, 0, &tracker);
          if (*arg)
            error (_("Junk at end of expression"));
-         w->cond_exp_valid_block = innermost_block.block ();
+         w->cond_exp_valid_block = tracker.block ();
        }
       else
        {
      ARG.  */
   std::string expression (arg, exp_end - arg);
   exp_start = arg = expression.c_str ();
-  expression_up exp = parse_exp_1 (&arg, 0, 0, 0);
+  innermost_block_tracker tracker;
+  expression_up exp = parse_exp_1 (&arg, 0, 0, 0, &tracker);
   exp_end = arg;
   /* Remove trailing whitespace from the expression before saving it.
      This makes the eventual display of the expression string a bit
       error (_("Cannot watch constant value `%.*s'."), len, exp_start);
     }
 
-  exp_valid_block = innermost_block.block ();
+  exp_valid_block = tracker.block ();
   struct value *mark = value_mark ();
   struct value *val_as_value = nullptr;
   fetch_subexp_value (exp.get (), &pc, &val_as_value, &result, NULL,
   if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
     {
       tok = cond_start = end_tok + 1;
-      parse_exp_1 (&tok, 0, 0, 0);
+      innermost_block_tracker if_tracker;
+      parse_exp_1 (&tok, 0, 0, 0, &if_tracker);
 
       /* The watchpoint expression may not be local, but the condition
         may still be.  E.g.: `watch global if local > 0'.  */
-      cond_exp_valid_block = innermost_block.block ();
+      cond_exp_valid_block = if_tracker.block ();
 
       cond_end = tok;
     }
 
                            error (_("No symbol \"%s\" in specified context."),
                                   copy_name ($3));
                          if (symbol_read_needs_frame (sym.symbol))
-
-                           innermost_block.update (sym);
+                           pstate->block_tracker->update (sym);
 
                          write_exp_elt_opcode (pstate, OP_VAR_VALUE);
                          write_exp_elt_block (pstate, sym.block);
                          if (sym.symbol)
                            {
                              if (symbol_read_needs_frame (sym.symbol))
-                               innermost_block.update (sym);
+                               pstate->block_tracker->update (sym);
 
                              /* If we found a function, see if it's
                                 an ifunc resolver that has the same
                              /* C++: it hangs off of `this'.  Must
                                 not inadvertently convert from a method call
                                 to data ref.  */
-                             innermost_block.update (sym);
+                             pstate->block_tracker->update (sym);
                              write_exp_elt_opcode (pstate, OP_THIS);
                              write_exp_elt_opcode (pstate, OP_THIS);
                              write_exp_elt_opcode (pstate, STRUCTOP_PTR);
 
                  if (sym.symbol && SYMBOL_CLASS (sym.symbol) != LOC_TYPEDEF)
                    {
                      if (symbol_read_needs_frame (sym.symbol))
-                       innermost_block.update (sym);
+                       pstate->block_tracker->update (sym);
                      write_exp_elt_opcode (pstate, OP_VAR_VALUE);
                      write_exp_elt_block (pstate, sym.block);
                      write_exp_elt_sym (pstate, sym.symbol);
                     {
                      /* It hangs off of `this'.  Must not inadvertently convert from a
                         method call to data ref.  */
-                     innermost_block.update (sym);
+                     pstate->block_tracker->update (sym);
                      write_exp_elt_opcode (pstate, OP_THIS);
                      write_exp_elt_opcode (pstate, OP_THIS);
                      write_exp_elt_opcode (pstate, STRUCTOP_PTR);
 
 
 /* From parse.c */
 
-extern expression_up parse_expression (const char *);
+class innermost_block_tracker;
+extern expression_up parse_expression (const char *,
+                                      innermost_block_tracker * = nullptr);
 
 extern expression_up parse_expression_with_language (const char *string,
                                                     enum language lang);
 extern struct type *parse_expression_for_completion
     (const char *, gdb::unique_xmalloc_ptr<char> *, enum type_code *);
 
+class innermost_block_tracker;
 extern expression_up parse_exp_1 (const char **, CORE_ADDR pc,
                                  const struct block *, int,
-                                 innermost_block_tracker_types
-                                   = INNERMOST_BLOCK_FOR_SYMBOLS);
+                                 innermost_block_tracker * = nullptr);
 
 /* From eval.c */
 
 
                          if (sym.symbol)
                            {
                              if (symbol_read_needs_frame (sym.symbol))
-                               innermost_block.update (sym);
+                               pstate->block_tracker->update (sym);
                              write_exp_elt_opcode (pstate, OP_VAR_VALUE);
                              write_exp_elt_block (pstate, sym.block);
                              write_exp_elt_sym (pstate, sym.symbol);
 
                          if (sym.symbol)
                            {
                              if (symbol_read_needs_frame (sym.symbol))
-                               innermost_block.update (sym);
+                               pstate->block_tracker->update (sym);
 
                              write_exp_elt_opcode (pstate, OP_VAR_VALUE);
                              write_exp_elt_block (pstate, sym.block);
 
 struct parser_state;
 class compile_instance;
 struct completion_match_for_lcd;
+class innermost_block_tracker;
 
 #define MAX_FORTRAN_DIMS  7    /* Maximum number of F77 array dims.  */
 
        for completion, not evaluation.  */
 
     void (*la_post_parser) (expression_up *expp, int void_context_p,
-                           int completing);
+                           int completing, innermost_block_tracker *tracker);
 
     void (*la_printchar) (int ch, struct type *chtype,
                          struct ui_file * stream);
 
                            error (_("No symbol \"%s\" in specified context."),
                                   copy_name ($3));
                          if (symbol_read_needs_frame (sym.symbol))
-                           innermost_block.update (sym);
+                           pstate->block_tracker->update (sym);
 
                          write_exp_elt_opcode (pstate, OP_VAR_VALUE);
                          write_exp_elt_block (pstate, sym.block);
                          if (sym.symbol)
                            {
                              if (symbol_read_needs_frame (sym.symbol))
-                               innermost_block.update (sym);
+                               pstate->block_tracker->update (sym);
 
                              write_exp_elt_opcode (pstate, OP_VAR_VALUE);
                              write_exp_elt_block (pstate, sym.block);
 
                          if (sym.symbol)
                            {
                              if (symbol_read_needs_frame (sym.symbol))
-                               innermost_block.update (sym);
+                               pstate->block_tracker->update (sym);
 
                              write_exp_elt_opcode (pstate, OP_VAR_VALUE);
                              write_exp_elt_block (pstate, sym.block);
                              /* Object pascal: it hangs off of `this'.  Must
                                 not inadvertently convert from a method call
                                 to data ref.  */
-                             innermost_block.update (sym);
+                             pstate->block_tracker->update (sym);
                              write_exp_elt_opcode (pstate, OP_THIS);
                              write_exp_elt_opcode (pstate, OP_THIS);
                              write_exp_elt_opcode (pstate, STRUCTOP_PTR);
 
     dump_subexp_body_standard,
     evaluate_subexp_standard
   };
-\f
-/* Global variables declared in parser-defs.h (and commented there).  */
-innermost_block_tracker innermost_block;
-
 \f
 static unsigned int expressiondebug = 0;
 static void
 static expression_up parse_exp_in_context (const char **, CORE_ADDR,
                                           const struct block *, int,
                                           int, int *,
-                                          innermost_block_tracker_types,
+                                          innermost_block_tracker *,
                                           expr_completion_state *);
 
 static void increase_expout_size (struct expr_builder *ps, size_t lenelt);
   str.ptr++;
   write_exp_string (ps, str);
   write_exp_elt_opcode (ps, OP_REGISTER);
-  innermost_block.update (ps->expression_context_block,
-                         INNERMOST_BLOCK_FOR_REGISTERS);
+  ps->block_tracker->update (ps->expression_context_block,
+                            INNERMOST_BLOCK_FOR_REGISTERS);
   return;
 }
 
 
 expression_up
 parse_exp_1 (const char **stringptr, CORE_ADDR pc, const struct block *block,
-            int comma, innermost_block_tracker_types tracker_types)
+            int comma, innermost_block_tracker *tracker)
 {
   return parse_exp_in_context (stringptr, pc, block, comma, 0, NULL,
-                              tracker_types, nullptr);
+                              tracker, nullptr);
 }
 
 /* As for parse_exp_1, except that if VOID_CONTEXT_P, then
 parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
                      const struct block *block,
                      int comma, int void_context_p, int *out_subexp,
-                     innermost_block_tracker_types tracker_types,
+                     innermost_block_tracker *tracker,
                      expr_completion_state *cstate)
 {
   const struct language_defn *lang = NULL;
   int subexp;
 
-  innermost_block.reset (tracker_types);
-
   if (*stringptr == 0 || **stringptr == 0)
     error_no_arg (_("expression to compute"));
 
   const struct block *expression_context_block = block;
   CORE_ADDR expression_context_pc = 0;
 
+  innermost_block_tracker local_tracker;
+  if (tracker == nullptr)
+    tracker = &local_tracker;
+
   /* If no context specified, try using the current frame, if any.  */
   if (!expression_context_block)
     expression_context_block = get_selected_block (&expression_context_pc);
 
   parser_state ps (lang, get_current_arch (), expression_context_block,
                   expression_context_pc, comma, *stringptr,
-                  cstate != nullptr);
+                  cstate != nullptr, tracker);
 
   scoped_restore_current_language lang_saver;
   set_language (lang->la_language);
   if (out_subexp)
     *out_subexp = subexp;
 
-  lang->la_post_parser (&result, void_context_p, ps.parse_completion);
+  lang->la_post_parser (&result, void_context_p, ps.parse_completion,
+                       tracker);
 
   if (expressiondebug)
     dump_prefix_expression (result.get (), gdb_stdlog);
    to use up all of the contents of STRING.  */
 
 expression_up
-parse_expression (const char *string)
+parse_expression (const char *string, innermost_block_tracker *tracker)
 {
-  expression_up exp = parse_exp_1 (&string, 0, 0, 0);
+  expression_up exp = parse_exp_1 (&string, 0, 0, 0, tracker);
   if (*string)
     error (_("Junk after end of expression."));
   return exp;
   TRY
     {
       exp = parse_exp_in_context (&string, 0, 0, 0, 0, &subexp,
-                                 INNERMOST_BLOCK_FOR_SYMBOLS, &cstate);
+                                 nullptr, &cstate);
     }
   CATCH (except, RETURN_MASK_ERROR)
     {
 /* A post-parser that does nothing.  */
 
 void
-null_post_parser (expression_up *exp, int void_context_p, int completin)
+null_post_parser (expression_up *exp, int void_context_p, int completin,
+                 innermost_block_tracker *tracker)
 {
 }
 
 
 struct block;
 struct language_defn;
 struct internalvar;
+class innermost_block_tracker;
 
 extern int parser_debug;
 
                CORE_ADDR context_pc,
                int comma,
                const char *input,
-               int completion)
+               int completion,
+               innermost_block_tracker *tracker)
     : expr_builder (lang, gdbarch),
       expression_context_block (context_block),
       expression_context_pc (context_pc),
       comma_terminates (comma),
       lexptr (input),
-      parse_completion (completion)
+      parse_completion (completion),
+      block_tracker (tracker)
   {
   }
 
   /* Completion state is updated here.  */
   expr_completion_state m_completion_state;
 
+  /* The innermost block tracker.  */
+  innermost_block_tracker *block_tracker;
+
 private:
 
   /* Data structure for saving values of arglist_len for function calls whose
 class innermost_block_tracker
 {
 public:
-  innermost_block_tracker ()
-    : m_types (INNERMOST_BLOCK_FOR_SYMBOLS),
+  innermost_block_tracker (innermost_block_tracker_types types
+                          = INNERMOST_BLOCK_FOR_SYMBOLS)
+    : m_types (types),
       m_innermost_block (NULL)
   { /* Nothing.  */ }
 
-  /* Reset the currently stored innermost block.  Usually called before
-     parsing a new expression.  As the most common case is that we only
-     want to gather the innermost block for symbols in an expression, this
-     becomes the default block tracker type.  */
-  void reset (innermost_block_tracker_types t = INNERMOST_BLOCK_FOR_SYMBOLS)
-  {
-    m_types = t;
-    m_innermost_block = NULL;
-  }
-
   /* Update the stored innermost block if the new block B is more inner
      than the currently stored block, or if no block is stored yet.  The
      type T tells us whether the block B was for a symbol or for a
   const struct block *m_innermost_block;
 };
 
-/* The innermost context required by the stack and register variables
-   we've encountered so far.  This is cleared by the expression
-   parsing functions before parsing an expression, and can queried
-   once the parse is complete.  */
-extern innermost_block_tracker innermost_block;
-
 /* A string token, either a char-string or bit-string.  Char-strings are
    used, for example, for the names of symbols.  */
 
 
 extern const char *op_name_standard (enum exp_opcode);
 
-extern void null_post_parser (expression_up *, int, int);
+extern void null_post_parser (expression_up *, int, int,
+                             innermost_block_tracker *);
 
 extern bool parse_float (const char *p, int len,
                         const struct type *type, gdb_byte *data);
 
       fmt.raw = 0;
     }
 
-  expression_up expr = parse_expression (exp);
+  innermost_block_tracker tracker;
+  expression_up expr = parse_expression (exp, &tracker);
 
   newobj = new display ();
 
   newobj->exp_string = xstrdup (exp);
   newobj->exp = std::move (expr);
-  newobj->block = innermost_block.block ();
+  newobj->block = tracker.block ();
   newobj->pspace = current_program_space;
   newobj->number = ++display_number;
   newobj->format = fmt;
 
       TRY
        {
-         d->exp = parse_expression (d->exp_string);
-         d->block = innermost_block.block ();
+         innermost_block_tracker tracker;
+         d->exp = parse_expression (d->exp_string, &tracker);
+         d->block = tracker.block ();
        }
       CATCH (ex, RETURN_MASK_ALL)
        {
 
 static void rustyyerror (rust_parser *parser, const char *msg);
 
 static struct stoken make_stoken (const char *);
-static struct block_symbol rust_lookup_symbol (const char *name,
-                                              const struct block *block,
-                                              const domain_enum domain);
 
 /* A regular expression for matching Rust numbers.  This is split up
    since it is very long and this gives us a way to comment the
   int lex_operator (YYSTYPE *lvalp);
   void push_back (char c);
 
+  void update_innermost_block (struct block_symbol sym);
+  struct block_symbol lookup_symbol (const char *name,
+                                    const struct block *block,
+                                    const domain_enum domain);
   struct type *rust_lookup_type (const char *name, const struct block *block);
   std::vector<struct type *> convert_params_to_types (rust_op_vector *params);
   struct type *convert_ast_to_type (const struct rust_op *operation);
 
 /* A helper that updates the innermost block as appropriate.  */
 
-static void
-update_innermost_block (struct block_symbol sym)
+void
+rust_parser::update_innermost_block (struct block_symbol sym)
 {
   if (symbol_read_needs_frame (sym.symbol))
-    innermost_block.update (sym);
+    pstate->block_tracker->update (sym);
 }
 
 /* Lex a hex number with at least MIN digits and at most MAX
 /* Like lookup_symbol, but handles Rust namespace conventions, and
    doesn't require field_of_this_result.  */
 
-static struct block_symbol
-rust_lookup_symbol (const char *name, const struct block *block,
-                   const domain_enum domain)
+struct block_symbol
+rust_parser::lookup_symbol (const char *name, const struct block *block,
+                           const domain_enum domain)
 {
   struct block_symbol result;
 
   munge_name_and_block (&name, &block);
 
-  result = lookup_symbol (name, block, domain, NULL);
+  result = ::lookup_symbol (name, block, domain, NULL);
   if (result.symbol != NULL)
     update_innermost_block (result);
   return result;
 
   munge_name_and_block (&name, &block);
 
-  result = lookup_symbol (name, block, STRUCT_DOMAIN, NULL);
+  result = ::lookup_symbol (name, block, STRUCT_DOMAIN, NULL);
   if (result.symbol != NULL)
     {
       update_innermost_block (result);
          }
 
        varname = convert_name (operation);
-       sym = rust_lookup_symbol (varname, pstate->expression_context_block,
-                                 VAR_DOMAIN);
+       sym = lookup_symbol (varname, pstate->expression_context_block,
+                            VAR_DOMAIN);
        if (sym.symbol != NULL && SYMBOL_CLASS (sym.symbol) != LOC_TYPEDEF)
          {
            write_exp_elt_opcode (pstate, OP_VAR_VALUE);
 
   // Set up dummy "parser", so that rust_type works.
   struct parser_state ps (&rust_language_defn, target_gdbarch (),
-                         nullptr, 0, 0, nullptr, 0);
+                         nullptr, 0, 0, nullptr, 0, nullptr);
   rust_parser parser (&ps);
 
   rust_lex_test_one (&parser, "", 0);
 
        }
 
       p = expression;
+
+      innermost_block_tracker tracker (INNERMOST_BLOCK_FOR_SYMBOLS
+                                      | INNERMOST_BLOCK_FOR_REGISTERS);
       /* Wrap the call to parse expression, so we can 
          return a sensible error.  */
       TRY
        {
-         var->root->exp = parse_exp_1 (&p, pc, block, 0,
-                                       INNERMOST_BLOCK_FOR_SYMBOLS
-                                       | INNERMOST_BLOCK_FOR_REGISTERS);
+         var->root->exp = parse_exp_1 (&p, pc, block, 0, &tracker);
        }
 
       CATCH (except, RETURN_MASK_ERROR)
 
       var->format = variable_default_display (var.get ());
       var->root->valid_block =
-       var->root->floating ? NULL : innermost_block.block ();
+       var->root->floating ? NULL : tracker.block ();
       var->name = expression;
       /* For a root var, the name and the expr are the same.  */
       var->path_expr = expression;