/* 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.
#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"
#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 <signal.h>
+#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
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);
/* The actual commands. */
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[] =
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.
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
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. */
}
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<demangle_parse_info> 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
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
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
{
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;
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
{
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<char> 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;
/* 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<char> 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);
}
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);
}
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<char> 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:
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:
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:
}
}
-/* 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<demangle_parse_info> 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<char> 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<demangle_parse_info> 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<char> us (cp_comp_to_string (info->tree,
+ estimated_len));
- if (ret == NULL)
+ if (!us)
{
warning (_("internal error: string \"%s\" failed to be canonicalized"),
string);
- return NULL;
+ return std::string ();
}
- if (strcmp (string, ret) == 0)
- {
- xfree (ret);
- return NULL;
- }
+ std::string ret (us.get ());
+
+ if (ret == string)
+ return std::string ();
return ret;
}
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<demangle_parse_info>
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. */
options, memory);
if (ret)
{
- info = cp_new_demangle_parse_info ();
+ std::unique_ptr<demangle_parse_info> info (new demangle_parse_info);
info->tree = ret;
*demangled_p = NULL;
return info;
/* 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<demangle_parse_info> info
+ = cp_demangled_name_to_comp (demangled_name, NULL);
if (info == NULL)
{
cp_class_name_from_physname (const char *physname)
{
void *storage = NULL;
- char *demangled_name = NULL, *ret;
+ char *demangled_name = NULL;
+ gdb::unique_xmalloc_ptr<char> ret;
struct demangle_component *ret_comp, *prev_comp, *cur_comp;
- struct demangle_parse_info *info;
+ std::unique_ptr<demangle_parse_info> info;
int done;
info = mangled_name_to_comp (physname, DMGL_ANSI,
break;
}
- ret = NULL;
if (cur_comp != NULL && prev_comp != NULL)
{
/* We want to discard the rightmost child of PREV_COMP. */
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,
method_name_from_physname (const char *physname)
{
void *storage = NULL;
- char *demangled_name = NULL, *ret;
+ char *demangled_name = NULL;
+ gdb::unique_xmalloc_ptr<char> ret;
struct demangle_component *ret_comp;
- struct demangle_parse_info *info;
+ std::unique_ptr<demangle_parse_info> info;
info = mangled_name_to_comp (physname, DMGL_ANSI,
&storage, &demangled_name);
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. */
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
char *
cp_func_name (const char *full_name)
{
- char *ret;
+ gdb::unique_xmalloc_ptr<char> ret;
struct demangle_component *ret_comp;
- struct demangle_parse_info *info;
+ std::unique_ptr<demangle_parse_info> info;
info = cp_demangled_name_to_comp (full_name, NULL);
if (!info)
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
{
int done = 0;
struct demangle_component *ret_comp;
- struct demangle_parse_info *info;
- char *ret = NULL;
+ std::unique_ptr<demangle_parse_info> info;
+ gdb::unique_xmalloc_ptr<char> ret;
if (demangled_name == NULL)
return NULL;
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
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)
{
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. */
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;
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);
}
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;
make_symbol_overload_list_adl_namespace (struct type *type,
const char *func_name)
{
- char *namespace;
+ 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)
{
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))
static void
reset_directive_searched (void *data)
{
- struct using_direct *direct = data;
+ struct using_direct *direct = (struct using_direct *) data;
direct->searched = 0;
}
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;
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. */
}
/* 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.
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. */
/* 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;
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)
{
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
return rtti_type;
}
-/* Don't allow just "maintenance cplus". */
+#ifdef HAVE_WORKING_FORK
-static void
-maint_cplus_command (char *arg, int from_tty)
-{
- printf_unfiltered (_("\"maintenance cplus\" must be followed "
- "by the name of a command.\n"));
- help_list (maint_cplus_cmd_list,
- "maintenance cplus ",
- -1, gdb_stdout);
-}
+/* If nonzero, attempt to catch crashes in the demangler and print
+ useful debugging information. */
-/* This is a front end for cp_find_first_component, for unit testing.
- Be careful when using it: see the NOTE above
- cp_find_first_component. */
+static int catch_demangler_crashes = 1;
-static void
-first_component_command (char *arg, int from_tty)
-{
- int len;
- char *prefix;
+/* Stack context and environment for demangler crash recovery. */
- if (!arg)
- return;
+static SIGJMP_BUF gdb_demangle_jmp_buf;
- len = cp_find_first_component (arg);
- prefix = alloca (len + 1);
+/* If nonzero, attempt to dump core from the signal handler. */
- memcpy (prefix, arg, len);
- prefix[len] = '\0';
+static int gdb_demangle_attempt_core_dump = 1;
- printf_unfiltered ("%s\n", prefix);
+/* 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);
}
-extern initialize_file_ftype _initialize_cp_support; /* -Wmissing-prototypes */
+#endif
-#define SKIP_SPACE(P) \
- do \
- { \
- while (*(P) == ' ' || *(P) == '\t') \
- ++(P); \
- } \
- while (0)
+/* A wrapper for bfd_demangle. */
-/* 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)
+char *
+gdb_demangle (const char *name, int options)
{
- int i;
- char *copy;
- const char *p;
- struct expression *expr;
- struct value *val;
- volatile struct gdb_exception except;
+ 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
- p = input;
+ if (crash_signal == 0)
+ result = bfd_demangle (NULL, name, options);
- if (strncmp (p, "operator", 8) == 0)
+#ifdef HAVE_WORKING_FORK
+ if (catch_demangler_crashes)
{
- int valid = 0;
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+ sigaction (SIGSEGV, &old_sa, NULL);
+#else
+ signal (SIGSEGV, ofunc);
+#endif
- p += 8;
- SKIP_SPACE (p);
- for (i = 0;
- i < sizeof (operator_tokens) / sizeof (operator_tokens[0]);
- ++i)
+ if (crash_signal != 0)
{
- int length = strlen (operator_tokens[i]);
+ static int error_reported = 0;
- /* 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)
+ if (!error_reported)
{
- const char *op = p;
+ 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);
+
+ target_terminal::scoped_restore_terminal_state term_state;
+ 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);
- valid = 1;
- p += length;
+ demangler_warning (__FILE__, __LINE__, "%s", short_msg);
- if (strncmp (op, "new", 3) == 0
- || strncmp (op, "delete", 6) == 0)
- {
+ do_cleanups (back_to);
- /* 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);
+ error_reported = 1;
}
+
+ result = NULL;
}
+ }
+#endif
- /* Check input for a conversion operator. */
+ return result;
+}
- /* Skip past base typename. */
- while (*p != '*' && *p != '&' && *p != 0 && *p != ' ')
- ++p;
- SKIP_SPACE (p);
+/* See cp-support.h. */
- /* Add modifiers '*' / '&'. */
- while (*p == '*' || *p == '&')
- {
- ++p;
- SKIP_SPACE (p);
- }
+int
+gdb_sniff_from_mangled_name (const char *mangled, char **demangled)
+{
+ *demangled = gdb_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+ return *demangled != NULL;
+}
- /* 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);
- }
+/* Don't allow just "maintenance cplus". */
+
+static void
+maint_cplus_command (char *arg, int from_tty)
+{
+ printf_unfiltered (_("\"maintenance cplus\" must be followed "
+ "by the name of a command.\n"));
+ help_list (maint_cplus_cmd_list,
+ "maintenance cplus ",
+ all_commands, gdb_stdout);
+}
- xfree (copy);
- if (expr)
- xfree (expr);
+/* This is a front end for cp_find_first_component, for unit testing.
+ Be careful when using it: see the NOTE above
+ cp_find_first_component. */
- if (val != NULL && value_type (val) != NULL)
- return (p - input);
- }
+static void
+first_component_command (const char *arg, int from_tty)
+{
+ int len;
+ char *prefix;
- return 0;
+ if (!arg)
+ return;
+
+ len = cp_find_first_component (arg);
+ prefix = (char *) alloca (len + 1);
+
+ memcpy (prefix, arg, len);
+ prefix[len] = '\0';
+
+ printf_unfiltered ("%s\n", prefix);
}
-/* Implement "info vtable". */
+/* Implement "info vtbl". */
static void
info_vtbl_command (char *arg, int from_tty)
&maint_cplus_cmd_list);
add_info ("vtbl", info_vtbl_command,
- _("Show the vtable for a C++ object.\n\
+ _("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
}