public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [C++/78252] libiberty demangler crash with lambda (auto)
@ 2016-11-30 19:06 Nathan Sidwell
  2016-12-01  7:53 ` Markus Trippelsdorf
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Nathan Sidwell @ 2016-11-30 19:06 UTC (permalink / raw)
  To: jason, iant; +Cc: nickc, GCC Patches, binutils, P

[-- Attachment #1: Type: text/plain, Size: 2356 bytes --]

This patch fixes a problem in libiberty's symbol demangler.  With a 
templated forwarding function such as std::forward, we can end up 
emitting mangled function names that encode lambda information.  Lambdas 
with auto argument types have a synthesized templated operator(), and 
g++ uses that when mangling the lambda.

Unfortunately g++ doesn't notice the template parameters there mean 
'auto' and emits regular template parameter references. (This is a bug, 
see below.)

But, as the forwarding function itself is a template, and the lambda is 
part of a template parameter substitution, we can end up with the 
demangler recursing unboundedly.  In other cases we can fail to demangle 
(returning null), or demangle to an unexpected type (substituting the 
current template parameter type into the place of the 'auto').

This patch fixes the demangler by noting when it's printing the argument 
types of a lambda.  In that case whenever we encounter a template 
parameter reference we emit 'auto', and also inhibit some &/&& smushing 
that needs checking.  AFAICT, once inside a lambda argument list we 
cannot encounter template parameter references that actually refer to an 
enclosing template argument list. That means we don't have the problem 
of disabling this additional check within the argument list printing.  I 
don't think we can meet a nested lambda type either, but the ++...-- 
idiom seemed safer to me.

We cannot do this substitution when parsing the mangled name, because 
g++ applies the usual squangling back references as-if there really was 
a template parameter reference.  Later squangling references to the type 
containing the lambda argument may or may not require the reference to 
be to an enclosing template argument, or be auto, depending on the 
context of the squangle reference.

I've also included a c++ testcase to check the mangling of the lambdas 
that cause this.  While this is a g++ bug, it's an ABI-affecting one, 
and we shouldn't change the behaviour unintentionally.  I've not 
investigated why the mangler's failing to check is_auto, and will look 
at that later.  I imagine a fix will be -fabi-version dependent. I have 
filed 78621 to track it.

ok?

Nick, we originally found this when GDB exploded. If you're ok with it, 
I'll commit to binutils/gdb when approved for gcc.

nathan
-- 
Nathan Sidwell

[-- Attachment #2: cp-dem.patch --]
[-- Type: text/x-patch, Size: 7230 bytes --]

2016-11-30  Nathan Sidwell  <nathan@acm.org>

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

	libiberty/
	* cp-demangle.c (struct p_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.

Index: gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C
===================================================================
--- gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C	(nonexistent)
+++ gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C	(working copy)
@@ -0,0 +1,47 @@
+// { dg-do compile { target c++14 } }
+
+// PR 78252
+
+// We erroneously mangle lambda auto parms asif template parameters (T<n>_),
+// rather than auto (Da).  While that's unfortunate, it'd be best if
+// we didn't accidentally change that.
+
+template<typename T> class X;
+
+template<typename T>
+T &&forward (T &v)
+{
+  return static_cast<T &&> (v);
+}
+
+template<typename T>
+void eat (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);
+}
+
+// { 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_:" } }
Index: libiberty/cp-demangle.c
===================================================================
--- libiberty/cp-demangle.c	(revision 243016)
+++ libiberty/cp-demangle.c	(working copy)
@@ -343,6 +343,12 @@ 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'.  This is a bug in name
+     mangling, and will demangle to something confusing.
+     Unfortunately it can also cause infinite recursion, if we don't
+     interpret this as '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 +4132,7 @@ d_print_init (struct d_print_info *dpi,
   dpi->opaque = opaque;
 
   dpi->demangle_failure = 0;
+  dpi->is_lambda_arg = 0;
 
   dpi->component_stack = NULL;
 
@@ -4783,33 +4790,35 @@ d_print_comp_inner (struct d_print_info
       }
 
     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)
+	d_append_buffer (dpi, "auto", 4);
+      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 +4955,8 @@ d_print_comp_inner (struct d_print_info
       {
 	/* 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 +5626,14 @@ d_print_comp_inner (struct d_print_info
 
     case DEMANGLE_COMPONENT_LAMBDA:
       d_append_string (dpi, "{lambda(");
+      /* We need to notice if we're printing a lambda argument type.
+	 When this is true, any template parameter reference is
+	 actually an instance of 'auto'.  Fortunately we can't meet
+	 real uses of template parameters inside the lambda
+	 arguments.  */
+      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: libiberty/testsuite/demangle-expected
===================================================================
--- libiberty/testsuite/demangle-expected	(revision 243016)
+++ libiberty/testsuite/demangle-expected	(working copy)
@@ -4634,3 +4634,27 @@ _Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRp
 # ?: expression with missing third component could crash.
 AquT_quT_4mxautouT_4mxxx
 AquT_quT_4mxautouT_4mxxx
+
+# pr c++/78252 unfortunate bug in g++'s lambda mangling would lead to
+# incorrect demangles, and at worst unbounded recursion
+_Z7forwardIRZ3FoovEUlRT_E_EOS0_S1_
+Foo()::{lambda(auto&)#1}& forward<Foo()::{lambda(auto&)#1}&>(Foo()::{lambda(auto&)#1}&)
+
+_Z7forwardIZ3FoovEUlRiRT_E_EOS1_S2_
+Foo()::{lambda(int&, auto&)#1}&& forward<Foo()::{lambda(int&, auto&)#1}>(Foo()::{lambda(int&, auto&)#1}&)
+
+_Z7forwardIZ3FoovEUlRT_R1XIiEE0_EOS0_S1_
+Foo()::{lambda(auto&, X<int>&)#2}&& forward<Foo()::{lambda(auto&, X<int>&)#2}>(Foo()::{lambda(auto&, X<int>&)#2}&)
+
+_Z7forwardIZ3FoovEUlPA5_T_E1_EOS0_RS0_
+Foo()::{lambda(auto (*&&forward<Foo()::{lambda(auto (*) [5])#3}>(auto&)) [5])#3}
+
+_Z3eatIZ3FoovEUlRiRT_E_EvS2_
+void eat<Foo()::{lambda(int&, auto&)#1}>(Foo()::{lambda(int&, auto&)#1}&)
+
+_Z3eatIZ3FoovEUlRT_R1XIiEE0_EvS1_
+void eat<Foo()::{lambda(auto&, X<int>&)#2}>(Foo()::{lambda(auto&, X<int>&)#2}&)
+
+_Z3eatIZ3FoovEUlPA5_T_E1_EvRS0_
+void eat<Foo()::{lambda(auto (*) [5])#3}>(Foo()::{lambda(auto (*&) [5])#3})
+

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++/78252] libiberty demangler crash with lambda (auto)
  2016-11-30 19:06 [C++/78252] libiberty demangler crash with lambda (auto) Nathan Sidwell
@ 2016-12-01  7:53 ` Markus Trippelsdorf
  2016-12-06 12:33 ` [C++/78252 PATCH] " Nathan Sidwell
  2016-12-12 13:54 ` [C++/78252] " Nathan Sidwell
  2 siblings, 0 replies; 5+ messages in thread
