[11/13] Move completion parsing to parser_state

Message ID 20190403013805.11978-12-tom@tromey.com
State New, archived
Headers

Commit Message

Tom Tromey April 3, 2019, 1:38 a.m. UTC
  This moves the globals and functions related to parsing for completion
to parser_state.  A new structure is introduced in order to return
completion results from the parse back to
parse_expression_for_completion.

gdb/ChangeLog
2019-04-02  Tom Tromey  <tom@tromey.com>

	* rust-exp.y (rust_parser::lex_identifier, rustyylex)
	(rust_parser::convert_ast_to_expression, rust_parse)
	(rust_lex_test_completion, rust_lex_tests): Update.
	* parser-defs.h (struct expr_completion_state): New.
	(struct parser_state) <parser_state>: Add completion parameter.
	<mark_struct_expression, mark_completion_tag>: New methods.
	<parse_completion, m_completion_state>: New members.
	(prefixify_expression, null_post_parser): Update.
	(mark_struct_expression, mark_completion_tag): Don't declare.
	* parse.c (parse_completion, expout_last_struct)
	(expout_tag_completion_type, expout_completion_name): Remove
	globals.
	(parser_state::mark_struct_expression)
	(parser_state::mark_completion_tag): Now methods.
	(prefixify_expression): Add last_struct parameter.
	(prefixify_subexp): Likewise.
	(parse_exp_1): Update.
	(parse_exp_in_context): Add cstate parameter.  Update.
	(parse_expression_for_completion): Create an
	expr_completion_state.
	(null_post_parser): Add "completion" parameter.
	* p-exp.y: Update rules.
	(yylex): Update.
	* language.h (struct language_defn) <la_post_parser>: Add
	"completing" parameter.
	* go-exp.y: Update rules.
	(lex_one_token): Update.
	* expression.h (parse_completion): Don't declare.
	* d-exp.y: Update rules.
	(lex_one_token): Update rules.
	* c-exp.y: Update rules.
	(lex_one_token): Update.
	* ada-lang.c (resolve): Add "parse_completion" parameter.
	(resolve_subexp): Likewise.
	(ada_resolve_function): Likewise.
---
 gdb/ChangeLog     | 38 +++++++++++++++++++
 gdb/ada-lang.c    | 35 ++++++++++--------
 gdb/c-exp.y       | 43 ++++++++++++----------
 gdb/d-exp.y       |  8 ++--
 gdb/expression.h  |  4 --
 gdb/go-exp.y      |  8 ++--
 gdb/language.h    |  7 +++-
 gdb/p-exp.y       |  6 +--
 gdb/parse.c       | 93 +++++++++++++++++++++--------------------------
 gdb/parser-defs.h | 53 +++++++++++++++++++++------
 gdb/rust-exp.y    | 16 ++++----
 11 files changed, 188 insertions(+), 123 deletions(-)
  

Patch

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index cdaf5589bc4..6e1c2cbeb3d 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -125,7 +125,7 @@  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 *);
+                                     struct type *, int);
 
 static void replace_operator_with_call (expression_up *, int, int, int,
                                         struct symbol *, const struct block *);
@@ -225,7 +225,7 @@  static int find_struct_field (const char *, struct type *, int,
 
 static int ada_resolve_function (struct block_symbol *, int,
                                  struct value **, int, const char *,
-                                 struct type *);
+                                 struct type *, int);
 
 static int ada_is_direct_array_type (struct type *);
 
@@ -3220,7 +3220,7 @@  ada_decoded_op_name (enum exp_opcode op)
    return type is preferred.  May change (expand) *EXP.  */
 
 static void
