* [PATCH 01/11] Avoid forward declaration in parse.c
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-04 14:21 ` [PATCH 02/11] Move innermost_block_tracker to expression.h Tom Tromey
` (10 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
This minorly rearranges parse.c to avoid the need for a forward
declaration.
---
gdb/parse.c | 42 ++++++++++++++++++------------------------
1 file changed, 18 insertions(+), 24 deletions(-)
diff --git a/gdb/parse.c b/gdb/parse.c
index a84b4b64fdb..e4678e9c6e8 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -72,12 +72,6 @@ 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 *,
- std::unique_ptr<expr_completion_base> *);
-
/* Documented at it's declaration. */
void
@@ -328,24 +322,6 @@ copy_name (struct stoken token)
}
\f
-/* Read an expression from the string *STRINGPTR points to,
- parse it, and return a pointer to a struct expression that we malloc.
- Use block BLOCK as the lexical context for variable names;
- if BLOCK is zero, use the block of the selected stack frame.
- Meanwhile, advance *STRINGPTR to point after the expression,
- at the first nonwhite character that is not part of the expression
- (possibly a null character).
-
- If COMMA is nonzero, stop if a comma is reached. */
-
-expression_up
-parse_exp_1 (const char **stringptr, CORE_ADDR pc, const struct block *block,
- int comma, innermost_block_tracker *tracker)
-{
- return parse_exp_in_context (stringptr, pc, block, comma, false,
- tracker, nullptr);
-}
-
/* As for parse_exp_1, except that if VOID_CONTEXT_P, then
no value is expected from the expression. */
@@ -453,6 +429,24 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
return result;
}
+/* Read an expression from the string *STRINGPTR points to,
+ parse it, and return a pointer to a struct expression that we malloc.
+ Use block BLOCK as the lexical context for variable names;
+ if BLOCK is zero, use the block of the selected stack frame.
+ Meanwhile, advance *STRINGPTR to point after the expression,
+ at the first nonwhite character that is not part of the expression
+ (possibly a null character).
+
+ If COMMA is nonzero, stop if a comma is reached. */
+
+expression_up
+parse_exp_1 (const char **stringptr, CORE_ADDR pc, const struct block *block,
+ int comma, innermost_block_tracker *tracker)
+{
+ return parse_exp_in_context (stringptr, pc, block, comma, false,
+ tracker, nullptr);
+}
+
/* Parse STRING as an expression, and complain if this fails to use up
all of the contents of STRING. TRACKER, if non-null, will be
updated by the parser. VOID_CONTEXT_P should be true to indicate
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 02/11] Move innermost_block_tracker to expression.h
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
2023-05-04 14:21 ` [PATCH 01/11] Avoid forward declaration in parse.c Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-04 14:21 ` [PATCH 03/11] Introduce and use parser flags Tom Tromey
` (9 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
I think parser-defs.h should hold declarations that can be used by
parser implementations, whereas expression.h should hold declarations
that are used by code that wants to call a parser. Following this
logic, this patch moves innermost_block_tracker to expression.h.
---
gdb/expression.h | 46 ++++++++++++++++++++++++++++++++++++++++++++--
gdb/parser-defs.h | 43 -------------------------------------------
2 files changed, 44 insertions(+), 45 deletions(-)
diff --git a/gdb/expression.h b/gdb/expression.h
index e6e4bec2e80..8d351b30a3a 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -21,6 +21,7 @@
#define EXPRESSION_H 1
#include "gdbtypes.h"
+#include "symtab.h"
/* While parsing expressions we need to track the innermost lexical block
that we encounter. In some situations we need to track the innermost
@@ -239,9 +240,51 @@ struct expression
typedef std::unique_ptr<expression> expression_up;
+/* When parsing expressions we track the innermost block that was
+ referenced. */
+
+class innermost_block_tracker
+{
+public:
+ innermost_block_tracker (innermost_block_tracker_types types
+ = INNERMOST_BLOCK_FOR_SYMBOLS)
+ : m_types (types),
+ m_innermost_block (NULL)
+ { /* Nothing. */ }
+
+ /* 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
+ register. The stored innermost block is only updated if the type T is
+ a type we are interested in, the types we are interested in are held
+ in M_TYPES and set during RESET. */
+ void update (const struct block *b, innermost_block_tracker_types t);
+
+ /* Overload of main UPDATE method which extracts the block from BS. */
+ void update (const struct block_symbol &bs)
+ {
+ update (bs.block, INNERMOST_BLOCK_FOR_SYMBOLS);
+ }
+
+ /* Return the stored innermost block. Can be nullptr if no symbols or
+ registers were found during an expression parse, and so no innermost
+ block was defined. */
+ const struct block *block () const
+ {
+ return m_innermost_block;
+ }
+
+private:
+ /* The type of innermost block being looked for. */
+ innermost_block_tracker_types m_types;
+
+ /* The currently stored innermost block found while parsing an
+ expression. */
+ const struct block *m_innermost_block;
+};
+
/* From parse.c */
-class innermost_block_tracker;
extern expression_up parse_expression (const char *,
innermost_block_tracker * = nullptr,
bool void_context_p = false);
@@ -270,7 +313,6 @@ struct expr_completion_base
extern expression_up parse_expression_for_completion
(const char *, std::unique_ptr<expr_completion_base> *completer);
-class innermost_block_tracker;
extern expression_up parse_exp_1 (const char **, CORE_ADDR pc,
const struct block *, int,
innermost_block_tracker * = nullptr);
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index 62829a86f9a..5c6bc222b6b 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -316,49 +316,6 @@ struct parser_state : public expr_builder
std::vector<expr::operation_up> m_operations;
};
-/* When parsing expressions we track the innermost block that was
- referenced. */
-
-class innermost_block_tracker
-{
-public:
- innermost_block_tracker (innermost_block_tracker_types types
- = INNERMOST_BLOCK_FOR_SYMBOLS)
- : m_types (types),
- m_innermost_block (NULL)
- { /* Nothing. */ }
-
- /* 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
- register. The stored innermost block is only updated if the type T is
- a type we are interested in, the types we are interested in are held
- in M_TYPES and set during RESET. */
- void update (const struct block *b, innermost_block_tracker_types t);
-
- /* Overload of main UPDATE method which extracts the block from BS. */
- void update (const struct block_symbol &bs)
- {
- update (bs.block, INNERMOST_BLOCK_FOR_SYMBOLS);
- }
-
- /* Return the stored innermost block. Can be nullptr if no symbols or
- registers were found during an expression parse, and so no innermost
- block was defined. */
- const struct block *block () const
- {
- return m_innermost_block;
- }
-
-private:
- /* The type of innermost block being looked for. */
- innermost_block_tracker_types m_types;
-
- /* The currently stored innermost block found while parsing an
- expression. */
- const struct block *m_innermost_block;
-};
-
/* A string token, either a char-string or bit-string. Char-strings are
used, for example, for the names of symbols. */
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 03/11] Introduce and use parser flags
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
2023-05-04 14:21 ` [PATCH 01/11] Avoid forward declaration in parse.c Tom Tromey
2023-05-04 14:21 ` [PATCH 02/11] Move innermost_block_tracker to expression.h Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-04 14:21 ` [PATCH 04/11] Simplify parser_state constructor Tom Tromey
` (8 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
This patch adds a new parser_flags type and changes the parser APIs to
use it rather than a collection of 'int' and 'bool'. More flags will
be added in subsquent patches.
---
gdb/ax-gdb.c | 3 ++-
gdb/breakpoint.c | 3 ++-
gdb/eval.c | 3 ++-
gdb/expression.h | 21 +++++++++++++++++++--
gdb/parse.c | 29 +++++++++++++----------------
gdb/printcmd.c | 5 ++++-
gdb/tracepoint.c | 10 ++++++----
7 files changed, 48 insertions(+), 26 deletions(-)
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 528f45e19eb..927dfc6337e 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -2615,7 +2615,8 @@ maint_agent_printf_command (const char *cmdrest, int from_tty)
const char *cmd1;
cmd1 = cmdrest;
- expression_up expr = parse_exp_1 (&cmd1, 0, (struct block *) 0, 1);
+ expression_up expr = parse_exp_1 (&cmd1, 0, (struct block *) 0,
+ PARSER_COMMA_TERMINATES);
argvec.push_back (expr.release ());
cmdrest = cmd1;
if (*cmdrest == ',')
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 30d438d06df..de3a7e9ef9c 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -2526,7 +2526,8 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
const char *cmd1;
cmd1 = cmdrest;
- expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1);
+ expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope),
+ PARSER_COMMA_TERMINATES);
argvec.push_back (expr.release ());
cmdrest = cmd1;
if (*cmdrest == ',')
diff --git a/gdb/eval.c b/gdb/eval.c
index 9d5ca0b47de..d8d53c28686 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -81,7 +81,8 @@ parse_and_eval (const char *exp)
struct value *
parse_to_comma_and_eval (const char **expp)
{
- expression_up expr = parse_exp_1 (expp, 0, nullptr, 1);
+ expression_up expr = parse_exp_1 (expp, 0, nullptr,
+ PARSER_COMMA_TERMINATES);
return expr->evaluate ();
}
diff --git a/gdb/expression.h b/gdb/expression.h
index 8d351b30a3a..2e2d2a090f9 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -283,11 +283,27 @@ class innermost_block_tracker
const struct block *m_innermost_block;
};
+/* Flags that can affect the parsers. */
+
+enum parser_flag
+{
+ /* This flag is set if the expression is being evaluated in a
+ context where a 'void' result type is expected. Parsers are free
+ to ignore this, or to use it to help with overload resolution
+ decisions. */
+ PARSER_VOID_CONTEXT = (1 << 0),
+
+ /* This flag is set if a top-level comma terminates the
+ expression. */
+ PARSER_COMMA_TERMINATES = (1 << 1),
+};
+DEF_ENUM_FLAGS_TYPE (enum parser_flag, parser_flags);
+
/* From parse.c */
extern expression_up parse_expression (const char *,
innermost_block_tracker * = nullptr,
- bool void_context_p = false);
+ parser_flags flags = 0);
extern expression_up parse_expression_with_language (const char *string,
enum language lang);
@@ -314,7 +330,8 @@ extern expression_up parse_expression_for_completion
(const char *, std::unique_ptr<expr_completion_base> *completer);
extern expression_up parse_exp_1 (const char **, CORE_ADDR pc,
- const struct block *, int,
+ const struct block *,
+ parser_flags flags,
innermost_block_tracker * = nullptr);
/* From eval.c */
diff --git a/gdb/parse.c b/gdb/parse.c
index e4678e9c6e8..ed0d0b8a880 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -328,7 +328,7 @@ copy_name (struct stoken token)
static expression_up
parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
const struct block *block,
- int comma, bool void_context_p,
+ parser_flags flags,
innermost_block_tracker *tracker,
std::unique_ptr<expr_completion_base> *completer)
{
@@ -398,8 +398,11 @@ 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,
- completer != nullptr, tracker, void_context_p);
+ expression_context_pc,
+ (flags & PARSER_COMMA_TERMINATES) != 0,
+ *stringptr,
+ completer != nullptr, tracker,
+ (flags & PARSER_VOID_CONTEXT) != 0);
scoped_restore_current_language lang_saver;
set_language (lang->la_language);
@@ -435,31 +438,25 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
if BLOCK is zero, use the block of the selected stack frame.
Meanwhile, advance *STRINGPTR to point after the expression,
at the first nonwhite character that is not part of the expression
- (possibly a null character).
-
- If COMMA is nonzero, stop if a comma is reached. */
+ (possibly a null character). FLAGS are passed to the parser. */
expression_up
parse_exp_1 (const char **stringptr, CORE_ADDR pc, const struct block *block,
- int comma, innermost_block_tracker *tracker)
+ parser_flags flags, innermost_block_tracker *tracker)
{
- return parse_exp_in_context (stringptr, pc, block, comma, false,
+ return parse_exp_in_context (stringptr, pc, block, flags,
tracker, nullptr);
}
/* Parse STRING as an expression, and complain if this fails to use up
all of the contents of STRING. TRACKER, if non-null, will be
- updated by the parser. VOID_CONTEXT_P should be true to indicate
- that the expression may be expected to return a value with void
- type. Parsers are free to ignore this, or to use it to help with
- overload resolution decisions. */
+ updated by the parser. FLAGS are passed to the parser. */
expression_up
parse_expression (const char *string, innermost_block_tracker *tracker,
- bool void_context_p)
+ parser_flags flags)
{
- expression_up exp = parse_exp_in_context (&string, 0, nullptr, 0,
- void_context_p,
+ expression_up exp = parse_exp_in_context (&string, 0, nullptr, flags,
tracker, nullptr);
if (*string)
error (_("Junk after end of expression."));
@@ -495,7 +492,7 @@ parse_expression_for_completion
try
{
- exp = parse_exp_in_context (&string, 0, 0, 0, false, nullptr, completer);
+ exp = parse_exp_in_context (&string, 0, 0, 0, nullptr, completer);
}
catch (const gdb_exception_error &except)
{
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index e903bf48fa5..e04a9c28739 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1315,7 +1315,10 @@ process_print_command_args (const char *args, value_print_options *print_opts,
/* VOIDPRINT is true to indicate that we do want to print a void
value, so invert it for parse_expression. */
- expression_up expr = parse_expression (exp, nullptr, !voidprint);
+ parser_flags flags = 0;
+ if (!voidprint)
+ flags = PARSER_VOID_CONTEXT;
+ expression_up expr = parse_expression (exp, nullptr, flags);
return expr->evaluate ();
}
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index ffda4a6439e..9e5ced1893e 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -680,7 +680,8 @@ validate_actionline (const char *line, struct breakpoint *b)
{
p = tmp_p;
expression_up exp = parse_exp_1 (&p, loc->address,
- block_for_pc (loc->address), 1);
+ block_for_pc (loc->address),
+ PARSER_COMMA_TERMINATES);
if (exp->first_opcode () == OP_VAR_VALUE)
{
@@ -732,7 +733,8 @@ validate_actionline (const char *line, struct breakpoint *b)
/* Only expressions are allowed for this action. */
expression_up exp = parse_exp_1 (&p, loc->address,
- block_for_pc (loc->address), 1);
+ block_for_pc (loc->address),
+ PARSER_COMMA_TERMINATES);
/* We have something to evaluate, make sure that the expr to
bytecode translator can handle it and that it's not too
@@ -1349,7 +1351,7 @@ encode_actions_1 (struct command_line *action,
const char *exp_start = action_exp;
expression_up exp = parse_exp_1 (&action_exp, tloc->address,
block_for_pc (tloc->address),
- 1);
+ PARSER_COMMA_TERMINATES);
switch (exp->first_opcode ())
{
@@ -1439,7 +1441,7 @@ encode_actions_1 (struct command_line *action,
{
expression_up exp = parse_exp_1 (&action_exp, tloc->address,
block_for_pc (tloc->address),
- 1);
+ PARSER_COMMA_TERMINATES);
agent_expr_up aexpr = gen_eval_for_expr (tloc->address,
exp.get ());
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 04/11] Simplify parser_state constructor
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
` (2 preceding siblings ...)
2023-05-04 14:21 ` [PATCH 03/11] Introduce and use parser flags Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-04 14:21 ` [PATCH 05/11] Boolify parser_state::comma_terminates Tom Tromey
` (7 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
This simplifies the parser_state constructor by having it accept a
parser_flags parameter.
---
gdb/parse.c | 7 ++-----
gdb/parser-defs.h | 9 ++++-----
gdb/rust-parse.c | 2 +-
3 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/gdb/parse.c b/gdb/parse.c
index ed0d0b8a880..2f014dd2172 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -398,11 +398,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,
- (flags & PARSER_COMMA_TERMINATES) != 0,
- *stringptr,
- completer != nullptr, tracker,
- (flags & PARSER_VOID_CONTEXT) != 0);
+ expression_context_pc, flags, *stringptr,
+ completer != nullptr, tracker);
scoped_restore_current_language lang_saver;
set_language (lang->la_language);
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index 5c6bc222b6b..2a246ff38f0 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -146,19 +146,18 @@ struct parser_state : public expr_builder
struct gdbarch *gdbarch,
const struct block *context_block,
CORE_ADDR context_pc,
- int comma,
+ parser_flags flags,
const char *input,
bool completion,
- innermost_block_tracker *tracker,
- bool void_p)
+ innermost_block_tracker *tracker)
: expr_builder (lang, gdbarch),
expression_context_block (context_block),
expression_context_pc (context_pc),
- comma_terminates (comma),
+ comma_terminates ((flags & PARSER_COMMA_TERMINATES) != 0),
lexptr (input),
parse_completion (completion),
block_tracker (tracker),
- void_context_p (void_p)
+ void_context_p ((flags & PARSER_VOID_CONTEXT) != 0)
{
}
diff --git a/gdb/rust-parse.c b/gdb/rust-parse.c
index 648e48dda40..6ba959065c9 100644
--- a/gdb/rust-parse.c
+++ b/gdb/rust-parse.c
@@ -2300,7 +2300,7 @@ rust_lex_tests (void)
{
/* Set up dummy "parser", so that rust_type works. */
struct parser_state ps (language_def (language_rust), target_gdbarch (),
- nullptr, 0, 0, nullptr, 0, nullptr, false);
+ nullptr, 0, 0, nullptr, 0, nullptr);
rust_parser parser (&ps);
rust_lex_test_one (&parser, "", 0);
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 05/11] Boolify parser_state::comma_terminates
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
` (3 preceding siblings ...)
2023-05-04 14:21 ` [PATCH 04/11] Simplify parser_state constructor Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-04 14:21 ` [PATCH 06/11] Rearrange parser_state Tom Tromey
` (6 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
parser_state::comma_terminates ought to be boolean, and changing it
does not require any other changes.
---
gdb/parser-defs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index 2a246ff38f0..e92b4804f47 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -277,7 +277,7 @@ struct parser_state : public expr_builder
/* Nonzero means stop parsing on first comma (if not within parentheses). */
- int comma_terminates;
+ bool comma_terminates;
/* During parsing of a C expression, the pointer to the next character
is in this variable. */
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 06/11] Rearrange parser_state
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
` (4 preceding siblings ...)
2023-05-04 14:21 ` [PATCH 05/11] Boolify parser_state::comma_terminates Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-04 14:21 ` [PATCH 07/11] Add PARSER_DEBUG flag Tom Tromey
` (5 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
This patch mildly rearranges parser_state, moving all the bool fields
together.
---
gdb/parser-defs.h | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index e92b4804f47..39046d04c8d 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -153,10 +153,10 @@ struct parser_state : public expr_builder
: expr_builder (lang, gdbarch),
expression_context_block (context_block),
expression_context_pc (context_pc),
- comma_terminates ((flags & PARSER_COMMA_TERMINATES) != 0),
lexptr (input),
- parse_completion (completion),
block_tracker (tracker),
+ comma_terminates ((flags & PARSER_COMMA_TERMINATES) != 0),
+ parse_completion (completion),
void_context_p ((flags & PARSER_VOID_CONTEXT) != 0)
{
}
@@ -275,10 +275,6 @@ struct parser_state : public expr_builder
point. */
const CORE_ADDR expression_context_pc;
- /* Nonzero means stop parsing on first comma (if not within parentheses). */
-
- bool comma_terminates;
-
/* During parsing of a C expression, the pointer to the next character
is in this variable. */
@@ -292,15 +288,18 @@ struct parser_state : public expr_builder
int arglist_len = 0;
- /* True if parsing an expression to attempt completion. */
- bool parse_completion;
-
/* Completion state is updated here. */
std::unique_ptr<expr_completion_base> m_completion_state;
/* The innermost block tracker. */
innermost_block_tracker *block_tracker;
+ /* Nonzero means stop parsing on first comma (if not within parentheses). */
+ bool comma_terminates;
+
+ /* True if parsing an expression to attempt completion. */
+ bool parse_completion;
+
/* True if no value is expected from the expression. */
bool void_context_p;
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 07/11] Add PARSER_DEBUG flag
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
` (5 preceding siblings ...)
2023-05-04 14:21 ` [PATCH 06/11] Rearrange parser_state Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-04 14:21 ` [PATCH 08/11] Add PARSER_LEAVE_BLOCK_ALONE flag Tom Tromey
` (4 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
This adds a new PARSER_DEBUG constant and changes the parser code to
use it. This lets us make the 'parser_debug' global 'static'.
---
gdb/ada-exp.y | 2 +-
gdb/c-exp.y | 2 +-
gdb/d-exp.y | 2 +-
gdb/expression.h | 5 +++++
gdb/f-exp.y | 2 +-
gdb/go-exp.y | 2 +-
gdb/parse.c | 2 +-
gdb/parser-defs.h | 8 +++++---
8 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 3e31d275046..23aebf0e236 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -1150,7 +1150,7 @@ ada_parse (struct parser_state *par_state)
original_expr = par_state->lexptr;
scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
- parser_debug);
+ par_state->debug);
lexer_init (yyin); /* (Re-)initialize lexer. */
obstack_free (&temp_parse_space, NULL);
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 9ee4115560a..a8c78414253 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -3403,7 +3403,7 @@ c_parse (struct parser_state *par_state)
= make_scoped_restore (&expression_macro_scope, macro_scope.get ());
scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
- parser_debug);
+ par_state->debug);
/* Initialize some state used by the lexer. */
last_was_structop = false;
diff --git a/gdb/d-exp.y b/gdb/d-exp.y
index 3a4e7ee0434..b0f2c0d1c10 100644
--- a/gdb/d-exp.y
+++ b/gdb/d-exp.y
@@ -1607,7 +1607,7 @@ d_parse (struct parser_state *par_state)
pstate = par_state;
scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
- parser_debug);
+ par_state->debug);
struct type_stack stack;
scoped_restore restore_type_stack = make_scoped_restore (&type_stack,
diff --git a/gdb/expression.h b/gdb/expression.h
index 2e2d2a090f9..c485b159ef8 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -296,6 +296,11 @@ enum parser_flag
/* This flag is set if a top-level comma terminates the
expression. */
PARSER_COMMA_TERMINATES = (1 << 1),
+
+ /* This flag is set if the parser should print debugging output as
+ it parses. For yacc-based parsers, this translates to setting
+ yydebug. */
+ PARSER_DEBUG = (1 << 2),
};
DEF_ENUM_FLAGS_TYPE (enum parser_flag, parser_flags);
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index 7fb1a9054e3..c0afebc0589 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -1697,7 +1697,7 @@ f_language::parser (struct parser_state *par_state) const
/* Setting up the parser state. */
scoped_restore pstate_restore = make_scoped_restore (&pstate);
scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
- parser_debug);
+ par_state->debug);
gdb_assert (par_state != NULL);
pstate = par_state;
last_was_structop = false;
diff --git a/gdb/go-exp.y b/gdb/go-exp.y
index 542a06d06d6..5c213f138f0 100644
--- a/gdb/go-exp.y
+++ b/gdb/go-exp.y
@@ -1525,7 +1525,7 @@ go_language::parser (struct parser_state *par_state) const
pstate = par_state;
scoped_restore restore_yydebug = make_scoped_restore (&yydebug,
- parser_debug);
+ par_state->debug);
/* Initialize some state used by the lexer. */
last_was_structop = 0;
diff --git a/gdb/parse.c b/gdb/parse.c
index 2f014dd2172..bbe5cf12d37 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -62,7 +62,7 @@ show_expressiondebug (struct ui_file *file, int from_tty,
/* True if an expression parser should set yydebug. */
-bool parser_debug;
+static bool parser_debug;
static void
show_parserdebug (struct ui_file *file, int from_tty,
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index 39046d04c8d..93ebdf5c061 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -32,8 +32,6 @@ struct language_defn;
struct internalvar;
class innermost_block_tracker;
-extern bool parser_debug;
-
/* A class that can be used to build a "struct expression". */
struct expr_builder
@@ -157,7 +155,8 @@ struct parser_state : public expr_builder
block_tracker (tracker),
comma_terminates ((flags & PARSER_COMMA_TERMINATES) != 0),
parse_completion (completion),
- void_context_p ((flags & PARSER_VOID_CONTEXT) != 0)
+ void_context_p ((flags & PARSER_VOID_CONTEXT) != 0),
+ debug ((flags & PARSER_DEBUG) != 0)
{
}
@@ -303,6 +302,9 @@ struct parser_state : public expr_builder
/* True if no value is expected from the expression. */
bool void_context_p;
+ /* True if parser debugging should be enabled. */
+ bool debug;
+
private:
/* Data structure for saving values of arglist_len for function calls whose
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 08/11] Add PARSER_LEAVE_BLOCK_ALONE flag
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
` (6 preceding siblings ...)
2023-05-04 14:21 ` [PATCH 07/11] Add PARSER_DEBUG flag Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-04 14:21 ` [PATCH 09/11] Add flags to parse_and_eval Tom Tromey
` (3 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
This adds a PARSER_LEAVE_BLOCK_ALONE flag, and changes the parse API
to respect it. This flag lets callers avoid any change to the
passed-in block and expression PC, letting them specify the context
exactly. In particular, now nullptr can be used to indicate that the
parse should not examine any local variables.
---
gdb/expression.h | 6 ++++++
gdb/parse.c | 37 +++++++++++++++++++++----------------
2 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/gdb/expression.h b/gdb/expression.h
index c485b159ef8..d1858776e8e 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -301,6 +301,12 @@ enum parser_flag
it parses. For yacc-based parsers, this translates to setting
yydebug. */
PARSER_DEBUG = (1 << 2),
+
+ /* Normally the expression-parsing functions like parse_exp_1 will
+ attempt to find a context block if one is not passed in. If set,
+ this flag suppresses this search and uses a null context for the
+ parse. */
+ PARSER_LEAVE_BLOCK_ALONE = (1 << 3),
};
DEF_ENUM_FLAGS_TYPE (enum parser_flag, parser_flags);
diff --git a/gdb/parse.c b/gdb/parse.c
index bbe5cf12d37..221733a3f90 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -344,26 +344,31 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
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);
- else if (pc == 0)
- expression_context_pc = expression_context_block->entry_pc ();
- else
- expression_context_pc = pc;
+ if ((flags & PARSER_LEAVE_BLOCK_ALONE) == 0)
+ {
+ /* If no context specified, try using the current frame, if any. */
+ if (!expression_context_block)
+ expression_context_block
+ = get_selected_block (&expression_context_pc);
+ else if (pc == 0)
+ expression_context_pc = expression_context_block->entry_pc ();
+ else
+ expression_context_pc = pc;
- /* Fall back to using the current source static context, if any. */
+ /* Fall back to using the current source static context, if any. */
- if (!expression_context_block)
- {
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ if (!expression_context_block)
+ {
+ struct symtab_and_line cursal
+ = get_current_source_symtab_and_line ();
- if (cursal.symtab)
- expression_context_block
- = cursal.symtab->compunit ()->blockvector ()->static_block ();
+ if (cursal.symtab)
+ expression_context_block
+ = cursal.symtab->compunit ()->blockvector ()->static_block ();
- if (expression_context_block)
- expression_context_pc = expression_context_block->entry_pc ();
+ if (expression_context_block)
+ expression_context_pc = expression_context_block->entry_pc ();
+ }
}
if (language_mode == language_mode_auto && block != NULL)
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 09/11] Add flags to parse_and_eval
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
` (7 preceding siblings ...)
2023-05-04 14:21 ` [PATCH 08/11] Add PARSER_LEAVE_BLOCK_ALONE flag Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-04 14:21 ` [PATCH 10/11] Add global_context parameter to gdb.parse_and_eval Tom Tromey
` (2 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
This adds a flags parameter to parse_and_eval.
---
gdb/eval.c | 4 ++--
gdb/value.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/gdb/eval.c b/gdb/eval.c
index d8d53c28686..457a6697923 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -67,9 +67,9 @@ parse_and_eval_long (const char *exp)
}
struct value *
-parse_and_eval (const char *exp)
+parse_and_eval (const char *exp, parser_flags flags)
{
- expression_up expr = parse_expression (exp);
+ expression_up expr = parse_expression (exp, nullptr, flags);
return expr->evaluate ();
}
diff --git a/gdb/value.h b/gdb/value.h
index d042d816409..a9c77a033ab 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -1313,7 +1313,7 @@ extern void fetch_subexp_value (struct expression *exp,
std::vector<value_ref_ptr> *val_chain,
bool preserve_errors);
-extern struct value *parse_and_eval (const char *exp);
+extern struct value *parse_and_eval (const char *exp, parser_flags flags = 0);
extern struct value *parse_to_comma_and_eval (const char **expp);
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 10/11] Add global_context parameter to gdb.parse_and_eval
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
` (8 preceding siblings ...)
2023-05-04 14:21 ` [PATCH 09/11] Add flags to parse_and_eval Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-04 14:54 ` Eli Zaretskii
2023-05-04 14:21 ` [PATCH 11/11] Handle DAP evaluate request without a frame ID Tom Tromey
2023-05-23 20:17 ` [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
11 siblings, 1 reply; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
This adds a 'global_context' parse_and_eval to gdb.parse_and_eval.
This lets users request a parse that is done at "global scope".
I considered letting callers pass in a block instead, with None
meaning "global" -- but then there didn't seem to be a clean way to
express the default for this parameter.
---
gdb/NEWS | 4 ++++
gdb/doc/python.texi | 7 ++++++-
gdb/python/python.c | 28 ++++++++++++++++++++++------
gdb/testsuite/gdb.python/py-value.c | 3 +++
gdb/testsuite/gdb.python/py-value.exp | 5 +++++
5 files changed, 40 insertions(+), 7 deletions(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index e3c095de09e..4bf5603b550 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -162,6 +162,10 @@ info main
(program-counter) values, and can be used as the frame-id when
calling gdb.PendingFrame.create_unwind_info.
+ ** gdb.parse_and_eval now has a new "global_context" parameter.
+ This can be used to request that the parse only examine global
+ symbols.
+
*** Changes in GDB 13
* MI version 1 is deprecated, and will be removed in GDB 14.
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 7c3a3ccd379..dca16bb84e0 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -419,11 +419,16 @@ using the @code{gdb.Value} constructor.
@end defun
@findex gdb.parse_and_eval
-@defun gdb.parse_and_eval (expression)
+@defun gdb.parse_and_eval (expression, @r{[}, global_context@r{]})
Parse @var{expression}, which must be a string, as an expression in
the current language, evaluate it, and return the result as a
@code{gdb.Value}.
+@var{global_context}, if provided, is a boolean indicating whether the
+parsing should be done in the global context. The default is
+@samp{False}, meaning that the current frame or current static context
+should be used.
+
This function can be useful when implementing a new command
(@pxref{CLI Commands In Python}, @pxref{GDB/MI Commands In Python}),
as it provides a way to parse the
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 168a0009f1b..42bb2ed34b1 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -969,19 +969,34 @@ gdbpy_decode_line (PyObject *self, PyObject *args)
/* Parse a string and evaluate it as an expression. */
static PyObject *
-gdbpy_parse_and_eval (PyObject *self, PyObject *args)
+gdbpy_parse_and_eval (PyObject *self, PyObject *args, PyObject *kw)
{
+ static const char *keywords[] = { "expression", "global_context", nullptr };
+
const char *expr_str;
+ PyObject *global_context_obj = nullptr;
- if (!PyArg_ParseTuple (args, "s", &expr_str))
- return NULL;
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!", keywords,
+ &expr_str,
+ &PyBool_Type, &global_context_obj))
+ return nullptr;
+
+ parser_flags flags = 0;
+ if (global_context_obj != NULL)
+ {
+ int cmp = PyObject_IsTrue (global_context_obj);
+ if (cmp < 0)
+ return nullptr;
+ if (cmp)
+ flags |= PARSER_LEAVE_BLOCK_ALONE;
+ }
PyObject *result = nullptr;
try
{
gdbpy_allow_threads allow_threads;
scoped_value_mark free_values;
- struct value *val = parse_and_eval (expr_str);
+ struct value *val = parse_and_eval (expr_str, flags);
result = value_to_value_object (val);
}
catch (const gdb_exception &except)
@@ -2591,8 +2606,9 @@ The first element contains any unparsed portion of the String parameter\n\
(or None if the string was fully parsed). The second element contains\n\
a tuple that contains all the locations that match, represented as\n\
gdb.Symtab_and_line objects (or None)."},
- { "parse_and_eval", gdbpy_parse_and_eval, METH_VARARGS,
- "parse_and_eval (String) -> Value.\n\
+ { "parse_and_eval", (PyCFunction) gdbpy_parse_and_eval,
+ METH_VARARGS | METH_KEYWORDS,
+ "parse_and_eval (String, [Boolean]) -> Value.\n\
Parse String as an expression, evaluate it, and return the result as a Value."
},
diff --git a/gdb/testsuite/gdb.python/py-value.c b/gdb/testsuite/gdb.python/py-value.c
index 5a578de5d50..f0b1f5f160c 100644
--- a/gdb/testsuite/gdb.python/py-value.c
+++ b/gdb/testsuite/gdb.python/py-value.c
@@ -79,6 +79,8 @@ int func2 (int arg1, int arg2)
char **save_argv;
+int shadowed = 23;
+
int
main (int argc, char *argv[])
{
@@ -96,6 +98,7 @@ main (int argc, char *argv[])
int i = 2;
int *ptr_i = &i;
struct str *xstr;
+ int shadowed = 97;
/* Prevent gcc from optimizing argv[] out. */
diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp
index 898208b90d1..9fc25814721 100644
--- a/gdb/testsuite/gdb.python/py-value.exp
+++ b/gdb/testsuite/gdb.python/py-value.exp
@@ -338,6 +338,11 @@ proc test_value_in_inferior {} {
gdb_py_test_silent_cmd "python str = '\"str\"'" "set up str variable" 1
gdb_test "python print (gdb.parse_and_eval (str).string (length = 10))" \
"gdb.error: Attempt to take address of value not located in memory.\r\nError while executing Python code."
+
+ gdb_test "python print (gdb.parse_and_eval ('shadowed'))" \
+ 97 "shadowed local value"
+ gdb_test "python print (gdb.parse_and_eval ('shadowed', global_context=True))" \
+ 23 "shadowed global value"
}
proc test_inferior_function_call {} {
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 10/11] Add global_context parameter to gdb.parse_and_eval
2023-05-04 14:21 ` [PATCH 10/11] Add global_context parameter to gdb.parse_and_eval Tom Tromey
@ 2023-05-04 14:54 ` Eli Zaretskii
2023-05-23 20:17 ` Tom Tromey
0 siblings, 1 reply; 15+ messages in thread
From: Eli Zaretskii @ 2023-05-04 14:54 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
> Date: Thu, 04 May 2023 08:21:31 -0600
> From: Tom Tromey via Gdb-patches <gdb-patches@sourceware.org>
>
> This adds a 'global_context' parse_and_eval to gdb.parse_and_eval.
> This lets users request a parse that is done at "global scope".
>
> I considered letting callers pass in a block instead, with None
> meaning "global" -- but then there didn't seem to be a clean way to
> express the default for this parameter.
> ---
> gdb/NEWS | 4 ++++
> gdb/doc/python.texi | 7 ++++++-
> gdb/python/python.c | 28 ++++++++++++++++++++++------
> gdb/testsuite/gdb.python/py-value.c | 3 +++
> gdb/testsuite/gdb.python/py-value.exp | 5 +++++
> 5 files changed, 40 insertions(+), 7 deletions(-)
Thanks.
> diff --git a/gdb/NEWS b/gdb/NEWS
> index e3c095de09e..4bf5603b550 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -162,6 +162,10 @@ info main
> (program-counter) values, and can be used as the frame-id when
> calling gdb.PendingFrame.create_unwind_info.
>
> + ** gdb.parse_and_eval now has a new "global_context" parameter.
> + This can be used to request that the parse only examine global
> + symbols.
> +
This part is OK.
> --- a/gdb/doc/python.texi
> +++ b/gdb/doc/python.texi
> @@ -419,11 +419,16 @@ using the @code{gdb.Value} constructor.
> @end defun
>
> @findex gdb.parse_and_eval
> -@defun gdb.parse_and_eval (expression)
> +@defun gdb.parse_and_eval (expression, @r{[}, global_context@r{]})
^
That comma is redundant, right?
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 10/11] Add global_context parameter to gdb.parse_and_eval
2023-05-04 14:54 ` Eli Zaretskii
@ 2023-05-23 20:17 ` Tom Tromey
0 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-23 20:17 UTC (permalink / raw)
To: Eli Zaretskii via Gdb-patches; +Cc: Tom Tromey, Eli Zaretskii
>>>>> "Eli" == Eli Zaretskii via Gdb-patches <gdb-patches@sourceware.org> writes:
>> --- a/gdb/doc/python.texi
>> +++ b/gdb/doc/python.texi
>> @@ -419,11 +419,16 @@ using the @code{gdb.Value} constructor.
>> @end defun
>>
>> @findex gdb.parse_and_eval
>> -@defun gdb.parse_and_eval (expression)
>> +@defun gdb.parse_and_eval (expression, @r{[}, global_context@r{]})
Eli> That comma is redundant, right?
Yes, I've removed it now.
Tom
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 11/11] Handle DAP evaluate request without a frame ID
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
` (9 preceding siblings ...)
2023-05-04 14:21 ` [PATCH 10/11] Add global_context parameter to gdb.parse_and_eval Tom Tromey
@ 2023-05-04 14:21 ` Tom Tromey
2023-05-23 20:17 ` [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
To: gdb-patches
DAP specifies that if an evaluate request does not have a frameID
parameter, then the expression is evaluated in the global scope.
---
gdb/python/lib/gdb/dap/evaluate.py | 4 ++-
gdb/testsuite/gdb.dap/frameless.c | 24 ++++++++++++++
gdb/testsuite/gdb.dap/frameless.exp | 62 +++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/gdb/python/lib/gdb/dap/evaluate.py b/gdb/python/lib/gdb/dap/evaluate.py
index 55d41b0806d..8ed2402d916 100644
--- a/gdb/python/lib/gdb/dap/evaluate.py
+++ b/gdb/python/lib/gdb/dap/evaluate.py
@@ -30,10 +30,12 @@ class EvaluateResult(VariableReference):
# Helper function to evaluate an expression in a certain frame.
@in_gdb_thread
def _evaluate(expr, frame_id):
+ global_context = True
if frame_id is not None:
frame = frame_for_id(frame_id)
frame.select()
- val = gdb.parse_and_eval(expr)
+ global_context = False
+ val = gdb.parse_and_eval(expr, global_context=global_context)
ref = EvaluateResult(val)
return ref.to_object()
diff --git a/gdb/testsuite/gdb.dap/frameless.c b/gdb/testsuite/gdb.dap/frameless.c
new file mode 100644
index 00000000000..fd17ad46dc2
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/frameless.c
@@ -0,0 +1,24 @@
+/* Copyright 2023 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int variable = 23;
+
+int main ()
+{
+ int variable = 97;
+ return 0; /* BREAK */
+}
diff --git a/gdb/testsuite/gdb.dap/frameless.exp b/gdb/testsuite/gdb.dap/frameless.exp
new file mode 100644
index 00000000000..3fb33467c94
--- /dev/null
+++ b/gdb/testsuite/gdb.dap/frameless.exp
@@ -0,0 +1,62 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test frameless evaluation in DAP.
+
+require allow_dap_tests
+
+load_lib dap-support.exp
+
+standard_testfile
+
+if {[build_executable ${testfile}.exp $testfile] == -1} {
+ return
+}
+
+if {[dap_launch $testfile] == ""} {
+ return
+}
+
+set line [gdb_get_line_number "BREAK"]
+set obj [dap_check_request_and_response "set breakpoint by line number" \
+ setBreakpoints \
+ [format {o source [o path [%s]] breakpoints [a [o line [i %d]]]} \
+ [list s $srcfile] $line]]
+set line_bpno [dap_get_breakpoint_number $obj]
+
+dap_check_request_and_response "start inferior" configurationDone
+dap_wait_for_event_and_check "inferior started" thread "body reason" started
+
+dap_wait_for_event_and_check "stopped at line breakpoint" stopped \
+ "body reason" breakpoint \
+ "body hitBreakpointIds" $line_bpno
+
+set bt [lindex [dap_check_request_and_response "backtrace" stackTrace \
+ {o threadId [i 1]}] \
+ 0]
+set frame_id [dict get [lindex [dict get $bt body stackFrames] 0] id]
+
+set obj [dap_check_request_and_response "evaluate variable in function" \
+ evaluate [format {o expression [s variable] frameId [i %s]} \
+ $frame_id]]
+dap_match_values "variable value in function" [lindex $obj 0] \
+ "body result" 97
+
+set obj [dap_check_request_and_response "evaluate variable globally" \
+ evaluate {o expression [s variable]}]
+dap_match_values "variable value globally" [lindex $obj 0] \
+ "body result" 23
+
+dap_shutdown
--
2.39.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 00/11] Fix frame-less expression evaluation in DAP
2023-05-04 14:21 [PATCH 00/11] Fix frame-less expression evaluation in DAP Tom Tromey
` (10 preceding siblings ...)
2023-05-04 14:21 ` [PATCH 11/11] Handle DAP evaluate request without a frame ID Tom Tromey
@ 2023-05-23 20:17 ` Tom Tromey
11 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-23 20:17 UTC (permalink / raw)
To: Tom Tromey via Gdb-patches; +Cc: Tom Tromey
>>>>> "Tom" == Tom Tromey via Gdb-patches <gdb-patches@sourceware.org> writes:
Tom> In DAP, an evaluation request without a frame ID should be done at the
Tom> global scope. This series implements this. Most of the series is
Tom> minor cleanups to the parser API, to make the final code a bit
Tom> cleaner.
Tom> Regression tested on x86-64 Fedora 36.
I'm checking this in now.
Tom
^ permalink raw reply [flat|nested] 15+ messages in thread