From: Markus Trippelsdorf @ 2016-12-01  7:53 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: jason, iant, nickc, GCC Patches, binutils, P

On 2016.11.30 at 14:06 -0500, Nathan Sidwell wrote:
> This patch fixes a problem in libiberty's symbol demangler.  With a
> templated forwarding function such as std::forward, we can end up emitting
> mangled function names that encode lambda information.  Lambdas with auto
> argument types have a synthesized templated operator(), and g++ uses that
> when mangling the lambda.
> 
> Unfortunately g++ doesn't notice the template parameters there mean 'auto'
> and emits regular template parameter references. (This is a bug, see below.)
> 
> But, as the forwarding function itself is a template, and the lambda is part
> of a template parameter substitution, we can end up with the demangler
> recursing unboundedly.  In other cases we can fail to demangle (returning
> null), or demangle to an unexpected type (substituting the current template
> parameter type into the place of the 'auto').
> 
> This patch fixes the demangler by noting when it's printing the argument
> types of a lambda.  In that case whenever we encounter a template parameter
> reference we emit 'auto', and also inhibit some &/&& smushing that needs
> checking.  AFAICT, once inside a lambda argument list we cannot encounter
> template parameter references that actually refer to an enclosing template
> argument list. That means we don't have the problem of disabling this
> additional check within the argument list printing.  I don't think we can
> meet a nested lambda type either, but the ++...-- idiom seemed safer to me.
> 
> We cannot do this substitution when parsing the mangled name, because g++
> applies the usual squangling back references as-if there really was a
> template parameter reference.  Later squangling references to the type
> containing the lambda argument may or may not require the reference to be to
> an enclosing template argument, or be auto, depending on the context of the
> squangle reference.
> 
> I've also included a c++ testcase to check the mangling of the lambdas that
> cause this.  While this is a g++ bug, it's an ABI-affecting one, and we
> shouldn't change the behaviour unintentionally.  I've not investigated why
> the mangler's failing to check is_auto, and will look at that later.  I
> imagine a fix will be -fabi-version dependent. I have filed 78621 to track
> it.