-resolve (expression_up *expp, int void_context_p)
+resolve (expression_up *expp, int void_context_p, int parse_completion)
 {
   struct type *context_type = NULL;
   int pc = 0;
@@ -3228,7 +3228,7 @@  resolve (expression_up *expp, int void_context_p)
   if (void_context_p)
     context_type = builtin_type ((*expp)->gdbarch)->builtin_void;
 
-  resolve_subexp (expp, &pc, 1, context_type);
+  resolve_subexp (expp, &pc, 1, context_type, parse_completion);
 }
 
 /* Resolve the operator of the subexpression beginning at
@@ -3242,7 +3242,7 @@  resolve (expression_up *expp, int void_context_p)
 
 static struct value *
 resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
-                struct type *context_type)
+                struct type *context_type, int parse_completion)
 {
   int pc = *pos;
   int i;
@@ -3267,19 +3267,20 @@  resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
       else
         {
           *pos += 3;
-          resolve_subexp (expp, pos, 0, NULL);
+          resolve_subexp (expp, pos, 0, NULL, parse_completion);
         }
       nargs = longest_to_int (exp->elts[pc + 1].longconst);
       break;
 
     case UNOP_ADDR:
       *pos += 1;
-      resolve_subexp (expp, pos, 0, NULL);
+      resolve_subexp (expp, pos, 0, NULL, parse_completion);
       break;
 
     case UNOP_QUAL:
       *pos += 3;
-      resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type));
+      resolve_subexp (expp, pos, 1, check_typedef (exp->elts[pc + 1].type),
+		      parse_completion);
       break;
 
     case OP_ATR_MODULUS:
@@ -3310,11 +3311,11 @@  resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
         struct value *arg1;
 
         *pos += 1;
-        arg1 = resolve_subexp (expp, pos, 0, NULL);
+        arg1 = resolve_subexp (expp, pos, 0, NULL, parse_completion);
         if (arg1 == NULL)
-          resolve_subexp (expp, pos, 1, NULL);
+          resolve_subexp (expp, pos, 1, NULL, parse_completion);
         else
-          resolve_subexp (expp, pos, 1, value_type (arg1));
+          resolve_subexp (expp, pos, 1, value_type (arg1), parse_completion);
         break;
       }
 
@@ -3402,7 +3403,7 @@  resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
 
   argvec = XALLOCAVEC (struct value *, nargs + 1);
   for (i = 0; i < nargs; i += 1)
-    argvec[i] = resolve_subexp (expp, pos, 1, NULL);
+    argvec[i] = resolve_subexp (expp, pos, 1, NULL, parse_completion);
   argvec[i] = NULL;
   exp = expp->get ();
 
@@ -3471,7 +3472,7 @@  resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
               i = ada_resolve_function
                 (candidates.data (), n_candidates, NULL, 0,
                  SYMBOL_LINKAGE_NAME (exp->elts[pc + 2].symbol),
-                 context_type);
+                 context_type, parse_completion);
               if (i < 0)
                 error (_("Could not find a match for %s"),
                        SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol));
@@ -3522,7 +3523,7 @@  resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
                   (candidates.data (), n_candidates,
                    argvec, nargs,
                    SYMBOL_LINKAGE_NAME (exp->elts[pc + 5].symbol),
-                   context_type);
+                   context_type, parse_completion);
                 if (i < 0)
                   error (_("Could not find a match for %s"),
                          SYMBOL_PRINT_NAME (exp->elts[pc + 5].symbol));
@@ -3566,7 +3567,8 @@  resolve_subexp (expression_up *expp, int *pos, int deprocedure_p,
                                     &candidates);
 
           i = ada_resolve_function (candidates.data (), n_candidates, argvec,
-				    nargs, ada_decoded_op_name (op), NULL);
+				    nargs, ada_decoded_op_name (op), NULL,
+				    parse_completion);
           if (i < 0)
             break;
 
@@ -3733,7 +3735,8 @@  return_match (struct type *func_type, struct type *context_type)
 static int
 ada_resolve_function (struct block_symbol syms[],
                       int nsyms, struct value **args, int nargs,
-                      const char *name, struct type *context_type)
+                      const char *name, struct type *context_type,
+		      int parse_completion)
 {
   int fallback;
   int k;
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index cab5cd55dbd..842b492e58a 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -364,7 +364,7 @@  exp	:	exp ARROW field_name
 	;
 
 exp	:	exp ARROW field_name COMPLETE
-			{ mark_struct_expression (pstate);
+			{ pstate->mark_struct_expression ();
 			  write_exp_elt_opcode (pstate, STRUCTOP_PTR);
 			  write_exp_string (pstate, $3);
 			  write_exp_elt_opcode (pstate, STRUCTOP_PTR); }
@@ -372,7 +372,7 @@  exp	:	exp ARROW field_name COMPLETE
 
 exp	:	exp ARROW COMPLETE
 			{ struct stoken s;
-			  mark_struct_expression (pstate);
+			  pstate->mark_struct_expression ();
 			  write_exp_elt_opcode (pstate, STRUCTOP_PTR);
 			  s.ptr = "";
 			  s.length = 0;
@@ -387,7 +387,7 @@  exp	:	exp ARROW '~' name
 	;
 
 exp	:	exp ARROW '~' name COMPLETE
-			{ mark_struct_expression (pstate);
+			{ pstate->mark_struct_expression ();
 			  write_exp_elt_opcode (pstate, STRUCTOP_PTR);
 			  write_destructor_name (pstate, $4);
 			  write_exp_elt_opcode (pstate, STRUCTOP_PTR); }
@@ -412,7 +412,7 @@  exp	:	exp '.' field_name
 	;
 
 exp	:	exp '.' field_name COMPLETE
-			{ mark_struct_expression (pstate);
+			{ pstate->mark_struct_expression ();
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
 			  write_exp_string (pstate, $3);
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); }
@@ -420,7 +420,7 @@  exp	:	exp '.' field_name COMPLETE
 
 exp	:	exp '.' COMPLETE
 			{ struct stoken s;
-			  mark_struct_expression (pstate);
+			  pstate->mark_struct_expression ();
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
 			  s.ptr = "";
 			  s.length = 0;
@@ -435,7 +435,7 @@  exp	:	exp '.' '~' name
 	;
 
 exp	:	exp '.' '~' name COMPLETE
-			{ mark_struct_expression (pstate);
+			{ pstate->mark_struct_expression ();
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
 			  write_destructor_name (pstate, $4);
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); }
@@ -1406,13 +1406,14 @@  typebase
 			}
 	|	STRUCT COMPLETE
 			{
-			  mark_completion_tag (TYPE_CODE_STRUCT, "", 0);
+			  pstate->mark_completion_tag (TYPE_CODE_STRUCT,
+						       "", 0);
 			  $$ = NULL;
 			}
 	|	STRUCT name COMPLETE
 			{
-			  mark_completion_tag (TYPE_CODE_STRUCT, $2.ptr,
-					       $2.length);
+			  pstate->mark_completion_tag (TYPE_CODE_STRUCT,
+						       $2.ptr, $2.length);
 			  $$ = NULL;
 			}
 	|	CLASS name
@@ -1421,13 +1422,14 @@  typebase
 			}
 	|	CLASS COMPLETE
 			{
-			  mark_completion_tag (TYPE_CODE_STRUCT, "", 0);
+			  pstate->mark_completion_tag (TYPE_CODE_STRUCT,
+						       "", 0);
 			  $$ = NULL;
 			}
 	|	CLASS name COMPLETE
 			{
-			  mark_completion_tag (TYPE_CODE_STRUCT, $2.ptr,
-					       $2.length);
+			  pstate->mark_completion_tag (TYPE_CODE_STRUCT,
+						       $2.ptr, $2.length);
 			  $$ = NULL;
 			}
 	|	UNION name
@@ -1437,13 +1439,14 @@  typebase
 			}
 	|	UNION COMPLETE
 			{
-			  mark_completion_tag (TYPE_CODE_UNION, "", 0);
+			  pstate->mark_completion_tag (TYPE_CODE_UNION,
+						       "", 0);
 			  $$ = NULL;
 			}
 	|	UNION name COMPLETE
 			{
-			  mark_completion_tag (TYPE_CODE_UNION, $2.ptr,
-					       $2.length);
+			  pstate->mark_completion_tag (TYPE_CODE_UNION,
+						       $2.ptr, $2.length);
 			  $$ = NULL;
 			}
 	|	ENUM name
@@ -1452,13 +1455,13 @@  typebase
 			}
 	|	ENUM COMPLETE
 			{
-			  mark_completion_tag (TYPE_CODE_ENUM, "", 0);
+			  pstate->mark_completion_tag (TYPE_CODE_ENUM, "", 0);
 			  $$ = NULL;
 			}
 	|	ENUM name COMPLETE
 			{
-			  mark_completion_tag (TYPE_CODE_ENUM, $2.ptr,
-					       $2.length);
+			  pstate->mark_completion_tag (TYPE_CODE_ENUM, $2.ptr,
+						       $2.length);
 			  $$ = NULL;
 			}
 	|	UNSIGNED type_name
@@ -2608,7 +2611,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
 	  saw_name_at_eof = 0;
 	  return COMPLETE;
 	}
-      else if (parse_completion && saw_structop)
+      else if (par_state->parse_completion && saw_structop)
 	return COMPLETE;
       else
         return 0;
@@ -2902,7 +2905,7 @@  lex_one_token (struct parser_state *par_state, bool *is_quoted_name)
   if (*tokstart == '$')
     return DOLLAR_VARIABLE;
 
-  if (parse_completion && *pstate->lexptr == '\0')
+  if (pstate->parse_completion && *pstate->lexptr == '\0')
     saw_name_at_eof = 1;
 
   yylval.ssym.stoken = yylval.sval;
diff --git a/gdb/d-exp.y b/gdb/d-exp.y
index c14c2d6fd6f..4d51cfdcb71 100644
--- a/gdb/d-exp.y
+++ b/gdb/d-exp.y
@@ -338,7 +338,7 @@  PostfixExpression:
 	PrimaryExpression
 |	PostfixExpression '.' COMPLETE
 		{ struct stoken s;
-		  mark_struct_expression (pstate);
+		  pstate->mark_struct_expression ();
 		  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
 		  s.ptr = "";
 		  s.length = 0;
@@ -349,7 +349,7 @@  PostfixExpression:
 		  write_exp_string (pstate, $3);
 		  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); }
 |	PostfixExpression '.' IDENTIFIER COMPLETE
-		{ mark_struct_expression (pstate);
+		{ pstate->mark_struct_expression ();
 		  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
 		  write_exp_string (pstate, $3);
 		  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); }
@@ -1107,7 +1107,7 @@  lex_one_token (struct parser_state *par_state)
       /* Might be a floating point number.  */
       if (pstate->lexptr[1] < '0' || pstate->lexptr[1] > '9')
 	{
-	  if (parse_completion)
+	  if (pstate->parse_completion)
 	    last_was_structop = 1;
 	  goto symbol;		/* Nope, must be a symbol.  */
 	}
