Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH 0/7] Leftovers from parsers cleanup
@ 2026-10-01 20:29 Simon Marchi
  2026-10-01 20:29 ` [PATCH 1/7] gdb: convert QUAL_* macros into an enum_flags Simon Marchi
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: Simon Marchi @ 2026-10-01 20:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Here are a few random patches that I wrote when doing the parser cleanup
I just merged.  I initially left them out because they were not
essential and the series was already long enough.

Simon Marchi (7):
  gdb: convert QUAL_* macros into an enum_flags
  gdb: convert INT_* macros into an enum_flags
  gdb: convert d_left and d_right macros into functions
  gdb: replace cp-name-parser.c macros with lambdas
  gdb: use std::string for f-exp-parser.c's tempbuf
  gdb: remove qsort kludge from ada-exp-parser.y
  gdb: make COMPLETE_CHAR a constexpr

 gdb/ada-exp-parser.h |   2 +-
 gdb/ada-exp-parser.y |   3 -
 gdb/ada-lex.l        |   4 +-
 gdb/cp-name-parser.c | 210 +++++++++++++++++++++++++------------------
 gdb/cp-name-parser.h |  59 ++++++++----
 gdb/cp-name-parser.y |  30 ++++---
 gdb/f-exp-parser.c   |  55 +++---------
 7 files changed, 199 insertions(+), 164 deletions(-)


base-commit: ad78106abfc1ab764f3cb7450493f14b1bd8e9a2
-- 
2.55.0


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

* [PATCH 1/7] gdb: convert QUAL_* macros into an enum_flags
  2026-10-01 20:29 [PATCH 0/7] Leftovers from parsers cleanup Simon Marchi
@ 2026-10-01 20:29 ` Simon Marchi
  2026-10-01 20:30 ` [PATCH 2/7] gdb: convert INT_* " Simon Marchi
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2026-10-01 20:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Replace the QUAL_CONST / QUAL_RESTRICT / QUAL_VOLATILE macros with an
enum plus an enum flags_type.  Use it where applicable.

Note that the value stored on the parser's union is the raw enum, not
the enum_flags type.  enum_flags has a user-provided default constructor
(to initialize it to 0), which would make the generated YYSTYPE union's
default constructor deleted.  The d_qualify helper function accepts the
enum_flags type though.

Change-Id: Ib146f6db66c849ac2f0ee575a98bff7b90d5e17c
---
 gdb/cp-name-parser.c |  4 ++--
 gdb/cp-name-parser.h | 21 ++++++++++++++-------
 gdb/cp-name-parser.y | 11 ++++++-----
 3 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/gdb/cp-name-parser.c b/gdb/cp-name-parser.c
index d04ed3594878..569d102213c8 100644
--- a/gdb/cp-name-parser.c
+++ b/gdb/cp-name-parser.c
@@ -110,8 +110,8 @@ cpname_state::make_name (const char *name, int len)
    may already be qualified; duplicate qualifiers are not created.  */
 
 struct demangle_component *
-cpname_state::d_qualify (struct demangle_component *lhs, int qualifiers,
-			 int is_method)
+cpname_state::d_qualify (struct demangle_component *lhs,
+			 qual_flags qualifiers, int is_method)
 {
   struct demangle_component **inner_p;
   enum demangle_component_type type;
diff --git a/gdb/cp-name-parser.h b/gdb/cp-name-parser.h
index 31b2227227fc..7585379f5be2 100644
--- a/gdb/cp-name-parser.h
+++ b/gdb/cp-name-parser.h
@@ -21,16 +21,11 @@
 #define GDB_CP_NAME_PARSER_H
 
 #include "demangle.h"
+#include "gdbsupport/enum-flags.h"
 
 union cp_name_parser_YYSTYPE;
 struct demangle_parse_info;
 
-/* Flags passed to cpname_state::d_qualify.  */
-
-#define QUAL_CONST 1
-#define QUAL_RESTRICT 2
-#define QUAL_VOLATILE 4
-
 /* Flags passed to cpname_state::d_int_type.  */
 
 #define INT_CHAR	(1 << 0)
@@ -46,6 +41,18 @@ struct demangle_parse_info;
 
 namespace cp_name_parser {
 
+/* Type qualifiers, passed to cpname_state::d_qualify.  */
+
+enum qual_flag
+{
+  QUAL_NONE = 0,
+  QUAL_CONST = 1,
+  QUAL_RESTRICT = 2,
+  QUAL_VOLATILE = 4,
+};
+
+DEF_ENUM_FLAGS_TYPE (enum qual_flag, qual_flags);
+
 /* State of an ongoing parse.  */
 
 struct cpname_state
@@ -100,7 +107,7 @@ struct cpname_state
   struct demangle_component *make_name (const char *name, int len);
 
   struct demangle_component *d_qualify (struct demangle_component *lhs,
-					int qualifiers, int is_method);
+					qual_flags qualifiers, int is_method);
 
   struct demangle_component *d_int_type (int flags);
 
diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y
index 57247f459fab..b41ca6b30a20 100644
--- a/gdb/cp-name-parser.y
+++ b/gdb/cp-name-parser.y
@@ -60,6 +60,7 @@
       int fold_flag;
     } abstract;
     int lval;
+    cp_name_parser::qual_flag qual;
     const char *opname;
   }
 
@@ -84,7 +85,7 @@
 
 %type <nested1> nested_name
 
-%type <lval> qualifier qualifiers qualifiers_opt
+%type <qual> qualifier qualifiers qualifiers_opt
 
 %type <lval> int_part int_seq
 
@@ -518,16 +519,16 @@ function_arglist:	'(' function_args ')' qualifiers_opt %prec NAME
 
 /* Should do something about DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL */
 qualifiers_opt	:	/* epsilon */
-			{ $$ = 0; }
+			{ $$ = cp_name_parser::QUAL_NONE; }
 		|	qualifiers
 		;
 
 qualifier	:	RESTRICT
-			{ $$ = QUAL_RESTRICT; }
+			{ $$ = cp_name_parser::QUAL_RESTRICT; }
 		|	VOLATILE_KEYWORD
-			{ $$ = QUAL_VOLATILE; }
+			{ $$ = cp_name_parser::QUAL_VOLATILE; }
 		|	CONST_KEYWORD
-			{ $$ = QUAL_CONST; }
+			{ $$ = cp_name_parser::QUAL_CONST; }
 		;
 
 qualifiers	:	qualifier
-- 
2.55.0


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

* [PATCH 2/7] gdb: convert INT_* macros into an enum_flags
  2026-10-01 20:29 [PATCH 0/7] Leftovers from parsers cleanup Simon Marchi
  2026-10-01 20:29 ` [PATCH 1/7] gdb: convert QUAL_* macros into an enum_flags Simon Marchi
