Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(623)

Unified Diff: libiberty/cp-demangle.c

Issue 124383005: GDB 7.6.50 (Closed) Base URL: http://git.chromium.org/native_client/nacl-gdb.git@upstream
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « libiberty/cp-demangle.h ('k') | libiberty/floatformat.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: libiberty/cp-demangle.c
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 27cc323f2a24c03c584e8ec74961d9d92e5e49b0..029151e320aadddd23642470434b5aa90761f9e1 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -275,6 +275,31 @@ struct d_growable_string
int allocation_failure;
};
+/* A demangle component and some scope captured when it was first
+ traversed. */
+
+struct d_saved_scope
+{
+ /* The component whose scope this is. */
+ const struct demangle_component *container;
+ /* The list of templates, if any, that was current when this
+ scope was captured. */
+ struct d_print_template *templates;
+};
+
+/* Checkpoint structure to allow backtracking. This holds copies
+ of the fields of struct d_info that need to be restored
+ if a trial parse needs to be backtracked over. */
+
+struct d_info_checkpoint
+{
+ const char *n;
+ int next_comp;
+ int next_sub;
+ int did_subs;
+ int expansion;
+};
+
enum { D_PRINT_BUFFER_LENGTH = 256 };
struct d_print_info
{
@@ -302,6 +327,12 @@ struct d_print_info
int pack_index;
/* Number of d_print_flush calls so far. */
unsigned long int flush_count;
+ /* Array of saved scopes for evaluating substitutions. */
+ struct d_saved_scope *saved_scopes;
+ /* Number of saved scopes in the above array. */
+ int num_saved_scopes;
+ /* The nearest enclosing template, if any. */
+ const struct demangle_component *current_template;
};
#ifdef CP_DEMANGLE_DEBUG
@@ -382,6 +413,9 @@ static struct demangle_component **
d_cv_qualifiers (struct d_info *, struct demangle_component **, int);
static struct demangle_component *
+d_ref_qualifier (struct d_info *, struct demangle_component *);
+
+static struct demangle_component *
d_function_type (struct d_info *);
static struct demangle_component *
@@ -425,6 +459,10 @@ d_add_substitution (struct d_info *, struct demangle_component *);
static struct demangle_component *d_substitution (struct d_info *, int);
+static void d_checkpoint (struct d_info *, struct d_info_checkpoint *);
+
+static void d_backtrack (struct d_info *, struct d_info_checkpoint *);
+
static void d_growable_string_init (struct d_growable_string *, size_t);
static inline void
@@ -508,6 +546,11 @@ d_dump (struct demangle_component *dc, int indent)
case DEMANGLE_COMPONENT_NAME:
printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s);
return;
+ case DEMANGLE_COMPONENT_TAGGED_NAME:
+ printf ("tagged name\n");
+ d_dump (dc->u.s_binary.left, indent + 2);
+ d_dump (dc->u.s_binary.right, indent + 2);
+ return;
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
printf ("template parameter %ld\n", dc->u.s_number.number);
return;
@@ -609,6 +652,12 @@ d_dump (struct demangle_component *dc, int indent)
case DEMANGLE_COMPONENT_CONST_THIS:
printf ("const this\n");
break;
+ case DEMANGLE_COMPONENT_REFERENCE_THIS:
+ printf ("reference this\n");
+ break;
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+ printf ("rvalue reference this\n");
+ break;
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
printf ("vendor type qualifier\n");
break;
@@ -696,6 +745,20 @@ d_dump (struct demangle_component *dc, int indent)
case DEMANGLE_COMPONENT_PACK_EXPANSION:
printf ("pack expansion\n");
break;
+ case DEMANGLE_COMPONENT_TLS_INIT:
+ printf ("tls init function\n");
+ break;
+ case DEMANGLE_COMPONENT_TLS_WRAPPER:
+ printf ("tls wrapper function\n");
+ break;
+ case DEMANGLE_COMPONENT_DEFAULT_ARG:
+ printf ("default argument %d\n", dc->u.s_unary_num.num);
+ d_dump (dc->u.s_unary_num.sub, indent+2);
+ return;
+ case DEMANGLE_COMPONENT_LAMBDA:
+ printf ("lambda %d\n", dc->u.s_unary_num.num);
+ d_dump (dc->u.s_unary_num.sub, indent+2);
+ return;
}
d_dump (d_left (dc), indent + 2);
@@ -803,6 +866,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
case DEMANGLE_COMPONENT_QUAL_NAME:
case DEMANGLE_COMPONENT_LOCAL_NAME:
case DEMANGLE_COMPONENT_TYPED_NAME:
+ case DEMANGLE_COMPONENT_TAGGED_NAME:
case DEMANGLE_COMPONENT_TEMPLATE:
case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
@@ -832,6 +896,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
case DEMANGLE_COMPONENT_COVARIANT_THUNK:
case DEMANGLE_COMPONENT_JAVA_CLASS:
case DEMANGLE_COMPONENT_GUARD:
+ case DEMANGLE_COMPONENT_TLS_INIT:
+ case DEMANGLE_COMPONENT_TLS_WRAPPER:
case DEMANGLE_COMPONENT_REFTEMP:
case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
@@ -871,6 +937,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_REFERENCE_THIS:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
case DEMANGLE_COMPONENT_ARGLIST:
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
break;
@@ -1109,6 +1177,8 @@ has_return_type (struct demangle_component *dc)
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_REFERENCE_THIS:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
return has_return_type (d_left (dc));
}
}
@@ -1164,7 +1234,9 @@ d_encoding (struct d_info *di, int top_level)
v2 demangler without DMGL_PARAMS. */
while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
- || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
+ || dc->type == DEMANGLE_COMPONENT_CONST_THIS
+ || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+ || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
dc = d_left (dc);
/* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then
@@ -1178,7 +1250,9 @@ d_encoding (struct d_info *di, int top_level)
dcr = d_right (dc);
while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS
- || dcr->type == DEMANGLE_COMPONENT_CONST_THIS)
+ || dcr->type == DEMANGLE_COMPONENT_CONST_THIS
+ || dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+ || dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
dcr = d_left (dcr);
dc->u.s_binary.right = dcr;
}
@@ -1194,6 +1268,23 @@ d_encoding (struct d_info *di, int top_level)
}
}
+/* <tagged-name> ::= <name> B <source-name> */
+
+static struct demangle_component *
+d_abi_tags (struct d_info *di, struct demangle_component *dc)
+{
+ char peek;
+ while (peek = d_peek_char (di),
+ peek == 'B')
+ {
+ struct demangle_component *tag;
+ d_advance (di, 1);
+ tag = d_source_name (di);
+ dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag);
+ }
+ return dc;
+}
+
/* <name> ::= <nested-name>
::= <unscoped-name>
::= <unscoped-template-name> <template-args>
@@ -1220,7 +1311,6 @@ d_name (struct d_info *di)
case 'Z':
return d_local_name (di);
- case 'L':
case 'U':
return d_unqualified_name (di);
@@ -1267,6 +1357,7 @@ d_name (struct d_info *di)
return dc;
}
+ case 'L':
default:
dc = d_unqualified_name (di);
if (d_peek_char (di) == 'I')
@@ -1283,8 +1374,8 @@ d_name (struct d_info *di)
}
}
-/* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
- ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+/* <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
+ ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
*/
static struct demangle_component *
@@ -1292,6 +1383,7 @@ d_nested_name (struct d_info *di)
{
struct demangle_component *ret;
struct demangle_component **pret;
+ struct demangle_component *rqual;
if (! d_check_char (di, 'N'))
return NULL;
@@ -1300,10 +1392,20 @@ d_nested_name (struct d_info *di)
if (pret == NULL)
return NULL;
+ /* Parse the ref-qualifier now and then attach it
+ once we have something to attach it to. */
+ rqual = d_ref_qualifier (di, NULL);
+
*pret = d_prefix (di);
if (*pret == NULL)
return NULL;
+ if (rqual)
+ {
+ d_left (rqual) = ret;
+ ret = rqual;
+ }
+
if (! d_check_char (di, 'E'))
return NULL;
@@ -1408,15 +1510,14 @@ d_prefix (struct d_info *di)
static struct demangle_component *
d_unqualified_name (struct d_info *di)
{
+ struct demangle_component *ret;
char peek;
peek = d_peek_char (di);
if (IS_DIGIT (peek))
- return d_source_name (di);
+ ret = d_source_name (di);
else if (IS_LOWER (peek))
{
- struct demangle_component *ret;
-
ret = d_operator_name (di);
if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR)
{
@@ -1425,14 +1526,11 @@ d_unqualified_name (struct d_info *di)
ret = d_make_comp (di, DEMANGLE_COMPONENT_UNARY, ret,
d_source_name (di));
}
- return ret;
}
else if (peek == 'C' || peek == 'D')
- return d_ctor_dtor_name (di);
+ ret = d_ctor_dtor_name (di);
else if (peek == 'L')
{
- struct demangle_component * ret;
-
d_advance (di, 1);
ret = d_source_name (di);
@@ -1440,22 +1538,27 @@ d_unqualified_name (struct d_info *di)
return NULL;
if (! d_discriminator (di))
return NULL;
- return ret;
}
else if (peek == 'U')
{
switch (d_peek_next_char (di))
{
case 'l':
- return d_lambda (di);
+ ret = d_lambda (di);
+ break;
case 't':
- return d_unnamed_type (di);
+ ret = d_unnamed_type (di);
+ break;
default:
return NULL;
}
}
else
return NULL;
+
+ if (d_peek_char (di) == 'B')
+ ret = d_abi_tags (di, ret);
+ return ret;
}
/* <source-name> ::= <(positive length) number> <identifier> */
@@ -1582,11 +1685,13 @@ const struct demangle_operator_info cplus_demangle_operators[] =
{ "an", NL ("&"), 2 },
{ "at", NL ("alignof "), 1 },
{ "az", NL ("alignof "), 1 },
+ { "cc", NL ("const_cast"), 2 },
{ "cl", NL ("()"), 2 },
{ "cm", NL (","), 2 },
{ "co", NL ("~"), 1 },
{ "dV", NL ("/="), 2 },
{ "da", NL ("delete[] "), 1 },
+ { "dc", NL ("dynamic_cast"), 2 },
{ "de", NL ("*"), 1 },
{ "dl", NL ("delete "), 1 },
{ "ds", NL (".*"), 2 },
@@ -1626,8 +1731,10 @@ const struct demangle_operator_info cplus_demangle_operators[] =
{ "qu", NL ("?"), 3 },
{ "rM", NL ("%="), 2 },
{ "rS", NL (">>="), 2 },
+ { "rc", NL ("reinterpret_cast"), 2 },
{ "rm", NL ("%"), 2 },
{ "rs", NL (">>"), 2 },
+ { "sc", NL ("static_cast"), 2 },
{ "st", NL ("sizeof "), 1 },
{ "sz", NL ("sizeof "), 1 },
{ "tr", NL ("throw"), 0 },
@@ -1646,8 +1753,15 @@ d_operator_name (struct d_info *di)
if (c1 == 'v' && IS_DIGIT (c2))
return d_make_extended_operator (di, c2 - '0', d_source_name (di));
else if (c1 == 'c' && c2 == 'v')
- return d_make_comp (di, DEMANGLE_COMPONENT_CAST,
- cplus_demangle_type (di), NULL);
+ {
+ struct demangle_component *type;
+ int was_conversion = di->is_conversion;
+
+ di->is_conversion = ! di->is_expression;
+ type = cplus_demangle_type (di);
+ di->is_conversion = was_conversion;
+ return d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL);
+ }
else
{
/* LOW is the inclusive lower bound. */
@@ -1863,6 +1977,14 @@ d_special_name (struct d_info *di)
return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS,
cplus_demangle_type (di), NULL);
+ case 'H':
+ return d_make_comp (di, DEMANGLE_COMPONENT_TLS_INIT,
+ d_name (di), NULL);
+
+ case 'W':
+ return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER,
+ d_name (di), NULL);
+
default:
return NULL;
}
@@ -2118,8 +2240,28 @@ cplus_demangle_type (struct d_info *di)
pret = d_cv_qualifiers (di, &ret, 0);
if (pret == NULL)
return NULL;
- *pret = cplus_demangle_type (di);
- if (! *pret || ! d_add_substitution (di, ret))
+ if (d_peek_char (di) == 'F')
+ {
+ /* cv-qualifiers before a function type apply to 'this',
+ so avoid adding the unqualified function type to
+ the substitution list. */
+ *pret = d_function_type (di);
+ }
+ else
+ *pret = cplus_demangle_type (di);
+ if (!*pret)
+ return NULL;
+ if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
+ || (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS)
+ {
+ /* Move the ref-qualifier outside the cv-qualifiers so that
+ they are printed in the right order. */
+ struct demangle_component *fn = d_left (*pret);
+ d_left (*pret) = ret;
+ ret = *pret;
+ *pret = fn;
+ }
+ if (! d_add_substitution (di, ret))
return NULL;
return ret;
}
@@ -2168,13 +2310,61 @@ cplus_demangle_type (struct d_info *di)
ret = d_template_param (di);
if (d_peek_char (di) == 'I')
{
- /* This is <template-template-param> <template-args>. The
- <template-template-param> part is a substitution
+ /* This may be <template-template-param> <template-args>.
+ If this is the type for a conversion operator, we can
+ have a <template-template-param> here only by following
+ a derivation like this:
+
+ <nested-name>
+ -> <template-prefix> <template-args>
+ -> <prefix> <template-unqualified-name> <template-args>
+ -> <unqualified-name> <template-unqualified-name> <template-args>
+ -> <source-name> <template-unqualified-name> <template-args>
+ -> <source-name> <operator-name> <template-args>
+ -> <source-name> cv <type> <template-args>
+ -> <source-name> cv <template-template-param> <template-args> <template-args>
+
+ where the <template-args> is followed by another.
+ Otherwise, we must have a derivation like this:
+
+ <nested-name>
+ -> <template-prefix> <template-args>
+ -> <prefix> <template-unqualified-name> <template-args>
+ -> <unqualified-name> <template-unqualified-name> <template-args>
+ -> <source-name> <template-unqualified-name> <template-args>
+ -> <source-name> <operator-name> <template-args>
+ -> <source-name> cv <type> <template-args>
+ -> <source-name> cv <template-param> <template-args>
+
+ where we need to leave the <template-args> to be processed
+ by d_prefix (following the <template-prefix>).
+
+ The <template-template-param> part is a substitution
candidate. */
- if (! d_add_substitution (di, ret))
- return NULL;
- ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
- d_template_args (di));
+ if (! di->is_conversion)
+ {
+ if (! d_add_substitution (di, ret))
+ return NULL;
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
+ d_template_args (di));
+ }
+ else
+ {
+ struct demangle_component *args;
+ struct d_info_checkpoint checkpoint;
+
+ d_checkpoint (di, &checkpoint);
+ args = d_template_args (di);
+ if (d_peek_char (di) == 'I')
+ {
+ if (! d_add_substitution (di, ret))
+ return NULL;
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
+ args);
+ }
+ else
+ d_backtrack (di, &checkpoint);
+ }
}
break;
@@ -2422,7 +2612,38 @@ d_cv_qualifiers (struct d_info *di,
return pret;
}
-/* <function-type> ::= F [Y] <bare-function-type> E */
+/* <ref-qualifier> ::= R
+ ::= O */
+
+static struct demangle_component *
+d_ref_qualifier (struct d_info *di, struct demangle_component *sub)
+{
+ struct demangle_component *ret = sub;
+ char peek;
+
+ peek = d_peek_char (di);
+ if (peek == 'R' || peek == 'O')
+ {
+ enum demangle_component_type t;
+ if (peek == 'R')
+ {
+ t = DEMANGLE_COMPONENT_REFERENCE_THIS;
+ di->expansion += sizeof "&";
+ }
+ else
+ {
+ t = DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS;
+ di->expansion += sizeof "&&";
+ }
+ d_advance (di, 1);
+
+ ret = d_make_comp (di, t, ret, NULL);
+ }
+
+ return ret;
+}
+
+/* <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E */
static struct demangle_component *
d_function_type (struct d_info *di)
@@ -2438,6 +2659,8 @@ d_function_type (struct d_info *di)
d_advance (di, 1);
}
ret = d_bare_function_type (di, 1);
+ ret = d_ref_qualifier (di, ret);
+
if (! d_check_char (di, 'E'))
return NULL;
return ret;
@@ -2460,6 +2683,10 @@ d_parmlist (struct d_info *di)
char peek = d_peek_char (di);
if (peek == '\0' || peek == 'E' || peek == '.')
break;
+ if ((peek == 'R' || peek == 'O')
+ && d_peek_next_char (di) == 'E')
+ /* Function ref-qualifier, not a ref prefix for a parameter type. */
+ break;
type = cplus_demangle_type (di);
if (type == NULL)
return NULL;
@@ -2610,41 +2837,32 @@ d_pointer_to_member_type (struct d_info *di)
{
struct demangle_component *cl;
struct demangle_component *mem;
- struct demangle_component **pmem;
if (! d_check_char (di, 'M'))
return NULL;
cl = cplus_demangle_type (di);
-
- /* The ABI specifies that any type can be a substitution source, and
- that M is followed by two types, and that when a CV-qualified
- type is seen both the base type and the CV-qualified types are
- substitution sources. The ABI also specifies that for a pointer
- to a CV-qualified member function, the qualifiers are attached to
- the second type. Given the grammar, a plain reading of the ABI
- suggests that both the CV-qualified member function and the
- non-qualified member function are substitution sources. However,
- g++ does not work that way. g++ treats only the CV-qualified
- member function as a substitution source. FIXME. So to work
- with g++, we need to pull off the CV-qualifiers here, in order to
- avoid calling add_substitution() in cplus_demangle_type(). But
- for a CV-qualified member which is not a function, g++ does
- follow the ABI, so we need to handle that case here by calling
- d_add_substitution ourselves. */
-
- pmem = d_cv_qualifiers (di, &mem, 1);
- if (pmem == NULL)
- return NULL;
- *pmem = cplus_demangle_type (di);
- if (*pmem == NULL)
+ if (cl == NULL)
return NULL;
- if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
- {
- if (! d_add_substitution (di, mem))
- return NULL;
- }
+ /* The ABI says, "The type of a non-static member function is considered
+ to be different, for the purposes of substitution, from the type of a
+ namespace-scope or static member function whose type appears
+ similar. The types of two non-static member functions are considered
+ to be different, for the purposes of substitution, if the functions
+ are members of different classes. In other words, for the purposes of
+ substitution, the class of which the function is a member is
+ considered part of the type of function."
+
+ For a pointer to member function, this call to cplus_demangle_type
+ will end up adding a (possibly qualified) non-member function type to
+ the substitution table, which is not correct; however, the member
+ function type will never be used in a substitution, so putting the
+ wrong type in the substitution table is harmless. */
+
+ mem = cplus_demangle_type (di);
+ if (mem == NULL)
+ return NULL;
return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
}
@@ -2809,6 +3027,18 @@ d_exprlist (struct d_info *di, char terminator)
return list;
}
+/* Returns nonzero iff OP is an operator for a C++ cast: const_cast,
+ dynamic_cast, static_cast or reinterpret_cast. */
+
+static int
+op_is_new_cast (struct demangle_component *op)
+{
+ const char *code = op->u.s_operator.op->code;
+ return (code[1] == 'c'
+ && (code[0] == 's' || code[0] == 'd'
+ || code[0] == 'c' || code[0] == 'r'));
+}
+
/* <expression> ::= <(unary) operator-name> <expression>
::= <(binary) operator-name> <expression> <expression>
::= <(trinary) operator-name> <expression> <expression> <expression>
@@ -2820,8 +3050,8 @@ d_exprlist (struct d_info *di, char terminator)
::= <expr-primary>
*/
-static struct demangle_component *
-d_expression (struct d_info *di)
+static inline struct demangle_component *
+d_expression_1 (struct d_info *di)
{
char peek;
@@ -2849,7 +3079,7 @@ d_expression (struct d_info *di)
{
d_advance (di, 2);
return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
- d_expression (di), NULL);
+ d_expression_1 (di), NULL);
}
else if (peek == 'f' && d_peek_next_char (di) == 'p')
{
@@ -2954,7 +3184,7 @@ d_expression (struct d_info *di)
&& d_check_char (di, '_'))
operand = d_exprlist (di, 'E');
else
- operand = d_expression (di);
+ operand = d_expression_1 (di);
if (suffix)
/* Indicate the suffix variant for d_print_comp. */
@@ -2971,7 +3201,10 @@ d_expression (struct d_info *di)
struct demangle_component *left;
struct demangle_component *right;
- left = d_expression (di);
+ if (op_is_new_cast (op))
+ left = cplus_demangle_type (di);
+ else
+ left = d_expression_1 (di);
if (!strcmp (code, "cl"))
right = d_exprlist (di, 'E');
else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
@@ -2982,7 +3215,7 @@ d_expression (struct d_info *di)
right, d_template_args (di));
}
else
- right = d_expression (di);
+ right = d_expression_1 (di);
return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op,
d_make_comp (di,
@@ -2998,9 +3231,9 @@ d_expression (struct d_info *di)
if (!strcmp (code, "qu"))
{
/* ?: expression. */
- first = d_expression (di);
- second = d_expression (di);
- third = d_expression (di);
+ first = d_expression_1 (di);
+ second = d_expression_1 (di);
+ third = d_expression_1 (di);
}
else if (code[0] == 'n')
{
@@ -3024,7 +3257,7 @@ d_expression (struct d_info *di)
else if (d_peek_char (di) == 'i'
&& d_peek_next_char (di) == 'l')
/* initializer-list. */
- third = d_expression (di);
+ third = d_expression_1 (di);
else
return NULL;
}
@@ -3044,6 +3277,18 @@ d_expression (struct d_info *di)
}
}
+static struct demangle_component *
+d_expression (struct d_info *di)
+{
+ struct demangle_component *ret;
+ int was_expression = di->is_expression;
+
+ di->is_expression = 1;
+ ret = d_expression_1 (di);
+ di->is_expression = was_expression;
+ return ret;
+}
+
/* <expr-primary> ::= L <type> <(value) number> E
::= L <type> <(value) float> E
::= L <mangled-name> E
@@ -3109,6 +3354,7 @@ d_expr_primary (struct d_info *di)
/* <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]
::= Z <(function) encoding> E s [<discriminator>]
+ ::= Z <(function) encoding> E d [<parameter> number>] _ <entity name>
*/
static struct demangle_component *
@@ -3428,6 +3674,26 @@ d_substitution (struct d_info *di, int prefix)
}
}
+static void
+d_checkpoint (struct d_info *di, struct d_info_checkpoint *checkpoint)
+{
+ checkpoint->n = di->n;
+ checkpoint->next_comp = di->next_comp;
+ checkpoint->next_sub = di->next_sub;
+ checkpoint->did_subs = di->did_subs;
+ checkpoint->expansion = di->expansion;
+}
+
+static void
+d_backtrack (struct d_info *di, struct d_info_checkpoint *checkpoint)
+{
+ di->n = checkpoint->n;
+ di->next_comp = checkpoint->next_comp;
+ di->next_sub = checkpoint->next_sub;
+ di->did_subs = checkpoint->did_subs;
+ di->expansion = checkpoint->expansion;
+}
+
/* Initialize a growable string. */
static void
@@ -3521,6 +3787,31 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
dpi->opaque = opaque;
dpi->demangle_failure = 0;
+
+ dpi->saved_scopes = NULL;
+ dpi->num_saved_scopes = 0;
+ dpi->current_template = NULL;
+}
+
+/* Free a print information structure. */
+
+static void
+d_print_free (struct d_print_info *dpi)
+{
+ int i;
+
+ for (i = 0; i < dpi->num_saved_scopes; i++)
+ {
+ struct d_print_template *ts, *tn;
+
+ for (ts = dpi->saved_scopes[i].templates; ts != NULL; ts = tn)
+ {
+ tn = ts->next;
+ free (ts);
+ }
+ }
+
+ free (dpi->saved_scopes);
}
/* Indicate that an error occurred during printing, and test for error. */
@@ -3605,6 +3896,7 @@ cplus_demangle_print_callback (int options,
demangle_callbackref callback, void *opaque)
{
struct d_print_info dpi;
+ int success;
d_print_init (&dpi, callback, opaque);
@@ -3612,7 +3904,9 @@ cplus_demangle_print_callback (int options,
d_print_flush (&dpi);
- return ! d_print_saw_error (&dpi);
+ success = ! d_print_saw_error (&dpi);
+ d_print_free (&dpi);
+ return success;
}
/* Turn components into a human readable string. OPTIONS is the
@@ -3710,6 +4004,7 @@ d_find_pack (struct d_print_info *dpi,
case DEMANGLE_COMPONENT_LAMBDA:
case DEMANGLE_COMPONENT_NAME:
+ case DEMANGLE_COMPONENT_TAGGED_NAME:
case DEMANGLE_COMPONENT_OPERATOR:
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
case DEMANGLE_COMPONENT_SUB_STD:
@@ -3768,6 +4063,36 @@ d_print_subexpr (struct d_print_info *dpi, int options,
d_append_char (dpi, ')');
}
+/* Return a shallow copy of the current list of templates.
+ On error d_print_error is called and a partial list may
+ be returned. Whatever is returned must be freed. */
+
+static struct d_print_template *
+d_copy_templates (struct d_print_info *dpi)
+{
+ struct d_print_template *src, *result, **link = &result;
+
+ for (src = dpi->templates; src != NULL; src = src->next)
+ {
+ struct d_print_template *dst =
+ (struct d_print_template *) malloc (sizeof (struct d_print_template));
+
+ if (dst == NULL)
+ {
+ d_print_error (dpi);
+ break;
+ }
+
+ dst->template_decl = src->template_decl;
+ *link = dst;
+ link = &dst->next;
+ }
+
+ *link = NULL;
+
+ return result;
+}
+
/* Subroutine to handle components. */
static void
@@ -3778,6 +4103,13 @@ d_print_comp (struct d_print_info *dpi, int options,
without needing to modify *dc. */
const struct demangle_component *mod_inner = NULL;
+ /* Variable used to store the current templates while a previously
+ captured scope is used. */
+ struct d_print_template *saved_templates;
+
+ /* Nonzero if templates have been stored in the above variable. */
+ int need_template_restore = 0;
+
if (dc == NULL)
{
d_print_error (dpi);
@@ -3795,6 +4127,13 @@ d_print_comp (struct d_print_info *dpi, int options,
d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
return;
+ case DEMANGLE_COMPONENT_TAGGED_NAME:
+ d_print_comp (dpi, options, d_left (dc));
+ d_append_string (dpi, "[abi:");
+ d_print_comp (dpi, options, d_right (dc));
+ d_append_char (dpi, ']');
+ return;
+
case DEMANGLE_COMPONENT_QUAL_NAME:
case DEMANGLE_COMPONENT_LOCAL_NAME:
d_print_comp (dpi, options, d_left (dc));
@@ -3802,7 +4141,17 @@ d_print_comp (struct d_print_info *dpi, int options,
d_append_string (dpi, "::");
else
d_append_char (dpi, '.');
- d_print_comp (dpi, options, d_right (dc));
+ {
+ struct demangle_component *local_name = d_right (dc);
+ if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
+ {
+ d_append_string (dpi, "{default arg#");
+ d_append_num (dpi, local_name->u.s_unary_num.num + 1);
+ d_append_string (dpi, "}::");
+ local_name = local_name->u.s_unary_num.sub;
+ }
+ d_print_comp (dpi, options, local_name);
+ }
return;
case DEMANGLE_COMPONENT_TYPED_NAME:
@@ -3837,7 +4186,9 @@ d_print_comp (struct d_print_info *dpi, int options,
if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS
&& typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS
- && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS)
+ && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS
+ && typed_name->type != DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
+ && typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS)
break;
typed_name = d_left (typed_name);
@@ -3871,7 +4222,10 @@ d_print_comp (struct d_print_info *dpi, int options,
local_name = local_name->u.s_unary_num.sub;
while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS
- || local_name->type == DEMANGLE_COMPONENT_CONST_THIS)
+ || local_name->type == DEMANGLE_COMPONENT_CONST_THIS
+ || local_name->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+ || (local_name->type
+ == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))
{
if (i >= sizeof adpm / sizeof adpm[0])
{
@@ -3918,6 +4272,12 @@ d_print_comp (struct d_print_info *dpi, int options,
{
struct d_print_mod *hold_dpm;
struct demangle_component *dcl;
+ const struct demangle_component *hold_current;
+
+ /* This template may need to be referenced by a cast operator
+ contained in its subtree. */
+ hold_current = dpi->current_template;
+ dpi->current_template = dc;
/* Don't push modifiers into a template definition. Doing so
could give the wrong definition for a template argument.
@@ -3954,6 +4314,7 @@ d_print_comp (struct d_print_info *dpi, int options,
}
dpi->modifiers = hold_dpm;
+ dpi->current_template = hold_current;
return;
}
@@ -4053,6 +4414,16 @@ d_print_comp (struct d_print_info *dpi, int options,
d_print_comp (dpi, options, d_left (dc));
return;
+ case DEMANGLE_COMPONENT_TLS_INIT:
+ d_append_string (dpi, "TLS init function for ");
+ d_print_comp (dpi, options, d_left (dc));
+ return;
+
+ case DEMANGLE_COMPONENT_TLS_WRAPPER:
+ d_append_string (dpi, "TLS wrapper function for ");
+ d_print_comp (dpi, options, d_left (dc));
+ return;
+
case DEMANGLE_COMPONENT_REFTEMP:
d_append_string (dpi, "reference temporary #");
d_print_comp (dpi, options, d_right (dc));
@@ -4114,12 +4485,58 @@ d_print_comp (struct d_print_info *dpi, int options,
const struct demangle_component *sub = d_left (dc);
if (sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
{
- struct demangle_component *a = d_lookup_template_argument (dpi, sub);
+ struct demangle_component *a;
+ struct d_saved_scope *scope = NULL, *scopes;
+ int i;
+
+ for (i = 0; i < dpi->num_saved_scopes; i++)
+ if (dpi->saved_scopes[i].container == sub)
+ scope = &dpi->saved_scopes[i];
+
+ if (scope == NULL)
+ {
+ size_t size;
+
+ /* This is the first time SUB has been traversed.
+ We need to capture the current templates so
+ they can be restored if SUB is reentered as a
+ substitution. */
+ ++dpi->num_saved_scopes;
+ size = sizeof (struct d_saved_scope) * dpi->num_saved_scopes;
+ scopes = (struct d_saved_scope *) realloc (dpi->saved_scopes,
+ size);
+ if (scopes == NULL)
+ {
+ d_print_error (dpi);
+ return;
+ }
+
+ dpi->saved_scopes = scopes;
+ scope = dpi->saved_scopes + (dpi->num_saved_scopes - 1);
+
+ scope->container = sub;
+ scope->templates = d_copy_templates (dpi);
+ if (d_print_saw_error (dpi))
+ return;
+ }
+ else
+ {
+ /* This traversal is reentering SUB as a substition.
+ Restore the original templates temporarily. */
+ saved_templates = dpi->templates;
+ dpi->templates = scope->templates;
+ need_template_restore = 1;
+ }
+
+ a = d_lookup_template_argument (dpi, sub);
if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
a = d_index_template_argument (a, dpi->pack_index);
if (a == NULL)
{
+ if (need_template_restore)
+ dpi->templates = saved_templates;
+
d_print_error (dpi);
return;
}
@@ -4138,6 +4555,8 @@ d_print_comp (struct d_print_info *dpi, int options,
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_REFERENCE_THIS:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
case DEMANGLE_COMPONENT_POINTER:
case DEMANGLE_COMPONENT_COMPLEX:
@@ -4165,6 +4584,9 @@ d_print_comp (struct d_print_info *dpi, int options,
dpi->modifiers = dpm.next;
+ if (need_template_restore)
+ dpi->templates = saved_templates;
+
return;
}
@@ -4455,6 +4877,17 @@ d_print_comp (struct d_print_info *dpi, int options,
return;
}
+ if (op_is_new_cast (d_left (dc)))
+ {
+ d_print_expr_op (dpi, options, d_left (dc));
+ d_append_char (dpi, '<');
+ d_print_comp (dpi, options, d_left (d_right (dc)));
+ d_append_string (dpi, ">(");
+ d_print_comp (dpi, options, d_right (d_right (dc)));
+ d_append_char (dpi, ')');
+ 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. */
@@ -4799,7 +5232,10 @@ d_print_mod_list (struct d_print_info *dpi, int options,
|| (! suffix
&& (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
- || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS)))
+ || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS
+ || mods->mod->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+ || (mods->mod->type
+ == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))))
{
d_print_mod_list (dpi, options, mods->next, suffix);
return;
@@ -4854,7 +5290,9 @@ d_print_mod_list (struct d_print_info *dpi, int options,
while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
- || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
+ || dc->type == DEMANGLE_COMPONENT_CONST_THIS
+ || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+ || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
dc = d_left (dc);
d_print_comp (dpi, options, dc);
@@ -4899,9 +5337,14 @@ d_print_mod (struct d_print_info *dpi, int options,
if ((options & DMGL_JAVA) == 0)
d_append_char (dpi, '*');
return;
+ case DEMANGLE_COMPONENT_REFERENCE_THIS:
+ /* For the ref-qualifier, put a space before the &. */
+ d_append_char (dpi, ' ');
case DEMANGLE_COMPONENT_REFERENCE:
d_append_char (dpi, '&');
return;
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+ d_append_char (dpi, ' ');
case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
d_append_string (dpi, "&&");
return;
@@ -4973,6 +5416,8 @@ d_print_function_type (struct d_print_info *dpi, int options,
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_REFERENCE_THIS:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
break;
default:
break;
@@ -5087,28 +5532,32 @@ static void
d_print_cast (struct d_print_info *dpi, int options,
const struct demangle_component *dc)
{
- if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
- d_print_comp (dpi, options, d_left (dc));
- else
- {
- struct d_print_mod *hold_dpm;
- struct d_print_template dpt;
-
- /* It appears that for a templated cast operator, we need to put
- the template parameters in scope for the operator name, but
- not for the parameters. The effect is that we need to handle
- the template printing here. */
-
- hold_dpm = dpi->modifiers;
- dpi->modifiers = NULL;
+ struct d_print_template dpt;
+ /* For a cast operator, we need the template parameters from
+ the enclosing template in scope for processing the type. */
+ if (dpi->current_template != NULL)
+ {
dpt.next = dpi->templates;
dpi->templates = &dpt;
- dpt.template_decl = d_left (dc);
+ dpt.template_decl = dpi->current_template;
+ }
+ if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
+ {
+ d_print_comp (dpi, options, d_left (dc));
+ if (dpi->current_template != NULL)
+ dpi->templates = dpt.next;
+ }
+ else
+ {
d_print_comp (dpi, options, d_left (d_left (dc)));
- dpi->templates = dpt.next;
+ /* For a templated cast operator, we need to remove the template
+ parameters from scope after printing the operator name,
+ so we need to handle the template printing here. */
+ if (dpi->current_template != NULL)
+ dpi->templates = dpt.next;
if (d_last_char (dpi) == '<')
d_append_char (dpi, ' ');
@@ -5119,8 +5568,6 @@ d_print_cast (struct d_print_info *dpi, int options,
if (d_last_char (dpi) == '>')
d_append_char (dpi, ' ');
d_append_char (dpi, '>');
-
- dpi->modifiers = hold_dpm;
}
}
@@ -5153,6 +5600,8 @@ cplus_demangle_init_info (const char *mangled, int options, size_t len,
di->last_name = NULL;
di->expansion = 0;
+ di->is_expression = 0;
+ di->is_conversion = 0;
}
/* Internal implementation for the demangler. If MANGLED is a g++ v3 ABI
@@ -5493,14 +5942,17 @@ is_ctor_or_dtor (const char *mangled,
{
switch (dc->type)
{
+ /* These cannot appear on a constructor or destructor. */
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_REFERENCE_THIS:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
default:
dc = NULL;
break;
case DEMANGLE_COMPONENT_TYPED_NAME:
case DEMANGLE_COMPONENT_TEMPLATE:
- case DEMANGLE_COMPONENT_RESTRICT_THIS:
- case DEMANGLE_COMPONENT_VOLATILE_THIS:
- case DEMANGLE_COMPONENT_CONST_THIS:
dc = d_left (dc);
break;
case DEMANGLE_COMPONENT_QUAL_NAME:
« no previous file with comments | « libiberty/cp-demangle.h ('k') | libiberty/floatformat.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698