@@ -1308,7 +1308,7 @@  lex_one_token (struct parser_state *par_state)
 	return NAME_OR_INT;
     }
 
-  if (parse_completion && *pstate->lexptr == '\0')
+  if (pstate->parse_completion && *pstate->lexptr == '\0')
     saw_name_at_eof = 1;
 
   return IDENTIFIER;
diff --git a/gdb/expression.h b/gdb/expression.h
index 8db4b9d7e26..8ce8c3269e3 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -123,10 +123,6 @@  extern expression_up parse_exp_1 (const char **, CORE_ADDR pc,
 				  innermost_block_tracker_types
 				    = INNERMOST_BLOCK_FOR_SYMBOLS);
 
-/* For use by parsers; set if we want to parse an expression and
-   attempt completion.  */
-extern int parse_completion;
-
 /* From eval.c */
 
 /* Values of NOSIDE argument to eval_subexp.  */
diff --git a/gdb/go-exp.y b/gdb/go-exp.y
index 358fd530918..771adc4416b 100644
--- a/gdb/go-exp.y
+++ b/gdb/go-exp.y
@@ -246,7 +246,7 @@  exp	:	exp '.' name_not_typename
 	;
 
 exp	:	exp '.' name_not_typename COMPLETE
-			{ mark_struct_expression (pstate);
+			{ pstate->mark_struct_expression ();
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
 			  write_exp_string (pstate, $3.stoken);
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); }
@@ -254,7 +254,7 @@  exp	:	exp '.' name_not_typename COMPLETE
 
 exp	:	exp '.' COMPLETE
 			{ struct stoken s;
-			  mark_struct_expression (pstate);
+			  pstate->mark_struct_expression ();
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
 			  s.ptr = "";
 			  s.length = 0;
@@ -1087,7 +1087,7 @@  lex_one_token (struct parser_state *par_state)
       /* Might be a floating point number.  */
       if (par_state->lexptr[1] < '0' || par_state->lexptr[1] > '9')
 	{
-	  if (parse_completion)
+	  if (pstate->parse_completion)
 	    last_was_structop = 1;
 	  goto symbol;		/* Nope, must be a symbol. */
 	}
@@ -1276,7 +1276,7 @@  lex_one_token (struct parser_state *par_state)
   if (*tokstart == '$')
     return DOLLAR_VARIABLE;
 
-  if (parse_completion && *par_state->lexptr == '\0')
+  if (pstate->parse_completion && *par_state->lexptr == '\0')
     saw_name_at_eof = 1;
   return NAME;
 }
