X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fcp-support.c;h=8bcbe657a4ea74a130d22f6adcac9ff951ca5fd1;hb=29592bde87d250ea56e8431053918899d3d0c16b;hp=17f8237e429d9262a903e45ac75eb6262447c0ca;hpb=bfd189b164f4f35510573c3b18f194e5613fe1cb;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 17f8237e42..8bcbe657a4 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-2005, 2007-2012 Free Software Foundation, Inc. + Copyright (C) 2002-2017 Free Software Foundation, Inc. Contributed by MontaVista Software. @@ -20,9 +20,7 @@ #include "defs.h" #include "cp-support.h" -#include "gdb_string.h" #include "demangle.h" -#include "gdb_assert.h" #include "gdbcmd.h" #include "dictionary.h" #include "objfiles.h" @@ -31,14 +29,14 @@ #include "block.h" #include "complaints.h" #include "gdbtypes.h" -#include "exceptions.h" #include "expression.h" #include "value.h" - +#include "cp-abi.h" +#include "namespace.h" +#include +#include "gdb_setjmp.h" #include "safe-ctype.h" -#include "psymtab.h" - #define d_left(dc) (dc)->u.s_binary.left #define d_right(dc) (dc)->u.s_binary.right @@ -59,7 +57,7 @@ static void overload_list_add_symbol (struct symbol *sym, const char *oload_name); static void make_symbol_overload_list_using (const char *func_name, - const char *namespace); + const char *the_namespace); static void make_symbol_overload_list_qualified (const char *func_name); @@ -72,19 +70,6 @@ struct cmd_list_element *maint_cplus_cmd_list = NULL; static void maint_cplus_command (char *arg, int from_tty); static void first_component_command (char *arg, int from_tty); -/* Operator validation. - NOTE: Multi-byte operators (usually the assignment variety - operator) must appear before the single byte version, i.e., "+=" - before "+". */ -static const char *operator_tokens[] = - { - "++", "+=", "+", "->*", "->", "--", "-=", "-", "*=", "*", - "/=", "/", "%=", "%", "!=", "==", "!", "&&", "<<=", "<<", - ">>=", ">>", "<=", "<", ">=", ">", "~", "&=", "&", "|=", - "||", "|", "^=", "^", "=", "()", "[]", ",", "new", "delete" - /* new[] and delete[] require special whitespace handling */ - }; - /* A list of typedefs which should not be substituted by replace_typedefs. */ static const char * const ignore_typedefs[] = { @@ -93,7 +78,9 @@ static const char * const ignore_typedefs[] = static void replace_typedefs (struct demangle_parse_info *info, - struct demangle_component *ret_comp); + struct demangle_component *ret_comp, + canonicalization_ftype *finder, + void *data); /* 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. @@ -105,25 +92,7 @@ copy_string_to_obstack (struct obstack *obstack, const char *string, long *len) { *len = strlen (string); - return obstack_copy (obstack, string, *len); -} - -/* A cleanup wrapper for cp_demangled_name_parse_free. */ - -static void -do_demangled_name_parse_free_cleanup (void *data) -{ - struct demangle_parse_info *info = (struct demangle_parse_info *) data; - - cp_demangled_name_parse_free (info); -} - -/* Create a cleanup for C++ name parsing. */ - -struct cleanup * -make_cleanup_cp_demangled_name_parse_free (struct demangle_parse_info *info) -{ - return make_cleanup (do_demangled_name_parse_free_cleanup, info); + return (char *) obstack_copy (obstack, string, *len); } /* Return 1 if STRING is clearly already in canonical form. This @@ -164,12 +133,13 @@ cp_already_canonical (const char *string) static int inspect_type (struct demangle_parse_info *info, - struct demangle_component *ret_comp) + struct demangle_component *ret_comp, + canonicalization_ftype *finder, + void *data) { int i; char *name; struct symbol *sym; - volatile struct gdb_exception except; /* Copy the symbol's name from RET_COMP and look it up in the symbol table. */ @@ -185,27 +155,54 @@ inspect_type (struct demangle_parse_info *info, } sym = NULL; - TRY_CATCH (except, RETURN_MASK_ALL) - { - sym = lookup_symbol (name, 0, VAR_DOMAIN, 0); - } - if (except.reason >= 0 && sym != NULL) + TRY + { + sym = lookup_symbol (name, 0, VAR_DOMAIN, 0).symbol; + } + CATCH (except, RETURN_MASK_ALL) + { + return 0; + } + END_CATCH + + if (sym != NULL) { struct type *otype = SYMBOL_TYPE (sym); - /* If the type is a typedef, replace it. */ - if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF) + if (finder != NULL) + { + const char *new_name = (*finder) (otype, data); + + if (new_name != NULL) + { + ret_comp->u.s_name.s = new_name; + ret_comp->u.s_name.len = strlen (new_name); + return 1; + } + + return 0; + } + + /* If the type is a typedef or namespace alias, replace it. */ + if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF + || TYPE_CODE (otype) == TYPE_CODE_NAMESPACE) { long len; int is_anon; struct type *type; - struct demangle_parse_info *i; - struct ui_file *buf; + std::unique_ptr i; /* Get the real type of the typedef. */ type = check_typedef (otype); + /* If the symbol is a namespace and its type name is no different + than the name we looked up, this symbol is not a namespace + alias and does not need to be substituted. */ + if (TYPE_CODE (otype) == TYPE_CODE_NAMESPACE + && strcmp (TYPE_NAME (type), name) == 0) + return 0; + is_anon = (TYPE_TAG_NAME (type) == NULL && (TYPE_CODE (type) == TYPE_CODE_ENUM || TYPE_CODE (type) == TYPE_CODE_STRUCT @@ -230,22 +227,21 @@ inspect_type (struct demangle_parse_info *info, type = last; } - buf = mem_fileopen (); - TRY_CATCH (except, RETURN_MASK_ERROR) - { - type_print (type, "", buf, -1); - } - + string_file buf; + TRY + { + type_print (type, "", &buf, -1); + } /* If type_print threw an exception, there is little point in continuing, so just bow out gracefully. */ - if (except.reason < 0) + CATCH (except, RETURN_MASK_ERROR) { - ui_file_delete (buf); return 0; } + END_CATCH - name = ui_file_obsavestring (buf, &info->obstack, &len); - ui_file_delete (buf); + len = buf.size (); + name = (char *) obstack_copy0 (&info->obstack, buf.c_str (), len); /* Turn the result into a new tree. Note that this tree will contain pointers into NAME, so NAME cannot @@ -255,13 +251,13 @@ inspect_type (struct demangle_parse_info *info, if (i != NULL) { /* Merge the two trees. */ - cp_merge_demangle_parse_infos (info, ret_comp, i); + cp_merge_demangle_parse_infos (info, ret_comp, i.get ()); /* Replace any newly introduced typedefs -- but not if the type is anonymous (that would lead to infinite looping). */ if (!is_anon) - replace_typedefs (info, ret_comp); + replace_typedefs (info, ret_comp, finder, data); } else { @@ -271,14 +267,12 @@ inspect_type (struct demangle_parse_info *info, Canonicalize the name again, and store it in the current node (RET_COMP). */ - char *canon = cp_canonicalize_string_no_typedefs (name); + std::string canon = cp_canonicalize_string_no_typedefs (name); - if (canon != NULL) + if (!canon.empty ()) { - /* Copy the canonicalization into the obstack and - free CANON. */ - name = copy_string_to_obstack (&info->obstack, canon, &len); - xfree (canon); + /* Copy the canonicalization into the obstack. */ + name = copy_string_to_obstack (&info->obstack, canon.c_str (), &len); } ret_comp->u.s_name.s = name; @@ -298,11 +292,11 @@ inspect_type (struct demangle_parse_info *info, static void replace_typedefs_qualified_name (struct demangle_parse_info *info, - struct demangle_component *ret_comp) + struct demangle_component *ret_comp, + canonicalization_ftype *finder, + void *data) { - long len; - char *name; - struct ui_file *buf = mem_fileopen (); + string_file buf; struct demangle_component *comp = ret_comp; /* Walk each node of the qualified name, reconstructing the name of @@ -314,34 +308,33 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info, { if (d_left (comp)->type == DEMANGLE_COMPONENT_NAME) { - struct demangle_component new; - - ui_file_write (buf, d_left (comp)->u.s_name.s, - d_left (comp)->u.s_name.len); - name = ui_file_obsavestring (buf, &info->obstack, &len); - new.type = DEMANGLE_COMPONENT_NAME; - new.u.s_name.s = name; - new.u.s_name.len = len; - if (inspect_type (info, &new)) + struct demangle_component newobj; + + buf.write (d_left (comp)->u.s_name.s, d_left (comp)->u.s_name.len); + newobj.type = DEMANGLE_COMPONENT_NAME; + newobj.u.s_name.s + = (char *) obstack_copy0 (&info->obstack, + buf.c_str (), buf.size ()); + newobj.u.s_name.len = buf.size (); + if (inspect_type (info, &newobj, finder, data)) { - char *n, *s; + char *s; long slen; /* A typedef was substituted in NEW. Convert it to a string and replace the top DEMANGLE_COMPONENT_QUAL_NAME node. */ - ui_file_rewind (buf); - n = cp_comp_to_string (&new, 100); + buf.clear (); + gdb::unique_xmalloc_ptr n + = cp_comp_to_string (&newobj, 100); if (n == NULL) { /* If something went astray, abort typedef substitutions. */ - ui_file_delete (buf); return; } - s = copy_string_to_obstack (&info->obstack, n, &slen); - xfree (n); + s = copy_string_to_obstack (&info->obstack, n.get (), &slen); d_left (ret_comp)->type = DEMANGLE_COMPONENT_NAME; d_left (ret_comp)->u.s_name.s = s; @@ -356,18 +349,18 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info, /* The current node is not a name, so simply replace any typedefs in it. Then print it to the stream to continue checking for more typedefs in the tree. */ - replace_typedefs (info, d_left (comp)); - name = cp_comp_to_string (d_left (comp), 100); + replace_typedefs (info, d_left (comp), finder, data); + gdb::unique_xmalloc_ptr name + = cp_comp_to_string (d_left (comp), 100); if (name == NULL) { /* If something went astray, abort typedef substitutions. */ - ui_file_delete (buf); return; } - fputs_unfiltered (name, buf); - xfree (name); + buf.puts (name.get ()); } - ui_file_write (buf, "::", 2); + + buf.write ("::", 2); comp = d_right (comp); } @@ -377,21 +370,20 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info, if (comp->type == DEMANGLE_COMPONENT_NAME) { - ui_file_write (buf, comp->u.s_name.s, comp->u.s_name.len); - name = ui_file_obsavestring (buf, &info->obstack, &len); + buf.write (comp->u.s_name.s, comp->u.s_name.len); /* Replace the top (DEMANGLE_COMPONENT_QUAL_NAME) node with a DEMANGLE_COMPONENT_NAME node containing the whole name. */ ret_comp->type = DEMANGLE_COMPONENT_NAME; - ret_comp->u.s_name.s = name; - ret_comp->u.s_name.len = len; - inspect_type (info, ret_comp); + ret_comp->u.s_name.s + = (char *) obstack_copy0 (&info->obstack, + buf.c_str (), buf.size ()); + ret_comp->u.s_name.len = buf.size (); + inspect_type (info, ret_comp, finder, data); } else - replace_typedefs (info, comp); - - ui_file_delete (buf); + replace_typedefs (info, comp, finder, data); } @@ -417,10 +409,52 @@ check_cv_qualifiers (struct demangle_component *ret_comp) static void replace_typedefs (struct demangle_parse_info *info, - struct demangle_component *ret_comp) + struct demangle_component *ret_comp, + canonicalization_ftype *finder, + void *data) { if (ret_comp) { + if (finder != NULL + && (ret_comp->type == DEMANGLE_COMPONENT_NAME + || ret_comp->type == DEMANGLE_COMPONENT_QUAL_NAME + || ret_comp->type == DEMANGLE_COMPONENT_TEMPLATE + || ret_comp->type == DEMANGLE_COMPONENT_BUILTIN_TYPE)) + { + gdb::unique_xmalloc_ptr local_name + = cp_comp_to_string (ret_comp, 10); + + if (local_name != NULL) + { + struct symbol *sym = NULL; + + sym = NULL; + TRY + { + sym = lookup_symbol (local_name.get (), 0, + VAR_DOMAIN, 0).symbol; + } + CATCH (except, RETURN_MASK_ALL) + { + } + END_CATCH + + if (sym != NULL) + { + struct type *otype = SYMBOL_TYPE (sym); + const char *new_name = (*finder) (otype, data); + + if (new_name != NULL) + { + ret_comp->type = DEMANGLE_COMPONENT_NAME; + ret_comp->u.s_name.s = new_name; + ret_comp->u.s_name.len = strlen (new_name); + return; + } + } + } + } + switch (ret_comp->type) { case DEMANGLE_COMPONENT_ARGLIST: @@ -431,23 +465,23 @@ replace_typedefs (struct demangle_parse_info *info, case DEMANGLE_COMPONENT_TEMPLATE: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: case DEMANGLE_COMPONENT_TYPED_NAME: - replace_typedefs (info, d_left (ret_comp)); - replace_typedefs (info, d_right (ret_comp)); + replace_typedefs (info, d_left (ret_comp), finder, data); + replace_typedefs (info, d_right (ret_comp), finder, data); break; case DEMANGLE_COMPONENT_NAME: - inspect_type (info, ret_comp); + inspect_type (info, ret_comp, finder, data); break; case DEMANGLE_COMPONENT_QUAL_NAME: - replace_typedefs_qualified_name (info, ret_comp); + replace_typedefs_qualified_name (info, ret_comp, finder, data); break; case DEMANGLE_COMPONENT_LOCAL_NAME: case DEMANGLE_COMPONENT_CTOR: case DEMANGLE_COMPONENT_ARRAY_TYPE: case DEMANGLE_COMPONENT_PTRMEM_TYPE: - replace_typedefs (info, d_right (ret_comp)); + replace_typedefs (info, d_right (ret_comp), finder, data); break; case DEMANGLE_COMPONENT_CONST: @@ -458,7 +492,8 @@ replace_typedefs (struct demangle_parse_info *info, case DEMANGLE_COMPONENT_RESTRICT_THIS: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_REFERENCE: - replace_typedefs (info, d_left (ret_comp)); + case DEMANGLE_COMPONENT_RVALUE_REFERENCE: + replace_typedefs (info, d_left (ret_comp), finder, data); break; default: @@ -467,73 +502,85 @@ replace_typedefs (struct demangle_parse_info *info, } } -/* Parse STRING and convert it to canonical form, resolving any typedefs. - If parsing fails, or if STRING is already canonical, return NULL. - Otherwise return the canonical form. The return value is allocated via - xmalloc. */ +/* Parse STRING and convert it to canonical form, resolving any + typedefs. If parsing fails, or if STRING is already canonical, + return the empty string. Otherwise return the canonical form. If + FINDER is not NULL, then type components are passed to FINDER to be + looked up. DATA is passed verbatim to FINDER. */ -char * -cp_canonicalize_string_no_typedefs (const char *string) +std::string +cp_canonicalize_string_full (const char *string, + canonicalization_ftype *finder, + void *data) { - char *ret; + std::string ret; unsigned int estimated_len; - struct demangle_parse_info *info; + std::unique_ptr info; - ret = NULL; estimated_len = strlen (string) * 2; info = cp_demangled_name_to_comp (string, NULL); if (info != NULL) { /* Replace all the typedefs in the tree. */ - replace_typedefs (info, info->tree); + replace_typedefs (info.get (), info->tree, finder, data); /* Convert the tree back into a string. */ - ret = cp_comp_to_string (info->tree, estimated_len); - gdb_assert (ret != NULL); - - /* Free the parse information. */ - cp_demangled_name_parse_free (info); + gdb::unique_xmalloc_ptr us = cp_comp_to_string (info->tree, + estimated_len); + gdb_assert (us); + ret = us.get (); /* Finally, compare the original string with the computed name, returning NULL if they are the same. */ - if (strcmp (string, ret) == 0) - { - xfree (ret); - return NULL; - } + if (ret == string) + return std::string (); } return ret; } +/* Like cp_canonicalize_string_full, but always passes NULL for + FINDER. */ + +std::string +cp_canonicalize_string_no_typedefs (const char *string) +{ + return cp_canonicalize_string_full (string, NULL, NULL); +} + /* Parse STRING and convert it to canonical form. If parsing fails, - or if STRING is already canonical, return NULL. Otherwise return - the canonical form. The return value is allocated via xmalloc. */ + or if STRING is already canonical, return the empty string. + Otherwise return the canonical form. */ -char * +std::string cp_canonicalize_string (const char *string) { - struct demangle_parse_info *info; + std::unique_ptr info; unsigned int estimated_len; - char *ret; if (cp_already_canonical (string)) - return NULL; + return std::string (); info = cp_demangled_name_to_comp (string, NULL); if (info == NULL) - return NULL; + return std::string (); estimated_len = strlen (string) * 2; - ret = cp_comp_to_string (info->tree, estimated_len); - cp_demangled_name_parse_free (info); + gdb::unique_xmalloc_ptr us (cp_comp_to_string (info->tree, + estimated_len)); - if (strcmp (string, ret) == 0) + if (!us) { - xfree (ret); - return NULL; + warning (_("internal error: string \"%s\" failed to be canonicalized"), + string); + return std::string (); } + std::string ret (us.get ()); + + if (ret == string) + return std::string (); + return ret; } @@ -543,12 +590,11 @@ cp_canonicalize_string (const char *string) freed when finished with the tree, or NULL if none was needed. OPTIONS will be passed to the demangler. */ -static struct demangle_parse_info * +static std::unique_ptr mangled_name_to_comp (const char *mangled_name, int options, void **memory, char **demangled_p) { char *demangled_name; - struct demangle_parse_info *info; /* If it looks like a v3 mangled name, then try to go directly to trees. */ @@ -560,7 +606,7 @@ mangled_name_to_comp (const char *mangled_name, int options, options, memory); if (ret) { - info = cp_new_demangle_parse_info (); + std::unique_ptr info (new demangle_parse_info); info->tree = ret; *demangled_p = NULL; return info; @@ -569,13 +615,14 @@ mangled_name_to_comp (const char *mangled_name, int options, /* If it doesn't, or if that failed, then try to demangle the name. */ - demangled_name = cplus_demangle (mangled_name, options); + demangled_name = gdb_demangle (mangled_name, options); if (demangled_name == NULL) return NULL; /* If we could demangle the name, parse it to build the component tree. */ - info = cp_demangled_name_to_comp (demangled_name, NULL); + std::unique_ptr info + = cp_demangled_name_to_comp (demangled_name, NULL); if (info == NULL) { @@ -593,9 +640,10 @@ char * cp_class_name_from_physname (const char *physname) { void *storage = NULL; - char *demangled_name = NULL, *ret; + char *demangled_name = NULL; + gdb::unique_xmalloc_ptr ret; struct demangle_component *ret_comp, *prev_comp, *cur_comp; - struct demangle_parse_info *info; + std::unique_ptr info; int done; info = mangled_name_to_comp (physname, DMGL_ANSI, @@ -662,7 +710,6 @@ cp_class_name_from_physname (const char *physname) break; } - ret = NULL; if (cur_comp != NULL && prev_comp != NULL) { /* We want to discard the rightmost child of PREV_COMP. */ @@ -674,8 +721,7 @@ cp_class_name_from_physname (const char *physname) xfree (storage); xfree (demangled_name); - cp_demangled_name_parse_free (info); - return ret; + return ret.release (); } /* Return the child of COMP which is the basename of a method, @@ -742,9 +788,10 @@ char * method_name_from_physname (const char *physname) { void *storage = NULL; - char *demangled_name = NULL, *ret; + char *demangled_name = NULL; + gdb::unique_xmalloc_ptr ret; struct demangle_component *ret_comp; - struct demangle_parse_info *info; + std::unique_ptr info; info = mangled_name_to_comp (physname, DMGL_ANSI, &storage, &demangled_name); @@ -753,7 +800,6 @@ method_name_from_physname (const char *physname) ret_comp = unqualified_name_from_comp (info->tree); - ret = NULL; if (ret_comp != NULL) /* The ten is completely arbitrary; we don't have a good estimate. */ @@ -761,8 +807,7 @@ method_name_from_physname (const char *physname) xfree (storage); xfree (demangled_name); - cp_demangled_name_parse_free (info); - return ret; + return ret.release (); } /* If FULL_NAME is the demangled name of a C++ function (including an @@ -774,9 +819,9 @@ method_name_from_physname (const char *physname) char * cp_func_name (const char *full_name) { - char *ret; + gdb::unique_xmalloc_ptr ret; struct demangle_component *ret_comp; - struct demangle_parse_info *info; + std::unique_ptr info; info = cp_demangled_name_to_comp (full_name, NULL); if (!info) @@ -784,12 +829,10 @@ cp_func_name (const char *full_name) ret_comp = unqualified_name_from_comp (info->tree); - ret = NULL; if (ret_comp != NULL) ret = cp_comp_to_string (ret_comp, 10); - cp_demangled_name_parse_free (info); - return ret; + return ret.release (); } /* DEMANGLED_NAME is the name of a function, including parameters and @@ -801,8 +844,8 @@ cp_remove_params (const char *demangled_name) { int done = 0; struct demangle_component *ret_comp; - struct demangle_parse_info *info; - char *ret = NULL; + std::unique_ptr info; + gdb::unique_xmalloc_ptr ret; if (demangled_name == NULL) return NULL; @@ -834,8 +877,7 @@ cp_remove_params (const char *demangled_name) if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME) ret = cp_comp_to_string (d_left (ret_comp), 10); - cp_demangled_name_parse_free (info); - return ret; + return ret.release (); } /* Here are some random pieces of trivia to keep in mind while trying @@ -891,10 +933,6 @@ cp_find_first_component (const char *name) the recursion easier, it also stops if it reaches an unexpected ')' or '>' if the value of PERMISSIVE is nonzero. */ -/* Let's optimize away calls to strlen("operator"). */ - -#define LENGTH_OF_OPERATOR 8 - static unsigned int cp_find_first_component_aux (const char *name, int permissive) { @@ -956,19 +994,25 @@ cp_find_first_component_aux (const char *name, int permissive) return strlen (name); } case '\0': - case ':': return index; + case ':': + /* ':' marks a component iff the next character is also a ':'. + Otherwise it is probably malformed input. */ + if (name[index + 1] == ':') + return index; + break; case 'o': /* Operator names can screw up the recursion. */ if (operator_possible - && strncmp (name + index, "operator", - LENGTH_OF_OPERATOR) == 0) + && startswith (name + index, CP_OPERATOR_STR)) { - index += LENGTH_OF_OPERATOR; + index += CP_OPERATOR_LEN; while (ISSPACE(name[index])) ++index; switch (name[index]) { + case '\0': + return index; /* Skip over one less than the appropriate number of characters: the for loop will skip over the last one. */ @@ -1104,28 +1148,27 @@ overload_list_add_symbol (struct symbol *sym, struct symbol ** make_symbol_overload_list (const char *func_name, - const char *namespace) + const char *the_namespace) { struct cleanup *old_cleanups; const char *name; sym_return_val_size = 100; sym_return_val_index = 0; - sym_return_val = xmalloc ((sym_return_val_size + 1) * - sizeof (struct symbol *)); + sym_return_val = XNEWVEC (struct symbol *, sym_return_val_size + 1); sym_return_val[0] = NULL; old_cleanups = make_cleanup (xfree, sym_return_val); - make_symbol_overload_list_using (func_name, namespace); + make_symbol_overload_list_using (func_name, the_namespace); - if (namespace[0] == '\0') + if (the_namespace[0] == '\0') name = func_name; else { char *concatenated_name - = alloca (strlen (namespace) + 2 + strlen (func_name) + 1); - strcpy (concatenated_name, namespace); + = (char *) alloca (strlen (the_namespace) + 2 + strlen (func_name) + 1); + strcpy (concatenated_name, the_namespace); strcat (concatenated_name, "::"); strcat (concatenated_name, func_name); name = concatenated_name; @@ -1145,14 +1188,10 @@ static void make_symbol_overload_list_block (const char *name, const struct block *block) { - struct dict_iterator iter; + struct block_iterator iter; struct symbol *sym; - const struct dictionary *dict = BLOCK_DICT (block); - - for (sym = dict_iter_name_first (dict, name, &iter); - sym != NULL; - sym = dict_iter_name_next (name, &iter)) + ALL_BLOCK_SYMBOLS_WITH_NAME (block, name, iter, sym) overload_list_add_symbol (sym, name); } @@ -1160,19 +1199,19 @@ make_symbol_overload_list_block (const char *name, static void make_symbol_overload_list_namespace (const char *func_name, - const char *namespace) + const char *the_namespace) { const char *name; const struct block *block = NULL; - if (namespace[0] == '\0') + if (the_namespace[0] == '\0') name = func_name; else { char *concatenated_name - = alloca (strlen (namespace) + 2 + strlen (func_name) + 1); + = (char *) alloca (strlen (the_namespace) + 2 + strlen (func_name) + 1); - strcpy (concatenated_name, namespace); + strcpy (concatenated_name, the_namespace); strcat (concatenated_name, "::"); strcat (concatenated_name, func_name); name = concatenated_name; @@ -1197,12 +1236,12 @@ static void make_symbol_overload_list_adl_namespace (struct type *type, const char *func_name) { - char *namespace; - char *type_name; + char *the_namespace; + const char *type_name; int i, prefix_len; while (TYPE_CODE (type) == TYPE_CODE_PTR - || TYPE_CODE (type) == TYPE_CODE_REF + || TYPE_IS_REFERENCE (type) || TYPE_CODE (type) == TYPE_CODE_ARRAY || TYPE_CODE (type) == TYPE_CODE_TYPEDEF) { @@ -1221,15 +1260,15 @@ make_symbol_overload_list_adl_namespace (struct type *type, if (prefix_len != 0) { - namespace = alloca (prefix_len + 1); - strncpy (namespace, type_name, prefix_len); - namespace[prefix_len] = '\0'; + the_namespace = (char *) alloca (prefix_len + 1); + strncpy (the_namespace, type_name, prefix_len); + the_namespace[prefix_len] = '\0'; - make_symbol_overload_list_namespace (func_name, namespace); + make_symbol_overload_list_namespace (func_name, the_namespace); } /* Check public base type */ - if (TYPE_CODE (type) == TYPE_CODE_CLASS) + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) for (i = 0; i < TYPE_N_BASECLASSES (type); i++) { if (BASETYPE_VIA_PUBLIC (type, i)) @@ -1263,7 +1302,7 @@ make_symbol_overload_list_adl (struct type **arg_types, int nargs, static void reset_directive_searched (void *data) { - struct using_direct *direct = data; + struct using_direct *direct = (struct using_direct *) data; direct->searched = 0; } @@ -1274,7 +1313,7 @@ reset_directive_searched (void *data) static void make_symbol_overload_list_using (const char *func_name, - const char *namespace) + const char *the_namespace) { struct using_direct *current; const struct block *block; @@ -1299,7 +1338,7 @@ make_symbol_overload_list_using (const char *func_name, if (current->alias != NULL || current->declaration != NULL) continue; - if (strcmp (namespace, current->import_dest) == 0) + if (strcmp (the_namespace, current->import_dest) == 0) { /* Mark this import as searched so that the recursive call does not search it again. */ @@ -1317,7 +1356,7 @@ make_symbol_overload_list_using (const char *func_name, } /* Now, add names for this namespace. */ - make_symbol_overload_list_namespace (func_name, namespace); + make_symbol_overload_list_namespace (func_name, the_namespace); } /* This does the bulk of the work of finding overloaded symbols. @@ -1327,12 +1366,9 @@ make_symbol_overload_list_using (const char *func_name, static void make_symbol_overload_list_qualified (const char *func_name) { - struct symbol *sym; - struct symtab *s; + struct compunit_symtab *cust; struct objfile *objfile; const struct block *b, *surrounding_static_block = 0; - struct dict_iterator iter; - const struct dictionary *dict; /* Look through the partial symtabs for all symbols which begin by matching FUNC_NAME. Make sure we read that symbol table in. */ @@ -1354,17 +1390,17 @@ make_symbol_overload_list_qualified (const char *func_name) /* Go through the symtabs and check the externs and statics for symbols which match. */ - ALL_PRIMARY_SYMTABS (objfile, s) + ALL_COMPUNITS (objfile, cust) { QUIT; - b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); + b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), GLOBAL_BLOCK); make_symbol_overload_list_block (func_name, b); } - ALL_PRIMARY_SYMTABS (objfile, s) + ALL_COMPUNITS (objfile, cust) { QUIT; - b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); + b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), STATIC_BLOCK); /* Don't do this block twice. */ if (b == surrounding_static_block) continue; @@ -1380,7 +1416,9 @@ cp_lookup_rtti_type (const char *name, struct block *block) struct symbol * rtti_sym; struct type * rtti_type; - rtti_sym = lookup_symbol (name, block, STRUCT_DOMAIN, NULL); + /* Use VAR_DOMAIN here as NAME may be a typedef. PR 18141, 18417. + Classes "live" in both STRUCT_DOMAIN and VAR_DOMAIN. */ + rtti_sym = lookup_symbol (name, block, VAR_DOMAIN, NULL).symbol; if (rtti_sym == NULL) { @@ -1394,11 +1432,11 @@ cp_lookup_rtti_type (const char *name, struct block *block) return NULL; } - rtti_type = SYMBOL_TYPE (rtti_sym); + rtti_type = check_typedef (SYMBOL_TYPE (rtti_sym)); switch (TYPE_CODE (rtti_type)) { - case TYPE_CODE_CLASS: + case TYPE_CODE_STRUCT: break; case TYPE_CODE_NAMESPACE: /* chastain/2003-11-26: the symbol tables often contain fake @@ -1415,6 +1453,147 @@ cp_lookup_rtti_type (const char *name, struct block *block) return rtti_type; } +#ifdef HAVE_WORKING_FORK + +/* If nonzero, attempt to catch crashes in the demangler and print + useful debugging information. */ + +static int catch_demangler_crashes = 1; + +/* Stack context and environment for demangler crash recovery. */ + +static SIGJMP_BUF gdb_demangle_jmp_buf; + +/* If nonzero, attempt to dump core from the signal handler. */ + +static int gdb_demangle_attempt_core_dump = 1; + +/* Signal handler for gdb_demangle. */ + +static void +gdb_demangle_signal_handler (int signo) +{ + if (gdb_demangle_attempt_core_dump) + { + if (fork () == 0) + dump_core (); + + gdb_demangle_attempt_core_dump = 0; + } + + SIGLONGJMP (gdb_demangle_jmp_buf, signo); +} + +#endif + +/* A wrapper for bfd_demangle. */ + +char * +gdb_demangle (const char *name, int options) +{ + char *result = NULL; + int crash_signal = 0; + +#ifdef HAVE_WORKING_FORK +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + struct sigaction sa, old_sa; +#else + sighandler_t ofunc; +#endif + static int core_dump_allowed = -1; + + if (core_dump_allowed == -1) + { + core_dump_allowed = can_dump_core (LIMIT_CUR); + + if (!core_dump_allowed) + gdb_demangle_attempt_core_dump = 0; + } + + if (catch_demangler_crashes) + { +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + sa.sa_handler = gdb_demangle_signal_handler; + sigemptyset (&sa.sa_mask); +#ifdef HAVE_SIGALTSTACK + sa.sa_flags = SA_ONSTACK; +#else + sa.sa_flags = 0; +#endif + sigaction (SIGSEGV, &sa, &old_sa); +#else + ofunc = signal (SIGSEGV, gdb_demangle_signal_handler); +#endif + + crash_signal = SIGSETJMP (gdb_demangle_jmp_buf); + } +#endif + + if (crash_signal == 0) + result = bfd_demangle (NULL, name, options); + +#ifdef HAVE_WORKING_FORK + if (catch_demangler_crashes) + { +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + sigaction (SIGSEGV, &old_sa, NULL); +#else + signal (SIGSEGV, ofunc); +#endif + + if (crash_signal != 0) + { + static int error_reported = 0; + + if (!error_reported) + { + char *short_msg, *long_msg; + struct cleanup *back_to; + + short_msg = xstrprintf (_("unable to demangle '%s' " + "(demangler failed with signal %d)"), + name, crash_signal); + back_to = make_cleanup (xfree, short_msg); + + long_msg = xstrprintf ("%s:%d: %s: %s", __FILE__, __LINE__, + "demangler-warning", short_msg); + make_cleanup (xfree, long_msg); + + make_cleanup_restore_target_terminal (); + target_terminal_ours_for_output (); + + begin_line (); + if (core_dump_allowed) + fprintf_unfiltered (gdb_stderr, + _("%s\nAttempting to dump core.\n"), + long_msg); + else + warn_cant_dump_core (long_msg); + + demangler_warning (__FILE__, __LINE__, "%s", short_msg); + + do_cleanups (back_to); + + error_reported = 1; + } + + result = NULL; + } + } +#endif + + return result; +} + +/* See cp-support.h. */ + +int +gdb_sniff_from_mangled_name (const char *mangled, char **demangled) +{ + *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI); + return *demangled != NULL; +} + /* Don't allow just "maintenance cplus". */ static void @@ -1424,7 +1603,7 @@ maint_cplus_command (char *arg, int from_tty) "by the name of a command.\n")); help_list (maint_cplus_cmd_list, "maintenance cplus ", - -1, gdb_stdout); + all_commands, gdb_stdout); } /* This is a front end for cp_find_first_component, for unit testing. @@ -1441,7 +1620,7 @@ first_component_command (char *arg, int from_tty) return; len = cp_find_first_component (arg); - prefix = alloca (len + 1); + prefix = (char *) alloca (len + 1); memcpy (prefix, arg, len); prefix[len] = '\0'; @@ -1451,109 +1630,16 @@ first_component_command (char *arg, int from_tty) extern initialize_file_ftype _initialize_cp_support; /* -Wmissing-prototypes */ -#define SKIP_SPACE(P) \ - do \ - { \ - while (*(P) == ' ' || *(P) == '\t') \ - ++(P); \ - } \ - while (0) - -/* Returns the length of the operator name or 0 if INPUT does not - point to a valid C++ operator. INPUT should start with - "operator". */ -int -cp_validate_operator (const char *input) -{ - int i; - char *copy; - const char *p; - struct expression *expr; - struct value *val; - volatile struct gdb_exception except; - p = input; +/* Implement "info vtbl". */ - if (strncmp (p, "operator", 8) == 0) - { - int valid = 0; - - p += 8; - SKIP_SPACE (p); - for (i = 0; - i < sizeof (operator_tokens) / sizeof (operator_tokens[0]); - ++i) - { - int length = strlen (operator_tokens[i]); - - /* By using strncmp here, we MUST have operator_tokens - ordered! See additional notes where operator_tokens is - defined above. */ - if (strncmp (p, operator_tokens[i], length) == 0) - { - const char *op = p; - - valid = 1; - p += length; - - if (strncmp (op, "new", 3) == 0 - || strncmp (op, "delete", 6) == 0) - { - - /* Special case: new[] and delete[]. We must be - careful to swallow whitespace before/in "[]". */ - SKIP_SPACE (p); - - if (*p == '[') - { - ++p; - SKIP_SPACE (p); - if (*p == ']') - ++p; - else - valid = 0; - } - } - - if (valid) - return (p - input); - } - } - - /* Check input for a conversion operator. */ - - /* Skip past base typename. */ - while (*p != '*' && *p != '&' && *p != 0 && *p != ' ') - ++p; - SKIP_SPACE (p); - - /* Add modifiers '*' / '&'. */ - while (*p == '*' || *p == '&') - { - ++p; - SKIP_SPACE (p); - } - - /* Check for valid type. [Remember: input starts with - "operator".] */ - copy = savestring (input + 8, p - input - 8); - expr = NULL; - val = NULL; - TRY_CATCH (except, RETURN_MASK_ALL) - { - expr = parse_expression (copy); - val = evaluate_type (expr); - } - - xfree (copy); - if (expr) - xfree (expr); - - if (val != NULL && value_type (val) != NULL) - return (p - input); - } +static void +info_vtbl_command (char *arg, int from_tty) +{ + struct value *value; - return 0; + value = parse_and_eval (arg); + cplus_print_vtable (value); } void @@ -1574,4 +1660,23 @@ _initialize_cp_support (void) first_component_command, _("Print the first class/namespace component of NAME."), &maint_cplus_cmd_list); + + add_info ("vtbl", info_vtbl_command, + _("Show the virtual function table for a C++ object.\n\ +Usage: info vtbl EXPRESSION\n\ +Evaluate EXPRESSION and display the virtual function table for the\n\ +resulting object.")); + +#ifdef HAVE_WORKING_FORK + add_setshow_boolean_cmd ("catch-demangler-crashes", class_maintenance, + &catch_demangler_crashes, _("\ +Set whether to attempt to catch demangler crashes."), _("\ +Show whether to attempt to catch demangler crashes."), _("\ +If enabled GDB will attempt to catch demangler crashes and\n\ +display the offending symbol."), + NULL, + NULL, + &maintenance_set_cmdlist, + &maintenance_show_cmdlist); +#endif }