From 02c727013cc3ae08b86ad360429f9a0dbdc0ec92 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tom@tromey.com>
Date: Fri, 11 Dec 2020 09:59:15 -0700
Subject: [PATCH] Avoid side effects in expression lexers

I noticed that some of the lexers were calling write_dollar_variable
from the lexer.  This seems like a bad practice, so this patch moves
the side effects into the parsers.

I tested this by re-running gdb.fortran and gdb.modula2; the Pascal
compiler on my machine seems not to work, so I couldn't test
gdb.pascal.

I note that the type-tracking in the Pascal is also incorrect, in that
a convenience variable's type may change between parsing and
evaluation (or even during the course of evaluation).

gdb/ChangeLog
2020-12-11  Tom Tromey  <tom@tromey.com>

	* p-exp.y (intvar): Remove global.
	(DOLLAR_VARIABLE): Change type.
	(start): Update.
	(exp): Call write_dollar_variable here...
	(yylex): ... not here.
	* m2-exp.y (DOLLAR_VARIABLE): Change type.
	(variable): Call write_dollar_variable here...
	(yylex): ... not here.
	* f-exp.y (DOLLAR_VARIABLE): Change type.
	(exp): Call write_dollar_variable here...
	(yylex): ... not here.
---
 gdb/ChangeLog | 14 ++++++++++++++
 gdb/f-exp.y   | 10 ++++------
 gdb/m2-exp.y  |  8 +++-----
 gdb/p-exp.y   | 46 ++++++++++++++++++++++------------------------
 4 files changed, 43 insertions(+), 35 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a3d977dc604..992da3db302 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,17 @@
+2020-12-11  Tom Tromey  <tom@tromey.com>
+
+	* p-exp.y (intvar): Remove global.
+	(DOLLAR_VARIABLE): Change type.
+	(start): Update.
+	(exp): Call write_dollar_variable here...
+	(yylex): ... not here.
+	* m2-exp.y (DOLLAR_VARIABLE): Change type.
+	(variable): Call write_dollar_variable here...
+	(yylex): ... not here.
+	* f-exp.y (DOLLAR_VARIABLE): Change type.
+	(exp): Call write_dollar_variable here...
+	(yylex): ... not here.
+
 2020-12-11  Tom Tromey  <tom@tromey.com>
 
 	* varobj.c (varobj_create): Update.
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index edfbe0cd220..ea32056f6db 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -174,7 +174,7 @@ static int parse_number (struct parser_state *, const char *, int,
 %token SINGLE DOUBLE PRECISION
 %token <lval> CHARACTER 
 
-%token <voidval> DOLLAR_VARIABLE
+%token <sval> DOLLAR_VARIABLE
 
 %token <opcode> ASSIGN_MODIFY
 %token <opcode> UNOP_INTRINSIC BINOP_INTRINSIC
@@ -509,6 +509,7 @@ exp	:	variable
 	;
 
 exp	:	DOLLAR_VARIABLE
+			{ write_dollar_variable (pstate, $1); }
 	;
 
 exp	:	SIZEOF '(' type ')'	%prec UNARY
@@ -1357,11 +1358,8 @@ yylex (void)
   yylval.sval.length = namelen;
   
   if (*tokstart == '$')
-    {
-      write_dollar_variable (pstate, yylval.sval);
-      return DOLLAR_VARIABLE;
-    }
-  
+    return DOLLAR_VARIABLE;
+
   /* Use token-type TYPENAME for symbols that happen to be defined
      currently as names of types; NAME for other symbols.
      The caller is not constrained to care about the distinction.  */
diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y
index f6f11126c69..d4f3c2c1e45 100644
--- a/gdb/m2-exp.y
+++ b/gdb/m2-exp.y
@@ -125,7 +125,7 @@ static int number_sign = 1;
 /* The GDB scope operator */
 %token COLONCOLON
 
-%token <voidval> DOLLAR_VARIABLE
+%token <sval> DOLLAR_VARIABLE
 
 /* M2 tokens */
 %left ','
@@ -535,6 +535,7 @@ variable:	fblock
 
 /* GDB internal ($foo) variable */
 variable:	DOLLAR_VARIABLE
+			{ write_dollar_variable (pstate, $1); }
 	;
 
 /* GDB scope operator */
@@ -952,10 +953,7 @@ yylex (void)
   yylval.sval.length = namelen;
 
   if (*tokstart == '$')
-    {
-      write_dollar_variable (pstate, yylval.sval);
-      return DOLLAR_VARIABLE;
-    }
+    return DOLLAR_VARIABLE;
 
   /* Use token-type BLOCKNAME for symbols that happen to be defined as
      functions.  If this is not so, then ...
diff --git a/gdb/p-exp.y b/gdb/p-exp.y
index 9caf15f69f5..618557c472a 100644
--- a/gdb/p-exp.y
+++ b/gdb/p-exp.y
@@ -115,7 +115,6 @@ static int parse_number (struct parser_state *,
 			 const char *, int, int, YYSTYPE *);
 
 static struct type *current_type;
-static struct internalvar *intvar;
 static int leftdiv_is_integer;
 static void push_current_type (void);
 static void pop_current_type (void);
@@ -161,7 +160,7 @@ static int search_field;
 /* Special type cases, put in to allow the parser to distinguish different
    legal basetypes.  */
 
-%token <voidval> DOLLAR_VARIABLE
+%token <sval> DOLLAR_VARIABLE
 
 
 /* Object pascal */
@@ -192,7 +191,6 @@ static int search_field;
 %%
 
 start   :	{ current_type = NULL;
-		  intvar = NULL;
 		  search_field = 0;
 		  leftdiv_is_integer = 0;
 		}
@@ -526,17 +524,28 @@ exp	:	variable
 	;
 
 exp	:	DOLLAR_VARIABLE
-			/* Already written by write_dollar_variable.
-			   Handle current_type.  */
- 			{  if (intvar) {
- 			     struct value * val, * mark;
+			{
+			  write_dollar_variable (pstate, $1);
 
-			     mark = value_mark ();
- 			     val = value_of_internalvar (pstate->gdbarch (),
- 							 intvar);
- 			     current_type = value_type (val);
-			     value_release_to_mark (mark);
- 			   }
+			  /* $ is the normal prefix for pascal
+			     hexadecimal values but this conflicts
+			     with the GDB use for debugger variables
+			     so in expression to enter hexadecimal
+			     values we still need to use C syntax with
+			     0xff */
+			  std::string tmp ($1.ptr, $1.length);
+			  /* Handle current_type.  */
+			  struct internalvar *intvar
+			    = lookup_only_internalvar (tmp.c_str () + 1);
+			  if (intvar != nullptr)
+			    {
+			      scoped_value_mark mark;
+
+			      value *val
+				= value_of_internalvar (pstate->gdbarch (),
+							intvar);
+			      current_type = value_type (val);
+			    }
  			}
  	;
 
@@ -1494,17 +1503,6 @@ yylex (void)
 
   if (*tokstart == '$')
     {
-      char *tmp;
-
-      /* $ is the normal prefix for pascal hexadecimal values
-	but this conflicts with the GDB use for debugger variables
-	so in expression to enter hexadecimal values
-	we still need to use C syntax with 0xff  */
-      write_dollar_variable (pstate, yylval.sval);
-      tmp = (char *) alloca (namelen + 1);
-      memcpy (tmp, tokstart, namelen);
-      tmp[namelen] = '\0';
-      intvar = lookup_only_internalvar (tmp + 1);
       free (uptokstart);
       return DOLLAR_VARIABLE;
     }