From: Tom Tromey Date: Sun, 23 Feb 2025 22:34:40 +0000 (-0700) Subject: Handle ">>" in cp-name-parser.y X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=caf77196512fd866663b216486c3ae317c20a2bf;p=thirdparty%2Fbinutils-gdb.git 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 ">". --- 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 }