re PR other/78252 (C++ demangler crashes with infinite recursion with lambda (auto))

libiberty/
	PR c++/78252
	* cp-demangle.c (struct d_print_info): Add is_lambda_arg field.
	(d_print_init): Initialize it.
	(d_print_comp_inner) <DEMANGLE_COMPONENT_TEMPLATE_PARAM>: Check
	is_lambda_arg for auto.
	<DEMANGLE_COMPONENT_REFERENCE,
	DEMANGLE_COMPONENT_RVALUE_REFERENCE>: Skip smashing check when
	is_lambda_arg.
	<DEMANGLE_COMPONENT_LAMBDA>: Increment is_lambda_arg around arg
	printing.
	* testsuite/demangle-expected: Add lambda auto mangling cases.

	gcc/testsuite/
	PR c++/78252
	* g++.dg/cpp1y/lambda-mangle-1.C: New.

From-SVN: r243566
This commit is contained in:
Nathan Sidwell 2016-12-12 17:00:37 +00:00 committed by Nathan Sidwell
parent b8cab8a549
commit 8e09a726e6
5 changed files with 175 additions and 22 deletions

View File

@ -1,3 +1,8 @@
2016-12-12 Nathan Sidwell <nathan@acm.org>
PR c++/78252
* g++.dg/cpp1y/lambda-mangle-1.C: New.
2016-12-12 Uros Bizjak <ubizjak@gmail.com>
PR target/78738

View File

@ -0,0 +1,88 @@
// { dg-do compile { target c++14 } }
// PRs 78621
// We erroneously mangled lambda auto parms as-if template parameters (T<n>_),
// rather than auto (Da). Fixed in abi version 11
template<typename T> class X;
template<typename T>
T &&forward (T &v)
{
return static_cast<T &&> (v);
}
template<typename T>
void eat (T &v)
{
}
template<typename S, typename T>
void eat (S &, T &v)
{
}
void Foo ()
{
auto lam = [](auto &) { };
auto lam_1 = [](int &, auto &) { };
auto lam_2 = [](auto &, X<int> &) { };
auto lam_3 = [](auto (*)[5]) { };
forward (lam);
forward (lam_1);
forward (lam_2);
forward (lam_3);
eat (lam);
eat (lam_1);
eat (lam_2);
eat (lam_3);
// The auto lambda should mangle similarly to the non-auto one
auto lambda_1 = [](float *, float *) { };
auto lambda_2 = [](auto *, auto *) { };
auto lambda_3 = [](auto *, auto *) { };
int *i;
eat (i, lambda_1);
eat (i, lambda_2);
// The autos should squangle to the first one.
eat (lambda_2, lambda_3);
}
template<typename X> void Bar ()
{
auto lambda_1 = [](X *, float *, float *) { };
auto lambda_2 = [](X *, auto *, auto *) { };
auto lambda_3 = [](X *, auto *...) {};
int *i;
eat (i, lambda_1);
eat (i, lambda_2);
eat (i, lambda_3);
}
void Baz ()
{
Bar<short> ();
}
// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_E_EOS0_S1_:" } }
// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRiRT_E0_EOS1_S2_:" } }
// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlRT_R1XIiEE1_EOS0_S1_:" } }
// { dg-final { scan-assembler "_Z7forwardIZ3FoovEUlPA5_T_E2_EOS0_RS0_:" } }
// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_E_EvS1_:" } }
// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRiRT_E0_EvS2_:" } }
// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlRT_R1XIiEE1_EvS1_:" } }
// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPA5_T_E2_EvRS0_:" } }
// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPfS1_E3_EvRT_RT0_:" } }
// { dg-final { scan-assembler "_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_:" } }
// { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E4_Z3FoovEUlS1_S3_E5_EvRS0_RS2_:" } }
// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } }
// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_:" } }
// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_zE1_EvRS3_RT0_:" } }

View File

@ -1,3 +1,17 @@
2016-12-12 Nathan Sidwell <nathan@acm.org>
PR c++/78252
* cp-demangle.c (struct d_print_info): Add is_lambda_arg field.
(d_print_init): Initialize it.
(d_print_comp_inner) <DEMANGLE_COMPONENT_TEMPLATE_PARAM>: Check
is_lambda_arg for auto.
<DEMANGLE_COMPONENT_REFERENCE,
DEMANGLE_COMPONENT_RVALUE_REFERENCE>: Skip smashing check when
is_lambda_arg.
<DEMANGLE_COMPONENT_LAMBDA>: Increment is_lambda_arg around arg
printing.
* testsuite/demangle-expected: Add lambda auto mangling cases.
2016-12-06 DJ Delorie <dj@redhat.com>
* argv.c (expandargv): Check for directories passed as @-files.

View File

