/* Demangler for g++ V3 ABI.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014
Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@wasabisystems.com>.
int allocation_failure;
};
+/* Stack of components, innermost first, used to avoid loops. */
+
+struct d_component_stack
+{
+ /* This component. */
+ const struct demangle_component *dc;
+ /* This component's parent. */
+ const struct d_component_stack *parent;
+};
+
+/* 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
{
int pack_index;
/* Number of d_print_flush calls so far. */
unsigned long int flush_count;
+ /* Stack of components, innermost first, used to avoid loops. */
+ const struct d_component_stack *component_stack;
+ /* Array of saved scopes for evaluating substitutions. */
+ struct d_saved_scope *saved_scopes;
+ /* Index of the next unused saved scope in the above array. */
+ int next_saved_scope;
+ /* Number of saved scopes in the above array. */
+ int num_saved_scopes;
+ /* Array of templates for saving into scopes. */
+ struct d_print_template *copy_templates;
+ /* Index of the next unused copy template in the above array. */
+ int next_copy_template;
+ /* Number of copy templates in the above array. */
+ int num_copy_templates;
+ /* The nearest enclosing template, if any. */
+ const struct demangle_component *current_template;
};
#ifdef CP_DEMANGLE_DEBUG
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
d_growable_string_callback_adapter (const char *, size_t, void *);
static void
-d_print_init (struct d_print_info *, demangle_callbackref, void *);
+d_print_init (struct d_print_info *, demangle_callbackref, void *,
+ const struct demangle_component *);
static inline void d_print_error (struct d_print_info *);
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
printf ("template parameter %ld\n", dc->u.s_number.number);
return;
+ case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+ printf ("function parameter %ld\n", dc->u.s_number.number);
+ return;
case DEMANGLE_COMPONENT_CTOR:
printf ("constructor %d\n", (int) dc->u.s_ctor.kind);
d_dump (dc->u.s_ctor.name, indent + 2);
printf ("pointer to member type\n");
break;
case DEMANGLE_COMPONENT_FIXED_TYPE:
- printf ("fixed-point type\n");
+ printf ("fixed-point type, accum? %d, sat? %d\n",
+ dc->u.s_fixed.accum, dc->u.s_fixed.sat);
+ d_dump (dc->u.s_fixed.length, indent + 2)
break;
case DEMANGLE_COMPONENT_ARGLIST:
printf ("argument list\n");
case DEMANGLE_COMPONENT_CHARACTER:
printf ("character '%c'\n", dc->u.s_character.character);
return;
+ case DEMANGLE_COMPONENT_NUMBER:
+ printf ("number %ld\n", dc->u.s_number.number);
+ return;
case DEMANGLE_COMPONENT_DECLTYPE:
printf ("decltype\n");
break;
case 'Z':
return d_local_name (di);
- case 'L':
case 'U':
return d_unqualified_name (di);
return dc;
}
+ case 'L':
default:
dc = d_unqualified_name (di);
if (d_peek_char (di) == 'I')
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. */
case '3':
kind = gnu_v3_complete_object_allocating_ctor;
break;
+ case '4':
+ kind = gnu_v3_unified_ctor;
+ break;
case '5':
kind = gnu_v3_object_ctor_group;
break;
case '2':
kind = gnu_v3_base_object_dtor;
break;
+ /* digit '3' is not used */
+ case '4':
+ kind = gnu_v3_unified_dtor;
+ break;
case '5':
kind = gnu_v3_object_dtor_group;
break;
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;
case 'U':
d_advance (di, 1);
ret = d_source_name (di);
+ if (d_peek_char (di) == 'I')
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
+ d_template_args (di));
ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL,
cplus_demangle_type (di), ret);
break;
::= <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;
{
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')
{
&& 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. */
if (op_is_new_cast (op))
left = cplus_demangle_type (di);
else
- left = d_expression (di);
+ left = d_expression_1 (di);
if (!strcmp (code, "cl"))
right = d_exprlist (di, 'E');
else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
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,
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')
{
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;
}
}
}
+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
{
const char *s;
int len;
+ struct demangle_component *c;
if (p->set_last_name != NULL)
di->last_name = d_make_sub (di, p->set_last_name,
len = p->simple_len;
}
di->expansion += len;
- return d_make_sub (di, s, len);
+ c = d_make_sub (di, s, len);
+ if (d_peek_char (di) == 'B')
+ {
+ /* If there are ABI tags on the abbreviation, it becomes
+ a substitution candidate. */
+ c = d_abi_tags (di, c);
+ d_add_substitution (di, c);
+ }
+ return c;
}
}
}
}
+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
d_growable_string_append_buffer (dgs, s, l);
}
+/* Walk the tree, counting the number of templates encountered, and
+ the number of times a scope might be saved. These counts will be
+ used to allocate data structures for d_print_comp, so the logic
+ here must mirror the logic d_print_comp will use. It is not
+ important that the resulting numbers are exact, so long as they
+ are larger than the actual numbers encountered. */
+
+static void
+d_count_templates_scopes (int *num_templates, int *num_scopes,
+ const struct demangle_component *dc)
+{
+ if (dc == NULL)
+ return;
+
+ switch (dc->type)
+ {
+ case DEMANGLE_COMPONENT_NAME:
+ case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+ case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+ case DEMANGLE_COMPONENT_SUB_STD:
+ case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+ case DEMANGLE_COMPONENT_OPERATOR:
+ case DEMANGLE_COMPONENT_CHARACTER:
+ case DEMANGLE_COMPONENT_NUMBER:
+ case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+ break;
+
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ (*num_templates)++;
+ goto recurse_left_right;
+
+ case DEMANGLE_COMPONENT_REFERENCE:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+ if (d_left (dc)->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
+ (*num_scopes)++;
+ goto recurse_left_right;
+
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ case DEMANGLE_COMPONENT_TYPED_NAME:
+ case DEMANGLE_COMPONENT_VTABLE:
+ case DEMANGLE_COMPONENT_VTT:
+ case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
+ case DEMANGLE_COMPONENT_TYPEINFO:
+ case DEMANGLE_COMPONENT_TYPEINFO_NAME:
+ case DEMANGLE_COMPONENT_TYPEINFO_FN:
+ case DEMANGLE_COMPONENT_THUNK:
+ case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
+ 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_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST:
+ 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:
+ case DEMANGLE_COMPONENT_IMAGINARY:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE:
+ case DEMANGLE_COMPONENT_FUNCTION_TYPE:
+ case DEMANGLE_COMPONENT_ARRAY_TYPE:
+ case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+ case DEMANGLE_COMPONENT_VECTOR_TYPE:
+ case DEMANGLE_COMPONENT_ARGLIST:
+ case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
+ case DEMANGLE_COMPONENT_INITIALIZER_LIST:
+ case DEMANGLE_COMPONENT_CAST:
+ case DEMANGLE_COMPONENT_NULLARY:
+ case DEMANGLE_COMPONENT_UNARY:
+ case DEMANGLE_COMPONENT_BINARY:
+ case DEMANGLE_COMPONENT_BINARY_ARGS:
+ case DEMANGLE_COMPONENT_TRINARY:
+ case DEMANGLE_COMPONENT_TRINARY_ARG1:
+ case DEMANGLE_COMPONENT_TRINARY_ARG2:
+ case DEMANGLE_COMPONENT_LITERAL:
+ case DEMANGLE_COMPONENT_LITERAL_NEG:
+ case DEMANGLE_COMPONENT_JAVA_RESOURCE:
+ case DEMANGLE_COMPONENT_COMPOUND_NAME:
+ case DEMANGLE_COMPONENT_DECLTYPE:
+ case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
+ case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
+ case DEMANGLE_COMPONENT_PACK_EXPANSION:
+ case DEMANGLE_COMPONENT_TAGGED_NAME:
+ case DEMANGLE_COMPONENT_CLONE:
+ recurse_left_right:
+ d_count_templates_scopes (num_templates, num_scopes,
+ d_left (dc));
+ d_count_templates_scopes (num_templates, num_scopes,
+ d_right (dc));
+ break;
+
+ case DEMANGLE_COMPONENT_CTOR:
+ d_count_templates_scopes (num_templates, num_scopes,
+ dc->u.s_ctor.name);
+ break;
+
+ case DEMANGLE_COMPONENT_DTOR:
+ d_count_templates_scopes (num_templates, num_scopes,
+ dc->u.s_dtor.name);
+ break;
+
+ case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+ d_count_templates_scopes (num_templates, num_scopes,
+ dc->u.s_extended_operator.name);
+ break;
+
+ case DEMANGLE_COMPONENT_FIXED_TYPE:
+ d_count_templates_scopes (num_templates, num_scopes,
+ dc->u.s_fixed.length);
+ break;
+
+ case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
+ case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
+ d_count_templates_scopes (num_templates, num_scopes,
+ d_left (dc));
+ break;
+
+ case DEMANGLE_COMPONENT_LAMBDA:
+ case DEMANGLE_COMPONENT_DEFAULT_ARG:
+ d_count_templates_scopes (num_templates, num_scopes,
+ dc->u.s_unary_num.sub);
+ break;
+ }
+}
+
/* Initialize a print information structure. */
static void
d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
- void *opaque)
+ void *opaque, const struct demangle_component *dc)
{
dpi->len = 0;
dpi->last_char = '\0';
dpi->opaque = opaque;
dpi->demangle_failure = 0;
+
+ dpi->component_stack = NULL;
+
+ dpi->saved_scopes = NULL;
+ dpi->next_saved_scope = 0;
+ dpi->num_saved_scopes = 0;
+
+ dpi->copy_templates = NULL;
+ dpi->next_copy_template = 0;
+ dpi->num_copy_templates = 0;
+
+ d_count_templates_scopes (&dpi->num_copy_templates,
+ &dpi->num_saved_scopes, dc);
+ dpi->num_copy_templates *= dpi->num_saved_scopes;
+
+ dpi->current_template = NULL;
}
/* Indicate that an error occurred during printing, and test for error. */
{
struct d_print_info dpi;
- d_print_init (&dpi, callback, opaque);
+ d_print_init (&dpi, callback, opaque, dc);
- d_print_comp (&dpi, options, dc);
+ {
+#ifdef CP_DYNAMIC_ARRAYS
+ __extension__ struct d_saved_scope scopes[dpi.num_saved_scopes];
+ __extension__ struct d_print_template temps[dpi.num_copy_templates];
+
+ dpi.saved_scopes = scopes;
+ dpi.copy_templates = temps;
+#else
+ dpi.saved_scopes = alloca (dpi.num_saved_scopes
+ * sizeof (*dpi.saved_scopes));
+ dpi.copy_templates = alloca (dpi.num_copy_templates
+ * sizeof (*dpi.copy_templates));
+#endif
+
+ d_print_comp (&dpi, options, dc);
+ }
d_print_flush (&dpi);
d_append_char (dpi, ')');
}
+/* Save the current scope. */
+
+static void
+d_save_scope (struct d_print_info *dpi,
+ const struct demangle_component *container)
+{
+ struct d_saved_scope *scope;
+ struct d_print_template *src, **link;
+
+ if (dpi->next_saved_scope >= dpi->num_saved_scopes)
+ {
+ d_print_error (dpi);
+ return;
+ }
+ scope = &dpi->saved_scopes[dpi->next_saved_scope];
+ dpi->next_saved_scope++;
+
+ scope->container = container;
+ link = &scope->templates;
+
+ for (src = dpi->templates; src != NULL; src = src->next)
+ {
+ struct d_print_template *dst;
+
+ if (dpi->next_copy_template >= dpi->num_copy_templates)
+ {
+ d_print_error (dpi);
+ return;
+ }
+ dst = &dpi->copy_templates[dpi->next_copy_template];
+ dpi->next_copy_template++;
+
+ dst->template_decl = src->template_decl;
+ *link = dst;
+ link = &dst->next;
+ }
+
+ *link = NULL;
+}
+
+/* Attempt to locate a previously saved scope. Returns NULL if no
+ corresponding saved scope was found. */
+
+static struct d_saved_scope *
+d_get_saved_scope (struct d_print_info *dpi,
+ const struct demangle_component *container)
+{
+ int i;
+
+ for (i = 0; i < dpi->next_saved_scope; i++)
+ if (dpi->saved_scopes[i].container == container)
+ return &dpi->saved_scopes[i];
+
+ return NULL;
+}
+
/* Subroutine to handle components. */
static void
-d_print_comp (struct d_print_info *dpi, int options,
- const struct demangle_component *dc)
+d_print_comp_inner (struct d_print_info *dpi, int options,
+ const struct demangle_component *dc)
{
/* Magic variable to let reference smashing skip over the next modifier
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);
{
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.
}
dpi->modifiers = hold_dpm;
+ dpi->current_template = hold_current;
return;
}
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 d_saved_scope *scope = d_get_saved_scope (dpi, sub);
+ struct demangle_component *a;
+
+ if (scope == NULL)
+ {
+ /* 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. */
+ d_save_scope (dpi, sub);
+ if (d_print_saw_error (dpi))
+ return;
+ }
+ else
+ {
+ const struct d_component_stack *dcse;
+ int found_self_or_parent = 0;
+
+ /* This traversal is reentering SUB as a substition.
+ If we are not beneath SUB or DC in the tree then we
+ need to restore SUB's template stack temporarily. */
+ for (dcse = dpi->component_stack; dcse != NULL;
+ dcse = dcse->parent)
+ {
+ if (dcse->dc == sub
+ || (dcse->dc == dc
+ && dcse != dpi->component_stack))
+ {
+ found_self_or_parent = 1;
+ break;
+ }
+ }
+
+ if (!found_self_or_parent)
+ {
+ 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;
}
dpi->modifiers = dpm.next;
+ if (need_template_restore)
+ dpi->templates = saved_templates;
+
return;
}
}
}
+static void
+d_print_comp (struct d_print_info *dpi, int options,
+ const struct demangle_component *dc)
+{
+ struct d_component_stack self;
+
+ self.dc = dc;
+ self.parent = dpi->component_stack;
+ dpi->component_stack = &self;
+
+ d_print_comp_inner (dpi, options, dc);
+
+ dpi->component_stack = self.parent;
+}
+
/* Print a Java dentifier. For Java we try to handle encoded extended
Unicode characters. The C++ ABI doesn't mention Unicode encoding,
so we don't it for C++. Characters are encoded as
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, ' ');
if (d_last_char (dpi) == '>')
d_append_char (dpi, ' ');
d_append_char (dpi, '>');
-
- dpi->modifiers = hold_dpm;
}
}
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
NULL);
d_advance (&di, strlen (d_str (&di)));
break;
+ default:
+ abort (); /* We have listed all the cases. */
}
/* If DMGL_PARAMS is set, then if we didn't consume the entire