diff options
Diffstat (limited to 'gdb/cp-support.c')
-rw-r--r-- | gdb/cp-support.c | 146 |
1 files changed, 117 insertions, 29 deletions
diff --git a/gdb/cp-support.c b/gdb/cp-support.c index bd714ad..cab7110 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -1,5 +1,5 @@ /* Helper routines for C++ support in GDB. - Copyright (C) 2002-2024 Free Software Foundation, Inc. + Copyright (C) 2002-2025 Free Software Foundation, Inc. Contributed by MontaVista Software. @@ -573,6 +573,17 @@ replace_typedefs (struct demangle_parse_info *info, } } +/* A helper to strip a trailing "()" from PTR. The string is modified + in place. */ + +static void +maybe_strip_parens (char *ptr) +{ + size_t len = strlen (ptr); + if (len > 2 && ptr[len - 2] == '(' && ptr[len - 1] == ')') + ptr[len - 2] = '\0'; +} + /* Parse STRING and convert it to canonical form, resolving any typedefs. If parsing fails, or if STRING is already canonical, return nullptr. Otherwise return the canonical form. If @@ -599,6 +610,9 @@ cp_canonicalize_string_full (const char *string, estimated_len); gdb_assert (us); + if (info->added_parens) + maybe_strip_parens (us.get ()); + /* Finally, compare the original string with the computed name, returning NULL if they are the same. */ if (strcmp (us.get (), string) == 0) @@ -647,6 +661,9 @@ cp_canonicalize_string (const char *string) return nullptr; } + if (info->added_parens) + maybe_strip_parens (us.get ()); + if (strcmp (us.get (), string) == 0) return nullptr; @@ -1390,7 +1407,6 @@ add_symbol_overload_list_using (const char *func_name, const char *the_namespace, std::vector<symbol *> *overload_list) { - struct using_direct *current; const struct block *block; /* First, go through the using directives. If any of them apply, @@ -1400,9 +1416,7 @@ add_symbol_overload_list_using (const char *func_name, for (block = get_selected_block (0); block != NULL; block = block->superblock ()) - for (current = block->get_using (); - current != NULL; - current = current->next) + for (using_direct *current : block->get_using ()) { /* Prevent recursive calls. */ if (current->searched) @@ -1439,38 +1453,35 @@ static void add_symbol_overload_list_qualified (const char *func_name, std::vector<symbol *> *overload_list) { - const struct block *surrounding_static_block = 0; - - /* Look through the partial symtabs for all symbols which begin by - matching FUNC_NAME. Make sure we read that symbol table in. */ - - for (objfile *objf : current_program_space->objfiles ()) - objf->expand_symtabs_for_function (func_name); + const block *selected_block = get_selected_block (0); /* Search upwards from currently selected frame (so that we can complete on local vars. */ - for (const block *b = get_selected_block (0); - b != nullptr; - b = b->superblock ()) + for (const block *b = selected_block; b != nullptr; b = b->superblock ()) add_symbol_overload_list_block (func_name, b, overload_list); - surrounding_static_block = get_selected_block (0); - surrounding_static_block = (surrounding_static_block == nullptr - ? nullptr - : surrounding_static_block->static_block ()); + const block *surrounding_static_block = (selected_block == nullptr + ? nullptr + : selected_block->static_block ()); /* Go through the symtabs and check the externs and statics for symbols which match. */ - const block *block = get_selected_block (0); - struct objfile *current_objfile = block ? block->objfile () : nullptr; + struct objfile *current_objfile = (selected_block + ? selected_block->objfile () + : nullptr); gdbarch_iterate_over_objfiles_in_search_order (current_objfile ? current_objfile->arch () : current_inferior ()->arch (), [func_name, surrounding_static_block, &overload_list] (struct objfile *obj) { + /* Look through the partial symtabs for all symbols which + begin by matching FUNC_NAME. Make sure we read that + symbol table in. */ + obj->expand_symtabs_for_function (func_name); + for (compunit_symtab *cust : obj->compunits ()) { QUIT; @@ -1709,21 +1720,60 @@ cp_search_name_hash (const char *search_name) unsigned int hash = 0; for (const char *string = search_name; *string != '\0'; ++string) { + const char *before_skip = string; string = skip_spaces (string); if (*string == '(') break; + /* Could it be the beginning of a function name? + If yes, does it begin with the keyword "operator"? */ + if ((string != before_skip || string == search_name) + && (string[0] == 'o' && startswith (string, CP_OPERATOR_STR))) + { + /* Hash the "operator" part. */ + for (size_t i = 0; i < CP_OPERATOR_LEN; ++i) + hash = SYMBOL_HASH_NEXT (hash, *string++); + + string = skip_spaces (string); + + /* If no more data to process, stop right now. This is specially + intended for SEARCH_NAMEs that end with "operator". In such + cases, the whole string is processed and STRING is pointing to a + null-byte. Letting the loop body resume naturally would lead to + a "++string" that causes STRING to point past the null-byte. */ + if (string[0] == '\0') + break; + + /* "<" and "<<" are sequences of interest here. This covers + "operator{<,<<,<=,<=>}". In the last 2 cases, the "=" and "=>" + parts are handled by the next iterations of the loop like other + input chars. The goal is to process all the operator-related '<' + chars, so that later if a '<' is visited it can be inferred for + sure that it is the beginning of a template parameter list. + + STRING is a null-byte terminated string. If string[0] is not + a null-byte, according to the previous check, string[1] is not + past the end of the allocation and can be referenced safely. */ + if (string[0] == '<') + { + hash = SYMBOL_HASH_NEXT (hash, *string); + if (string[1] == '<') + hash = SYMBOL_HASH_NEXT (hash, *++string); + continue; + } + } + /* Ignore ABI tags such as "[abi:cxx11]. */ if (*string == '[' && startswith (string + 1, "abi:") && string[5] != ':') break; - /* Ignore template parameter lists. */ - if (string[0] == '<' - && string[1] != '(' && string[1] != '<' && string[1] != '=' - && string[1] != ' ' && string[1] != '\0') + /* Ignore template parameter lists. The likely "operator{<,<<,<=,<=>}" + are already taken care of. Therefore, any encounter of '<' character + at this point is related to template lists. */ + if (*string == '<') break; hash = SYMBOL_HASH_NEXT (hash, *string); @@ -1731,6 +1781,44 @@ cp_search_name_hash (const char *search_name) return hash; } +#if GDB_SELF_TEST + +namespace selftests { + +static void +test_cp_search_name_hash () +{ + SELF_CHECK (cp_search_name_hash ("void func<(enum_test)0>(int*, int)") + == cp_search_name_hash ("void func")); + SELF_CHECK (cp_search_name_hash ("operator") + != cp_search_name_hash ("operator<")); + SELF_CHECK (cp_search_name_hash ("operator") + != cp_search_name_hash ("operator<<")); + SELF_CHECK (cp_search_name_hash ("operator<") + != cp_search_name_hash ("operator<<")); + SELF_CHECK (cp_search_name_hash ("operator<") + == cp_search_name_hash ("operator <")); + SELF_CHECK (cp_search_name_hash ("operator") + != cp_search_name_hash ("foo_operator")); + SELF_CHECK (cp_search_name_hash ("operator") + != cp_search_name_hash ("operator_foo")); + SELF_CHECK (cp_search_name_hash ("operator<") + != cp_search_name_hash ("foo_operator")); + SELF_CHECK (cp_search_name_hash ("operator<") + != cp_search_name_hash ("operator_foo")); + SELF_CHECK (cp_search_name_hash ("operator<<") + != cp_search_name_hash ("foo_operator")); + SELF_CHECK (cp_search_name_hash ("operator<<") + != cp_search_name_hash ("operator_foo")); + + SELF_CHECK (cp_search_name_hash ("func") + == cp_search_name_hash ("func[abi:cxx11]")); +} + +} /* namespace selftests */ + +#endif /* GDB_SELF_TEST */ + /* Helper for cp_symbol_name_matches (i.e., symbol_name_matcher_ftype implementation for symbol_name_match_type::WILD matching). Split to a separate function for unit-testing convenience. @@ -2196,7 +2284,7 @@ test_cp_remove_params () #undef CHECK_INCOMPL } -} // namespace selftests +} /* namespace selftests */ #endif /* GDB_SELF_CHECK */ @@ -2299,9 +2387,7 @@ find_toplevel_char (const char *s, char c) return 0; } -void _initialize_cp_support (); -void -_initialize_cp_support () +INIT_GDB_FILE (cp_support) { cmd_list_element *maintenance_cplus = add_basic_prefix_cmd ("cplus", class_maintenance, @@ -2343,5 +2429,7 @@ display the offending symbol."), selftests::test_cp_symbol_name_matches); selftests::register_test ("cp_remove_params", selftests::test_cp_remove_params); + selftests::register_test ("cp_search_name_hash", + selftests::test_cp_search_name_hash); #endif } |