diff --git a/gdb/language.h b/gdb/language.h
index d56ec200208..5fc175703a0 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -176,9 +176,12 @@  struct language_defn
        la_parser, perform any remaining processing necessary to complete
        its translation.  *EXPP may change; la_post_parser is responsible 
        for releasing its previous contents, if necessary.  If 
-       VOID_CONTEXT_P, then no value is expected from the expression.  */
+       VOID_CONTEXT_P, then no value is expected from the expression.
+       If COMPLETING is non-zero, then the expression has been parsed
+       for completion, not evaluation.  */
 
-    void (*la_post_parser) (expression_up *expp, int void_context_p);
+    void (*la_post_parser) (expression_up *expp, int void_context_p,
+			    int completing);
 
     void (*la_printchar) (int ch, struct type *chtype,
 			  struct ui_file * stream);
diff --git a/gdb/p-exp.y b/gdb/p-exp.y
index 0f78126222c..493876815d9 100644
--- a/gdb/p-exp.y
+++ b/gdb/p-exp.y
@@ -285,14 +285,14 @@  exp	:	field_exp name
 			}
 	;
 exp	:	field_exp  name COMPLETE
-			{ mark_struct_expression (pstate);
+			{ pstate->mark_struct_expression ();
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
 			  write_exp_string (pstate, $2);
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT); }
 	;
 exp	:	field_exp COMPLETE
 			{ struct stoken s;
-			  mark_struct_expression (pstate);
+			  pstate->mark_struct_expression ();
 			  write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
 			  s.ptr = "";
 			  s.length = 0;
@@ -1162,7 +1162,7 @@  yylex (void)
   switch (c = *tokstart)
     {
     case 0:
-      if (search_field && parse_completion)
+      if (search_field && pstate->parse_completion)
 	return COMPLETE;
       else
        return 0;
diff --git a/gdb/parse.c b/gdb/parse.c
index 6ee61577068..7984a324fe0 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -69,20 +69,6 @@  const struct exp_descriptor exp_descriptor_standard =
 innermost_block_tracker innermost_block;
 static struct type_stack type_stack;
 
-/* True if parsing an expression to attempt completion.  */
-int parse_completion;
-
-/* The index of the last struct expression directly before a '.' or
-   '->'.  This is set when parsing and is only used when completing a
-   field name.  It is -1 if no dereference operation was found.  */
-static int expout_last_struct = -1;
-
-/* If we are completing a tagged type name, this will be nonzero.  */
-static enum type_code expout_tag_completion_type = TYPE_CODE_UNDEF;
-
-/* The token for tagged type name completion.  */
-static gdb::unique_xmalloc_ptr<char> expout_completion_name;
-
 
 static unsigned int expressiondebug = 0;
 static void
@@ -105,12 +91,13 @@  show_parserdebug (struct ui_file *file, int from_tty,
 
 
 static int prefixify_subexp (struct expression *, struct expression *, int,
-			     int);
+			     int, int);
 
 static expression_up parse_exp_in_context (const char **, CORE_ADDR,
 					   const struct block *, int,
 					   int, int *,
-					   innermost_block_tracker_types);
+					   innermost_block_tracker_types,
+					   expr_completion_state *);
 
 static void increase_expout_size (struct expr_builder *ps, size_t lenelt);
 
@@ -507,15 +494,15 @@  write_exp_msymbol (struct expr_builder *ps,
   write_exp_elt_opcode (ps, OP_VAR_MSYM_VALUE);
 }
 
-/* Mark the current index as the starting location of a structure
-   expression.  This is used when completing on field names.  */
+/* See parser-defs.h.  */
 
 void
-mark_struct_expression (struct expr_builder *ps)
+parser_state::mark_struct_expression ()
 {
   gdb_assert (parse_completion
-	      && expout_tag_completion_type == TYPE_CODE_UNDEF);
-  expout_last_struct = ps->expout_ptr;
+	      && (m_completion_state.expout_tag_completion_type
+		  == TYPE_CODE_UNDEF));
+  m_completion_state.expout_last_struct = expout_ptr;
 }
 
 /* Indicate that the current parser invocation is completing a tag.
@@ -523,17 +510,19 @@  mark_struct_expression (struct expr_builder *ps)
    start of the tag name.  */
 
 void
