string* previous_argument; /* The last function argument demangled. */
int nrepeats; /* The number of times to repeat the previous
argument. */
+ int *proctypevec; /* Indices of currently processed remembered typevecs. */
+ int proctypevec_size;
+ int nproctypes;
};
#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
"DLANG style demangling"
}
,
+ {
+ RUST_DEMANGLING_STYLE_STRING,
+ rust_demangling,
+ "Rust style demangling"
+ }
+ ,
{
NULL, unknown_demangling, NULL
}
static void remember_type (struct work_stuff *, const char *, int);
+static void push_processed_type (struct work_stuff *, int);
+
+static void pop_processed_type (struct work_stuff *);
+
static void remember_Btype (struct work_stuff *, const char *, int, int);
static int register_Btype (struct work_stuff *);
work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
/* The V3 ABI demangling is implemented elsewhere. */
- if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
+ if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING)
{
ret = cplus_demangle_v3 (mangled, work->options);
- if (ret || GNU_V3_DEMANGLING)
+ if (GNU_V3_DEMANGLING)
+ return ret;
+
+ if (ret)
+ {
+ /* Rust symbols are GNU_V3 mangled plus some extra subtitutions.
+ The subtitutions are always smaller, so do in place changes. */
+ if (rust_is_mangled (ret))
+ rust_demangle_sym (ret);
+ else if (RUST_DEMANGLING)
+ {
+ free (ret);
+ ret = NULL;
+ }
+ }
+
+ if (ret || RUST_DEMANGLING)
return ret;
}
return (ret);
}
+char *
+rust_demangle (const char *mangled, int options)
+{
+ /* Rust symbols are GNU_V3 mangled plus some extra subtitutions. */
+ char *ret = cplus_demangle_v3 (mangled, options);
+
+ /* The Rust subtitutions are always smaller, so do in place changes. */
+ if (ret != NULL)
+ {
+ if (rust_is_mangled (ret))
+ rust_demangle_sym (ret);
+ else
+ {
+ free (ret);
+ ret = NULL;
+ }
+ }
+
+ return ret;
+}
+
/* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */
char *
int len0;
const char* p;
char *d;
- char *demangled;
+ char *demangled = NULL;
/* Discard leading _ada_, which is used for library level subprograms. */
if (strncmp (mangled, "_ada_", 5) == 0)
return demangled;
unknown:
+ XDELETEVEC (demangled);
len0 = strlen (mangled);
demangled = XNEWVEC (char, len0 + 3);
memcpy (to->btypevec[i], from->btypevec[i], len);
}
+ if (from->proctypevec)
+ to->proctypevec =
+ XDUPVEC (int, from->proctypevec, from->proctypevec_size);
+
if (from->ntmpl_args)
to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
/* Discard the remembered types, if any. */
forget_types (work);
- if (work -> typevec != NULL)
+ if (work->typevec != NULL)
{
- free ((char *) work -> typevec);
- work -> typevec = NULL;
- work -> typevec_size = 0;
+ free ((char *) work->typevec);
+ work->typevec = NULL;
+ work->typevec_size = 0;
+ }
+ if (work->proctypevec != NULL)
+ {
+ free (work->proctypevec);
+ work->proctypevec = NULL;
+ work->proctypevec_size = 0;
}
if (work->tmpl_argvec)
{
0);
if (!(work->constructor & 1))
expect_return_type = 1;
- (*mangled)++;
+ if (!**mangled)
+ success = 0;
+ else
+ (*mangled)++;
break;
}
- else
- /* fall through */
- {;}
+ /* fall through */
default:
if (AUTO_DEMANGLING || GNU_DEMANGLING)
{
int idx;
(*mangled)++;
+ if (**mangled == '\0')
+ return (0);
(*mangled)++;
idx = consume_count_with_underscores (mangled);
int success = 1;
const char *p;
- if ((*mangled)[0] == '_'
+ if ((*mangled)[0] == '_' && (*mangled)[1] != '\0'
&& strchr (cplus_markers, (*mangled)[1]) != NULL
&& (*mangled)[2] == '_')
{
&& (*mangled)[3] == 't'
&& (*mangled)[4] == '_')
|| ((*mangled)[1] == 'v'
- && (*mangled)[2] == 't'
+ && (*mangled)[2] == 't' && (*mangled)[3] != '\0'
&& strchr (cplus_markers, (*mangled)[3]) != NULL)))
{
/* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
do_type (struct work_stuff *work, const char **mangled, string *result)
{
int n;
+ int i;
+ int is_proctypevec;
int done;
int success;
string decl;
done = 0;
success = 1;
+ is_proctypevec = 0;
while (success && !done)
{
int member;
success = 0;
}
else
- {
- remembered_type = work -> typevec[n];
+ for (i = 0; i < work->nproctypes; i++)
+ if (work -> proctypevec [i] == n)
+ success = 0;
+
+ if (success)
+ {
+ is_proctypevec = 1;
+ push_processed_type (work, n);
+ remembered_type = work->typevec[n];
mangled = &remembered_type;
}
break;
break;
}
- if (*(*mangled)++ != 'F')
+ if (*(*mangled) != 'F')
{
success = 0;
break;
}
+ (*mangled)++;
}
if ((member && !demangle_nested_args (work, mangled, &decl))
|| **mangled != '_')
string_delete (result);
string_delete (&decl);
+ if (is_proctypevec)
+ pop_processed_type (work);
+
if (success)
/* Assume an integral type, if we're not sure. */
return (int) ((tk == tk_none) ? tk_integral : tk);
success = 0;
break;
}
+ /* fall through */
case 'I':
(*mangled)++;
if (**mangled == '_')
return 1;
}
+static void
+push_processed_type (struct work_stuff *work, int typevec_index)
+{
+ if (work->nproctypes >= work->proctypevec_size)
+ {
+ if (!work->proctypevec_size)
+ {
+ work->proctypevec_size = 4;
+ work->proctypevec = XNEWVEC (int, work->proctypevec_size);
+ }
+ else
+ {
+ if (work->proctypevec_size < 16)
+ /* Double when small. */
+ work->proctypevec_size *= 2;
+ else
+ {
+ /* Grow slower when large. */
+ if (work->proctypevec_size > (INT_MAX / 3) * 2)
+ xmalloc_failed (INT_MAX);
+ work->proctypevec_size = (work->proctypevec_size * 3 / 2);
+ }
+ work->proctypevec
+ = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size);
+ }
+ }
+ work->proctypevec [work->nproctypes++] = typevec_index;
+}
+
+static void
+pop_processed_type (struct work_stuff *work)
+{
+ work->nproctypes--;
+}
+
static void
remember_type (struct work_stuff *work, const char *start, int len)
{
{
string_append (declp, ", ");
}
+ push_processed_type (work, t);
if (!do_arg (work, &tem, &arg))
{
+ pop_processed_type (work);
return (0);
}
+ pop_processed_type (work);
if (PRINT_ARG_TYPES)
{
string_appends (declp, &arg);