Thanks. This patch also fixes:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70909

-- 
Markus

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++/78252 PATCH] libiberty demangler crash with lambda (auto)
  2016-11-30 19:06 [C++/78252] libiberty demangler crash with lambda (auto) Nathan Sidwell
  2016-12-01  7:53 ` Markus Trippelsdorf
@ 2016-12-06 12:33 ` Nathan Sidwell
  2016-12-12 13:54 ` [C++/78252] " Nathan Sidwell
  2 siblings, 0 replies; 5+ messages in thread
From: Nathan Sidwell @ 2016-12-06 12:33 UTC (permalink / raw)
  To: jason, iant; +Cc: nickc, GCC Patches, binutils, P

Ping?
https://gcc.gnu.org/ml/gcc-patches/2016-11/msg03102.html

Don't get confused by the chatter on 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70909.  That defect mixes 
demangler recursion due to malformed symbols with recursion on 
well-formed ones.  This patch fixes the well-formed lambda subset of 
that recursion problem.

nathan


On 11/30/2016 02:06 PM, Nathan Sidwell wrote:
> This patch fixes a problem in libiberty's symbol demangler.  With a
> templated forwarding function such as std::forward, we can end up
> emitting mangled function names that encode lambda information.  Lambdas
> with auto argument types have a synthesized templated operator(), and
> g++ uses that when mangling the lambda.
>
> Unfortunately g++ doesn't notice the template parameters there mean
> 'auto' and emits regular template parameter references. (This is a bug,
> see below.)
>
> But, as the forwarding function itself is a template, and the lambda is
> part of a template parameter substitution, we can end up with the
> demangler recursing unboundedly.  In other cases we can fail to demangle
> (returning null), or demangle to an unexpected type (substituting the
> current template parameter type into the place of the 'auto').
>
> This patch fixes the demangler by noting when it's printing the argument
> types of a lambda.  In that case whenever we encounter a template
> parameter reference we emit 'auto', and also inhibit some &/&& smushing
> that needs checking.  AFAICT, once inside a lambda argument list we
> cannot encounter template parameter references that actually refer to an
> enclosing template argument list. That means we don't have the problem
> of disabling this additional check within the argument list printing.  I
> don't think we can meet a nested lambda type either, but the ++...--
> idiom seemed safer to me.
>
> We cannot do this substitution when parsing the mangled name, because
> g++ applies the usual squangling back references as-if there really was
> a template parameter reference.  Later squangling references to the type
> containing the lambda argument may or may not require the reference to
> be to an enclosing template argument, or be auto, depending on the
> context of the squangle reference.
>
> I've also included a c++ testcase to check the mangling of the lambdas
> that cause this.  While this is a g++ bug, it's an ABI-affecting one,
> and we shouldn't change the behaviour unintentionally.  I've not
> investigated why the mangler's failing to check is_auto, and will look
> at that later.  I imagine a fix will be -fabi-version dependent. I have
> filed 78621 to track it.
>
> ok?
>
> Nick, we originally found this when GDB exploded. If you're ok with it,
> I'll commit to binutils/gdb when approved for gcc.
>
> nathan


-- 
Nathan Sidwell

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++/78252] libiberty demangler crash with lambda (auto)
  2016-11-30 19:06 [C++/78252] libiberty demangler crash with lambda (auto) Nathan Sidwell
  2016-12-01  7:53 ` Markus Trippelsdorf
  2016-12-06 12:33 ` [C++/78252 PATCH] " Nathan Sidwell
@ 2016-12-12 13:54 ` Nathan Sidwell
  2016-12-12 16:53   ` Jason Merrill
  2 siblings, 1 reply; 5+ messages in thread
From: Nathan Sidwell @ 2016-12-12 13:54 UTC (permalink / raw)
  To: jason, iant; +Cc: nickc, GCC Patches, binutils, P

[-- Attachment #1: Type: text/plain, Size: 500 bytes --]

following discussion on the ABI list, here's an update to the generic 
lambda demangler patch.

The guts of the patch are the same as before -- note when we're printing 
a generic lambda's parms and interpret template type parm references 
differently.  however:
1) don't refer to this as a mangling bug, because it isn't
2) add a ':$n' suffix to each generic parm, as that's how g++ itself 
shows them in diagnostics and the like.

I'll mark 78621 as not a bug too.

ok?

nathan

-- 
Nathan Sidwell

[-- Attachment #2: auto-dem-78252.diff --]
[-- Type: text/x-patch, Size: 8636 bytes --]

2016-12-12  Nathan Sidwell  <nathan@acm.org>

	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.

Index: libiberty/cp-demangle.c
===================================================================
--- libiberty/cp-demangle.c	(revision 243546)
+++ libiberty/cp-demangle.c	(working copy)
@@ -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,
   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
       }
 
     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
       {
 	/* 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
 
     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: libiberty/testsuite/demangle-expected
===================================================================
--- libiberty/testsuite/demangle-expected	(revision 243546)
+++ libiberty/testsuite/demangle-expected	(working copy)
@@ -4634,3 +4634,32 @@ _Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRp
 # ?: 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}&)
Index: gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C
===================================================================
--- gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C	(revision 0)
+++ gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C	(working copy)
@@ -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_:" } }

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [C++/78252] libiberty demangler crash with lambda (auto)
  2016-12-12 13:54 ` [C++/78252] " Nathan Sidwell