-mark_completion_tag (enum type_code tag, const char *ptr, int length)
+parser_state::mark_completion_tag (enum type_code tag, const char *ptr,
+				   int length)
 {
   gdb_assert (parse_completion
-	      && expout_tag_completion_type == TYPE_CODE_UNDEF
-	      && expout_completion_name == NULL
-	      && expout_last_struct == -1);
+	      && (m_completion_state.expout_tag_completion_type
+		  == TYPE_CODE_UNDEF)
+	      && m_completion_state.expout_completion_name == NULL
+	      && m_completion_state.expout_last_struct == -1);
   gdb_assert (tag == TYPE_CODE_UNION
 	      || tag == TYPE_CODE_STRUCT
 	      || tag == TYPE_CODE_ENUM);
-  expout_tag_completion_type = tag;
-  expout_completion_name.reset (xstrndup (ptr, length));
+  m_completion_state.expout_tag_completion_type = tag;
+  m_completion_state.expout_completion_name.reset (xstrndup (ptr, length));
 }
 
 
@@ -755,7 +744,7 @@  copy_name (struct stoken token)
 /* See comments on parser-defs.h.  */
 
 int
-prefixify_expression (struct expression *expr)
+prefixify_expression (struct expression *expr, int last_struct)
 {
   gdb_assert (expr->nelts > 0);
   int len = sizeof (struct expression) + EXP_ELEM_TO_BYTES (expr->nelts);
@@ -767,7 +756,7 @@  prefixify_expression (struct expression *expr)
   /* Copy the original expression into temp.  */
   memcpy (temp, expr, len);
 
-  return prefixify_subexp (temp, expr, inpos, outpos);
+  return prefixify_subexp (temp, expr, inpos, outpos, last_struct);
 }
 
 /* Return the number of exp_elements in the postfix subexpression 
@@ -987,13 +976,14 @@  operator_length_standard (const struct expression *expr, int endpos,
 /* Copy the subexpression ending just before index INEND in INEXPR
    into OUTEXPR, starting at index OUTBEG.
    In the process, convert it from suffix to prefix form.
-   If EXPOUT_LAST_STRUCT is -1, then this function always returns -1.
+   If LAST_STRUCT is -1, then this function always returns -1.
    Otherwise, it returns the index of the subexpression which is the
-   left-hand-side of the expression at EXPOUT_LAST_STRUCT.  */
+   left-hand-side of the expression at LAST_STRUCT.  */
 
 static int
 prefixify_subexp (struct expression *inexpr,
-		  struct expression *outexpr, int inend, int outbeg)
+		  struct expression *outexpr, int inend, int outbeg,
+		  int last_struct)
 {
   int oplen;
   int args;
@@ -1010,7 +1000,7 @@  prefixify_subexp (struct expression *inexpr,
 	  EXP_ELEM_TO_BYTES (oplen));
   outbeg += oplen;
 
-  if (expout_last_struct == inend)
+  if (last_struct == inend)
     result = outbeg - oplen;
 
   /* Find the lengths of the arg subexpressions.  */
@@ -1034,7 +1024,7 @@  prefixify_subexp (struct expression *inexpr,
 
       oplen = arglens[i];
       inend += oplen;
-      r = prefixify_subexp (inexpr, outexpr, inend, outbeg);
+      r = prefixify_subexp (inexpr, outexpr, inend, outbeg, last_struct);
       if (r != -1)
 	{
 	  /* Return immediately.  We probably have only parsed a
@@ -1063,7 +1053,7 @@  parse_exp_1 (const char **stringptr, CORE_ADDR pc, const struct block *block,
 	     int comma, innermost_block_tracker_types tracker_types)
 {
   return parse_exp_in_context (stringptr, pc, block, comma, 0, NULL,
-			       tracker_types);
+			       tracker_types, nullptr);
 }
 
 /* As for parse_exp_1, except that if VOID_CONTEXT_P, then
@@ -1077,15 +1067,13 @@  static expression_up
 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_types tracker_types,
+		      expr_completion_state *cstate)
 {
   const struct language_defn *lang = NULL;
   int subexp;
 
   type_stack.elements.clear ();
-  expout_last_struct = -1;
-  expout_tag_completion_type = TYPE_CODE_UNDEF;
-  expout_completion_name.reset ();
   innermost_block.reset (tracker_types);
 
   if (*stringptr == 0 || **stringptr == 0)
@@ -1147,7 +1135,8 @@  parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
      to the value matching SELECTED_FRAME as set by get_current_arch.  */
 
   parser_state ps (lang, get_current_arch (), expression_context_block,
-		   expression_context_pc, comma, *stringptr);
+		   expression_context_pc, comma, *stringptr,
+		   cstate != nullptr);
 
   scoped_restore_current_language lang_saver;
   set_language (lang->la_language);
@@ -1161,7 +1150,7 @@  parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
       /* If parsing for completion, allow this to succeed; but if no
 	 expression elements have been written, then there's nothing
 	 to do, so fail.  */
-      if (! parse_completion || ps.expout_ptr == 0)
+      if (! ps.parse_completion || ps.expout_ptr == 0)
 	throw_exception (except);
     }
   END_CATCH
@@ -1177,15 +1166,18 @@  parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
     dump_raw_expression (result.get (), gdb_stdlog,
 			 "before conversion to prefix form");
 
-  subexp = prefixify_expression (result.get ());
+  subexp = prefixify_expression (result.get (),
+				 ps.m_completion_state.expout_last_struct);
   if (out_subexp)
     *out_subexp = subexp;
 
-  lang->la_post_parser (&result, void_context_p);
+  lang->la_post_parser (&result, void_context_p, ps.parse_completion);
 
   if (expressiondebug)
     dump_prefix_expression (result.get (), gdb_stdlog);
 
+  if (cstate != nullptr)
+    *cstate = std::move (ps.m_completion_state);
   *stringptr = ps.lexptr;
   return result;
 }
