From patchwork Wed Apr 3 01:38:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 32144 Received: (qmail 28365 invoked by alias); 3 Apr 2019 01:38:23 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 28276 invoked by uid 89); 3 Apr 2019 01:38:22 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-16.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy= X-HELO: gateway34.websitewelcome.com Received: from gateway34.websitewelcome.com (HELO gateway34.websitewelcome.com) (192.185.148.204) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 03 Apr 2019 01:38:11 +0000 Received: from cm14.websitewelcome.com (cm14.websitewelcome.com [100.42.49.7]) by gateway34.websitewelcome.com (Postfix) with ESMTP id 9E32227A00B for ; Tue, 2 Apr 2019 20:38:10 -0500 (CDT) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id BUqwhr2Nf2qH7BUqwhFYew; Tue, 02 Apr 2019 20:38:10 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=e8gMvOFUHjlqD2+Ak5gHnoP/shbdOUGJTNaNGaLH7d4=; b=eoVXYmvXTs46477xydA19m4WnJ NW1E7lyz6QWKggPTw9aADt0V8Hmx7JLYCJ41FMmMnI/SZzCbr9okzZWqRC7h91abW77Dlbm55FH36 Oid7WjFIGqbEwmOIxIfUPMhGe; Received: from 174-29-37-56.hlrn.qwest.net ([174.29.37.56]:34720 helo=bapiya.Home) by box5379.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.91) (envelope-from ) id 1hBUqw-002Gj6-BY; Tue, 02 Apr 2019 20:38:10 -0500 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 11/13] Move completion parsing to parser_state Date: Tue, 2 Apr 2019 19:38:03 -0600 Message-Id: <20190403013805.11978-12-tom@tromey.com> In-Reply-To: <20190403013805.11978-1-tom@tromey.com> References: <20190403013805.11978-1-tom@tromey.com> 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 * 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) : Add completion parameter. : New methods. : 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) : 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(-) 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 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 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);