re PR other/78252 (C++ demangler crashes with infinite recursion with lambda (auto))
authorNathan Sidwell <nathan@acm.org>
Mon, 12 Dec 2016 17:00:37 +0000 (17:00 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 12 Dec 2016 17:00:37 +0000 (17:00 +0000)
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

gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C [new file with mode: 0644]
libiberty/ChangeLog
libiberty/cp-demangle.c
libiberty/testsuite/demangle-expected

index 510586915627287e2a84f3c96cf2076a801b0a6d..982a203ec65c144b249d5bc53ff2d56f5676e878 100644 (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
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 (file)
index 0000000..ca0910b
--- /dev/null
@@ -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_:" } }
index 1e9e7066e0274c833aad947b9273eb89f1e9edcc..f2e6b373e01a0c997c697e9511b1df3909e11eb7 100644 (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.
index a006994cf2bf7c89358f8d099099f47ad18b803c..6c2f902955e6a298b98b645d86ad1e1b4e617391 100644 (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 (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
-         a = d_index_template_argument (a, dpi->pack_index);
+      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 == NULL)
-         {
-           d_print_error (dpi);
-           return;
-         }
+         if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
+           a = d_index_template_argument (a, dpi->pack_index);
 
-       /* 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.  */
+         if (a == NULL)
+           {
+             d_print_error (dpi);
+             return;
+           }
 
-       hold_dpt = dpi->templates;
-       dpi->templates = hold_dpt->next;
+         /* 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.  */
 
-       d_print_comp (dpi, options, a);
+         hold_dpt = dpi->templates;
+         dpi->templates = hold_dpt->next;
 
-       dpi->templates = hold_dpt;
+         d_print_comp (dpi, options, a);
 
-       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, '}');
index af491d8196ef99dffc2d807366665c86c101ae8e..803decdb096babc2e1b3d4e7bdac3dda2f83aff2 100644 (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}&)