From 8e09a726e62c6ade9ea25e1f1a9269141ce73e81 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 12 Dec 2016 17:00:37 +0000 Subject: [PATCH] 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) : Check is_lambda_arg for auto. : Skip smashing check when is_lambda_arg. : 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 --- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C | 88 ++++++++++++++++++++ libiberty/ChangeLog | 14 ++++ libiberty/cp-demangle.c | 61 +++++++++----- libiberty/testsuite/demangle-expected | 29 +++++++ 5 files changed, 175 insertions(+), 22 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 51058691562..982a203ec65 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-12-12 Nathan Sidwell + + PR c++/78252 + * g++.dg/cpp1y/lambda-mangle-1.C: New. + 2016-12-12 Uros Bizjak PR target/78738 diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C new file mode 100644 index 00000000000..ca0910be503 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C @@ -0,0 +1,88 @@ +// { dg-do compile { target c++14 } } + +// PRs 78621 + +// We erroneously mangled lambda auto parms as-if template parameters (T_), +// rather than auto (Da). Fixed in abi version 11 + +template class X; + +template +T &&forward (T &v) +{ + return static_cast (v); +} + +template +void eat (T &v) +{ +} + +template + void eat (S &, T &v) +{ +} + +void Foo () +{ + auto lam = [](auto &) { }; + auto lam_1 = [](int &, auto &) { }; + auto lam_2 = [](auto &, X &) { }; + 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 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 (); +} + +// { 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_:" } } diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 1e9e7066e02..f2e6b373e01 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,17 @@ +2016-12-12 Nathan Sidwell + + PR c++/78252 + * cp-demangle.c (struct d_print_info): Add is_lambda_arg field. + (d_print_init): Initialize it. + (d_print_comp_inner) : Check + is_lambda_arg for auto. + : Skip smashing check when + is_lambda_arg. + : Increment is_lambda_arg around arg + printing. + * testsuite/demangle-expected: Add lambda auto mangling cases. + 2016-12-06 DJ Delorie * argv.c (expandargv): Check for directories passed as @-files. diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index a006994cf2b..6c2f902955e 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -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 + '[] (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, '}'); diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index af491d8196e..803decdb096 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -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}&) + +_Z7forwardIZ3FoovEUlRiRT_E_EOS1_S2_ +Foo()::{lambda(int&, auto:1&)#1}&& forward(Foo()::{lambda(int&, auto:1&)#1}&) + +_Z7forwardIZ3FoovEUlRT_R1XIiEE0_EOS0_S1_ +Foo()::{lambda(auto:1&, X&)#2}&& forward&)#2}>(Foo()::{lambda(auto:1&, X&)#2}&) + +_Z7forwardIZ3FoovEUlPA5_T_E1_EOS0_RS0_ +Foo()::{lambda(auto:1 (*&&forward(auto:1&)) [5])#3} + +_Z3eatIZ3FoovEUlRiRT_E_EvS2_ +void eat(Foo()::{lambda(int&, auto:1&)#1}&) + +_Z3eatIZ3FoovEUlRT_R1XIiEE0_EvS1_ +void eat&)#2}>(Foo()::{lambda(auto:1&, X&)#2}&) + +_Z3eatIZ3FoovEUlPA5_T_E1_EvRS0_ +void eat(Foo()::{lambda(auto:1 (*&) [5])#3}) + +_Z3eatIPiZ3FoovEUlPT_PT0_E4_EvRS1_RS3_ +void eat(int*&, Foo()::{lambda(auto:1*, auto:2*)#6}&) + +_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_ +void eat()::{lambda(short*, auto:1*, auto:2*)#2}>(int*&, void Bar()::{lambda(short*, auto:1*, auto:2*)#2}&)