@@ -1233,12 +1225,12 @@  parse_expression_for_completion (const char *string,
   expression_up exp;
   struct value *val;
   int subexp;
+  expr_completion_state cstate;
 
   TRY
     {
-      parse_completion = 1;
       exp = parse_exp_in_context (&string, 0, 0, 0, 0, &subexp,
-				  INNERMOST_BLOCK_FOR_SYMBOLS);
+				  INNERMOST_BLOCK_FOR_SYMBOLS, &cstate);
     }
   CATCH (except, RETURN_MASK_ERROR)
     {
@@ -1246,18 +1238,17 @@  parse_expression_for_completion (const char *string,
     }
   END_CATCH
 
-  parse_completion = 0;
   if (exp == NULL)
     return NULL;
 
-  if (expout_tag_completion_type != TYPE_CODE_UNDEF)
+  if (cstate.expout_tag_completion_type != TYPE_CODE_UNDEF)
     {
-      *code = expout_tag_completion_type;
-      *name = std::move (expout_completion_name);
+      *code = cstate.expout_tag_completion_type;
+      *name = std::move (cstate.expout_completion_name);
       return NULL;
     }
 
-  if (expout_last_struct == -1)
+  if (cstate.expout_last_struct == -1)
     return NULL;
 
   const char *fieldname = extract_field_op (exp.get (), &subexp);
@@ -1278,7 +1269,7 @@  parse_expression_for_completion (const char *string,
 /* A post-parser that does nothing.  */
 
 void
-null_post_parser (expression_up *exp, int void_context_p)
+null_post_parser (expression_up *exp, int void_context_p, int completin)
 {
 }
 
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index a01511584d7..2c1ea15d05e 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -76,6 +76,22 @@  struct expr_builder
   size_t expout_ptr;
 };
 
+/* This is used for expression completion.  */
+
+struct expr_completion_state
+{
+  /* The index of the last struct expression directly before a '.' or
+     '->'.  This is set when parsing and is only used when completing a
+     field name.  It is -1 if no dereference operation was found.  */
+  int expout_last_struct = -1;
+
+  /* If we are completing a tagged type name, this will be nonzero.  */
+  enum type_code expout_tag_completion_type = TYPE_CODE_UNDEF;
+
+  /* The token for tagged type name completion.  */
+  gdb::unique_xmalloc_ptr<char> expout_completion_name;
+};
+
 /* An instance of this type is instantiated during expression parsing,
    and passed to the appropriate parser.  It holds both inputs to the
    parser, and result.  */
@@ -90,12 +106,14 @@  struct parser_state : public expr_builder
 		const struct block *context_block,
 		CORE_ADDR context_pc,
 		int comma,
-		const char *input)
+		const char *input,
+		int completion)
     : expr_builder (lang, gdbarch),
       expression_context_block (context_block),
       expression_context_pc (context_pc),
       comma_terminates (comma),