@ 2026-10-01 20:30 ` Simon Marchi
  2026-10-01 20:30 ` [PATCH 3/7] gdb: convert d_left and d_right macros into functions Simon Marchi
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2026-10-01 20:30 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Same as the previous patch, but for the INT_* macros passed to
cpname_state::d_int_type.  Add an INT_NONE enumerator, since a raw enum
value can't be assigned 0:

      CXX    cp-name-parser-gen.o
    gdb/cp-name-parser.y: In function ‘int cpname_yyparse(cp_name_parser::cpname_state*)’:
    gdb/cp-name-parser.y:544:67: error: invalid conversion from ‘int’ to ‘cp_name_parser::int_flag’ [-fpermissive]
      544 |                         { $$ = 0; }
          |                                                                   ^
          |                                                                   |
          |                                                                   int

Change-Id: Ia4e8b576adfd5b3baa3fb4c4beda2517d1d87449
---
 gdb/cp-name-parser.c |  4 ++--
 gdb/cp-name-parser.h | 27 ++++++++++++++++-----------
 gdb/cp-name-parser.y | 19 +++++++++++--------
 3 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/gdb/cp-name-parser.c b/gdb/cp-name-parser.c
index 569d102213c8..6615efd6abb1 100644
--- a/gdb/cp-name-parser.c
+++ b/gdb/cp-name-parser.c
@@ -147,7 +147,7 @@ cpname_state::d_qualify (struct demangle_component *lhs,
 /* Return a builtin type corresponding to FLAGS.  */
 
 struct demangle_component *
-cpname_state::d_int_type (int flags)
+cpname_state::d_int_type (int_flags flags)
 {
   const char *name;
 
@@ -162,7 +162,7 @@ cpname_state::d_int_type (int flags)
     case INT_UNSIGNED | INT_CHAR:
       name = "unsigned char";
       break;
-    case 0:
+    case INT_NONE:
     case INT_SIGNED:
       name = "int";
       break;
diff --git a/gdb/cp-name-parser.h b/gdb/cp-name-parser.h
index 7585379f5be2..083631f20a67 100644
--- a/gdb/cp-name-parser.h
+++ b/gdb/cp-name-parser.h
@@ -26,16 +26,6 @@
 union cp_name_parser_YYSTYPE;
 struct demangle_parse_info;
 
-/* Flags passed to cpname_state::d_int_type.  */
-
-#define INT_CHAR	(1 << 0)
-#define INT_SHORT	(1 << 1)
-#define INT_LONG	(1 << 2)
-#define INT_LLONG	(1 << 3)
-
-#define INT_SIGNED	(1 << 4)
-#define INT_UNSIGNED	(1 << 5)
-
 #define d_left(dc) (dc)->u.s_binary.left
 #define d_right(dc) (dc)->u.s_binary.right
 
@@ -53,6 +43,21 @@ enum qual_flag
 
 DEF_ENUM_FLAGS_TYPE (enum qual_flag, qual_flags);
 
+/* Integer type specifiers, passed to cpname_state::d_int_type.  */
+
+enum int_flag
+{
+  INT_NONE = 0,
+  INT_CHAR = 1 << 0,
+  INT_SHORT = 1 << 1,
+  INT_LONG = 1 << 2,
+  INT_LLONG = 1 << 3,
+  INT_SIGNED = 1 << 4,
+  INT_UNSIGNED = 1 << 5,
+};
+
+DEF_ENUM_FLAGS_TYPE (enum int_flag, int_flags);
+
 /* State of an ongoing parse.  */
 
 struct cpname_state
@@ -109,7 +114,7 @@ struct cpname_state
   struct demangle_component *d_qualify (struct demangle_component *lhs,
 					qual_flags qualifiers, int is_method);
 
-  struct demangle_component *d_int_type (int flags);
+  struct demangle_component *d_int_type (int_flags flags);
 
   struct demangle_component *d_unary (const char *name,
 				      struct demangle_component *lhs);
diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y
index b41ca6b30a20..4b4be60f4fba 100644
--- a/gdb/cp-name-parser.y
+++ b/gdb/cp-name-parser.y
@@ -61,6 +61,7 @@
     } abstract;
     int lval;
     cp_name_parser::qual_flag qual;
+    cp_name_parser::int_flag int_type;
     const char *opname;
   }
 