@ -343,6 +343,9 @@ struct d_print_info
struct d_print_mod *modifiers;
/* Set to 1 if we saw a demangling error. */
int demangle_failure;
/* Non-zero if we're printing a lambda argument. A template
parameter reference actually means 'auto'. */
int is_lambda_arg;
/* The current index into any template argument packs we are using
for printing, or -1 to print the whole pack. */
int pack_index;
@ -4126,6 +4129,7 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
dpi->opaque = opaque;
dpi->demangle_failure = 0;
dpi->is_lambda_arg = 0;
dpi->component_stack = NULL;
@ -4783,33 +4787,41 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
}
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
{
struct d_print_template *hold_dpt;
struct demangle_component *a = d_lookup_template_argument (dpi, dc);
if (dpi->is_lambda_arg)
{
/* Show the template parm index, as that's how g++ displays
these, and future proofs us against potential
'[]<typename T> (T *a, T *b) {...}'. */
d_append_buffer (dpi, "auto:", 5);
d_append_num (dpi, dc->u.s_number.number + 1);
}
else
{
struct d_print_template *hold_dpt;
struct demangle_component *a = d_lookup_template_argument (dpi, dc);
if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
a = d_index_template_argument (a, dpi->pack_index);
if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
a = d_index_template_argument (a, dpi->pack_index);
if (a == NULL)
{
d_print_error (dpi);
return;
}
if (a == NULL)
{
d_print_error (dpi);
return;
}
/* While processing this parameter, we need to pop the list of
templates. This is because the template parameter may
itself be a reference to a parameter of an outer
template. */
/* While processing this parameter, we need to pop the list
of templates. This is because the template parameter may
itself be a reference to a parameter of an outer
template. */
hold_dpt = dpi->templates;
dpi->templates = hold_dpt->next;
hold_dpt = dpi->templates;
dpi->templates = hold_dpt->next;
d_print_comp (dpi, options, a);
d_print_comp (dpi, options, a);
dpi->templates = hold_dpt;
return;
}
dpi->templates = hold_dpt;
}
return;
case DEMANGLE_COMPONENT_CTOR:
d_print_comp (dpi, options, dc->u.s_ctor.name);
@ -4946,7 +4958,8 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
{
/* Handle reference smashing: & + && = &. */
const struct demangle_component *sub = d_left (dc);
if (sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
if (!dpi->is_lambda_arg
&& sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
{
struct d_saved_scope *scope = d_get_saved_scope (dpi, sub);
struct demangle_component *a;
@ -5616,7 +5629,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
case DEMANGLE_COMPONENT_LAMBDA:
d_append_string (dpi, "{lambda(");
/* Generic lambda auto parms are mangled as the template type
parm they are. */
dpi->is_lambda_arg++;
d_print_comp (dpi, options, dc->u.s_unary_num.sub);
dpi->is_lambda_arg--;
d_append_string (dpi, ")#");
d_append_num (dpi, dc->u.s_unary_num.num + 1);
d_append_char (dpi, '}');

View File

@ -4634,3 +4634,32 @@ _Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRplT_LiEEE
# ?: expression with missing third component could crash.
AquT_quT_4mxautouT_4mxxx
AquT_quT_4mxautouT_4mxxx
# pr c++/78252 generic lambda mangling uses template parms, and leads
# to unbounded recursion if not dealt with properly
_Z7forwardIRZ3FoovEUlRT_E_EOS0_S1_
Foo()::{lambda(auto:1&)#1}& forward<Foo()::{lambda(auto:1&)#1}&>(Foo()::{lambda(auto:1&)#1}&)
_Z7forwardIZ3FoovEUlRiRT_E_EOS1_S2_
Foo()::{lambda(int&, auto:1&)#1}&& forward<Foo()::{lambda(int&, auto:1&)#1}>(Foo()::{lambda(int&, auto:1&)#1}&)
_Z7forwardIZ3FoovEUlRT_R1XIiEE0_EOS0_S1_
Foo()::{lambda(auto:1&, X<int>&)#2}&& forward<Foo()::{lambda(auto:1&, X<int>&)#2}>(Foo()::{lambda(auto:1&, X<int>&)#2}&)
_Z7forwardIZ3FoovEUlPA5_T_E1_EOS0_RS0_
Foo()::{lambda(auto:1 (*&&forward<Foo()::{lambda(auto:1 (*) [5])#3}>(auto:1&)) [5])#3}
_Z3eatIZ3FoovEUlRiRT_E_EvS2_
void eat<Foo()::{lambda(int&, auto:1&)#1}>(Foo()::{lambda(int&, auto:1&)#1}&)
_Z3eatIZ3FoovEUlRT_R1XIiEE0_EvS1_
void eat<Foo()::{lambda(auto:1&, X<int>&)#2}>(Foo()::{lambda(auto:1&, X<int>&)#2}&)
_Z3eatIZ3FoovEUlPA5_T_E1_EvRS0_
void eat<Foo()::{lambda(auto:1 (*) [5])#3}>(Foo()::{lambda(auto:1 (*&) [5])#3})
_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_
void eat<int*, Foo()::{lambda(auto:1*, auto:2*)#6}>(int*&, Foo()::{lambda(auto:1*, auto:2*)#6}&)
_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_
void eat<int*, void Bar<short>()::{lambda(short*, auto:1*, auto:2*)#2}>(int*&, void Bar<short>()::{lambda(short*, auto:1*, auto:2*)#2}&)