-      lexptr (input)
+      lexptr (input),
+      parse_completion (completion)
   {
   }
 
@@ -121,6 +139,17 @@  struct parser_state : public expr_builder
     return val;
   }
 
+  /* Mark the current index as the starting location of a structure
+     expression.  This is used when completing on field names.  */
+
+  void mark_struct_expression ();
+
+  /* Indicate that the current parser invocation is completing a tag.
+     TAG is the type code of the tag, and PTR and LENGTH represent the
+     start of the tag name.  */
+
+  void mark_completion_tag (enum type_code tag, const char *ptr, int length);
+
 
   /* If this is nonzero, this block is used as the lexical context for
      symbol names.  */
@@ -151,6 +180,12 @@  struct parser_state : public expr_builder
 
   int arglist_len = 0;
 
+  /* True if parsing an expression to attempt completion.  */
+  int parse_completion;
+
+  /* Completion state is updated here.  */
+  expr_completion_state m_completion_state;
+
 private:
 
   /* Data structure for saving values of arglist_len for function calls whose
@@ -300,12 +335,13 @@  struct type_stack
 
 /* Reverse an expression from suffix form (in which it is constructed)
    to prefix form (in which we can conveniently print or execute it).
-   Ordinarily this always returns -1.  However, if EXPOUT_LAST_STRUCT
+   Ordinarily this always returns -1.  However, if LAST_STRUCT
    is not -1 (i.e., we are trying to complete a field name), it will
    return the index of the subexpression which is the left-hand-side
-   of the struct operation at EXPOUT_LAST_STRUCT.  */
+   of the struct operation at LAST_STRUCT.  */
 
