[PATCH 2/3] PR other/61321 - demangler crash on casts in template parameters

2014-05-27 Thread Pedro Alves
The fix for bug 59195:

 [C++ demangler handles conversion operator incorrectly]
 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59195

unfortunately makes the demangler crash due to infinite recursion, in
case of casts in template parameters.

For example, with:

 template struct A {};
 template  void function_temp(A) {}
 template void function_temp(A);

The 'function_temp' instantiation above mangles to:

  _Z13function_tempIiEv1AIXszcvT_Li999EEE

The demangler parses this as:

typed name
  template
name 'function_temp'
template argument list
  builtin type int
  function type
builtin type void
argument list
  template  (*)
name 'A'
template argument list
  unary operator
operator sizeof
unary operator
  cast
template parameter 0(**)
  literal
builtin type int
name '999'

And after the fix for 59195, due to:

 static void
 d_print_cast (struct d_print_info *dpi, int options,
   const struct demangle_component *dc)
 {
 ...
   /* For a cast operator, we need the template parameters from
  the enclosing template in scope for processing the type.  */
   if (dpi->current_template != NULL)
 {
   dpt.next = dpi->templates;
   dpi->templates = &dpt;
   dpt.template_decl = dpi->current_template;
 }

when printing the template argument list of A (what should be ""), the template parameter 0 (that is, "T_", the '**' above) now
refers to the first parameter of the the template argument list of the
'A' template (the '*' above), exactly what we were already trying to
print.  This leads to infinite recursion, and stack exaustion.  The
template parameter 0 should actually refer to the first parameter of
the 'function_temp' template.

Where it reads "for the cast operator" in the comment in d_print_cast
(above), it's really talking about a conversion operator, like:

  struct A { template  explicit operator U(); };

We don't want to inject the template parameters from the enclosing
template in scope when processing a cast _expression_, only when
handling a conversion operator.

The problem is that DEMANGLE_COMPONENT_CAST is currently ambiguous,
and means _both_ 'conversion operator' and 'cast expression'.

Fix this by adding a new DEMANGLE_COMPONENT_CONVERSION component type,
which does what DEMANGLE_COMPONENT_CAST does today, and making
DEMANGLE_COMPONENT_CAST just simply print its component subtree.

I think we could instead reuse DEMANGLE_COMPONENT_CAST and in
d_print_comp_inner still do:

 @@ -5001,9 +5013,9 @@ d_print_comp_inner (struct d_print_info *dpi, int 
options,
d_print_comp (dpi, options, dc->u.s_extended_operator.name);
return;

 case DEMANGLE_COMPONENT_CAST:
   d_append_string (dpi, "operator ");
 - d_print_cast (dpi, options, dc);
 + d_print_conversion (dpi, options, dc);
   return;

leaving the unary cast case below calling d_print_cast, but seems to
me that spliting the component types makes it easier to reason about
the code.

g++'s testsuite actually generates three symbols that crash the
demangler in the same way.  I've added those as tests in the demangler
testsuite as well.

And then this fixes PR other/61233 too, which happens to be a
demangler crash originally reported to GDB, at:
https://sourceware.org/bugzilla/show_bug.cgi?id=16957

Bootstrapped and regtested on x86_64 Fedora 20.

Also ran this through GDB's testsuite.  GDB will require a small
update to use DEMANGLE_COMPONENT_CONVERSION in one place it's using
DEMANGLE_COMPONENT_CAST in its sources.

libiberty/
2014-05-27  Pedro Alves 

PR other/61321
PR other/61233
* demangle.h (enum demangle_component_type)
: New value.
* cp-demangle.c (d_demangle_callback, d_make_comp): Handle
DEMANGLE_COMPONENT_CONVERSION.
(is_ctor_dtor_or_conversion): Handle DEMANGLE_COMPONENT_CONVERSION
instead of DEMANGLE_COMPONENT_CAST.
(d_operator_name): Return a DEMANGLE_COMPONENT_CONVERSION
component if handling a conversion.
(d_count_templates_scopes, d_print_comp_inner): Handle
DEMANGLE_COMPONENT_CONVERSION.
(d_print_comp_inner): Handle DEMANGLE_COMPONENT_CONVERSION instead
of DEMANGLE_COMPONENT_CAST.
(d_print_cast): Rename as ...
(d_print_conversion): ... this.  Adjust comments.
(d_print_cast): Rewrite - simply print the left subcomponent.
* cp-demint.c (cplus_demangle_fill_component): Handle
DEMANGLE_COMPONENT_CONVERSION.

* testsuite/demangle-expected: Add tests.
---
 include/demangle.h|  4 
 libiberty/cp-demangle.c   | 37 +++
 libiberty/cp-demint.c |  1 +
 libiberty/testsuite/demangle-expected | 23 ++
 4 files changed, 57 insertions(+), 8 deletions(-)

diff --git 

Re: [PATCH 2/3] PR other/61321 - demangler crash on casts in template parameters

2014-10-13 Thread Cary Coutant
Ping. Jason, do you still think the special-case for conversion ops is
inappropriate?

-cary


On Fri, Jul 25, 2014 at 2:16 AM, Pedro Alves  wrote:
> On 07/24/2014 11:35 PM, Cary Coutant wrote:
>>> It seems that the problem here is more general; a template argument list is
>>> not in scope within that same template argument list.  Can't we fix that
>>> without special-casing conversion ops?
>>
>> I think conversion ops really are a special case.
>
> Thanks Cary.  FWIW, I agree.
>
> (GDB 7.8 hasn't been released yet, though it's close.  If this
> patch is approved as is, we'll be able to have the crash
> fixed there.  If this requires a significant rewrite though,
> I'm afraid I might not be able to do it myself anytime soon.)
>
>> It's the only case
>> where the template parameters refer to the template argument list from
>> the cast operator's enclosing template. In a cast expression, like
>> anywhere else you might have a template parameter, the template
>> parameter refers to the template argument list of the immediately
>> enclosing template.
>>
>> I think this note from Section 5.1.3 (Operator Encodings) of the ABI
>> is what makes this a special case (it's an informative comment in the
>> document, but seems to me to be normative):
>>
>> "For a user-defined conversion operator the result type (i.e., the
>> type to which the operator converts) is part of the mangled name of
>> the function. If the conversion operator is a member template, the
>> result type will appear before the template parameters. There may be
>> forward references in the result type to the template parameters."
>>
>
> --
> Thanks,
> Pedro Alves
>


Re: [PATCH 2/3] PR other/61321 - demangler crash on casts in template parameters

2014-07-24 Thread Cary Coutant
> It seems that the problem here is more general; a template argument list is
> not in scope within that same template argument list.  Can't we fix that
> without special-casing conversion ops?

I think conversion ops really are a special case. It's the only case
where the template parameters refer to the template argument list from
the cast operator's enclosing template. In a cast expression, like
anywhere else you might have a template parameter, the template
parameter refers to the template argument list of the immediately
enclosing template.

I think this note from Section 5.1.3 (Operator Encodings) of the ABI
is what makes this a special case (it's an informative comment in the
document, but seems to me to be normative):

"For a user-defined conversion operator the result type (i.e., the
type to which the operator converts) is part of the mangled name of
the function. If the conversion operator is a member template, the
result type will appear before the template parameters. There may be
forward references in the result type to the template parameters."

-cary


Re: [PATCH 2/3] PR other/61321 - demangler crash on casts in template parameters

2014-07-25 Thread Pedro Alves
On 07/24/2014 11:35 PM, Cary Coutant wrote:
>> It seems that the problem here is more general; a template argument list is
>> not in scope within that same template argument list.  Can't we fix that
>> without special-casing conversion ops?
> 
> I think conversion ops really are a special case. 

Thanks Cary.  FWIW, I agree.

(GDB 7.8 hasn't been released yet, though it's close.  If this
patch is approved as is, we'll be able to have the crash
fixed there.  If this requires a significant rewrite though,
I'm afraid I might not be able to do it myself anytime soon.)

> It's the only case
> where the template parameters refer to the template argument list from
> the cast operator's enclosing template. In a cast expression, like
> anywhere else you might have a template parameter, the template
> parameter refers to the template argument list of the immediately
> enclosing template.
> 
> I think this note from Section 5.1.3 (Operator Encodings) of the ABI
> is what makes this a special case (it's an informative comment in the
> document, but seems to me to be normative):
> 
> "For a user-defined conversion operator the result type (i.e., the
> type to which the operator converts) is part of the mangled name of
> the function. If the conversion operator is a member template, the
> result type will appear before the template parameters. There may be
> forward references in the result type to the template parameters."
> 

-- 
Thanks,
Pedro Alves



Re: [PATCH 2/3] PR other/61321 - demangler crash on casts in template parameters

2014-05-30 Thread Cary Coutant
> Fix this by adding a new DEMANGLE_COMPONENT_CONVERSION component type,
> which does what DEMANGLE_COMPONENT_CAST does today, and making
> DEMANGLE_COMPONENT_CAST just simply print its component subtree.
>
> I think we could instead reuse DEMANGLE_COMPONENT_CAST and in
> d_print_comp_inner still do:
>
>  @@ -5001,9 +5013,9 @@ d_print_comp_inner (struct d_print_info *dpi, int 
> options,
> d_print_comp (dpi, options, dc->u.s_extended_operator.name);
> return;
>
>  case DEMANGLE_COMPONENT_CAST:
>d_append_string (dpi, "operator ");
>  - d_print_cast (dpi, options, dc);
>  + d_print_conversion (dpi, options, dc);
>return;
>
> leaving the unary cast case below calling d_print_cast, but seems to
> me that spliting the component types makes it easier to reason about
> the code.

I agree.

> libiberty/
> 2014-05-27  Pedro Alves 
>
> PR other/61321
> PR other/61233
> * demangle.h (enum demangle_component_type)
> : New value.
> * cp-demangle.c (d_demangle_callback, d_make_comp): Handle
> DEMANGLE_COMPONENT_CONVERSION.
> (is_ctor_dtor_or_conversion): Handle DEMANGLE_COMPONENT_CONVERSION
> instead of DEMANGLE_COMPONENT_CAST.
> (d_operator_name): Return a DEMANGLE_COMPONENT_CONVERSION
> component if handling a conversion.
> (d_count_templates_scopes, d_print_comp_inner): Handle
> DEMANGLE_COMPONENT_CONVERSION.
> (d_print_comp_inner): Handle DEMANGLE_COMPONENT_CONVERSION instead
> of DEMANGLE_COMPONENT_CAST.
> (d_print_cast): Rename as ...
> (d_print_conversion): ... this.  Adjust comments.
> (d_print_cast): Rewrite - simply print the left subcomponent.
> * cp-demint.c (cplus_demangle_fill_component): Handle
> DEMANGLE_COMPONENT_CONVERSION.
>
> * testsuite/demangle-expected: Add tests.

Looks good to me. Thanks!

Ian, does this look good to you?

-cary


Re: [PATCH 2/3] PR other/61321 - demangler crash on casts in template parameters

2014-05-30 Thread Ian Lance Taylor
On Fri, May 30, 2014 at 10:37 AM, Cary Coutant  wrote:
>> Fix this by adding a new DEMANGLE_COMPONENT_CONVERSION component type,
>> which does what DEMANGLE_COMPONENT_CAST does today, and making
>> DEMANGLE_COMPONENT_CAST just simply print its component subtree.
>>
>> I think we could instead reuse DEMANGLE_COMPONENT_CAST and in
>> d_print_comp_inner still do:
>>
>>  @@ -5001,9 +5013,9 @@ d_print_comp_inner (struct d_print_info *dpi, int 
>> options,
>> d_print_comp (dpi, options, dc->u.s_extended_operator.name);
>> return;
>>
>>  case DEMANGLE_COMPONENT_CAST:
>>d_append_string (dpi, "operator ");
>>  - d_print_cast (dpi, options, dc);
>>  + d_print_conversion (dpi, options, dc);
>>return;
>>
>> leaving the unary cast case below calling d_print_cast, but seems to
>> me that spliting the component types makes it easier to reason about
>> the code.
>
> I agree.
>
>> libiberty/
>> 2014-05-27  Pedro Alves 
>>
>> PR other/61321
>> PR other/61233
>> * demangle.h (enum demangle_component_type)
>> : New value.
>> * cp-demangle.c (d_demangle_callback, d_make_comp): Handle
>> DEMANGLE_COMPONENT_CONVERSION.
>> (is_ctor_dtor_or_conversion): Handle DEMANGLE_COMPONENT_CONVERSION
>> instead of DEMANGLE_COMPONENT_CAST.
>> (d_operator_name): Return a DEMANGLE_COMPONENT_CONVERSION
>> component if handling a conversion.
>> (d_count_templates_scopes, d_print_comp_inner): Handle
>> DEMANGLE_COMPONENT_CONVERSION.
>> (d_print_comp_inner): Handle DEMANGLE_COMPONENT_CONVERSION instead
>> of DEMANGLE_COMPONENT_CAST.
>> (d_print_cast): Rename as ...
>> (d_print_conversion): ... this.  Adjust comments.
>> (d_print_cast): Rewrite - simply print the left subcomponent.
>> * cp-demint.c (cplus_demangle_fill_component): Handle
>> DEMANGLE_COMPONENT_CONVERSION.
>>
>> * testsuite/demangle-expected: Add tests.
>
> Looks good to me. Thanks!
>
> Ian, does this look good to you?

I tend to defer to Jason on this sort of newfangled mangling
nuttiness, but I can take a look if he doesn't have time.

Ian


Re: [PATCH 2/3] PR other/61321 - demangler crash on casts in template parameters

2014-05-30 Thread Pedro Alves
On 05/30/2014 07:05 PM, Ian Lance Taylor wrote:
>> > Looks good to me. Thanks!

Thanks Cary!

>> > Ian, does this look good to you?
> I tend to defer to Jason on this sort of newfangled mangling
> nuttiness, but I can take a look if he doesn't have time.

Thanks!

FWIW, it'd be great to have this approved/rejected, as I'd
like to get this fixed in gdb 7.8, and we're just about
to branch.

Thanks,
-- 
Pedro Alves



Re: [PATCH 2/3] PR other/61321 - demangler crash on casts in template parameters

2014-06-02 Thread Jason Merrill

On 05/27/2014 07:57 AM, Pedro Alves wrote:

And after the fix for 59195, due to:

  static void
  d_print_cast (struct d_print_info *dpi, int options,
   const struct demangle_component *dc)
  {
  ...
/* For a cast operator, we need the template parameters from
   the enclosing template in scope for processing the type.  */
if (dpi->current_template != NULL)
  {
dpt.next = dpi->templates;
dpi->templates = &dpt;
dpt.template_decl = dpi->current_template;
  }

when printing the template argument list of A (what should be ""), the template parameter 0 (that is, "T_", the '**' above) now
refers to the first parameter of the the template argument list of the
'A' template (the '*' above), exactly what we were already trying to
print.  This leads to infinite recursion, and stack exaustion.  The
template parameter 0 should actually refer to the first parameter of
the 'function_temp' template.


It seems that the problem here is more general; a template argument list 
is not in scope within that same template argument list.  Can't we fix 
that without special-casing conversion ops?


Jason



Re: [PATCH 2/3] PR other/61321 - demangler crash on casts in template parameters

2014-11-10 Thread Cary Coutant
Ping. I'm getting more reports of this bug internally, and it would be
nice to have the fix upstream.

-cary


On Mon, Oct 13, 2014 at 11:43 AM, Cary Coutant  wrote:
> Ping. Jason, do you still think the special-case for conversion ops is
> inappropriate?
>
> -cary
>
>
> On Fri, Jul 25, 2014 at 2:16 AM, Pedro Alves  wrote:
>> On 07/24/2014 11:35 PM, Cary Coutant wrote:
 It seems that the problem here is more general; a template argument list is
 not in scope within that same template argument list.  Can't we fix that
 without special-casing conversion ops?
>>>
>>> I think conversion ops really are a special case.
>>
>> Thanks Cary.  FWIW, I agree.
>>
>> (GDB 7.8 hasn't been released yet, though it's close.  If this
>> patch is approved as is, we'll be able to have the crash
>> fixed there.  If this requires a significant rewrite though,
>> I'm afraid I might not be able to do it myself anytime soon.)
>>
>>> It's the only case
>>> where the template parameters refer to the template argument list from
>>> the cast operator's enclosing template. In a cast expression, like
>>> anywhere else you might have a template parameter, the template
>>> parameter refers to the template argument list of the immediately
>>> enclosing template.
>>>
>>> I think this note from Section 5.1.3 (Operator Encodings) of the ABI
>>> is what makes this a special case (it's an informative comment in the
>>> document, but seems to me to be normative):
>>>
>>> "For a user-defined conversion operator the result type (i.e., the
>>> type to which the operator converts) is part of the mangled name of
>>> the function. If the conversion operator is a member template, the
>>> result type will appear before the template parameters. There may be
>>> forward references in the result type to the template parameters."
>>>
>>
>> --
>> Thanks,
>> Pedro Alves
>>


Re: [PATCH 2/3] PR other/61321 - demangler crash on casts in template parameters

2014-11-12 Thread Jason Merrill

Sorry I forgot about this for so long.  The patch is OK.

Jason