public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 00/11] Fix frame-less expression evaluation in DAP
@ 2023-05-04 14:21 Tom Tromey
  2023-05-04 14:21 ` [PATCH 01/11] Avoid forward declaration in parse.c Tom Tromey
                   ` (11 more replies)
  0 siblings, 12 replies; 15+ messages in thread
From: Tom Tromey @ 2023-05-04 14:21 UTC (permalink / raw)
  To: gdb-patches

In DAP, an evaluation request without a frame ID should be done at the
global scope.  This series implements this.  Most of the series is
minor cleanups to the parser API, to make the final code a bit
cleaner.

Regression tested on x86-64 Fedora 36.

---
Tom Tromey (11):
      Avoid forward declaration in parse.c
      Move innermost_block_tracker to expression.h
      Introduce and use parser flags
      Simplify parser_state constructor
      Boolify parser_state::comma_terminates
      Rearrange parser_state
      Add PARSER_DEBUG flag
      Add PARSER_LEAVE_BLOCK_ALONE flag
      Add flags to parse_and_eval
      Add global_context parameter to gdb.parse_and_eval
      Handle DAP evaluate request without a frame ID

 gdb/NEWS                              |  4 ++
 gdb/ada-exp.y                         |  2 +-
 gdb/ax-gdb.c                          |  3 +-
 gdb/breakpoint.c                      |  3 +-
 gdb/c-exp.y                           |  2 +-
 gdb/d-exp.y                           |  2 +-
 gdb/doc/python.texi                   |  7 ++-
 gdb/eval.c                            |  7 +--
 gdb/expression.h                      | 78 ++++++++++++++++++++++++++--
 gdb/f-exp.y                           |  2 +-
 gdb/go-exp.y                          |  2 +-
 gdb/parse.c                           | 97 ++++++++++++++++-------------------
 gdb/parser-defs.h                     | 73 ++++++--------------------
 gdb/printcmd.c                        |  5 +-
 gdb/python/lib/gdb/dap/evaluate.py    |  4 +-
 gdb/python/python.c                   | 28 +++++++---
 gdb/rust-parse.c                      |  2 +-
 gdb/testsuite/gdb.dap/frameless.c     | 24 +++++++++
 gdb/testsuite/gdb.dap/frameless.exp   | 62 ++++++++++++++++++++++
 gdb/testsuite/gdb.python/py-value.c   |  3 ++
 gdb/testsuite/gdb.python/py-value.exp |  5 ++
 gdb/tracepoint.c                      | 10 ++--
 gdb/value.h                           |  2 +-
 23 files changed, 288 insertions(+), 139 deletions(-)
---
base-commit: 3539414584be0094b0a4fe56dfd64ea79d802edc
change-id: 20230504-frameless-2cafb628e8d4

Best regards,
-- 
Tom Tromey <tromey@adacore.com>


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [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

* [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 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

* 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

end of thread, other threads:[~2023-05-23 20:18 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 03/11] Introduce and use parser flags Tom Tromey
2023-05-04 14:21 ` [PATCH 04/11] Simplify parser_state constructor Tom Tromey
2023-05-04 14:21 ` [PATCH 05/11] Boolify parser_state::comma_terminates Tom Tromey
2023-05-04 14:21 ` [PATCH 06/11] Rearrange parser_state Tom Tromey
2023-05-04 14:21 ` [PATCH 07/11] Add PARSER_DEBUG flag Tom Tromey
2023-05-04 14:21 ` [PATCH 08/11] Add PARSER_LEAVE_BLOCK_ALONE flag Tom Tromey
2023-05-04 14:21 ` [PATCH 09/11] Add flags to parse_and_eval Tom Tromey
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
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).