merge from gcc

This commit is contained in:
DJ Delorie
2003-12-04 20:03:39 +00:00
parent f57a841aea
commit 858b45cfbf
3 changed files with 298 additions and 125 deletions

View File

@ -1,3 +1,53 @@
2003-12-04 Ian Lance Taylor <ian@wasabisystems.com>
* cp-demangle.c (IS_UPPER, IS_LOWER): Define.
(d_last_char): Define new macro.
(d_make_name): Reject an empty name.
(d_prefix, d_unqualified_name, d_type): Use new IS_* macros.
(d_substitution, d_print_identifier): Likewise.
(d_print_comp) [D_COMP_OPERATOR]: Likewise.
(d_print_comp) [D_COMP_TEMPLATE]: Use new d_last_char macro.
(d_print_mod) Use new d_last_char macro.
(d_print_cast): Use new d_last_char macro.
(is_ctor_or_dtor): Don't leak memory.
Fix handling of member function modifiers:
* cp-demangle.c (enum d_comp_type): Add D_COMP_RESTRICT_THIS,
D_COMP_VOLATILE_THIS, and D_COMP_CONST_THIS.
(d_dump): Dump new d_comp_type values.
(d_make_comp): Accept new d_comp_type values.
(has_return_type): Only accept _THIS variants of qualifiers.
(d_encoding): Without DMGL_PARAMS, only remove _THIS variants of
qualifiers.
(d_cv_qualifiers): Add member_fn parameter. Change all callers.
(d_print_comp) [D_COMP_TYPED_NAME]: Rather than removing
qualifiers and printing them at the end, add _THIS qualifiers to
the modifier list.
(d_print_comp) [D_COMP_*_THIS]: New cases.
(d_print_comp) [D_COMP_PTRMEM_TYPE]: Remove special handling of
qualifiers.
(d_print_mod_list): Add suffix parameter. Change all callers.
Keep walking the list even if the current modifier has been
printed.
(d_print_mod): Handle new _THIS qualifiers.
(d_print_function_type): Handle new _THIS qualifiers when deciding
whether to print a parenthesis. Put a space before the
parenthesis in some cases. Call d_print_mod_list again at the
end, passing suffix as 1.
(is_ctor_or_dtor): Look for new _THIS qualifiers.
* testsuite/demangle-expected: Add test case.
Fix for PR gcc/13304:
* cp-demangle.c (d_print_comp) [D_COMP_TEMPLATE]: If the character
before the '<' is itself a '<', insert a space.
(d_print_cast): Likewise.
* testsuite/demangle-expected: Add test case.
Fix for PR gcc/13244:
* cp-demangle.c (d_print_comp) [D_COMP_BINARY]: Wrap an expression
which uses the '>' operator in an extra layer of parens.
* testsuite/demangle-expected: Add test case.
2003-12-03 Ian Lance Taylor <ian@wasabisystems.com> 2003-12-03 Ian Lance Taylor <ian@wasabisystems.com>
* floatformat.c: Include "config.h" and <string.h> if available. * floatformat.c: Include "config.h" and <string.h> if available.

View File

