From: Simon Marchi <simon.marchi@efficios.com>
To: gdb-patches@sourceware.org
Cc: Simon Marchi <simon.marchi@polymtl.ca>
Subject: [PATCH 07/13] gdb: extract lex_char_literal from cpname_yylex
Date: Tue, 20 Oct 2026 12:17:29 -0400 [thread overview]
Message-ID: <20261020162054.2140671-8-simon.marchi@efficios.com> (raw)
In-Reply-To: <20261020162054.2140671-1-simon.marchi@efficios.com>
From: Simon Marchi <simon.marchi@polymtl.ca>
Move the code lexing character constants in the C++ name parser to its own
function, lex_char_literal. This makes the code easier to read, but also a
later patch will call it from another place.
The comment mentioned that a quote could also start a quoted symbol
reference, like 'foo(int,int)', but this code doesn't seem handle that, it
really just handles character constants, so drop that part of the comment.
While at it, add selftests for the error paths of this function ("empty
character constant" and "invalid character constant"). Add a new
should_not_parse helper for that.
Change-Id: I6413606d03d8291f29117decf1c34000323e4533
---
gdb/cp-name-parser.c | 87 ++++++++++++++++++++++++++++----------------
1 file changed, 56 insertions(+), 31 deletions(-)
diff --git a/gdb/cp-name-parser.c b/gdb/cp-name-parser.c
index 8012d6cc0a20..d7ecb534b718 100644
--- a/gdb/cp-name-parser.c
+++ b/gdb/cp-name-parser.c
@@ -554,6 +554,45 @@ cpname_yyerror (cp_name_parser::cpname_state *state, const char *msg)
state->global_errmsg = msg ? msg : "parse error";
}
+/* Lex a character constant ('0' or '\177' for example), starting at the
+ opening quote at STATE->LEXPTR. Store the result in LVALP and return
+ INT, or ERROR on error. */
+
+static int
+lex_char_literal (cp_name_parser_YYSTYPE *lvalp,
+ cp_name_parser::cpname_state *state)
+{
+ /* Skip opening quote. */
+ state->lexptr++;
+
+ int c = *state->lexptr++;
+ if (c == '\\')
+ c = cp_parse_escape (&state->lexptr);
+ else if (c == '\'')
+ {
+ cpname_yyerror (state, _("empty character constant"));
+ return ERROR;
+ }
+
+ /* We over-allocate here, but it doesn't really matter. */
+ char *copy = (char *) obstack_alloc (&state->demangle_info->obstack, 30);
+ xsnprintf (copy, 30, "%d", c);
+
+ c = *state->lexptr++;
+ if (c != '\'')
+ {
+ cpname_yyerror (state, _("invalid character constant"));
+ return ERROR;
+ }
+
+ lvalp->comp
+ = state->fill_comp (DEMANGLE_COMPONENT_LITERAL,
+ state->make_builtin_type ("char"),
+ state->make_name (copy, strlen (copy)));
+
+ return INT;
+}
+
/* Read one token, getting characters through LEXPTR. */
int
@@ -563,7 +602,6 @@ cpname_yylex (cp_name_parser_YYSTYPE *lvalp,
int c;
int namelen;
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. */
@@ -605,36 +643,7 @@ cpname_yylex (cp_name_parser_YYSTYPE *lvalp,
goto retry;
case '\'':
- /* We either have a character constant ('0' or '\177' for example)
- or we have a quoted symbol reference ('foo(int,int)' in C++
- for example). */
- state->lexptr++;
- c = *state->lexptr++;
- if (c == '\\')
- c = cp_parse_escape (&state->lexptr);
- else if (c == '\'')
- {
- cpname_yyerror (state, _("empty character constant"));
- return ERROR;
- }
-
- /* We over-allocate here, but it doesn't really matter . */
- copy = (char *) obstack_alloc (&state->demangle_info->obstack, 30);
- xsnprintf (copy, 30, "%d", c);
-
- c = *state->lexptr++;
- if (c != '\'')
- {
- cpname_yyerror (state, _("invalid character constant"));
- return ERROR;
- }
-
- lvalp->comp
- = state->fill_comp (DEMANGLE_COMPONENT_LITERAL,
- state->make_builtin_type ("char"),
- state->make_name (copy, strlen (copy)));
-
- return INT;
+ return lex_char_literal (lvalp, state);
case '(':
if (startswith (tokstart, "(anonymous namespace)"))
@@ -1038,6 +1047,8 @@ should_canonicalize_to (const char *name, const char *expected)
SELF_CHECK (streq (result, expected));
}
+/* Check that parsing NAME succeeds. */
+
static void
should_parse (const char *name)
{
@@ -1045,6 +1056,17 @@ should_parse (const char *name)
SELF_CHECK (parsed != nullptr);
}
+/* Check that parsing NAME fails with error message EXPECTED_ERRMSG. */
+
+static void
+should_not_parse (const char *name, const char *expected_errmsg)
+{
+ std::string errmsg;
+ auto parsed = cp_demangled_name_to_comp (name, &errmsg);
+ SELF_CHECK (parsed == nullptr);
+ SELF_CHECK (errmsg == expected_errmsg);
+}
+
static void
canonicalize_tests ()
{
@@ -1084,6 +1106,9 @@ static void
parser_tests ()
{
should_parse ("void whatever::operator<=><int, int>");
+
+ should_not_parse ("C<''>", "empty character constant");
+ should_not_parse ("C<'ab'>", "invalid character constant");
}
#endif
--
2.56.0
next prev parent reply other threads:[~2026-10-20 16:22 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 16:17 [PATCH 00/13] Make the C++ name parser recognize more char literal forms Simon Marchi
2026-10-20 16:17 ` [PATCH 01/13] gdb: make demangle_parse_info own the memory its tree points into Simon Marchi
2026-10-20 16:17 ` [PATCH 02/13] gdb: remove p_allocated_size parameter of gdb_cplus_demangle_print Simon Marchi
2026-10-20 16:17 ` [PATCH 03/13] gdb: modernize mangled_name_to_comp and cp_class_name_from_physname Simon Marchi
2026-10-20 16:17 ` [PATCH 04/13] gdb: fix crash in "maint canonicalize" without argument Simon Marchi
2026-10-20 16:17 ` [PATCH 05/13] gdb: move C++ name parser parsing selftest to its own test Simon Marchi
2026-10-20 16:17 ` [PATCH 06/13] gdb: check exact results in the canonicalize selftest Simon Marchi
2026-10-21 15:21 ` Tom Tromey
2026-10-21 15:48 ` Simon Marchi
2026-10-21 16:56 ` Tom Tromey
2026-10-21 17:01 ` Simon Marchi
2026-10-21 17:48 ` Tom Tromey
2026-10-22 16:28 ` Simon Marchi
2026-10-20 16:17 ` Simon Marchi [this message]
2026-10-21 15:22 ` [PATCH 07/13] gdb: extract lex_char_literal from cpname_yylex Tom Tromey
2026-10-20 16:17 ` [PATCH 08/13] gdb: remove \^ escape sequence support from C++ name parser Simon Marchi
2026-10-20 16:17 ` [PATCH 09/13] gdb: remove backslash-newline handling from cp_parse_escape Simon Marchi
2026-10-20 16:17 ` [PATCH 10/13] gdb: fix out-of-bounds reads in lex_char_literal Simon Marchi
2026-10-20 16:17 ` [PATCH 11/13] gdb: handle hexadecimal escapes in C++ name parser Simon Marchi
2026-10-20 16:17 ` [PATCH 12/13] gdb: handle character literal encoding prefixes " Simon Marchi
2026-10-20 16:17 ` [PATCH 13/13] gdb: handle universal character names " Simon Marchi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261020162054.2140671-8-simon.marchi@efficios.com \
--to=simon.marchi@efficios.com \
--cc=gdb-patches@sourceware.org \
--cc=simon.marchi@polymtl.ca \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox