/* Helper routines for C++ support in GDB.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2017 Free Software Foundation, Inc.
Contributed by MontaVista Software.
#include "cp-abi.h"
#include "namespace.h"
#include <signal.h>
-
+#include "gdb_setjmp.h"
#include "safe-ctype.h"
#define d_left(dc) (dc)->u.s_binary.left
return (char *) 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 1 if STRING is clearly already in canonical form. This
function is conservative; things which it does not recognize are
assumed to be non-canonical, and the parser will sort them out
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);
type = last;
}
- buf = mem_fileopen ();
+ string_file buf;
TRY
- {
- type_print (type, "", buf, -1);
- }
-
+ {
+ type_print (type, "", &buf, -1);
+ }
/* If type_print threw an exception, there is little point
in continuing, so just bow out gracefully. */
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
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;
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
{
struct demangle_component newobj;
- 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);
+ 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 = name;
- newobj.u.s_name.len = len;
+ 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 (&newobj, 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;
typedefs in it. Then print it to the stream to continue
checking for more typedefs in the tree. */
replace_typedefs (info, d_left (comp), finder, data);
- name = cp_comp_to_string (d_left (comp), 100);
+ 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;
+ 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, finder, data);
-
- ui_file_delete (buf);
}
|| ret_comp->type == DEMANGLE_COMPONENT_TEMPLATE
|| ret_comp->type == DEMANGLE_COMPONENT_BUILTIN_TYPE))
{
- char *local_name = cp_comp_to_string (ret_comp, 10);
+ gdb::unique_xmalloc_ptr<char> local_name
+ = cp_comp_to_string (ret_comp, 10);
if (local_name != NULL)
{
sym = NULL;
TRY
{
- sym = lookup_symbol (local_name, 0, VAR_DOMAIN, 0).symbol;
+ sym = lookup_symbol (local_name.get (), 0,
+ VAR_DOMAIN, 0).symbol;
}
CATCH (except, RETURN_MASK_ALL)
{
}
END_CATCH
- xfree (local_name);
-
if (sym != NULL)
{
struct type *otype = SYMBOL_TYPE (sym);
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_POINTER:
case DEMANGLE_COMPONENT_REFERENCE:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
replace_typedefs (info, d_left (ret_comp), finder, data);
break;
}
}
-/* 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. If FINDER is not NULL, then type components are passed to
- FINDER to be looked up. DATA is passed verbatim to FINDER. */
+/* 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 *
+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, finder, data);
+ 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. */
-char *
+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 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)
{
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. */
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)
{
"demangler-warning", short_msg);
make_cleanup (xfree, long_msg);
- target_terminal_ours ();
+ make_cleanup_restore_target_terminal ();
+ target_terminal_ours_for_output ();
+
begin_line ();
if (core_dump_allowed)
fprintf_unfiltered (gdb_stderr,
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