aboutsummaryrefslogtreecommitdiff
path: root/gdb/parse.c
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2022-02-22 09:48:25 -0700
committerTom Tromey <tromey@adacore.com>2022-04-04 12:46:09 -0600
commit1e237aba2216f89b9a4b3235ad8d09d1b1b8f039 (patch)
tree088adb7b45abf2f494d139e2a4865355d8cef3bf /gdb/parse.c
parent28c4b1ffaa41b17af11984c0383a8a37ea00eef4 (diff)
downloadgdb-1e237aba2216f89b9a4b3235ad8d09d1b1b8f039.zip
gdb-1e237aba2216f89b9a4b3235ad8d09d1b1b8f039.tar.gz
gdb-1e237aba2216f89b9a4b3235ad8d09d1b1b8f039.tar.bz2
Refactor expression completion
This refactors the gdb expression completion code to make it easier to add more types of completers. In the old approach, just two kinds of completers were supported: field names for some sub-expression, or tag names (like "enum something"). The data for each kind was combined in single structure, "expr_completion_state", and handled explicitly by complete_expression. In the new approach, the parser state just holds an object that is responsible for implementing completion. This way, new completion types can be added by subclassing this base object. The structop completer is moved into structop_base_operation, and new objects are defined for use by the completion code. This moves much of the logic of expression completion out of completer.c as well.
Diffstat (limited to 'gdb/parse.c')
-rw-r--r--gdb/parse.c84
1 files changed, 36 insertions, 48 deletions
diff --git a/gdb/parse.c b/gdb/parse.c
index 8886ab0..7637e57 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -72,10 +72,11 @@ show_parserdebug (struct ui_file *file, int from_tty,
}
-static expression_up parse_exp_in_context (const char **, CORE_ADDR,
- const struct block *, int,
- bool, innermost_block_tracker *,
- expr_completion_state *);
+static expression_up parse_exp_in_context
+ (const char **, CORE_ADDR,
+ const struct block *, int,
+ bool, innermost_block_tracker *,
+ std::unique_ptr<expr_completion_base> *);
/* Documented at it's declaration. */
@@ -171,15 +172,22 @@ find_minsym_type_and_address (minimal_symbol *msymbol,
}
}
+bool
+expr_complete_tag::complete (struct expression *exp,
+ completion_tracker &tracker)
+{
+ collect_symbol_completion_matches_type (tracker, m_name.get (),
+ m_name.get (), m_code);
+ return true;
+}
+
/* See parser-defs.h. */
void
parser_state::mark_struct_expression (expr::structop_base_operation *op)
{
- gdb_assert (parse_completion
- && (m_completion_state.expout_tag_completion_type
- == TYPE_CODE_UNDEF));
- m_completion_state.expout_last_op = op;
+ gdb_assert (parse_completion && m_completion_state == nullptr);
+ m_completion_state.reset (new expr_complete_structop (op));
}
/* Indicate that the current parser invocation is completing a tag.
@@ -190,17 +198,12 @@ void
parser_state::mark_completion_tag (enum type_code tag, const char *ptr,
int length)
{
- gdb_assert (parse_completion
- && (m_completion_state.expout_tag_completion_type
- == TYPE_CODE_UNDEF)
- && m_completion_state.expout_completion_name == NULL
- && m_completion_state.expout_last_op == nullptr);
+ gdb_assert (parse_completion && m_completion_state == nullptr);
gdb_assert (tag == TYPE_CODE_UNION
|| tag == TYPE_CODE_STRUCT
|| tag == TYPE_CODE_ENUM);
- m_completion_state.expout_tag_completion_type = tag;
- m_completion_state.expout_completion_name
- = make_unique_xstrndup (ptr, length);
+ m_completion_state.reset
+ (new expr_complete_tag (tag, make_unique_xstrndup (ptr, length)));
}
/* See parser-defs.h. */
@@ -433,7 +436,7 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
const struct block *block,
int comma, bool void_context_p,
innermost_block_tracker *tracker,
- expr_completion_state *cstate)
+ std::unique_ptr<expr_completion_base> *completer)
{
const struct language_defn *lang = NULL;
@@ -501,7 +504,7 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
parser_state ps (lang, get_current_arch (), expression_context_block,
expression_context_pc, comma, *stringptr,
- cstate != nullptr, tracker, void_context_p);
+ completer != nullptr, tracker, void_context_p);
scoped_restore_current_language lang_saver;
set_language (lang->la_language);
@@ -525,8 +528,8 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
if (expressiondebug)
dump_prefix_expression (result.get (), gdb_stdlog);
- if (cstate != nullptr)
- *cstate = std::move (ps.m_completion_state);
+ if (completer != nullptr)
+ *completer = std::move (ps.m_completion_state);
*stringptr = ps.lexptr;
return result;
}
@@ -566,47 +569,32 @@ parse_expression_with_language (const char *string, enum language lang)
return parse_expression (string);
}
-/* Parse STRING as an expression. If parsing ends in the middle of a
- field reference, return the type of the left-hand-side of the
- reference; furthermore, if the parsing ends in the field name,
- return the field name in *NAME. If the parsing ends in the middle
- of a field reference, but the reference is somehow invalid, throw
- an exception. In all other cases, return NULL. */
-
-struct type *
-parse_expression_for_completion (const char *string,
- gdb::unique_xmalloc_ptr<char> *name,
- enum type_code *code)
+/* Parse STRING as an expression. If the parse is marked for
+ completion, set COMPLETER and return the expression. In all other
+ cases, return NULL. */
+
+expression_up
+parse_expression_for_completion
+ (const char *string,
+ std::unique_ptr<expr_completion_base> *completer)
{
expression_up exp;
- expr_completion_state cstate;
try
{
- exp = parse_exp_in_context (&string, 0, 0, 0, false, nullptr, &cstate);
+ exp = parse_exp_in_context (&string, 0, 0, 0, false, nullptr, completer);
}
catch (const gdb_exception_error &except)
{
/* Nothing, EXP remains NULL. */
}
- if (exp == NULL)
- return NULL;
-
- if (cstate.expout_tag_completion_type != TYPE_CODE_UNDEF)
- {
- *code = cstate.expout_tag_completion_type;
- *name = std::move (cstate.expout_completion_name);
- return NULL;
- }
-
- if (cstate.expout_last_op == nullptr)
+ /* If we didn't get a completion result, be sure to also not return
+ an expression to our caller. */
+ if (*completer == nullptr)
return nullptr;
- expr::structop_base_operation *op = cstate.expout_last_op;
- const std::string &fld = op->get_string ();
- *name = make_unique_xstrdup (fld.c_str ());
- return value_type (op->evaluate_lhs (exp.get ()));
+ return exp;
}
/* Parse floating point value P of length LEN.