-extern int prefixify_expression (struct expression *expr);
+extern int prefixify_expression (struct expression *expr,
+				 int last_struct = -1);
 
 extern void write_exp_elt_opcode (struct expr_builder *, enum exp_opcode);
 
@@ -336,8 +372,6 @@  extern void write_exp_msymbol (struct expr_builder *,
 
 extern void write_dollar_variable (struct parser_state *, struct stoken str);
 
-extern void mark_struct_expression (struct expr_builder *);
-
 extern const char *find_template_name_end (const char *);
 
 extern char *copy_name (struct stoken);
@@ -384,7 +418,7 @@  extern struct type *follow_types (struct type *);
 
 extern type_instance_flags follow_type_instance_flags ();
 
-extern void null_post_parser (expression_up *, int);
+extern void null_post_parser (expression_up *, int, int);
 
 extern bool parse_float (const char *p, int len,
 			 const struct type *type, gdb_byte *data);
@@ -483,8 +517,5 @@  extern void parser_fprintf (FILE *, const char *, ...) ATTRIBUTE_PRINTF (2, 3);
 
 extern int exp_uses_objfile (struct expression *exp, struct objfile *objfile);
 
-extern void mark_completion_tag (enum type_code, const char *ptr,
-				 int length);
-
 #endif /* PARSER_DEFS_H */
 
diff --git a/gdb/rust-exp.y b/gdb/rust-exp.y
index 782117e93e2..999ab25f070 100644
--- a/gdb/rust-exp.y
+++ b/gdb/rust-exp.y
@@ -1438,10 +1438,10 @@  rust_parser::lex_identifier (YYSTYPE *lvalp)
       return 0;
     }
 
-  if (token == NULL || (parse_completion && pstate->lexptr[0] == '\0'))
+  if (token == NULL || (pstate->parse_completion && pstate->lexptr[0] == '\0'))
     lvalp->sval = make_stoken (copy_name (start, length));
 
-  if (parse_completion && pstate->lexptr[0] == '\0')
+  if (pstate->parse_completion && pstate->lexptr[0] == '\0')
     {
       /* Prevent rustyylex from returning two COMPLETE tokens.  */
       pstate->prev_lexptr = pstate->lexptr;
@@ -1650,7 +1650,7 @@  rustyylex (YYSTYPE *lvalp, rust_parser *parser)
   pstate->prev_lexptr = pstate->lexptr;
   if (pstate->lexptr[0] == '\0')
     {
-      if (parse_completion)
+      if (pstate->parse_completion)
 	{
 	  lvalp->sval = make_stoken ("");
 	  return COMPLETE;
@@ -2225,7 +2225,7 @@  rust_parser::convert_ast_to_expression (const struct rust_op *operation,
 	convert_ast_to_expression (operation->left.op, top);
 
 	if (operation->completing)
-	  mark_struct_expression (pstate);
+	  pstate->mark_struct_expression ();
 	write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
 	write_exp_string (pstate, operation->right.sval);
 	write_exp_elt_opcode (pstate, STRUCTOP_STRUCT);
@@ -2544,7 +2544,7 @@  rust_parse (struct parser_state *state)
 
   result = rustyyparse (&parser);
 
-  if (!result || (parse_completion && parser.rust_ast != NULL))
+  if (!result || (state->parse_completion && parser.rust_ast != NULL))
     parser.convert_ast_to_expression (parser.rust_ast, parser.rust_ast);
 
   return result;
@@ -2684,14 +2684,14 @@  rust_lex_test_completion (rust_parser *parser)
 {
   const int expected[] = { IDENT, '.', COMPLETE, 0 };
 
-  parse_completion = 1;
+  parser->pstate->parse_completion = 1;
 
   rust_lex_test_sequence (parser, "something.wha", ARRAY_SIZE (expected),
 			  expected);
   rust_lex_test_sequence (parser, "something.", ARRAY_SIZE (expected),
 			  expected);
 
-  parse_completion = 0;
+  parser->pstate->parse_completion = 0;
 }
 
 /* Test pushback.  */
@@ -2726,7 +2726,7 @@  rust_lex_tests (void)
 
   // Set up dummy "parser", so that rust_type works.
   struct parser_state ps (&rust_language_defn, target_gdbarch (),
-			  nullptr, 0, 0, nullptr);
+			  nullptr, 0, 0, nullptr, 0);
   rust_parser parser (&ps);
 
   rust_lex_test_one (&parser, "", 0);