diff options
Diffstat (limited to 'gdb/cp-name-parser.y')
-rw-r--r-- | gdb/cp-name-parser.y | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y index 10f6e2d..7221b78 100644 --- a/gdb/cp-name-parser.y +++ b/gdb/cp-name-parser.y @@ -39,7 +39,6 @@ #include <unistd.h> -#include "gdbsupport/gdb-safe-ctype.h" #include "demangle.h" #include "cp-support.h" #include "c-support.h" @@ -374,6 +373,22 @@ function | colon_ext_only function_arglist start_opt { $$ = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp); if ($3) $$ = state->fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $3); } + | colon_ext_only + { + /* This production is a hack to handle + something like "name::operator new[]" -- + without arguments, this ordinarily would + not parse, but canonicalizing it is + important. So we infer the "()" and then + remove it when converting back to string. + Note that this works because this + production is terminal. */ + demangle_component *comp + = state->fill_comp (DEMANGLE_COMPONENT_FUNCTION_TYPE, + nullptr, nullptr); + $$ = state->fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, comp); + state->demangle_info->added_parens = true; + } | conversion_op_name start_opt { $$ = $1.comp; @@ -1346,7 +1361,7 @@ cpname_state::parse_number (const char *p, int len, int parsed_float, /* See if it has `f' or `l' suffix (float or long double). */ - c = TOLOWER (p[len - 1]); + c = c_tolower (p[len - 1]); if (c == 'f') { @@ -1358,7 +1373,7 @@ cpname_state::parse_number (const char *p, int len, int parsed_float, len--; type = make_builtin_type ("long double"); } - else if (ISDIGIT (c) || c == '.') + else if (c_isdigit (c) || c == '.') type = make_builtin_type ("double"); else return ERROR; @@ -1423,10 +1438,10 @@ cpname_state::parse_number (const char *p, int len, int parsed_float, for (int off = 0; off < len; ++off) { int dig; - if (ISDIGIT (p[off])) + if (c_isdigit (p[off])) dig = p[off] - '0'; else - dig = TOLOWER (p[off]) - 'a' + 10; + dig = c_tolower (p[off]) - 'a' + 10; if (dig >= base) return ERROR; value *= base; @@ -1753,7 +1768,7 @@ yylex (YYSTYPE *lvalp, cpname_state *state) } /* We will take any letters or digits. parse_number will complain if past the radix, or if L or U are not final. */ - else if (! ISALNUM (*p)) + else if (! c_isalnum (*p)) break; if (no_tick.has_value ()) no_tick->push_back (*p); @@ -2047,6 +2062,11 @@ cp_demangled_name_to_comp (const char *demangled_name, auto result = std::make_unique<demangle_parse_info> (); cpname_state state (demangled_name, result.get ()); + /* Note that we can't set yydebug here, as is done in the other + parsers. Bison implements yydebug as a global, even with a pure + parser, and this parser is run from worker threads. So, changing + yydebug causes TSan reports. If you need to debug this parser, + debug gdb and set the global from the outer gdb. */ if (yyparse (&state)) { if (state.global_errmsg && errmsg) @@ -2106,13 +2126,17 @@ canonicalize_tests () should_be_the_same ("Foozle<int>::fogey<Empty<int> > (Empty<int>)", "Foozle<int>::fogey<Empty<int>> (Empty<int>)"); + + should_be_the_same ("something :: operator new [ ]", + "something::operator new[]"); + should_be_the_same ("something :: operator new", + "something::operator new"); + should_be_the_same ("operator()", "operator ()"); } #endif -void _initialize_cp_name_parser (); -void -_initialize_cp_name_parser () +INIT_GDB_FILE (cp_name_parser) { #if GDB_SELF_TEST selftests::register_test ("canonicalize", canonicalize_tests); |