aboutsummaryrefslogtreecommitdiff
path: root/libiberty/cp-demangle.c
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2003-12-15 17:45:42 +0000
committerDJ Delorie <dj@redhat.com>2003-12-15 17:45:42 +0000
commit97ceaf5b4df58353b0a8e5663cb7ee6e4ae63605 (patch)
tree947568cb9d232c502316f07f18b7e543cdb63f37 /libiberty/cp-demangle.c
parenta711c44f29cfb1af925157ef24ec9254ccd0e68a (diff)
downloadgdb-97ceaf5b4df58353b0a8e5663cb7ee6e4ae63605.zip
gdb-97ceaf5b4df58353b0a8e5663cb7ee6e4ae63605.tar.gz
gdb-97ceaf5b4df58353b0a8e5663cb7ee6e4ae63605.tar.bz2
merge from gcc
Diffstat (limited to 'libiberty/cp-demangle.c')
-rw-r--r--libiberty/cp-demangle.c134
1 files changed, 102 insertions, 32 deletions
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index a5835df..e675752 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -141,6 +141,23 @@ struct d_builtin_type_info
enum d_builtin_type_print print;
};
+/* Information we keep for the standard substitutions. */
+
+struct d_standard_sub_info
+{
+ /* The code for this substitution. */
+ char code;
+ /* The simple string it expands to. */
+ const char *simple_expansion;
+ /* The results of a full, verbose, expansion. This is used when
+ qualifying a constructor/destructor, or when in verbose mode. */
+ const char *full_expansion;
+ /* What to set the last_name field of d_info to; NULL if we should
+ not set it. This is only relevant when qualifying a
+ constructor/destructor. */
+ const char *set_last_name;
+};
+
/* Component types found in mangled names. */
enum d_comp_type
@@ -239,7 +256,9 @@ enum d_comp_type
D_COMP_TRINARY_ARG1,
D_COMP_TRINARY_ARG2,
/* A literal. */
- D_COMP_LITERAL
+ D_COMP_LITERAL,
+ /* A negative literal. */
+ D_COMP_LITERAL_NEG
};
/* A component of the mangled name. */
@@ -489,7 +508,7 @@ static struct d_comp *d_expr_primary PARAMS ((struct d_info *));
static struct d_comp *d_local_name PARAMS ((struct d_info *));
static int d_discriminator PARAMS ((struct d_info *));
static int d_add_substitution PARAMS ((struct d_info *, struct d_comp *));
-static struct d_comp *d_substitution PARAMS ((struct d_info *));
+static struct d_comp *d_substitution PARAMS ((struct d_info *, int));
static void d_print_resize PARAMS ((struct d_print_info *, size_t));
static void d_print_append_char PARAMS ((struct d_print_info *, int));
static void d_print_append_buffer PARAMS ((struct d_print_info *, const char *,
@@ -683,6 +702,9 @@ d_dump (dc, indent)
case D_COMP_LITERAL:
printf ("literal\n");
break;
+ case D_COMP_LITERAL_NEG:
+ printf ("negative literal\n");
+ break;
}
d_dump (d_left (dc), indent + 2);
@@ -737,6 +759,7 @@ d_make_comp (di, type, left, right)
case D_COMP_TRINARY_ARG1:
case D_COMP_TRINARY_ARG2:
case D_COMP_LITERAL:
+ case D_COMP_LITERAL_NEG:
if (left == NULL || right == NULL)
return NULL;
break;
@@ -1087,7 +1110,7 @@ d_name (di)
if (d_peek_next_char (di) != 't')
{
- dc = d_substitution (di);
+ dc = d_substitution (di, 0);
subst = 1;
}
else
@@ -1202,7 +1225,7 @@ d_prefix (di)
|| peek == 'D')
dc = d_unqualified_name (di);
else if (peek == 'S')
- dc = d_substitution (di);
+ dc = d_substitution (di, 1);
else if (peek == 'I')
{
if (ret == NULL)
@@ -1776,7 +1799,7 @@ d_type (di)
|| peek_next == '_'
|| IS_UPPER (peek_next))
{
- ret = d_substitution (di);
+ ret = d_substitution (di, 0);
/* The substituted name may have been a template name and
may be followed by tepmlate args. */
if (d_peek_char (di) == 'I')
@@ -2254,6 +2277,7 @@ d_expr_primary (di)
else
{
struct d_comp *type;
+ enum d_comp_type t;
const char *s;
type = d_type (di);
@@ -2269,11 +2293,16 @@ d_expr_primary (di)
constant in any readable form anyhow. We don't attempt to
handle these cases. */
+ t = D_COMP_LITERAL;
+ if (d_peek_char (di) == 'n')
+ {
+ t = D_COMP_LITERAL_NEG;
+ d_advance (di, 1);
+ }
s = d_str (di);
while (d_peek_char (di) != 'E')
d_advance (di, 1);
- ret = d_make_comp (di, D_COMP_LITERAL, type,
- d_make_name (di, s, d_str (di) - s));
+ ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s));
}
if (d_next_char (di) != 'E')
return NULL;
@@ -2363,11 +2392,39 @@ d_add_substitution (di, dc)
::= Si
::= So
::= Sd
+
+ If PREFIX is non-zero, then this type is being used as a prefix in
+ a qualified name. In this case, for the standard substitutions, we
+ need to check whether we are being used as a prefix for a
+ constructor or destructor, and return a full template name.
+ Otherwise we will get something like std::iostream::~iostream()
+ which does not correspond particularly well to any function which
+ actually appears in the source.
*/
+static const struct d_standard_sub_info standard_subs[] =
+{
+ { 't', "std", "std", NULL },
+ { 'a', "std::allocator", "std::allocator", "allocator" },
+ { 'b', "std::basic_string", "std::basic_string", "basic_string" },
+ { 's', "std::string",
+ "std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
+ "basic_string" },
+ { 'i', "std::istream",
+ "std::basic_istream<char, std::char_traits<char> >",
+ "basic_istream" },
+ { 'o', "std::ostream",
+ "std::basic_ostream<char, std::char_traits<char> >",
+ "basic_ostream" },
+ { 'd', "std::iostream",
+ "std::basic_iostream<char, std::char_traits<char> >",
+ "basic_iostream" }
+};
+
static struct d_comp *
-d_substitution (di)
+d_substitution (di, prefix)
struct d_info *di;
+ int prefix;
{
char c;
@@ -2404,31 +2461,36 @@ d_substitution (di)
}
else
{
- switch (c)
+ int verbose;
+ const struct d_standard_sub_info *p;
+ const struct d_standard_sub_info *pend;
+
+ verbose = (di->options & DMGL_VERBOSE) != 0;
+ if (! verbose && prefix)
{
- case 't':
- return d_make_sub (di, "std");
- case 'a':
- di->last_name = d_make_sub (di, "allocator");
- return d_make_sub (di, "std::allocator");
- case 'b':
- di->last_name = d_make_sub (di, "basic_string");
- return d_make_sub (di, "std::basic_string");
- case 's':
- di->last_name = d_make_sub (di, "string");
- return d_make_sub (di, "std::string");
- case 'i':
- di->last_name = d_make_sub (di, "istream");
- return d_make_sub (di, "std::istream");
- case 'o':
- di->last_name = d_make_sub (di, "ostream");
- return d_make_sub (di, "std::ostream");
- case 'd':
- di->last_name = d_make_sub (di, "iostream");
- return d_make_sub (di, "std::iostream");
- default:
- return NULL;
+ char peek;
+
+ peek = d_peek_char (di);
+ if (peek == 'C' || peek == 'D')
+ verbose = 1;
}
+
+ pend = (&standard_subs[0]
+ + sizeof standard_subs / sizeof standard_subs[0]);
+ for (p = &standard_subs[0]; p < pend; ++p)
+ {
+ if (c == p->code)
+ {
+ if (p->set_last_name != NULL)
+ di->last_name = d_make_sub (di, p->set_last_name);
+ if (verbose)
+ return d_make_sub (di, p->full_expansion);
+ else
+ return d_make_sub (di, p->simple_expansion);
+ }
+ }
+
+ return NULL;
}
}
@@ -3031,6 +3093,7 @@ d_print_comp (dpi, dc)
return;
case D_COMP_LITERAL:
+ case D_COMP_LITERAL_NEG:
/* For some builtin types, produce simpler output. */
if (d_left (dc)->type == D_COMP_BUILTIN_TYPE)
{
@@ -3039,6 +3102,8 @@ d_print_comp (dpi, dc)
case D_PRINT_INT:
if (d_right (dc)->type == D_COMP_NAME)
{
+ if (dc->type == D_COMP_LITERAL_NEG)
+ d_append_char (dpi, '-');
d_print_comp (dpi, d_right (dc));
return;
}
@@ -3047,6 +3112,8 @@ d_print_comp (dpi, dc)
case D_PRINT_LONG:
if (d_right (dc)->type == D_COMP_NAME)
{
+ if (dc->type == D_COMP_LITERAL_NEG)
+ d_append_char (dpi, '-');
d_print_comp (dpi, d_right (dc));
d_append_char (dpi, 'l');
return;
@@ -3055,7 +3122,8 @@ d_print_comp (dpi, dc)
case D_PRINT_BOOL:
if (d_right (dc)->type == D_COMP_NAME
- && d_right (dc)->u.s_name.len == 1)
+ && d_right (dc)->u.s_name.len == 1
+ && dc->type == D_COMP_LITERAL)
{
switch (d_right (dc)->u.s_name.s[0])
{
@@ -3079,6 +3147,8 @@ d_print_comp (dpi, dc)
d_append_char (dpi, '(');
d_print_comp (dpi, d_left (dc));
d_append_char (dpi, ')');
+ if (dc->type == D_COMP_LITERAL_NEG)
+ d_append_char (dpi, '-');
d_print_comp (dpi, d_right (dc));
return;