mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
c++: Fix demangling of <unresolved-name>
The ABI for unresolved scoped names on the RHS of . and -> used to be sr <type> <unqualified-id> That changed years ago to something more complex, but G++ was never updated. This change was particularly incompatible for simple qualified-ids like A::x, which were previously mangled as sr1A1x, and now sr1AE1x. This obviously makes life hard for demanglers, which can't know whether to consume that E or not. To work around this, we now try demangling with the newer ABI, and if that fails and we saw an "sr", try again with the older ABI. libiberty/ChangeLog: PR c++/67343 * cp-demangle.h (struct d_info): Add unresolved_name_state. * cp-demangle.c (d_prefix): Add subst parm. (d_nested_name): Pass it. (d_unresolved_name): Split out from... (d_expression_1): ...here. (d_demangle_callback): Maybe retry with old sr mangling. * testsuite/demangle-expected: Add test.
This commit is contained in:
parent
93ac0c05ff
commit
58fb912c15
@ -429,7 +429,7 @@ static struct demangle_component *d_name (struct d_info *);
|
||||
|
||||
static struct demangle_component *d_nested_name (struct d_info *);
|
||||
|
||||
static struct demangle_component *d_prefix (struct d_info *);
|
||||
static struct demangle_component *d_prefix (struct d_info *, int);
|
||||
|
||||
static struct demangle_component *d_unqualified_name (struct d_info *);
|
||||
|
||||
@ -1510,7 +1510,7 @@ d_nested_name (struct d_info *di)
|
||||
once we have something to attach it to. */
|
||||
rqual = d_ref_qualifier (di, NULL);
|
||||
|
||||
*pret = d_prefix (di);
|
||||
*pret = d_prefix (di, 1);
|
||||
if (*pret == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -1536,10 +1536,12 @@ d_nested_name (struct d_info *di)
|
||||
<template-prefix> ::= <prefix> <(template) unqualified-name>
|
||||
::= <template-param>
|
||||
::= <substitution>
|
||||
*/
|
||||
|
||||
SUBST is true if we should add substitutions (as normal), false
|
||||
if not (in an unresolved-name). */
|
||||
|
||||
static struct demangle_component *
|
||||
d_prefix (struct d_info *di)
|
||||
d_prefix (struct d_info *di, int subst)
|
||||
{
|
||||
struct demangle_component *ret = NULL;
|
||||
|
||||
@ -1605,7 +1607,7 @@ d_prefix (struct d_info *di)
|
||||
else
|
||||
ret = d_make_comp (di, comb_type, ret, dc);
|
||||
|
||||
if (peek != 'S' && d_peek_char (di) != 'E')
|
||||
if (peek != 'S' && d_peek_char (di) != 'E' && subst)
|
||||
{
|
||||
if (! d_add_substitution (di, ret))
|
||||
return NULL;
|
||||
@ -3291,14 +3293,58 @@ op_is_new_cast (struct demangle_component *op)
|
||||
|| code[0] == 'c' || code[0] == 'r'));
|
||||
}
|
||||
|
||||
/* <unresolved-name> ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
|
||||
::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
|
||||
# T::N::x /decltype(p)::N::x
|
||||
::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
|
||||
# A::x, N::y, A<T>::z; "gs" means leading "::"
|
||||
::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
|
||||
|
||||
"gs" is handled elsewhere, as a unary operator. */
|
||||
|
||||
static struct demangle_component *
|
||||
d_unresolved_name (struct d_info *di)
|
||||
{
|
||||
struct demangle_component *type;
|
||||
struct demangle_component *name;
|
||||
char peek;
|
||||
|
||||
/* Consume the "sr". */
|
||||
d_advance (di, 2);
|
||||
|
||||
peek = d_peek_char (di);
|
||||
if (di->unresolved_name_state
|
||||
&& (IS_DIGIT (peek)
|
||||
|| IS_LOWER (peek)
|
||||
|| peek == 'C'
|
||||
|| peek == 'U'
|
||||
|| peek == 'L'))
|
||||
{
|
||||
/* The third production is ambiguous with the old unresolved-name syntax
|
||||
of <type> <base-unresolved-name>; in the old mangling, A::x was mangled
|
||||
as sr1A1x, now sr1AE1x. So we first try to demangle using the new
|
||||
mangling, then with the old if that fails. */
|
||||
di->unresolved_name_state = -1;
|
||||
type = d_prefix (di, 0);
|
||||
if (d_peek_char (di) == 'E')
|
||||
d_advance (di, 1);
|
||||
}
|
||||
else
|
||||
type = cplus_demangle_type (di);
|
||||
name = d_unqualified_name (di);
|
||||
if (d_peek_char (di) == 'I')
|
||||
name = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
|
||||
d_template_args (di));
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name);
|
||||
}
|
||||
|
||||
/* <expression> ::= <(unary) operator-name> <expression>
|
||||
::= <(binary) operator-name> <expression> <expression>
|
||||
::= <(trinary) operator-name> <expression> <expression> <expression>
|
||||
::= cl <expression>+ E
|
||||
::= st <type>
|
||||
::= <template-param>
|
||||
::= sr <type> <unqualified-name>
|
||||
::= sr <type> <unqualified-name> <template-args>
|
||||
::= <unresolved-name>
|
||||
::= <expr-primary>
|
||||
|
||||
<braced-expression> ::= <expression>
|
||||
@ -3308,7 +3354,7 @@ op_is_new_cast (struct demangle_component *op)
|
||||
# [expr ... expr] = expr
|
||||
*/
|
||||
|
||||
static inline struct demangle_component *
|
||||
static struct demangle_component *
|
||||
d_expression_1 (struct d_info *di)
|
||||
{
|
||||
char peek;
|
||||
@ -3319,20 +3365,7 @@ d_expression_1 (struct d_info *di)
|
||||
else if (peek == 'T')
|
||||
return d_template_param (di);
|
||||
else if (peek == 's' && d_peek_next_char (di) == 'r')
|
||||
{
|
||||
struct demangle_component *type;
|
||||
struct demangle_component *name;
|
||||
|
||||
d_advance (di, 2);
|
||||
type = cplus_demangle_type (di);
|
||||
name = d_unqualified_name (di);
|
||||
if (d_peek_char (di) != 'I')
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name);
|
||||
else
|
||||
return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type,
|
||||
d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
|
||||
d_template_args (di)));
|
||||
}
|
||||
return d_unresolved_name (di);
|
||||
else if (peek == 's' && d_peek_next_char (di) == 'p')
|
||||
{
|
||||
d_advance (di, 2);
|
||||
@ -6397,6 +6430,9 @@ d_demangle_callback (const char *mangled, int options,
|
||||
type = DCT_TYPE;
|
||||
}
|
||||
|
||||
di.unresolved_name_state = 1;
|
||||
|
||||
again:
|
||||
cplus_demangle_init_info (mangled, options, strlen (mangled), &di);
|
||||
|
||||
/* PR 87675 - Check for a mangled string that is so long
|
||||
@ -6455,6 +6491,13 @@ d_demangle_callback (const char *mangled, int options,
|
||||
if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0')
|
||||
dc = NULL;
|
||||
|
||||
/* See discussion in d_unresolved_name. */
|
||||
if (dc == NULL && di.unresolved_name_state == -1)
|
||||
{
|
||||
di.unresolved_name_state = 0;
|
||||
goto again;
|
||||
}
|
||||
|
||||
#ifdef CP_DEMANGLE_DEBUG
|
||||
d_dump (dc, 0);
|
||||
#endif
|
||||
|
@ -122,6 +122,10 @@ struct d_info
|
||||
/* Non-zero if we are parsing the type operand of a conversion
|
||||
operator, but not when in an expression. */
|
||||
int is_conversion;
|
||||
/* 1: using new unresolved-name grammar.
|
||||
-1: using new unresolved-name grammar and saw an unresolved-name.
|
||||
0: using old unresolved-name grammar. */
|
||||
int unresolved_name_state;
|
||||
/* If DMGL_NO_RECURSE_LIMIT is not active then this is set to
|
||||
the current recursion level. */
|
||||
unsigned int recursion_level;
|
||||
|
@ -1485,3 +1485,6 @@ decltype (({parm#1}.(operator A*))()) j<A>(A)
|
||||
|
||||
_Z1fI1AEDtdtfp_srT_1xES1_
|
||||
decltype ({parm#1}.A::x) f<A>(A)
|
||||
|
||||
_Z2f6IP1AEDtptfp_gssr1A1BE1xET_
|
||||
decltype ({parm#1}->(::A::B::x)) f6<A*>(A*)
|
||||
|
Loading…
Reference in New Issue
Block a user