@ -28,6 +28,43 @@
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* This code implements a demangler for the g++ V3 ABI. The ABI is
described on this web page:
http://www.codesourcery.com/cxx-abi/abi.html#mangling
This code was written while looking at the demangler written by
Alex Samuel <samuel@codesourcery.com>.
This code first pulls the mangled name apart into a list of
components, and then walks the list generating the demangled
name.
This file will normally define the following functions, q.v.:
char *cplus_demangle_v3(const char *mangled, int options)
char *java_demangle_v3(const char *mangled)
enum gnu_v3_ctor_kinds is_gnu_v3_mangled_ctor (const char *name)
enum gnu_v3_dtor_kinds is_gnu_v3_mangled_dtor (const char *name)
Preprocessor macros you can define while compiling this file:
IN_LIBGCC2
If defined, this file defines the following function, q.v.:
char *__cxa_demangle (const char *mangled, char *buf, size_t *len,
int *status)
instead of cplus_demangle_v3() and java_demangle_v3().
IN_GLIBCPP_V3
If defined, this file defines only __cxa_demangle().
STANDALONE_DEMANGLER
If defined, this file defines a main() function which demangles
any arguments, or, if none, demangles stdin.
CP_DEMANGLE_DEBUG
If defined, turns on debugging mode, which prints information on
stdout about the mangled string. This is not generally useful.
*/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@ -45,19 +82,18 @@
#include "libiberty.h" #include "libiberty.h"
#include "demangle.h" #include "demangle.h"
/* This code implements a demangler for the g++ V3 ABI. The ABI is /* We avoid pulling in the ctype tables, to prevent pulling in
described on this web page: additional unresolved symbols when this code is used in a library.
http://www.codesourcery.com/cxx-abi/abi.html#mangling FIXME: Is this really a valid reason? This comes from the original
V3 demangler code.
This code was written while looking at the demangler written by As of this writing this file has the following undefined references
Alex Samuel <samuel@codesourcery.com>. when compiled with -DIN_GLIBCPP_V3: malloc, realloc, free, memcpy,
strcpy, strcat, strlen. */
This code first pulls the mangled name apart into a list of
components, and then walks the list generating the demangled
name. */
/* Avoid pulling in the ctype tables for this simple usage. */
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
#define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
#define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z')
/* The prefix prepended by GCC to an identifier represnting the /* The prefix prepended by GCC to an identifier represnting the
anonymous namespace. */ anonymous namespace. */
@ -155,6 +191,12 @@ enum d_comp_type
D_COMP_VOLATILE, D_COMP_VOLATILE,
/* The const qualifier. */ /* The const qualifier. */
D_COMP_CONST, D_COMP_CONST,
/* The restrict qualifier modifying a member function. */
D_COMP_RESTRICT_THIS,
/* The volatile qualifier modifying a member function. */
D_COMP_VOLATILE_THIS,
/* The const qualifier modifying a member function. */
D_COMP_CONST_THIS,
/* A vendor qualifier. */ /* A vendor qualifier. */
D_COMP_VENDOR_TYPE_QUAL, D_COMP_VENDOR_TYPE_QUAL,
/* A pointer. */ /* A pointer. */
@ -389,6 +431,9 @@ struct d_print_info
} \ } \
while (0) while (0)
#define d_last_char(dpi) \
((dpi)->buf == NULL || (dpi)->len == 0 ? '\0' : (dpi)->buf[(dpi)->len - 1])
#ifdef CP_DEMANGLE_DEBUG #ifdef CP_DEMANGLE_DEBUG
static void d_dump PARAMS ((struct d_comp *, int)); static void d_dump PARAMS ((struct d_comp *, int));
#endif #endif
@ -430,7 +475,7 @@ static int d_call_offset PARAMS ((struct d_info *, int));
static struct d_comp *d_ctor_dtor_name PARAMS ((struct d_info *)); static struct d_comp *d_ctor_dtor_name PARAMS ((struct d_info *));
static struct d_comp *d_type PARAMS ((struct d_info *)); static struct d_comp *d_type PARAMS ((struct d_info *));
static struct d_comp **d_cv_qualifiers PARAMS ((struct d_info *, static struct d_comp **d_cv_qualifiers PARAMS ((struct d_info *,
struct d_comp **)); struct d_comp **, int));
static struct d_comp *d_function_type PARAMS ((struct d_info *)); static struct d_comp *d_function_type PARAMS ((struct d_info *));
static struct d_comp *d_bare_function_type PARAMS ((struct d_info *, int)); static struct d_comp *d_bare_function_type PARAMS ((struct d_info *, int));
static struct d_comp *d_class_enum_type PARAMS ((struct d_info *)); static struct d_comp *d_class_enum_type PARAMS ((struct d_info *));
@ -456,7 +501,7 @@ static void d_print_comp PARAMS ((struct d_print_info *,
static void d_print_identifier PARAMS ((struct d_print_info *, const char *, static void d_print_identifier PARAMS ((struct d_print_info *, const char *,
int)); int));
static void d_print_mod_list PARAMS ((struct d_print_info *, static void d_print_mod_list PARAMS ((struct d_print_info *,
struct d_print_mod *)); struct d_print_mod *, int));
static void d_print_mod PARAMS ((struct d_print_info *, static void d_print_mod PARAMS ((struct d_print_info *,
const struct d_comp *)); const struct d_comp *));
static void d_print_function_type PARAMS ((struct d_print_info *, static void d_print_function_type PARAMS ((struct d_print_info *,
@ -572,6 +617,15 @@ d_dump (dc, indent)
case D_COMP_CONST: case D_COMP_CONST:
printf ("const\n"); printf ("const\n");
break; break;
case D_COMP_RESTRICT_THIS:
printf ("restrict this\n");
break;
case D_COMP_VOLATILE_THIS:
printf ("volatile this\n");
break;
case D_COMP_CONST_THIS:
printf ("const this\n");
break;
case D_COMP_VENDOR_TYPE_QUAL: case D_COMP_VENDOR_TYPE_QUAL:
printf ("vendor type qualifier\n"); printf ("vendor type qualifier\n");
break; break;
@ -725,6 +779,9 @@ d_make_comp (di, type, left, right)
case D_COMP_RESTRICT: case D_COMP_RESTRICT:
case D_COMP_VOLATILE: case D_COMP_VOLATILE:
case D_COMP_CONST: case D_COMP_CONST:
case D_COMP_RESTRICT_THIS:
case D_COMP_VOLATILE_THIS:
case D_COMP_CONST_THIS:
break; break;
/* Other types should not be seen here. */ /* Other types should not be seen here. */
@ -751,6 +808,8 @@ d_make_name (di, s, len)
{ {
struct d_comp *p; struct d_comp *p;
if (s == NULL || len == 0)
return NULL;
p = d_make_empty (di, D_COMP_NAME); p = d_make_empty (di, D_COMP_NAME);
if (p != NULL) if (p != NULL)
{ {
@ -922,10 +981,9 @@ has_return_type (dc)
return 0; return 0;
case D_COMP_TEMPLATE: case D_COMP_TEMPLATE:
return ! is_ctor_dtor_or_conversion (d_left (dc)); return ! is_ctor_dtor_or_conversion (d_left (dc));
case D_COMP_RESTRICT: case D_COMP_RESTRICT_THIS:
case D_COMP_VOLATILE: case D_COMP_VOLATILE_THIS:
case D_COMP_CONST: case D_COMP_CONST_THIS:
case D_COMP_VENDOR_TYPE_QUAL:
return has_return_type (d_left (dc)); return has_return_type (d_left (dc));
} }
} }
@ -981,9 +1039,9 @@ d_encoding (di, top_level)
/* Strip off any initial CV-qualifiers, as they really apply /* Strip off any initial CV-qualifiers, as they really apply
to the `this' parameter, and they were not output by the to the `this' parameter, and they were not output by the
v2 demangler without DMGL_PARAMS. */ v2 demangler without DMGL_PARAMS. */
while (dc->type == D_COMP_RESTRICT while (dc->type == D_COMP_RESTRICT_THIS
|| dc->type == D_COMP_VOLATILE || dc->type == D_COMP_VOLATILE_THIS
|| dc->type == D_COMP_CONST) || dc->type == D_COMP_CONST_THIS)
dc = d_left (dc); dc = d_left (dc);
return dc; return dc;
} }
@ -1092,7 +1150,7 @@ d_nested_name (di)
if (d_next_char (di) != 'N') if (d_next_char (di) != 'N')
return NULL; return NULL;
pret = d_cv_qualifiers (di, &ret); pret = d_cv_qualifiers (di, &ret, 1);
if (pret == NULL) if (pret == NULL)
return NULL; return NULL;
@ -1139,7 +1197,7 @@ d_prefix (di)
comb_type = D_COMP_QUAL_NAME; comb_type = D_COMP_QUAL_NAME;
if (IS_DIGIT (peek) if (IS_DIGIT (peek)
|| (peek >= 'a' && peek <= 'z') || IS_LOWER (peek)
|| peek == 'C' || peek == 'C'
|| peek == 'D') || peek == 'D')
dc = d_unqualified_name (di); dc = d_unqualified_name (di);
@ -1186,7 +1244,7 @@ d_unqualified_name (di)
peek = d_peek_char (di); peek = d_peek_char (di);
if (IS_DIGIT (peek)) if (IS_DIGIT (peek))
return d_source_name (di); return d_source_name (di);
else if (peek >= 'a' && peek <= 'z') else if (IS_LOWER (peek))
return d_operator_name (di); return d_operator_name (di);
else if (peek == 'C' || peek == 'D') else if (peek == 'C' || peek == 'D')
return d_ctor_dtor_name (di); return d_ctor_dtor_name (di);
@ -1648,7 +1706,7 @@ d_type (di)
{ {
struct d_comp **pret; struct d_comp **pret;
pret = d_cv_qualifiers (di, &ret); pret = d_cv_qualifiers (di, &ret, 0);
if (pret == NULL) if (pret == NULL)
return NULL; return NULL;
*pret = d_type (di); *pret = d_type (di);
@ -1716,7 +1774,7 @@ d_type (di)
peek_next = d_peek_next_char (di); peek_next = d_peek_next_char (di);
if (IS_DIGIT (peek_next) if (IS_DIGIT (peek_next)
|| peek_next == '_' || peek_next == '_'
|| (peek_next >= 'A' && peek_next <= 'Z')) || IS_UPPER (peek_next))
{ {
ret = d_substitution (di); ret = d_substitution (di);
/* The substituted name may have been a template name and /* The substituted name may have been a template name and
@ -1782,9 +1840,10 @@ d_type (di)
/* <CV-qualifiers> ::= [r] [V] [K] */ /* <CV-qualifiers> ::= [r] [V] [K] */
static struct d_comp ** static struct d_comp **
d_cv_qualifiers (di, pret) d_cv_qualifiers (di, pret, member_fn)
struct d_info *di; struct d_info *di;
struct d_comp **pret; struct d_comp **pret;
int member_fn;
{ {
char peek; char peek;
@ -1795,11 +1854,11 @@ d_cv_qualifiers (di, pret)
d_advance (di, 1); d_advance (di, 1);
if (peek == 'r') if (peek == 'r')
t = D_COMP_RESTRICT; t = member_fn ? D_COMP_RESTRICT_THIS: D_COMP_RESTRICT;
else if (peek == 'V') else if (peek == 'V')
t = D_COMP_VOLATILE; t = member_fn ? D_COMP_VOLATILE_THIS : D_COMP_VOLATILE;
else else
t = D_COMP_CONST; t = member_fn ? D_COMP_CONST_THIS: D_COMP_CONST;
*pret = d_make_comp (di, t, NULL, NULL); *pret = d_make_comp (di, t, NULL, NULL);
if (*pret == NULL) if (*pret == NULL)
@ -1970,7 +2029,7 @@ d_pointer_to_member_type (di)
with g++, we need to pull off the CV-qualifiers here, in order to with g++, we need to pull off the CV-qualifiers here, in order to
avoid calling add_substitution() in d_type(). */ avoid calling add_substitution() in d_type(). */
pmem = d_cv_qualifiers (di, &mem); pmem = d_cv_qualifiers (di, &mem, 1);
if (pmem == NULL) if (pmem == NULL)
return NULL; return NULL;
*pmem = d_type (di); *pmem = d_type (di);
@ -2316,7 +2375,7 @@ d_substitution (di)
return NULL; return NULL;
c = d_next_char (di); c = d_next_char (di);
if (c == '_' || IS_DIGIT (c) || (c >= 'A' && c <= 'Z')) if (c == '_' || IS_DIGIT (c) || IS_UPPER (c))
{ {
int id; int id;
@ -2327,7 +2386,7 @@ d_substitution (di)
{ {
if (IS_DIGIT (c)) if (IS_DIGIT (c))
id = id * 36 + c - '0'; id = id * 36 + c - '0';
else if (c >= 'A' && c <= 'Z') else if (IS_UPPER (c))
id = id * 36 + c - 'A' + 10; id = id * 36 + c - 'A' + 10;
else else
return NULL; return NULL;
@ -2527,28 +2586,40 @@ d_print_comp (dpi, dc)
case D_COMP_TYPED_NAME: case D_COMP_TYPED_NAME:
{ {
const struct d_comp *typed_name; struct d_print_mod *hold_modifiers;
struct d_print_mod dpm; struct d_comp *typed_name;
struct d_print_mod adpm[4];
unsigned int i;
struct d_print_template dpt; struct d_print_template dpt;
/* Pass the name down to the type so that it can be printed in /* Pass the name down to the type so that it can be printed in
the right place for the type. If the name has the right place for the type. We also have to pass down
CV-qualifiers, they are really method qualifiers; pull them any CV-qualifiers, which apply to the this parameter. */
off now and print them after everything else. Note that we hold_modifiers = dpi->modifiers;
don't handle D_COMP_VENDOR_TYPE_QUAL here; it's not i = 0;
accepted by d_cv_qualifiers() either. */
typed_name = d_left (dc); typed_name = d_left (dc);
while (typed_name != NULL while (typed_name != NULL)
&& (typed_name->type == D_COMP_RESTRICT {
|| typed_name->type == D_COMP_VOLATILE if (i >= sizeof adpm / sizeof adpm[0])
|| typed_name->type == D_COMP_CONST)) {
typed_name = d_left (typed_name); d_print_error (dpi);
return;
}
dpm.next = dpi->modifiers; adpm[i].next = dpi->modifiers;
dpi->modifiers = &dpm; dpi->modifiers = &adpm[i];
dpm.mod = typed_name; adpm[i].mod = typed_name;
dpm.printed = 0; adpm[i].printed = 0;
dpm.templates = dpi->templates; adpm[i].templates = dpi->templates;
++i;
if (typed_name->type != D_COMP_RESTRICT_THIS
&& typed_name->type != D_COMP_VOLATILE_THIS
&& typed_name->type != D_COMP_CONST_THIS)
break;
typed_name = d_left (typed_name);
}
/* If typed_name is a template, then it applies to the /* If typed_name is a template, then it applies to the
function type as well. */ function type as well. */
@ -2564,26 +2635,19 @@ d_print_comp (dpi, dc)
if (typed_name->type == D_COMP_TEMPLATE) if (typed_name->type == D_COMP_TEMPLATE)
dpi->templates = dpt.next; dpi->templates = dpt.next;
/* If the modifier didn't get printed by the type, print it /* If the modifiers didn't get printed by the type, print them
now. */ now. */
if (! dpm.printed) while (i > 0)
{
--i;
if (! adpm[i].printed)
{ {
d_append_char (dpi, ' '); d_append_char (dpi, ' ');
d_print_comp (dpi, typed_name); d_print_mod (dpi, adpm[i].mod);
}
} }
dpi->modifiers = dpm.next; dpi->modifiers = hold_modifiers;
/* Now print any CV-qualifiers on the type. */
typed_name = d_left (dc);
while (typed_name != NULL
&& (typed_name->type == D_COMP_RESTRICT
|| typed_name->type == D_COMP_VOLATILE
|| typed_name->type == D_COMP_CONST))
{
d_print_mod (dpi, typed_name);
typed_name = d_left (typed_name);
}
return; return;
} }
@ -2600,11 +2664,13 @@ d_print_comp (dpi, dc)
dpi->modifiers = NULL; dpi->modifiers = NULL;
d_print_comp (dpi, d_left (dc)); d_print_comp (dpi, d_left (dc));
if (d_last_char (dpi) == '<')
d_append_char (dpi, ' ');
d_append_char (dpi, '<'); d_append_char (dpi, '<');
d_print_comp (dpi, d_right (dc)); d_print_comp (dpi, d_right (dc));
/* Avoid generating two consecutive '>' characters, to avoid /* Avoid generating two consecutive '>' characters, to avoid
the C++ syntactic ambiguity. */ the C++ syntactic ambiguity. */
if (dpi->buf != NULL && dpi->buf[dpi->len - 1] == '>') if (d_last_char (dpi) == '>')
d_append_char (dpi, ' '); d_append_char (dpi, ' ');
d_append_char (dpi, '>'); d_append_char (dpi, '>');
@ -2737,6 +2803,9 @@ d_print_comp (dpi, dc)
case D_COMP_RESTRICT: case D_COMP_RESTRICT:
case D_COMP_VOLATILE: case D_COMP_VOLATILE:
case D_COMP_CONST: case D_COMP_CONST:
case D_COMP_RESTRICT_THIS:
case D_COMP_VOLATILE_THIS:
case D_COMP_CONST_THIS:
case D_COMP_VENDOR_TYPE_QUAL: case D_COMP_VENDOR_TYPE_QUAL:
case D_COMP_POINTER: case D_COMP_POINTER:
case D_COMP_REFERENCE: case D_COMP_REFERENCE:
@ -2832,27 +2901,15 @@ d_print_comp (dpi, dc)
case D_COMP_PTRMEM_TYPE: case D_COMP_PTRMEM_TYPE:
{ {
const struct d_comp *target_type;
struct d_print_mod dpm; struct d_print_mod dpm;
/* Pass the name down to the type so that it can be printed in
the right place for the type. If the type has
CV-qualifiers, they are really method qualifiers; pull them
off now and print them after everything else. */
target_type = d_right (dc);
while (target_type != NULL
&& (target_type->type == D_COMP_RESTRICT
|| target_type->type == D_COMP_VOLATILE
|| target_type->type == D_COMP_CONST))
target_type = d_left (target_type);
dpm.next = dpi->modifiers; dpm.next = dpi->modifiers;
dpi->modifiers = &dpm; dpi->modifiers = &dpm;
dpm.mod = dc; dpm.mod = dc;
dpm.printed = 0; dpm.printed = 0;
dpm.templates = dpi->templates; dpm.templates = dpi->templates;
d_print_comp (dpi, target_type); d_print_comp (dpi, d_right (dc));
/* If the modifier didn't get printed by the type, print it /* If the modifier didn't get printed by the type, print it
now. */ now. */
@ -2865,17 +2922,6 @@ d_print_comp (dpi, dc)
dpi->modifiers = dpm.next; dpi->modifiers = dpm.next;
/* Now print any CV-qualifiers on the type. */
target_type = d_right (dc);
while (target_type != NULL
&& (target_type->type == D_COMP_RESTRICT
|| target_type->type == D_COMP_VOLATILE
|| target_type->type == D_COMP_CONST))
{
d_print_mod (dpi, target_type);
target_type = d_left (target_type);
}
return; return;
} }
@ -2895,7 +2941,7 @@ d_print_comp (dpi, dc)
d_append_string (dpi, "operator"); d_append_string (dpi, "operator");
c = dc->u.s_operator.op->name[0]; c = dc->u.s_operator.op->name[0];
if (c >= 'a' && c <= 'z') if (IS_LOWER (c))
d_append_char (dpi, ' '); d_append_char (dpi, ' ');
d_append_string (dpi, dc->u.s_operator.op->name); d_append_string (dpi, dc->u.s_operator.op->name);
return; return;
@ -2933,6 +2979,14 @@ d_print_comp (dpi, dc)
d_print_error (dpi); d_print_error (dpi);
return; return;
} }
/* We wrap an expression which uses the greater-than operator in
an extra layer of parens so that it does not get confused
with the '>' which ends the template parameters. */
if (d_left (dc)->type == D_COMP_OPERATOR
&& strcmp (d_left (dc)->u.s_operator.op->name, ">") == 0)
d_append_char (dpi, '(');
d_append_char (dpi, '('); d_append_char (dpi, '(');
d_print_comp (dpi, d_left (d_right (dc))); d_print_comp (dpi, d_left (d_right (dc)));
d_append_string (dpi, ") "); d_append_string (dpi, ") ");
@ -2940,6 +2994,11 @@ d_print_comp (dpi, dc)
d_append_string (dpi, " ("); d_append_string (dpi, " (");
d_print_comp (dpi, d_right (d_right (dc))); d_print_comp (dpi, d_right (d_right (dc)));
d_append_char (dpi, ')'); d_append_char (dpi, ')');
if (d_left (dc)->type == D_COMP_OPERATOR
&& strcmp (d_left (dc)->u.s_operator.op->name, ">") == 0)
d_append_char (dpi, ')');
return; return;
case D_COMP_BINARY_ARGS: case D_COMP_BINARY_ARGS:
@ -3064,7 +3123,7 @@ d_print_identifier (dpi, name, len)
{ {
int dig; int dig;
if (*q >= '0' && *q <= '9') if (IS_DIGIT (*q))
dig = *q - '0'; dig = *q - '0';
else if (*q >= 'A' && *q <= 'F') else if (*q >= 'A' && *q <= 'F')
dig = *q - 'A' + 10; dig = *q - 'A' + 10;
@ -3090,18 +3149,30 @@ d_print_identifier (dpi, name, len)
} }
} }
/* Print a list of modifiers. */ /* Print a list of modifiers. SUFFIX is 1 if we are printing
qualifiers on this after printing a function. */
static void static void
d_print_mod_list (dpi, mods) d_print_mod_list (dpi, mods, suffix)
struct d_print_info *dpi; struct d_print_info *dpi;
struct d_print_mod *mods; struct d_print_mod *mods;
int suffix;
{ {
struct d_print_template *hold_dpt; struct d_print_template *hold_dpt;
if (mods == NULL || mods->printed || d_print_saw_error (dpi)) if (mods == NULL || d_print_saw_error (dpi))
return; return;
if (mods->printed
|| (! suffix
&& (mods->mod->type == D_COMP_RESTRICT_THIS
|| mods->mod->type == D_COMP_VOLATILE_THIS
|| mods->mod->type == D_COMP_CONST_THIS)))
{
d_print_mod_list (dpi, mods->next, suffix);
return;
}
mods->printed = 1; mods->printed = 1;
hold_dpt = dpi->templates; hold_dpt = dpi->templates;
@ -3124,7 +3195,7 @@ d_print_mod_list (dpi, mods)
dpi->templates = hold_dpt; dpi->templates = hold_dpt;
d_print_mod_list (dpi, mods->next); d_print_mod_list (dpi, mods->next, suffix);
} }
/* Print a modifier. */ /* Print a modifier. */
@ -3137,12 +3208,15 @@ d_print_mod (dpi, mod)
switch (mod->type) switch (mod->type)
{ {
case D_COMP_RESTRICT: case D_COMP_RESTRICT:
case D_COMP_RESTRICT_THIS:
d_append_string (dpi, " restrict"); d_append_string (dpi, " restrict");
return; return;
case D_COMP_VOLATILE: case D_COMP_VOLATILE:
case D_COMP_VOLATILE_THIS:
d_append_string (dpi, " volatile"); d_append_string (dpi, " volatile");
return; return;
case D_COMP_CONST: case D_COMP_CONST:
case D_COMP_CONST_THIS:
d_append_string (dpi, " const"); d_append_string (dpi, " const");
return; return;
case D_COMP_VENDOR_TYPE_QUAL: case D_COMP_VENDOR_TYPE_QUAL:
@ -3164,7 +3238,7 @@ d_print_mod (dpi, mod)
d_append_string (dpi, "imaginary "); d_append_string (dpi, "imaginary ");
return; return;
case D_COMP_PTRMEM_TYPE: case D_COMP_PTRMEM_TYPE:
if (dpi->buf != NULL && dpi->buf[dpi->len - 1] != '(') if (d_last_char (dpi) != '(')
d_append_char (dpi, ' '); d_append_char (dpi, ' ');
d_print_comp (dpi, d_left (mod)); d_print_comp (dpi, d_left (mod));
d_append_string (dpi, "::*"); d_append_string (dpi, "::*");
@ -3213,6 +3287,10 @@ d_print_function_type (dpi, dc, mods)
case D_COMP_PTRMEM_TYPE: case D_COMP_PTRMEM_TYPE:
need_paren = 1; need_paren = 1;
break; break;
case D_COMP_RESTRICT_THIS:
case D_COMP_VOLATILE_THIS:
case D_COMP_CONST_THIS:
break;
default: default:
break; break;
} }
@ -3224,9 +3302,23 @@ d_print_function_type (dpi, dc, mods)
need_paren = 1; need_paren = 1;
if (need_paren) if (need_paren)
d_append_char (dpi, '('); {
switch (d_last_char (dpi))
{
case ' ':
case '(':
case '*':
break;
d_print_mod_list (dpi, mods); default:
d_append_char (dpi, ' ');
break;
}
d_append_char (dpi, '(');
}
d_print_mod_list (dpi, mods, 0);
if (need_paren) if (need_paren)
d_append_char (dpi, ')'); d_append_char (dpi, ')');
@ -3237,6 +3329,8 @@ d_print_function_type (dpi, dc, mods)
d_print_comp (dpi, d_right (dc)); d_print_comp (dpi, d_right (dc));
d_append_char (dpi, ')'); d_append_char (dpi, ')');
d_print_mod_list (dpi, mods, 1);
} }
/* Print an array type, except for the element type. */ /* Print an array type, except for the element type. */
@ -3277,7 +3371,7 @@ d_print_array_type (dpi, dc, mods)
if (need_paren) if (need_paren)
d_append_string (dpi, " ("); d_append_string (dpi, " (");
d_print_mod_list (dpi, mods); d_print_mod_list (dpi, mods, 0);
if (need_paren) if (need_paren)
d_append_char (dpi, ')'); d_append_char (dpi, ')');
@ -3337,11 +3431,13 @@ d_print_cast (dpi, dc)
dpi->templates = dpt.next; dpi->templates = dpt.next;
if (d_last_char (dpi) == '<')
d_append_char (dpi, ' ');
d_append_char (dpi, '<'); d_append_char (dpi, '<');
d_print_comp (dpi, d_right (d_left (dc))); d_print_comp (dpi, d_right (d_left (dc)));
/* Avoid generating two consecutive '>' characters, to avoid /* Avoid generating two consecutive '>' characters, to avoid
the C++ syntactic ambiguity. */ the C++ syntactic ambiguity. */
if (dpi->buf != NULL && dpi->buf[dpi->len - 1] == '>') if (d_last_char (dpi) == '>')
d_append_char (dpi, ' '); d_append_char (dpi, ' ');
d_append_char (dpi, '>'); d_append_char (dpi, '>');
@ -3653,6 +3749,7 @@ is_ctor_or_dtor (mangled, ctor_kind, dtor_kind)
{ {
struct d_info di; struct d_info di;
struct d_comp *dc; struct d_comp *dc;
int ret;
*ctor_kind = (enum gnu_v3_ctor_kinds) 0; *ctor_kind = (enum gnu_v3_ctor_kinds) 0;
*dtor_kind = (enum gnu_v3_dtor_kinds) 0; *dtor_kind = (enum gnu_v3_dtor_kinds) 0;
@ -3662,21 +3759,21 @@ is_ctor_or_dtor (mangled, ctor_kind, dtor_kind)
dc = d_mangled_name (&di, 1); dc = d_mangled_name (&di, 1);
if (dc == NULL || d_peek_char (&di) != '\0') ret = 0;
return 0; if (d_peek_char (&di) == '\0')
{
while (dc != NULL) while (dc != NULL)
{ {
switch (dc->type) switch (dc->type)
{ {
default: default:
return 0; dc = NULL;
break;
case D_COMP_TYPED_NAME: case D_COMP_TYPED_NAME:
case D_COMP_TEMPLATE: case D_COMP_TEMPLATE:
case D_COMP_RESTRICT: case D_COMP_RESTRICT_THIS:
case D_COMP_VOLATILE: case D_COMP_VOLATILE_THIS:
case D_COMP_CONST: case D_COMP_CONST_THIS:
case D_COMP_VENDOR_TYPE_QUAL:
dc = d_left (dc); dc = d_left (dc);
break; break;
case D_COMP_QUAL_NAME: case D_COMP_QUAL_NAME:
@ -3684,14 +3781,22 @@ is_ctor_or_dtor (mangled, ctor_kind, dtor_kind)
break; break;
case D_COMP_CTOR: case D_COMP_CTOR:
*ctor_kind = dc->u.s_ctor.kind; *ctor_kind = dc->u.s_ctor.kind;
return 1; ret = 1;
dc = NULL;
break;
case D_COMP_DTOR: case D_COMP_DTOR:
*dtor_kind = dc->u.s_dtor.kind; *dtor_kind = dc->u.s_dtor.kind;
return 1; ret = 1;
dc = NULL;
break;
}
} }
} }
return 0; free (di.subs);
free (di.comps);
return ret;
} }
/* Return whether NAME is the mangled form of a g++ V3 ABI constructor /* Return whether NAME is the mangled form of a g++ V3 ABI constructor

View File

@ -2883,11 +2883,29 @@ void __gnu_debug::_Error_formatter::_M_format_word<unsigned long>(char*, int, ch
--format=gnu-v3 --format=gnu-v3
_ZSt18uninitialized_copyIN9__gnu_cxx17__normal_iteratorIPSt4pairISsPFbP6sqlitePPcEESt6vectorIS9_SaIS9_EEEESE_ET0_T_SG_SF_ _ZSt18uninitialized_copyIN9__gnu_cxx17__normal_iteratorIPSt4pairISsPFbP6sqlitePPcEESt6vectorIS9_SaIS9_EEEESE_ET0_T_SG_SF_
__gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > > std::uninitialized_copy<__gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > >, __gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > > >(__gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > >, __gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > >, __gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > >) __gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > > std::uninitialized_copy<__gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > >, __gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > > >(__gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > >, __gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > >, __gnu_cxx::__normal_iterator<std::pair<std::string, bool (*)(sqlite*, char**)>*, std::vector<std::pair<std::string, bool (*)(sqlite*, char**)>, std::allocator<std::pair<std::string, bool (*)(sqlite*, char**)> > > >)
#
# The new demangler used to fail on this. # The new demangler used to fail on this.
--format=gnu-v3 --format=gnu-v3
_Z1fP1cIPFiiEE _Z1fP1cIPFiiEE
f(c<int (*)(int)>*) f(c<int (*)(int)>*)
# #
# Wrap expressions using '>' in an extra layer of parens to avoid
# confusion with the '>' which ends the template parameters.
--format=gnu-v3
_Z4dep9ILi3EEvP3fooIXgtT_Li2EEE
void dep9<3>(foo<((3) > (2))>*)
#
# Watch out for templated version of `operator<'--it needs an extra
# space.
--format=gnu-v3
_ZStltI9file_pathSsEbRKSt4pairIT_T0_ES6_
bool std::operator< <file_path, std::string>(std::pair<file_path, std::string> const&, std::pair<file_path, std::string> const&)
#
# More hairy qualifier handling.
--format=gnu-v3
_Z9hairyfuncM1YKFPVPFrPA2_PM1XKFKPA3_ilEPcEiE
hairyfunc(int (* const (X::** (* restrict (* volatile*(Y::*)(int) const)(char*)) [2])(long) const) [3])
#
# This caused an infinite loop. # This caused an infinite loop.
# #
# This is generated by an EDG compiler (kcc 4.0). To demangle it # This is generated by an EDG compiler (kcc 4.0). To demangle it