@ 2016-12-12 16:53   ` Jason Merrill
  0 siblings, 0 replies; 5+ messages in thread
From: Jason Merrill @ 2016-12-12 16:53 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: Ian Lance Taylor, nickc, GCC Patches, binutils, P

OK.

On Mon, Dec 12, 2016 at 8:53 AM, Nathan Sidwell <nathan@acm.org> wrote:
> following discussion on the ABI list, here's an update to the generic lambda
> demangler patch.
>
> The guts of the patch are the same as before -- note when we're printing a
> generic lambda's parms and interpret template type parm references
> differently.  however:
> 1) don't refer to this as a mangling bug, because it isn't
> 2) add a ':$n' suffix to each generic parm, as that's how g++ itself shows
> them in diagnostics and the like.
>
> I'll mark 78621 as not a bug too.
>
> ok?
>
> nathan
>
> --
> Nathan Sidwell

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-12-12 16:53 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-30 19:06 [C++/78252] libiberty demangler crash with lambda (auto) Nathan Sidwell
2016-12-01  7:53 ` Markus Trippelsdorf
2016-12-06 12:33 ` [C++/78252 PATCH] " Nathan Sidwell
2016-12-12 13:54 ` [C++/78252] " Nathan Sidwell
2016-12-12 16:53   ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).