X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fcp-support.c;h=0300727434d93471ccc389b039331178eab8e307;hb=7570a17cbbe647db6260ae2391f92c0509de7924;hp=0e506f5b46e6e8f0ed88ace32380bd91fd603faa;hpb=696d6f4d5c1bc9b36d0402c2393efe62e49392d9;p=binutils-gdb.git diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 0e506f5b46e..0300727434d 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-2021 Free Software Foundation, Inc. + Copyright (C) 2002-2023 Free Software Foundation, Inc. Contributed by MontaVista Software. @@ -20,6 +20,7 @@ #include "defs.h" #include "cp-support.h" +#include "language.h" #include "demangle.h" #include "gdbcmd.h" #include "dictionary.h" @@ -35,12 +36,13 @@ #include "namespace.h" #include #include "gdbsupport/gdb_setjmp.h" -#include "safe-ctype.h" +#include "gdbsupport/gdb-safe-ctype.h" #include "gdbsupport/selftest.h" #include "gdbsupport/gdb-sigmask.h" #include #include "event-top.h" #include "run-on-main-thread.h" +#include "typeprint.h" #define d_left(dc) (dc)->u.s_binary.left #define d_right(dc) (dc)->u.s_binary.right @@ -70,18 +72,16 @@ static void add_symbol_overload_list_qualified struct cmd_list_element *maint_cplus_cmd_list = NULL; -/* A list of typedefs which should not be substituted by replace_typedefs. */ -static const char * const ignore_typedefs[] = - { - "std::istream", "std::iostream", "std::ostream", "std::string" - }; - static void replace_typedefs (struct demangle_parse_info *info, struct demangle_component *ret_comp, canonicalization_ftype *finder, void *data); +static struct demangle_component * + gdb_cplus_demangle_v3_components (const char *mangled, + int options, void **mem); + /* A convenience function to copy STRING into OBSTACK, returning a pointer to the newly allocated string and saving the number of bytes saved in LEN. @@ -146,13 +146,6 @@ inspect_type (struct demangle_parse_info *info, memcpy (name, ret_comp->u.s_name.s, ret_comp->u.s_name.len); name[ret_comp->u.s_name.len] = '\0'; - /* Ignore any typedefs that should not be substituted. */ - for (const char *ignorable : ignore_typedefs) - { - if (strcmp (name, ignorable) == 0) - return 0; - } - sym = NULL; try @@ -166,7 +159,7 @@ inspect_type (struct demangle_parse_info *info, if (sym != NULL) { - struct type *otype = SYMBOL_TYPE (sym); + struct type *otype = sym->type (); if (finder != NULL) { @@ -220,10 +213,10 @@ inspect_type (struct demangle_parse_info *info, struct type *last = otype; /* Find the last typedef for the type. */ - while (TYPE_TARGET_TYPE (last) != NULL - && (TYPE_TARGET_TYPE (last)->code () + while (last->target_type () != NULL + && (last->target_type ()->code () == TYPE_CODE_TYPEDEF)) - last = TYPE_TARGET_TYPE (last); + last = last->target_type (); /* If there is only one typedef for this anonymous type, do not substitute it. */ @@ -238,7 +231,14 @@ inspect_type (struct demangle_parse_info *info, string_file buf; try { - type_print (type, "", &buf, -1); + /* Avoid using the current language. If the language is + C, and TYPE is a struct/class, the printed type is + prefixed with "struct " or "class ", which we don't + want when we're expanding a C++ typedef. Print using + the type symbol's language to expand a C++ typedef + the C++ way even if the current language is C. */ + const language_defn *lang = language_def (sym->language ()); + lang->print_type (type, "", &buf, -1, 0, &type_print_raw_options); } /* If type_print threw an exception, there is little point in continuing, so just bow out gracefully. */ @@ -512,7 +512,7 @@ replace_typedefs (struct demangle_parse_info *info, if (sym != NULL) { - struct type *otype = SYMBOL_TYPE (sym); + struct type *otype = sym->type (); const char *new_name = (*finder) (otype, data); if (new_name != NULL) @@ -670,8 +670,8 @@ mangled_name_to_comp (const char *mangled_name, int options, { struct demangle_component *ret; - ret = cplus_demangle_v3_components (mangled_name, - options, memory); + ret = gdb_cplus_demangle_v3_components (mangled_name, + options, memory); if (ret) { std::unique_ptr info (new demangle_parse_info); @@ -1215,7 +1215,7 @@ overload_list_add_symbol (struct symbol *sym, { /* If there is no type information, we can't do anything, so skip. */ - if (SYMBOL_TYPE (sym) == NULL) + if (sym->type () == NULL) return; /* skip any symbols that we've already considered. */ @@ -1274,12 +1274,9 @@ add_symbol_overload_list_block (const char *name, const struct block *block, std::vector *overload_list) { - struct block_iterator iter; - struct symbol *sym; - lookup_name_info lookup_name (name, symbol_name_match_type::FULL); - ALL_BLOCK_SYMBOLS_WITH_NAME (block, lookup_name, iter, sym) + for (struct symbol *sym : block_iterator_range (block, &lookup_name)) overload_list_add_symbol (sym, name, overload_list); } @@ -1307,15 +1304,17 @@ add_symbol_overload_list_namespace (const char *func_name, } /* Look in the static block. */ - block = block_static_block (get_selected_block (0)); - if (block) - add_symbol_overload_list_block (name, block, overload_list); - - /* Look in the global block. */ - block = block_global_block (block); - if (block) - add_symbol_overload_list_block (name, block, overload_list); + block = get_selected_block (0); + block = block == nullptr ? nullptr : block->static_block (); + if (block != nullptr) + { + add_symbol_overload_list_block (name, block, overload_list); + /* Look in the global block. */ + block = block->global_block (); + if (block) + add_symbol_overload_list_block (name, block, overload_list); + } } /* Search the namespace of the given type and namespace of and public @@ -1337,7 +1336,7 @@ add_symbol_overload_list_adl_namespace (struct type *type, if (type->code () == TYPE_CODE_TYPEDEF) type = check_typedef (type); else - type = TYPE_TARGET_TYPE (type); + type = type->target_type (); } type_name = type->name (); @@ -1400,8 +1399,8 @@ add_symbol_overload_list_using (const char *func_name, for (block = get_selected_block (0); block != NULL; - block = BLOCK_SUPERBLOCK (block)) - for (current = block_using (block); + block = block->superblock ()) + for (current = block->get_using (); current != NULL; current = current->next) { @@ -1440,7 +1439,7 @@ static void add_symbol_overload_list_qualified (const char *func_name, std::vector *overload_list) { - const struct block *b, *surrounding_static_block = 0; + 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. */ @@ -1451,36 +1450,43 @@ add_symbol_overload_list_qualified (const char *func_name, /* Search upwards from currently selected frame (so that we can complete on local vars. */ - for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b)) + for (const block *b = get_selected_block (0); + b != nullptr; + b = b->superblock ()) add_symbol_overload_list_block (func_name, b, overload_list); - surrounding_static_block = block_static_block (get_selected_block (0)); + surrounding_static_block = get_selected_block (0); + surrounding_static_block = (surrounding_static_block == nullptr + ? nullptr + : surrounding_static_block->static_block ()); /* Go through the symtabs and check the externs and statics for symbols which match. */ - for (objfile *objfile : current_program_space->objfiles ()) - { - for (compunit_symtab *cust : objfile->compunits ()) - { - QUIT; - b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), GLOBAL_BLOCK); - add_symbol_overload_list_block (func_name, b, overload_list); - } - } - - for (objfile *objfile : current_program_space->objfiles ()) - { - for (compunit_symtab *cust : objfile->compunits ()) - { - QUIT; - b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), STATIC_BLOCK); - /* Don't do this block twice. */ - if (b == surrounding_static_block) - continue; - add_symbol_overload_list_block (func_name, b, overload_list); - } - } + const block *block = get_selected_block (0); + struct objfile *current_objfile = block ? block->objfile () : nullptr; + + gdbarch_iterate_over_objfiles_in_search_order + (current_objfile ? current_objfile->arch () : target_gdbarch (), + [func_name, surrounding_static_block, &overload_list] + (struct objfile *obj) + { + for (compunit_symtab *cust : obj->compunits ()) + { + QUIT; + const struct block *b = cust->blockvector ()->global_block (); + add_symbol_overload_list_block (func_name, b, overload_list); + + b = cust->blockvector ()->static_block (); + /* Don't do this block twice. */ + if (b == surrounding_static_block) + continue; + + add_symbol_overload_list_block (func_name, b, overload_list); + } + + return 0; + }, current_objfile); } /* Lookup the rtti type for a class name. */ @@ -1501,13 +1507,13 @@ cp_lookup_rtti_type (const char *name, const struct block *block) return NULL; } - if (SYMBOL_CLASS (rtti_sym) != LOC_TYPEDEF) + if (rtti_sym->aclass () != LOC_TYPEDEF) { warning (_("RTTI symbol for class '%s' is not a type"), name); return NULL; } - rtti_type = check_typedef (SYMBOL_TYPE (rtti_sym)); + rtti_type = check_typedef (rtti_sym->type ()); switch (rtti_type->code ()) { @@ -1583,9 +1589,9 @@ report_failed_demangle (const char *name, bool core_dump_allowed, begin_line (); if (core_dump_allowed) - fprintf_unfiltered (gdb_stderr, - _("%s\nAttempting to dump core.\n"), - long_msg.c_str ()); + gdb_printf (gdb_stderr, + _("%s\nAttempting to dump core.\n"), + long_msg.c_str ()); else warn_cant_dump_core (long_msg.c_str ()); @@ -1631,7 +1637,7 @@ gdb_demangle (const char *name, int options) #endif if (crash_signal == 0) - result.reset (bfd_demangle (NULL, name, options)); + result.reset (bfd_demangle (NULL, name, options | DMGL_VERBOSE)); #ifdef HAVE_WORKING_FORK if (catch_demangler_crashes) @@ -1650,7 +1656,13 @@ gdb_demangle (const char *name, int options) we might be in a background thread. Instead, arrange for the reporting to happen on the main thread. */ std::string copy = name; - run_on_main_thread ([=] () + run_on_main_thread ([ +#if __cplusplus >= 201402L + =, copy = std::move (copy) +#else + = +#endif + ] () { report_failed_demangle (copy.c_str (), core_dump_allowed, crash_signal); @@ -1666,6 +1678,28 @@ gdb_demangle (const char *name, int options) /* See cp-support.h. */ +char * +gdb_cplus_demangle_print (int options, + struct demangle_component *tree, + int estimated_length, + size_t *p_allocated_size) +{ + return cplus_demangle_print (options | DMGL_VERBOSE, tree, + estimated_length, p_allocated_size); +} + +/* A wrapper for cplus_demangle_v3_components that forces + DMGL_VERBOSE. */ + +static struct demangle_component * +gdb_cplus_demangle_v3_components (const char *mangled, + int options, void **mem) +{ + return cplus_demangle_v3_components (mangled, options | DMGL_VERBOSE, mem); +} + +/* See cp-support.h. */ + unsigned int cp_search_name_hash (const char *search_name) { @@ -1692,6 +1726,12 @@ cp_search_name_hash (const char *search_name) && string[5] != ':') break; + /* Ignore template parameter lists. */ + if (string[0] == '<' + && string[1] != '(' && string[1] != '<' && string[1] != '=' + && string[1] != ' ' && string[1] != '\0') + break; + hash = SYMBOL_HASH_NEXT (hash, *string); } return hash; @@ -1742,10 +1782,12 @@ cp_symbol_name_matches_1 (const char *symbol_search_name, completion_match_for_lcd *match_for_lcd = (comp_match_res != NULL ? &comp_match_res->match_for_lcd : NULL); + gdb_assert (match_for_lcd == nullptr || match_for_lcd->empty ()); + while (true) { if (strncmp_iw_with_mode (sname, lookup_name, lookup_name_len, - mode, language_cplus, match_for_lcd) == 0) + mode, language_cplus, match_for_lcd, true) == 0) { if (comp_match_res != NULL) { @@ -1775,6 +1817,11 @@ cp_symbol_name_matches_1 (const char *symbol_search_name, return true; } + /* Clear match_for_lcd so the next strncmp_iw_with_mode call starts + from scratch. */ + if (match_for_lcd != nullptr) + match_for_lcd->clear (); + unsigned int len = cp_find_first_component (sname); if (sname[len] == '\0') @@ -2062,7 +2109,7 @@ quote (const char *str) /* Check that removing parameter info out of NAME produces EXPECTED. COMPLETION_MODE indicates whether we're testing normal and completion mode. FILE and LINE are used to provide better test - location information in case ithe check fails. */ + location information in case the check fails. */ static void check_remove_params (const char *file, int line, @@ -2185,7 +2232,7 @@ first_component_command (const char *arg, int from_tty) memcpy (prefix, arg, len); prefix[len] = '\0'; - printf_unfiltered ("%s\n", prefix); + gdb_printf ("%s\n", prefix); } /* Implement "info vtbl". */ @@ -2199,6 +2246,80 @@ info_vtbl_command (const char *arg, int from_tty) cplus_print_vtable (value); } +/* See description in cp-support.h. */ + +const char * +find_toplevel_char (const char *s, char c) +{ + int quoted = 0; /* zero if we're not in quotes; + '"' if we're in a double-quoted string; + '\'' if we're in a single-quoted string. */ + int depth = 0; /* Number of unclosed parens we've seen. */ + const char *scan; + + for (scan = s; *scan; scan++) + { + if (quoted) + { + if (*scan == quoted) + quoted = 0; + else if (*scan == '\\' && *(scan + 1)) + scan++; + } + else if (*scan == c && ! quoted && depth == 0) + return scan; + else if (*scan == '"' || *scan == '\'') + quoted = *scan; + else if (*scan == '(' || *scan == '<') + depth++; + else if ((*scan == ')' || *scan == '>') && depth > 0) + depth--; + else if (*scan == 'o' && !quoted && depth == 0) + { + /* Handle C++ operator names. */ + if (strncmp (scan, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0) + { + scan += CP_OPERATOR_LEN; + if (*scan == c) + return scan; + while (ISSPACE (*scan)) + { + ++scan; + if (*scan == c) + return scan; + } + if (*scan == '\0') + break; + + switch (*scan) + { + /* Skip over one less than the appropriate number of + characters: the for loop will skip over the last + one. */ + case '<': + if (scan[1] == '<') + { + scan++; + if (*scan == c) + return scan; + } + break; + case '>': + if (scan[1] == '>') + { + scan++; + if (*scan == c) + return scan; + } + break; + } + } + } + } + + return 0; +} + void _initialize_cp_support (); void _initialize_cp_support ()