@@ -87,7 +88,7 @@
 
 %type <qual> qualifier qualifiers qualifiers_opt
 
-%type <lval> int_part int_seq
+%type <int_type> int_part int_seq
 
 %token <comp> INT
 %token <comp> FLOAT
@@ -540,22 +541,24 @@ qualifiers	:	qualifier
    invalid output for them - an error would be better.  */
 
 int_part	:	INT_KEYWORD
-			{ $$ = 0; }
+			{ $$ = cp_name_parser::INT_NONE; }
 		|	SIGNED_KEYWORD
-			{ $$ = INT_SIGNED; }
+			{ $$ = cp_name_parser::INT_SIGNED; }
 		|	UNSIGNED
-			{ $$ = INT_UNSIGNED; }
+			{ $$ = cp_name_parser::INT_UNSIGNED; }
 		|	CHAR
-			{ $$ = INT_CHAR; }
+			{ $$ = cp_name_parser::INT_CHAR; }
 		|	LONG
-			{ $$ = INT_LONG; }
+			{ $$ = cp_name_parser::INT_LONG; }
 		|	SHORT
-			{ $$ = INT_SHORT; }
+			{ $$ = cp_name_parser::INT_SHORT; }
 		;
 
 int_seq		:	int_part
 		|	int_seq int_part
-			{ $$ = $1 | $2; if ($1 & $2 & INT_LONG) $$ = $1 | INT_LLONG; }
+			{ $$ = $1 | $2;
+			  if ($1 & $2 & cp_name_parser::INT_LONG)
+			    $$ = $1 | cp_name_parser::INT_LLONG; }
 		;
 
 builtin_type	:	int_seq
-- 
2.55.0


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

* [PATCH 3/7] gdb: convert d_left and d_right macros into functions
  2026-10-01 20:29 [PATCH 0/7] Leftovers from parsers cleanup Simon Marchi
  2026-10-01 20:29 ` [PATCH 1/7] gdb: convert QUAL_* macros into an enum_flags Simon Marchi
  2026-10-01 20:30 ` [PATCH 2/7] gdb: convert INT_* " Simon Marchi
@ 2026-10-01 20:30 ` Simon Marchi
  2026-10-01 20:30 ` [PATCH 4/7] gdb: replace cp-name-parser.c macros with lambdas Simon Marchi
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2026-10-01 20:30 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Replace the d_left and d_right macros with static inline functions.
They need to return a reference, because some callers assign to the
result:

  d_right ($1.last) = $2;

and some take the address:

  $$.last = &d_right ($$.comp);

Change-Id: I7d8bd71ffde82a0fdfd2e2dcb87461043f82ef4f
---
 gdb/cp-name-parser.h | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/gdb/cp-name-parser.h b/gdb/cp-name-parser.h
index 083631f20a67..f9d3a6968f9d 100644
--- a/gdb/cp-name-parser.h
+++ b/gdb/cp-name-parser.h
@@ -26,8 +26,21 @@
 union cp_name_parser_YYSTYPE;
 struct demangle_parse_info;
 
