From caf77196512fd866663b216486c3ae317c20a2bf Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sun, 23 Feb 2025 15:34:40 -0700 Subject: [PATCH] Handle ">>" in cp-name-parser.y I noticed that a certain name didn't work correctly when trying to remove the parameters. I put this into lookup_name_info-selftests.c. I tracked this down to the fact that cp-name-parser.y doesn't handle ">>" to end templates. This patch fixes this in a simple way -- accepting the "RSH" token where appropriate and then un-pushing a ">". --- gdb/cp-name-parser.y | 21 +++++++++++++++++++++ gdb/unittests/lookup_name_info-selftests.c | 3 +++ 2 files changed, 24 insertions(+) diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y index 14ee6cfb9fc..6c36abea4b0 100644 --- a/gdb/cp-name-parser.y +++ b/gdb/cp-name-parser.y @@ -81,6 +81,14 @@ struct cpname_state demangle_info (info) { } + /* Un-push a character into the lexer. This can only un-push the + previous character in the input string. */ + void unpush (char c) + { + gdb_assert (lexptr[-1] == c); + --lexptr; + } + /* LEXPTR is the current pointer into our lex buffer. PREV_LEXPTR is the start of the last token lexed, only used for diagnostics. ERROR_LEXPTR is the first place an error occurred. GLOBAL_ERRMSG @@ -515,6 +523,11 @@ conversion_op_name unqualified_name: oper | oper '<' template_params '>' { $$ = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); } + | oper '<' template_params RSH + { + $$ = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); + state->unpush ('>'); + } | '~' NAME { $$ = state->make_dtor (gnu_v3_complete_object_dtor, $2); } ; @@ -580,6 +593,11 @@ nested_name : NAME COLONCOLON /* DEMANGLE_COMPONENT_TEMPLATE_ARGLIST */ templ : NAME '<' template_params '>' { $$ = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); } + | NAME '<' template_params RSH + { + $$ = state->fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); + state->unpush ('>'); + } ; template_params : template_arg @@ -2085,6 +2103,9 @@ canonicalize_tests () should_be_the_same ("something", "something"); should_parse ("void whatever::operator<=>"); + + should_be_the_same ("Foozle::fogey > (Empty)", + "Foozle::fogey> (Empty)"); } #endif diff --git a/gdb/unittests/lookup_name_info-selftests.c b/gdb/unittests/lookup_name_info-selftests.c index a6b50851cc9..fb4be2133cb 100644 --- a/gdb/unittests/lookup_name_info-selftests.c +++ b/gdb/unittests/lookup_name_info-selftests.c @@ -96,6 +96,9 @@ run_tests () CHECK (language_cplus, "A::B::C()", "A::B::C"); CHECK (language_cplus, "A::B::C", "A::B::C"); + CHECK (language_cplus, "Foozle::fogey> (Empty)", + "Foozle::fogey >"); + #undef CHECK #undef CHECK_INCOMPL } -- 2.39.5