-#define d_left(dc) (dc)->u.s_binary.left
-#define d_right(dc) (dc)->u.s_binary.right
+/* Return a reference to the left child of binary component DC.  */
+
+static inline struct demangle_component *&
+d_left (struct demangle_component *dc)
+{
+  return dc->u.s_binary.left;
+}
+
+/* Return a reference to the right child of binary component DC.  */
+
+static inline struct demangle_component *&
+d_right (struct demangle_component *dc)
+{
+  return dc->u.s_binary.right;
+}
 
 namespace cp_name_parser {
 
-- 
2.55.0


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

* [PATCH 4/7] gdb: replace cp-name-parser.c macros with lambdas
  2026-10-01 20:29 [PATCH 0/7] Leftovers from parsers cleanup Simon Marchi
                   ` (2 preceding siblings ...)
  2026-10-01 20:30 ` [PATCH 3/7] gdb: convert d_left and d_right macros into functions Simon Marchi
@ 2026-10-01 20:30 ` Simon Marchi
  2026-10-01 20:30 ` [PATCH 5/7] gdb: use std::string for f-exp-parser.c's tempbuf Simon Marchi
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2026-10-01 20:30 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Replace the HANDLE_QUAL, HANDLE_SPECIAL, HANDLE_TOKEN2 and HANDLE_TOKEN3
macros with lambdas.

The lexer macros expanded to a return statement.  The lambdas instead
return whether they matched, and the call sites return the token:

  if (match_op_token ("-="))
    return ASSIGN_MODIFY;

HANDLE_TOKEN2 and HANDLE_TOKEN3 only differed in the number of
characters they compared, so they become a single match_op_token lambda
comparing the whole string.

Change-Id: I1319e2e8bb9650ee253e429912c596df26ccaf6c
---
 gdb/cp-name-parser.c | 202 +++++++++++++++++++++++++------------------
 1 file changed, 120 insertions(+), 82 deletions(-)

diff --git a/gdb/cp-name-parser.c b/gdb/cp-name-parser.c
index 6615efd6abb1..80779fbc6062 100644
--- a/gdb/cp-name-parser.c
+++ b/gdb/cp-name-parser.c
@@ -113,33 +113,34 @@ struct demangle_component *
 cpname_state::d_qualify (struct demangle_component *lhs,
 			 qual_flags qualifiers, int is_method)
 {
-  struct demangle_component **inner_p;
-  enum demangle_component_type type;
+  demangle_component **inner_p = &lhs;
+  demangle_component_type type = (*inner_p)->type;
+
+  auto handle_qual = [&] (demangle_component_type qual_type,
+			  demangle_component_type method_qual_type,
+			  qual_flag qual)
+    {
+      if ((qualifiers & qual) && type != qual_type && type != method_qual_type)
+	{
+	  *inner_p = fill_comp (is_method ? method_qual_type : qual_type,
+				*inner_p, nullptr);
+	  inner_p = &d_left (*inner_p);
+	  type = (*inner_p)->type;
+	}
+      else if (type == qual_type || type == method_qual_type)
+	{
+	  inner_p = &d_left (*inner_p);
+	  type = (*inner_p)->type;
+	}
+    };
 
   /* For now the order is CONST (innermost), VOLATILE, RESTRICT.  */
-
-#define HANDLE_QUAL(TYPE, MTYPE, QUAL)				\
-  if ((qualifiers & QUAL) && (type != TYPE) && (type != MTYPE))	\
-    {								\
-      *inner_p = fill_comp (is_method ? MTYPE : TYPE,		\
-			    *inner_p, NULL);			\
-      inner_p = &d_left (*inner_p);				\
-      type = (*inner_p)->type;					\
-    }								\
-  else if (type == TYPE || type == MTYPE)			\
-    {								\
-      inner_p = &d_left (*inner_p);				\
-      type = (*inner_p)->type;					\
-    }
-
-  inner_p = &lhs;
-
-  type = (*inner_p)->type;
-
-  HANDLE_QUAL (DEMANGLE_COMPONENT_RESTRICT, DEMANGLE_COMPONENT_RESTRICT_THIS, QUAL_RESTRICT);
-  HANDLE_QUAL (DEMANGLE_COMPONENT_VOLATILE, DEMANGLE_COMPONENT_VOLATILE_THIS, QUAL_VOLATILE);
-  HANDLE_QUAL (DEMANGLE_COMPONENT_CONST, DEMANGLE_COMPONENT_CONST_THIS, QUAL_CONST);
-#undef HANDLE_QUAL
+  handle_qual (DEMANGLE_COMPONENT_RESTRICT, DEMANGLE_COMPONENT_RESTRICT_THIS,
+	       QUAL_RESTRICT);
+  handle_qual (DEMANGLE_COMPONENT_VOLATILE, DEMANGLE_COMPONENT_VOLATILE_THIS,
+	       QUAL_VOLATILE);
+  handle_qual (DEMANGLE_COMPONENT_CONST, DEMANGLE_COMPONENT_CONST_THIS,
+	       QUAL_CONST);
 
   return lhs;
 }
@@ -546,30 +547,6 @@ cp_parse_escape (const char **string_ptr)
       }
 }
 
-#define HANDLE_SPECIAL(string, comp)				\
-  if (startswith (tokstart, string))				\
-    {								\
-      state->lexptr = tokstart + sizeof (string) - 1;			\
-      lvalp->lval = comp;					\
-      return DEMANGLER_SPECIAL;					\
-    }
-
-#define HANDLE_TOKEN2(string, token)			\
-  if (state->lexptr[1] == string[1])				\
-    {							\
-      state->lexptr += 2;					\
-      lvalp->opname = string;				\
-      return token;					\
-    }
-
-#define HANDLE_TOKEN3(string, token)			\
-  if (state->lexptr[1] == string[1] && state->lexptr[2] == string[2])	\
-    {							\
-      state->lexptr += 3;					\
-      lvalp->opname = string;				\
-      return token;					\
-    }
-
 void
 cpname_yyerror (cp_name_parser::cpname_state *state, const char *msg)
 {
@@ -591,6 +568,30 @@ cpname_yylex (cp_name_parser_YYSTYPE *lvalp,
   const char *tokstart;
   char *copy;
 
+  /* If the input starts with OP_STR, consume it, use OP_STR as the
+     token's operator name and return true.  Otherwise, return false.  */
+  auto match_op_token = [&] (const char *op_str)
+    {
+      if (!startswith (tokstart, op_str))
+	return false;
+
+      state->lexptr = tokstart + strlen (op_str);
+      lvalp->opname = op_str;
+      return true;
+    };
+
+  /* If the input starts with STR, consume it, use COMP as the token
+     value and return true.  Otherwise, return false.  */
+  auto match_special = [&] (const char *str, demangle_component_type comp)
+    {
+      if (!startswith (tokstart, str))
+	return false;
+
+      state->lexptr = tokstart + strlen (str);
+      lvalp->lval = comp;
+      return true;
+    };
+
  retry:
   state->prev_lexptr = state->lexptr;
   tokstart = state->lexptr;
@@ -667,9 +668,12 @@ cpname_yylex (cp_name_parser_YYSTYPE *lvalp,
       goto try_number;
 
     case '-':
-      HANDLE_TOKEN2 ("-=", ASSIGN_MODIFY);
-      HANDLE_TOKEN2 ("--", DECREMENT);
-      HANDLE_TOKEN2 ("->", ARROW);
+      if (match_op_token ("-="))
+	return ASSIGN_MODIFY;
+      if (match_op_token ("--"))
+	return DECREMENT;
+      if (match_op_token ("->"))
+	return ARROW;
 
       /* For construction vtables.  This is kind of hokey.  */
       if (startswith (tokstart, "-in-"))
@@ -771,59 +775,79 @@ cpname_yylex (cp_name_parser_YYSTYPE *lvalp,
       }
 
     case '+':
-      HANDLE_TOKEN2 ("+=", ASSIGN_MODIFY);
-      HANDLE_TOKEN2 ("++", INCREMENT);
+      if (match_op_token ("+="))
+	return ASSIGN_MODIFY;
+      if (match_op_token ("++"))
+	return INCREMENT;
       state->lexptr++;
       return c;
     case '*':
-      HANDLE_TOKEN2 ("*=", ASSIGN_MODIFY);
+      if (match_op_token ("*="))
+	return ASSIGN_MODIFY;
       state->lexptr++;
       return c;
     case '/':
-      HANDLE_TOKEN2 ("/=", ASSIGN_MODIFY);
+      if (match_op_token ("/="))
+	return ASSIGN_MODIFY;
       state->lexptr++;
       return c;
     case '%':
-      HANDLE_TOKEN2 ("%=", ASSIGN_MODIFY);
+      if (match_op_token ("%="))
+	return ASSIGN_MODIFY;
       state->lexptr++;
       return c;
     case '|':
-      HANDLE_TOKEN2 ("|=", ASSIGN_MODIFY);
-      HANDLE_TOKEN2 ("||", OROR);
+      if (match_op_token ("|="))
+	return ASSIGN_MODIFY;
+      if (match_op_token ("||"))
+	return OROR;
       state->lexptr++;
       return c;
     case '&':
-      HANDLE_TOKEN2 ("&=", ASSIGN_MODIFY);
-      HANDLE_TOKEN2 ("&&", ANDAND);
+      if (match_op_token ("&="))
+	return ASSIGN_MODIFY;
+      if (match_op_token ("&&"))
+	return ANDAND;
       state->lexptr++;
       return c;
     case '^':
-      HANDLE_TOKEN2 ("^=", ASSIGN_MODIFY);
+      if (match_op_token ("^="))
+	return ASSIGN_MODIFY;
       state->lexptr++;
       return c;
     case '!':
-      HANDLE_TOKEN2 ("!=", NOTEQUAL);
+      if (match_op_token ("!="))
+	return NOTEQUAL;
       state->lexptr++;
       return c;
     case '<':
-      HANDLE_TOKEN3 ("<<=", ASSIGN_MODIFY);
-      HANDLE_TOKEN3 ("<=>", SPACESHIP);
-      HANDLE_TOKEN2 ("<=", LEQ);
-      HANDLE_TOKEN2 ("<<", LSH);
+      if (match_op_token ("<<="))
+	return ASSIGN_MODIFY;
+      if (match_op_token ("<=>"))
+	return SPACESHIP;
+      if (match_op_token ("<="))
+	return LEQ;
+      if (match_op_token ("<<"))
+	return LSH;
       state->lexptr++;
       return c;
     case '>':
-      HANDLE_TOKEN3 (">>=", ASSIGN_MODIFY);
-      HANDLE_TOKEN2 (">=", GEQ);
-      HANDLE_TOKEN2 (">>", RSH);
+      if (match_op_token (">>="))
+	return ASSIGN_MODIFY;
+      if (match_op_token (">="))
+	return GEQ;
+      if (match_op_token (">>"))
+	return RSH;
       state->lexptr++;
       return c;
     case '=':
-      HANDLE_TOKEN2 ("==", EQUAL);
+      if (match_op_token ("=="))
+	return EQUAL;
       state->lexptr++;
       return c;
     case ':':
-      HANDLE_TOKEN2 ("::", COLONCOLON);
+      if (match_op_token ("::"))
+	return COLONCOLON;
       state->lexptr++;
       return c;
 
@@ -882,13 +906,21 @@ cpname_yylex (cp_name_parser_YYSTYPE *lvalp,
 	return STATIC_CAST;
       break;
     case 9:
-      HANDLE_SPECIAL ("covariant return thunk to ", DEMANGLE_COMPONENT_COVARIANT_THUNK);
-      HANDLE_SPECIAL ("reference temporary for ", DEMANGLE_COMPONENT_REFTEMP);
+      if (match_special ("covariant return thunk to ",
+			 DEMANGLE_COMPONENT_COVARIANT_THUNK))
+	return DEMANGLER_SPECIAL;
+      if (match_special ("reference temporary for ",
+			 DEMANGLE_COMPONENT_REFTEMP))
+	return DEMANGLER_SPECIAL;
       break;
     case 8:
-      HANDLE_SPECIAL ("typeinfo for ", DEMANGLE_COMPONENT_TYPEINFO);
-      HANDLE_SPECIAL ("typeinfo fn for ", DEMANGLE_COMPONENT_TYPEINFO_FN);
-      HANDLE_SPECIAL ("typeinfo name for ", DEMANGLE_COMPONENT_TYPEINFO_NAME);
+      if (match_special ("typeinfo for ", DEMANGLE_COMPONENT_TYPEINFO))
+	return DEMANGLER_SPECIAL;
+      if (match_special ("typeinfo fn for ", DEMANGLE_COMPONENT_TYPEINFO_FN))
+	return DEMANGLER_SPECIAL;
+      if (match_special ("typeinfo name for ",
+			 DEMANGLE_COMPONENT_TYPEINFO_NAME))
+	return DEMANGLER_SPECIAL;
       if (startswith (tokstart, "operator"))
 	return OPERATOR;
       if (startswith (tokstart, "restrict"))
@@ -901,7 +933,9 @@ cpname_yylex (cp_name_parser_YYSTYPE *lvalp,
 	return VOLATILE_KEYWORD;
       break;
     case 7:
-      HANDLE_SPECIAL ("virtual thunk to ", DEMANGLE_COMPONENT_VIRTUAL_THUNK);
+      if (match_special ("virtual thunk to ",
+			 DEMANGLE_COMPONENT_VIRTUAL_THUNK))
+	return DEMANGLER_SPECIAL;
       if (startswith (tokstart, "wchar_t"))
 	return WCHAR_T;
       break;
@@ -929,7 +963,8 @@ cpname_yylex (cp_name_parser_YYSTYPE *lvalp,
 	  return DEMANGLER_SPECIAL;
 	}
 
-      HANDLE_SPECIAL ("vtable for ", DEMANGLE_COMPONENT_VTABLE);
+      if (match_special ("vtable for ", DEMANGLE_COMPONENT_VTABLE))
+	return DEMANGLER_SPECIAL;
       if (startswith (tokstart, "delete"))
 	return DELETE;
       if (startswith (tokstart, "struct"))
@@ -942,7 +977,8 @@ cpname_yylex (cp_name_parser_YYSTYPE *lvalp,
 	return DOUBLE_KEYWORD;
       break;
     case 5:
-      HANDLE_SPECIAL ("guard variable for ", DEMANGLE_COMPONENT_GUARD);
+      if (match_special ("guard variable for ", DEMANGLE_COMPONENT_GUARD))
+	return DEMANGLER_SPECIAL;
       if (startswith (tokstart, "false"))
 	return FALSEKEYWORD;
       if (startswith (tokstart, "class"))
@@ -971,8 +1007,10 @@ cpname_yylex (cp_name_parser_YYSTYPE *lvalp,
 	return TRUEKEYWORD;
       break;
     case 3:
-      HANDLE_SPECIAL ("VTT for ", DEMANGLE_COMPONENT_VTT);
-      HANDLE_SPECIAL ("non-virtual thunk to ", DEMANGLE_COMPONENT_THUNK);
+      if (match_special ("VTT for ", DEMANGLE_COMPONENT_VTT))
+	return DEMANGLER_SPECIAL;
+      if (match_special ("non-virtual thunk to ", DEMANGLE_COMPONENT_THUNK))
+	return DEMANGLER_SPECIAL;
       if (startswith (tokstart, "new"))
 	return NEW;
       if (startswith (tokstart, "int"))
-- 
2.55.0


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

* [PATCH 5/7] gdb: use std::string for f-exp-parser.c's tempbuf
  2026-10-01 20:29 [PATCH 0/7] Leftovers from parsers cleanup Simon Marchi
                   ` (3 preceding siblings ...)
  2026-10-01 20:30 ` [PATCH 4/7] gdb: replace cp-name-parser.c macros with lambdas Simon Marchi
@ 2026-10-01 20:30 ` Simon Marchi
  2026-10-01 20:30 ` [PATCH 6/7] gdb: remove qsort kludge from ada-exp-parser.y Simon Marchi
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2026-10-01 20:30 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Replace the tempbuf / tempbufsize / tempbufindex trio, the
GROWBY_MIN_SIZE and CHECKBUF macros and the growbuf_by_size function
with a single std::string.  match_string_literal is the only user of
that buffer.  std::string null-terminates, so the explicit terminator
write goes away.

Change-Id: Ia978b6340d59e99b5c8f4dd0ea904471c66f37f6
---
 gdb/f-exp-parser.c | 55 +++++++++++-----------------------------------
 1 file changed, 13 insertions(+), 42 deletions(-)

diff --git a/gdb/f-exp-parser.c b/gdb/f-exp-parser.c
index 9e0c7aa6650c..010561d83ba5 100644
--- a/gdb/f-exp-parser.c
+++ b/gdb/f-exp-parser.c
@@ -25,7 +25,7 @@
 #include "language.h"
 #include "parser-defs.h"
 #include "value.h"
-#include <algorithm>
+#include <string>
 
 /* The entry point of the bison/yacc-generated parser, defined in
    f-exp-parser-gen.c.  Bison produces a declaration for f_yyparse in
@@ -574,40 +574,6 @@ static const f_token f_keywords[] =
   { "precision", PRECISION, OP_NULL, true },
 };
 
-/* Implementation of a dynamically expandable buffer for processing input
-   characters acquired through lexptr and building a value to return in
-   yylval.  Ripped off from ch-exp.y */
-
-static char *tempbuf;		/* Current buffer contents */
-static int tempbufsize;		/* Size of allocated buffer */
-static int tempbufindex;	/* Current index into buffer */
-
-#define GROWBY_MIN_SIZE 64	/* Minimum amount to grow buffer by */
-
-#define CHECKBUF(size) \
-  do { \
-    if (tempbufindex + (size) >= tempbufsize) \
-      { \
-	growbuf_by_size (size); \
-      } \
-  } while (0);
-
-/* Grow the static temp buffer if necessary, including allocating the
-   first one on demand.  */
-
-static void
-growbuf_by_size (int count)
-{
-  int growby;
-
-  growby = std::max (count, GROWBY_MIN_SIZE);
-  tempbufsize += growby;
-  if (tempbuf == NULL)
-    tempbuf = (char *) xmalloc (tempbufsize);
-  else
-    tempbuf = (char *) xrealloc (tempbuf, tempbufsize);
-}
-
 /* Blatantly ripped off from ch-exp.y. This routine recognizes F77
    string-literals.
 
@@ -622,9 +588,13 @@ match_string_literal (void)
 {
   const char *tokptr = pstate->lexptr;
 
-  for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
+  /* Buffer used to build and hold the string value returned in f_yylval.  Its
+     contents are only valid until the next call.  */
+  static std::string tempbuf;
+
+  tempbuf.clear ();
+  for (tokptr++; *tokptr != '\0'; tokptr++)
     {
-      CHECKBUF (1);
       if (*tokptr == *pstate->lexptr)
 	{
 	  if (*(tokptr + 1) == *pstate->lexptr)
@@ -632,16 +602,17 @@ match_string_literal (void)
 	  else
 	    break;
 	}
-      tempbuf[tempbufindex++] = *tokptr;
+
+      tempbuf += *tokptr;
     }
+
   if (*tokptr == '\0'					/* no terminator */
-      || tempbufindex == 0)				/* no string */
+      || tempbuf.empty ())				/* no string */
     return 0;
   else
     {
-      tempbuf[tempbufindex] = '\0';
-      f_yylval.sval.ptr = tempbuf;
-      f_yylval.sval.length = tempbufindex;
+      f_yylval.sval.ptr = tempbuf.c_str ();
+      f_yylval.sval.length = tempbuf.size ();
       pstate->lexptr = ++tokptr;
       return STRING_LITERAL;
     }
-- 
2.55.0


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

* [PATCH 6/7] gdb: remove qsort kludge from ada-exp-parser.y
  2026-10-01 20:29 [PATCH 0/7] Leftovers from parsers cleanup Simon Marchi
                   ` (4 preceding siblings ...)
  2026-10-01 20:30 ` [PATCH 5/7] gdb: use std::string for f-exp-parser.c's tempbuf Simon Marchi
@ 2026-10-01 20:30 ` Simon Marchi
  2026-10-01 20:30 ` [PATCH 7/7] gdb: make COMPLETE_CHAR a constexpr Simon Marchi
  2026-10-14 12:54 ` [PATCH 0/7] Leftovers from parsers cleanup Tom Tromey
  7 siblings, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2026-10-01 20:30 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Remove the "#define qsort __qsort__dummy" kludge, which was there to
avoid a conflict between defs.h and non-standard stdlib.h files.  This
was introduced in 2002, I am pretty sure this is not needed anymore.

Change-Id: I22d42f13ad4bdd6fc118ac4e1f30abdb79beb659
---
 gdb/ada-exp-parser.y | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/gdb/ada-exp-parser.y b/gdb/ada-exp-parser.y
index b5b925e8911e..d37ab12c3bcf 100644
--- a/gdb/ada-exp-parser.y
+++ b/gdb/ada-exp-parser.y
@@ -838,7 +838,4 @@ primary	:	'*' primary		%prec '.'
 /* yylex defined in ada-lex-gen.c: Reads one token, getting characters */
 /* through lexptr.  */
 
-/* The following kludge was found necessary to prevent conflicts between */
-/* defs.h and non-standard stdlib.h files.  */
-#define qsort __qsort__dummy
 #include "ada-lex-gen.c"
-- 
2.55.0


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

* [PATCH 7/7] gdb: make COMPLETE_CHAR a constexpr
  2026-10-01 20:29 [PATCH 0/7] Leftovers from parsers cleanup Simon Marchi
                   ` (5 preceding siblings ...)
  2026-10-01 20:30 ` [PATCH 6/7] gdb: remove qsort kludge from ada-exp-parser.y Simon Marchi
@ 2026-10-01 20:30 ` Simon Marchi
  2026-10-14 12:54 ` [PATCH 0/7] Leftovers from parsers cleanup Tom Tromey
  7 siblings, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2026-10-01 20:30 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

In ada-exp-parser.h, make COMPLETE_CHAR a constexpr rather than a
macro.

While at it, fix the comment in ada-lex.l that refers to it.  It used
the wrong name (COMPLETION_CHAR), and the constant is no longer
"below", it is now in ada-exp-parser.h.  The explanation it points to
is now the comment on ada_parse_state::returned_complete.

Change-Id: I4ecfec782add66ab658bcb1494b1f78cdd432218
---
 gdb/ada-exp-parser.h | 2 +-
 gdb/ada-lex.l        | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/gdb/ada-exp-parser.h b/gdb/ada-exp-parser.h
index 0f438647437e..09a716e6636c 100644
--- a/gdb/ada-exp-parser.h
+++ b/gdb/ada-exp-parser.h
@@ -24,7 +24,7 @@
 #include "parser-defs.h"
 
 /* The character we use to represent the completion point.  */
-#define COMPLETE_CHAR '\001'
+constexpr char COMPLETE_CHAR = '\001';
 
 namespace ada_exp_parser
 {
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 62edcd251966..857176c4d83d 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -39,8 +39,8 @@ OPER    ([-+*/=<>&]|"<="|">="|"**"|"/="|"and"|"or"|"xor"|"not"|"mod"|"rem"|"abs"
 EXP	(e[+-]{NUM10})
 POSEXP  (e"+"?{NUM10})
 
-/* This must agree with COMPLETION_CHAR below.  See the comment there
-   for the explanation.  */
+/* This must agree with COMPLETE_CHAR in ada-exp-parser.h.  See the
+   comment on ada_parse_state::returned_complete for the explanation.  */
 COMPLETE "\001"
 NOT_COMPLETE [^\001]
 
-- 
2.55.0


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

* Re: [PATCH 0/7] Leftovers from parsers cleanup
  2026-10-01 20:29 [PATCH 0/7] Leftovers from parsers cleanup Simon Marchi
                   ` (6 preceding siblings ...)
  2026-10-01 20:30 ` [PATCH 7/7] gdb: make COMPLETE_CHAR a constexpr Simon Marchi
@ 2026-10-14 12:54 ` Tom Tromey
  2026-10-14 13:13   ` Simon Marchi
  7 siblings, 1 reply; 10+ messages in thread
From: Tom Tromey @ 2026-10-14 12:54 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

>>>>> "Simon" == Simon Marchi <simon.marchi@efficios.com> writes:

Simon> Here are a few random patches that I wrote when doing the parser cleanup
Simon> I just merged.  I initially left them out because they were not
Simon> essential and the series was already long enough.

Thanks, this looks good.
Approved-By: Tom Tromey <tom@tromey.com>

Tom

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

* Re: [PATCH 0/7] Leftovers from parsers cleanup
  2026-10-14 12:54 ` [PATCH 0/7] Leftovers from parsers cleanup Tom Tromey
@ 2026-10-14 13:13   ` Simon Marchi
  0 siblings, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2026-10-14 13:13 UTC (permalink / raw)
  To: Tom Tromey, Simon Marchi; +Cc: gdb-patches

On 10/14/26 8:54 AM, Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simon.marchi@efficios.com> writes:
> 
> Simon> Here are a few random patches that I wrote when doing the parser cleanup
> Simon> I just merged.  I initially left them out because they were not
> Simon> essential and the series was already long enough.
> 
> Thanks, this looks good.
> Approved-By: Tom Tromey <tom@tromey.com>
> 
> Tom

Thanks, pushed.

Simon

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

end of thread, other threads:[~2026-10-14 13:14 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-01 20:29 [PATCH 0/7] Leftovers from parsers cleanup Simon Marchi
2026-10-01 20:29 ` [PATCH 1/7] gdb: convert QUAL_* macros into an enum_flags Simon Marchi
2026-10-01 20:30 ` [PATCH 2/7] gdb: convert INT_* " Simon Marchi
2026-10-01 20:30 ` [PATCH 3/7] gdb: convert d_left and d_right macros into functions Simon Marchi
2026-10-01 20:30 ` [PATCH 4/7] gdb: replace cp-name-parser.c macros with lambdas Simon Marchi
2026-10-01 20:30 ` [PATCH 5/7] gdb: use std::string for f-exp-parser.c's tempbuf Simon Marchi
2026-10-01 20:30 ` [PATCH 6/7] gdb: remove qsort kludge from ada-exp-parser.y Simon Marchi
2026-10-01 20:30 ` [PATCH 7/7] gdb: make COMPLETE_CHAR a constexpr Simon Marchi
2026-10-14 12:54 ` [PATCH 0/7] Leftovers from parsers cleanup Tom Tromey
2026-10-14 13:13   ` Simon Marchi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox