diff mbox

[committed] Support dumping type bindings and 'mutable' qualifier in lambda diagnostics.

Message ID 1377809860-28282-1-git-send-email-adam@jessamine.co.uk
State New
Headers show

Commit Message

Adam Butcher Aug. 29, 2013, 8:57 p.m. UTC
From: abutcher <abutcher@138bc75d-0d04-0410-961f-82ee72b054a4>

	* error.c (dump_lambda_function): New function, dependent on ...
	(dump_substitution): ... this new function, factored out of ...
	(subst_to_string): ... here and ...
	(dump_function_decl): ... here.  Updated to early-out with call to
	dump_lambda_function after determining template bindings.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202087 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog |  8 +++++++
 gcc/cp/error.c   | 73 +++++++++++++++++++++++++++++++++++---------------------
 2 files changed, 54 insertions(+), 27 deletions(-)

Comments

Gabriel Dos Reis Aug. 29, 2013, 8:59 p.m. UTC | #1
On Thu, Aug 29, 2013 at 3:57 PM, Adam Butcher <adam@jessamine.co.uk> wrote:
> From: abutcher <abutcher@138bc75d-0d04-0410-961f-82ee72b054a4>
>
>         * error.c (dump_lambda_function): New function, dependent on ...
>         (dump_substitution): ... this new function, factored out of ...
>         (subst_to_string): ... here and ...
>         (dump_function_decl): ... here.  Updated to early-out with call to
>         dump_lambda_function after determining template bindings.

Please go ahead and commit it.  You do have SVN commit access, right?

-- Gaby

>
> git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202087 138bc75d-0d04-0410-961f-82ee72b054a4
> ---
>  gcc/cp/ChangeLog |  8 +++++++
>  gcc/cp/error.c   | 73 +++++++++++++++++++++++++++++++++++---------------------
>  2 files changed, 54 insertions(+), 27 deletions(-)
>
> diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
> index bf49198..f848b81 100644
> --- a/gcc/cp/ChangeLog
> +++ b/gcc/cp/ChangeLog
> @@ -1,3 +1,11 @@
> +2013-08-29  Adam Butcher  <adam@jessamine.co.uk>
> +
> +       * error.c (dump_lambda_function): New function, dependent on ...
> +       (dump_substitution): ... this new function, factored out of ...
> +       (subst_to_string): ... here and ...
> +       (dump_function_decl): ... here.  Updated to early-out with call to
> +       dump_lambda_function after determining template bindings.
> +
>  2013-08-28  Paolo Carlini  <paolo.carlini@oracle.com>
>
>         PR c++/58255
> diff --git a/gcc/cp/error.c b/gcc/cp/error.c
> index c82a0ce..af71000 100644
> --- a/gcc/cp/error.c
> +++ b/gcc/cp/error.c
> @@ -1363,6 +1363,47 @@ find_typenames (tree t)
>    return ft.typenames;
>  }
>
> +/* Output the "[with ...]" clause for a template instantiation T iff
> +   TEMPLATE_PARMS, TEMPLATE_ARGS and FLAGS are suitable.  T may be NULL if
> +   formatting a deduction/substitution diagnostic rather than an
> +   instantiation.  */
> +
> +static void
> +dump_substitution (cxx_pretty_printer *pp,
> +                   tree t, tree template_parms, tree template_args,
> +                   int flags)
> +{
> +  if (template_parms != NULL_TREE && template_args != NULL_TREE
> +      && !(flags & TFF_NO_TEMPLATE_BINDINGS))
> +    {
> +      vec<tree, va_gc> *typenames = t ? find_typenames (t) : NULL;
> +      pp_cxx_whitespace (pp);
> +      pp_cxx_left_bracket (pp);
> +      pp->translate_string ("with");
> +      pp_cxx_whitespace (pp);
> +      dump_template_bindings (pp, template_parms, template_args, typenames);
> +      pp_cxx_right_bracket (pp);
> +    }
> +}
> +
> +/* Dump the lambda function FN including its 'mutable' qualifier and any
> +   template bindings.  */
> +
> +static void
> +dump_lambda_function (cxx_pretty_printer *pp,
> +                     tree fn, tree template_parms, tree template_args,
> +                     int flags)
> +{
> +  /* A lambda's signature is essentially its "type".  */
> +  dump_type (pp, DECL_CONTEXT (fn), flags);
> +  if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) & TYPE_QUAL_CONST))
> +    {
> +      pp->padding = pp_before;
> +      pp_c_ws_string (pp, "mutable");
> +    }
> +  dump_substitution (pp, fn, template_parms, template_args, flags);
> +}
> +
>  /* Pretty print a function decl. There are several ways we want to print a
>     function declaration. The TFF_ bits in FLAGS tells us how to behave.
>     As error can only apply the '#' flag once to give 0 and 1 for V, there
> @@ -1379,15 +1420,6 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
>    int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
>    int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
>    tree exceptions;
> -  vec<tree, va_gc> *typenames = NULL;
> -
> -  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
> -    {
> -      /* A lambda's signature is essentially its "type", so defer.  */
> -      gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
> -      dump_type (pp, DECL_CONTEXT (t), flags);
> -      return;
> -    }
>
>    flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
>    if (TREE_CODE (t) == TEMPLATE_DECL)
> @@ -1409,10 +1441,12 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
>         {
>           template_parms = DECL_TEMPLATE_PARMS (tmpl);
>           t = tmpl;
> -         typenames = find_typenames (t);
>         }
>      }
>
> +  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
> +    return dump_lambda_function (pp, t, template_parms, template_args, flags);
> +
>    fntype = TREE_TYPE (t);
>    parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
>
> @@ -1476,17 +1510,7 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
>        if (show_return)
>         dump_type_suffix (pp, TREE_TYPE (fntype), flags);
>
> -      /* If T is a template instantiation, dump the parameter binding.  */
> -      if (template_parms != NULL_TREE && template_args != NULL_TREE
> -         && !(flags & TFF_NO_TEMPLATE_BINDINGS))
> -       {
> -         pp_cxx_whitespace (pp);
> -         pp_cxx_left_bracket (pp);
> -         pp_cxx_ws_string (pp, M_("with"));
> -         pp_cxx_whitespace (pp);
> -         dump_template_bindings (pp, template_parms, template_args, typenames);
> -         pp_cxx_right_bracket (pp);
> -       }
> +      dump_substitution (pp, t, template_parms, template_args, flags);
>      }
>    else if (template_args)
>      {
> @@ -2950,12 +2974,7 @@ subst_to_string (tree p)
>
>    reinit_cxx_pp ();
>    dump_template_decl (cxx_pp, TREE_PURPOSE (p), flags);
> -  pp_cxx_whitespace (cxx_pp);
> -  pp_cxx_left_bracket (cxx_pp);
> -  pp_cxx_ws_string (cxx_pp, M_("with"));
> -  pp_cxx_whitespace (cxx_pp);
> -  dump_template_bindings (cxx_pp, tparms, targs, NULL);
> -  pp_cxx_right_bracket (cxx_pp);
> +  dump_substitution (cxx_pp, NULL, tparms, targs, /*flags=*/0);
>    return pp_ggc_formatted_text (cxx_pp);
>  }
>
> --
> 1.8.4
>
Adam Butcher Aug. 29, 2013, 9:06 p.m. UTC | #2
On 29.08.2013 21:59, Gabriel Dos Reis wrote:
> On Thu, Aug 29, 2013 at 3:57 PM, Adam Butcher <adam@jessamine.co.uk> 
> wrote:
>> From: abutcher <abutcher@138bc75d-0d04-0410-961f-82ee72b054a4>
>>
>>         * error.c (dump_lambda_function): New function, dependent on 
>> ...
>>         (dump_substitution): ... this new function, factored out of 
>> ...
>>         (subst_to_string): ... here and ...
>>         (dump_function_decl): ... here.  Updated to early-out with 
>> call to
>>         dump_lambda_function after determining template bindings.
>
> Please go ahead and commit it.  You do have SVN commit access, right?
>
Yes, this is the committed patch.  I was under the impression that I 
should ping the list with the commit once pushed.

Adam


>> git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202087 
>> 138bc75d-0d04-0410-961f-82ee72b054a4
>> ---
>>  gcc/cp/ChangeLog |  8 +++++++
>>  gcc/cp/error.c   | 73 
>> +++++++++++++++++++++++++++++++++++---------------------
>>  2 files changed, 54 insertions(+), 27 deletions(-)
>>
>> diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
>> index bf49198..f848b81 100644
>> --- a/gcc/cp/ChangeLog
>> +++ b/gcc/cp/ChangeLog
>> @@ -1,3 +1,11 @@
>> +2013-08-29  Adam Butcher  <adam@jessamine.co.uk>
>> +
>> +       * error.c (dump_lambda_function): New function, dependent on 
>> ...
>> +       (dump_substitution): ... this new function, factored out of 
>> ...
>> +       (subst_to_string): ... here and ...
>> +       (dump_function_decl): ... here.  Updated to early-out with 
>> call to
>> +       dump_lambda_function after determining template bindings.
>> +
>>  2013-08-28  Paolo Carlini  <paolo.carlini@oracle.com>
>>
>>         PR c++/58255
>> diff --git a/gcc/cp/error.c b/gcc/cp/error.c
>> index c82a0ce..af71000 100644
>> --- a/gcc/cp/error.c
>> +++ b/gcc/cp/error.c
>> @@ -1363,6 +1363,47 @@ find_typenames (tree t)
>>    return ft.typenames;
>>  }
>>
>> +/* Output the "[with ...]" clause for a template instantiation T 
>> iff
>> +   TEMPLATE_PARMS, TEMPLATE_ARGS and FLAGS are suitable.  T may be 
>> NULL if
>> +   formatting a deduction/substitution diagnostic rather than an
>> +   instantiation.  */
>> +
>> +static void
>> +dump_substitution (cxx_pretty_printer *pp,
>> +                   tree t, tree template_parms, tree template_args,
>> +                   int flags)
>> +{
>> +  if (template_parms != NULL_TREE && template_args != NULL_TREE
>> +      && !(flags & TFF_NO_TEMPLATE_BINDINGS))
>> +    {
>> +      vec<tree, va_gc> *typenames = t ? find_typenames (t) : NULL;
>> +      pp_cxx_whitespace (pp);
>> +      pp_cxx_left_bracket (pp);
>> +      pp->translate_string ("with");
>> +      pp_cxx_whitespace (pp);
>> +      dump_template_bindings (pp, template_parms, template_args, 
>> typenames);
>> +      pp_cxx_right_bracket (pp);
>> +    }
>> +}
>> +
>> +/* Dump the lambda function FN including its 'mutable' qualifier 
>> and any
>> +   template bindings.  */
>> +
>> +static void
>> +dump_lambda_function (cxx_pretty_printer *pp,
>> +                     tree fn, tree template_parms, tree 
>> template_args,
>> +                     int flags)
>> +{
>> +  /* A lambda's signature is essentially its "type".  */
>> +  dump_type (pp, DECL_CONTEXT (fn), flags);
>> +  if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) & 
>> TYPE_QUAL_CONST))
>> +    {
>> +      pp->padding = pp_before;
>> +      pp_c_ws_string (pp, "mutable");
>> +    }
>> +  dump_substitution (pp, fn, template_parms, template_args, flags);
>> +}
>> +
>>  /* Pretty print a function decl. There are several ways we want to 
>> print a
>>     function declaration. The TFF_ bits in FLAGS tells us how to 
>> behave.
>>     As error can only apply the '#' flag once to give 0 and 1 for V, 
>> there
>> @@ -1379,15 +1420,6 @@ dump_function_decl (cxx_pretty_printer *pp, 
>> tree t, int flags)
>>    int show_return = flags & TFF_RETURN_TYPE || flags & 
>> TFF_DECL_SPECIFIERS;
>>    int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
>>    tree exceptions;
>> -  vec<tree, va_gc> *typenames = NULL;
>> -
>> -  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
>> -    {
>> -      /* A lambda's signature is essentially its "type", so defer.  
>> */
>> -      gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
>> -      dump_type (pp, DECL_CONTEXT (t), flags);
>> -      return;
>> -    }
>>
>>    flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
>>    if (TREE_CODE (t) == TEMPLATE_DECL)
>> @@ -1409,10 +1441,12 @@ dump_function_decl (cxx_pretty_printer *pp, 
>> tree t, int flags)
>>         {
>>           template_parms = DECL_TEMPLATE_PARMS (tmpl);
>>           t = tmpl;
>> -         typenames = find_typenames (t);
>>         }
>>      }
>>
>> +  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
>> +    return dump_lambda_function (pp, t, template_parms, 
>> template_args, flags);
>> +
>>    fntype = TREE_TYPE (t);
>>    parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
>>
>> @@ -1476,17 +1510,7 @@ dump_function_decl (cxx_pretty_printer *pp, 
>> tree t, int flags)
>>        if (show_return)
>>         dump_type_suffix (pp, TREE_TYPE (fntype), flags);
>>
>> -      /* If T is a template instantiation, dump the parameter 
>> binding.  */
>> -      if (template_parms != NULL_TREE && template_args != NULL_TREE
>> -         && !(flags & TFF_NO_TEMPLATE_BINDINGS))
>> -       {
>> -         pp_cxx_whitespace (pp);
>> -         pp_cxx_left_bracket (pp);
>> -         pp_cxx_ws_string (pp, M_("with"));
>> -         pp_cxx_whitespace (pp);
>> -         dump_template_bindings (pp, template_parms, template_args, 
>> typenames);
>> -         pp_cxx_right_bracket (pp);
>> -       }
>> +      dump_substitution (pp, t, template_parms, template_args, 
>> flags);
>>      }
>>    else if (template_args)
>>      {
>> @@ -2950,12 +2974,7 @@ subst_to_string (tree p)
>>
>>    reinit_cxx_pp ();
>>    dump_template_decl (cxx_pp, TREE_PURPOSE (p), flags);
>> -  pp_cxx_whitespace (cxx_pp);
>> -  pp_cxx_left_bracket (cxx_pp);
>> -  pp_cxx_ws_string (cxx_pp, M_("with"));
>> -  pp_cxx_whitespace (cxx_pp);
>> -  dump_template_bindings (cxx_pp, tparms, targs, NULL);
>> -  pp_cxx_right_bracket (cxx_pp);
>> +  dump_substitution (cxx_pp, NULL, tparms, targs, /*flags=*/0);
>>    return pp_ggc_formatted_text (cxx_pp);
>>  }
>>
>> --
>> 1.8.4
>>
Gabriel Dos Reis Aug. 29, 2013, 9:10 p.m. UTC | #3
On Thu, Aug 29, 2013 at 4:06 PM, Adam Butcher <adam@jessamine.co.uk> wrote:
> On 29.08.2013 21:59, Gabriel Dos Reis wrote:
>>
>> On Thu, Aug 29, 2013 at 3:57 PM, Adam Butcher <adam@jessamine.co.uk>
>> wrote:
>>>
>>> From: abutcher <abutcher@138bc75d-0d04-0410-961f-82ee72b054a4>
>>>
>>>         * error.c (dump_lambda_function): New function, dependent on ...
>>>         (dump_substitution): ... this new function, factored out of ...
>>>         (subst_to_string): ... here and ...
>>>         (dump_function_decl): ... here.  Updated to early-out with call
>>> to
>>>         dump_lambda_function after determining template bindings.
>>
>>
>> Please go ahead and commit it.  You do have SVN commit access, right?
>>
> Yes, this is the committed patch.  I was under the impression that I should
> ping the list with the commit once pushed.

yes, you are right; my confusion.


>
> Adam
>
>
>
>>> git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202087
>>> 138bc75d-0d04-0410-961f-82ee72b054a4
>>> ---
>>>  gcc/cp/ChangeLog |  8 +++++++
>>>  gcc/cp/error.c   | 73
>>> +++++++++++++++++++++++++++++++++++---------------------
>>>  2 files changed, 54 insertions(+), 27 deletions(-)
>>>
>>> diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
>>> index bf49198..f848b81 100644
>>> --- a/gcc/cp/ChangeLog
>>> +++ b/gcc/cp/ChangeLog
>>> @@ -1,3 +1,11 @@
>>> +2013-08-29  Adam Butcher  <adam@jessamine.co.uk>
>>> +
>>> +       * error.c (dump_lambda_function): New function, dependent on ...
>>> +       (dump_substitution): ... this new function, factored out of ...
>>> +       (subst_to_string): ... here and ...
>>> +       (dump_function_decl): ... here.  Updated to early-out with call
>>> to
>>> +       dump_lambda_function after determining template bindings.
>>> +
>>>  2013-08-28  Paolo Carlini  <paolo.carlini@oracle.com>
>>>
>>>         PR c++/58255
>>> diff --git a/gcc/cp/error.c b/gcc/cp/error.c
>>> index c82a0ce..af71000 100644
>>> --- a/gcc/cp/error.c
>>> +++ b/gcc/cp/error.c
>>> @@ -1363,6 +1363,47 @@ find_typenames (tree t)
>>>    return ft.typenames;
>>>  }
>>>
>>> +/* Output the "[with ...]" clause for a template instantiation T iff
>>> +   TEMPLATE_PARMS, TEMPLATE_ARGS and FLAGS are suitable.  T may be NULL
>>> if
>>> +   formatting a deduction/substitution diagnostic rather than an
>>> +   instantiation.  */
>>> +
>>> +static void
>>> +dump_substitution (cxx_pretty_printer *pp,
>>> +                   tree t, tree template_parms, tree template_args,
>>> +                   int flags)
>>> +{
>>> +  if (template_parms != NULL_TREE && template_args != NULL_TREE
>>> +      && !(flags & TFF_NO_TEMPLATE_BINDINGS))
>>> +    {
>>> +      vec<tree, va_gc> *typenames = t ? find_typenames (t) : NULL;
>>> +      pp_cxx_whitespace (pp);
>>> +      pp_cxx_left_bracket (pp);
>>> +      pp->translate_string ("with");
>>> +      pp_cxx_whitespace (pp);
>>> +      dump_template_bindings (pp, template_parms, template_args,
>>> typenames);
>>> +      pp_cxx_right_bracket (pp);
>>> +    }
>>> +}
>>> +
>>> +/* Dump the lambda function FN including its 'mutable' qualifier and any
>>> +   template bindings.  */
>>> +
>>> +static void
>>> +dump_lambda_function (cxx_pretty_printer *pp,
>>> +                     tree fn, tree template_parms, tree template_args,
>>> +                     int flags)
>>> +{
>>> +  /* A lambda's signature is essentially its "type".  */
>>> +  dump_type (pp, DECL_CONTEXT (fn), flags);
>>> +  if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) &
>>> TYPE_QUAL_CONST))
>>> +    {
>>> +      pp->padding = pp_before;
>>> +      pp_c_ws_string (pp, "mutable");
>>> +    }
>>> +  dump_substitution (pp, fn, template_parms, template_args, flags);
>>> +}
>>> +
>>>  /* Pretty print a function decl. There are several ways we want to print
>>> a
>>>     function declaration. The TFF_ bits in FLAGS tells us how to behave.
>>>     As error can only apply the '#' flag once to give 0 and 1 for V,
>>> there
>>> @@ -1379,15 +1420,6 @@ dump_function_decl (cxx_pretty_printer *pp, tree
>>> t, int flags)
>>>    int show_return = flags & TFF_RETURN_TYPE || flags &
>>> TFF_DECL_SPECIFIERS;
>>>    int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
>>>    tree exceptions;
>>> -  vec<tree, va_gc> *typenames = NULL;
>>> -
>>> -  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
>>> -    {
>>> -      /* A lambda's signature is essentially its "type", so defer.  */
>>> -      gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
>>> -      dump_type (pp, DECL_CONTEXT (t), flags);
>>> -      return;
>>> -    }
>>>
>>>    flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
>>>    if (TREE_CODE (t) == TEMPLATE_DECL)
>>> @@ -1409,10 +1441,12 @@ dump_function_decl (cxx_pretty_printer *pp, tree
>>> t, int flags)
>>>         {
>>>           template_parms = DECL_TEMPLATE_PARMS (tmpl);
>>>           t = tmpl;
>>> -         typenames = find_typenames (t);
>>>         }
>>>      }
>>>
>>> +  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
>>> +    return dump_lambda_function (pp, t, template_parms, template_args,
>>> flags);
>>> +
>>>    fntype = TREE_TYPE (t);
>>>    parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
>>>
>>> @@ -1476,17 +1510,7 @@ dump_function_decl (cxx_pretty_printer *pp, tree
>>> t, int flags)
>>>        if (show_return)
>>>         dump_type_suffix (pp, TREE_TYPE (fntype), flags);
>>>
>>> -      /* If T is a template instantiation, dump the parameter binding.
>>> */
>>> -      if (template_parms != NULL_TREE && template_args != NULL_TREE
>>> -         && !(flags & TFF_NO_TEMPLATE_BINDINGS))
>>> -       {
>>> -         pp_cxx_whitespace (pp);
>>> -         pp_cxx_left_bracket (pp);
>>> -         pp_cxx_ws_string (pp, M_("with"));
>>> -         pp_cxx_whitespace (pp);
>>> -         dump_template_bindings (pp, template_parms, template_args,
>>> typenames);
>>> -         pp_cxx_right_bracket (pp);
>>> -       }
>>> +      dump_substitution (pp, t, template_parms, template_args, flags);
>>>      }
>>>    else if (template_args)
>>>      {
>>> @@ -2950,12 +2974,7 @@ subst_to_string (tree p)
>>>
>>>    reinit_cxx_pp ();
>>>    dump_template_decl (cxx_pp, TREE_PURPOSE (p), flags);
>>> -  pp_cxx_whitespace (cxx_pp);
>>> -  pp_cxx_left_bracket (cxx_pp);
>>> -  pp_cxx_ws_string (cxx_pp, M_("with"));
>>> -  pp_cxx_whitespace (cxx_pp);
>>> -  dump_template_bindings (cxx_pp, tparms, targs, NULL);
>>> -  pp_cxx_right_bracket (cxx_pp);
>>> +  dump_substitution (cxx_pp, NULL, tparms, targs, /*flags=*/0);
>>>    return pp_ggc_formatted_text (cxx_pp);
>>>  }
>>>
>>> --
>>> 1.8.4
>>>
>
diff mbox

Patch

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bf49198..f848b81 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@ 
+2013-08-29  Adam Butcher  <adam@jessamine.co.uk>
+
+	* error.c (dump_lambda_function): New function, dependent on ...
+	(dump_substitution): ... this new function, factored out of ...
+	(subst_to_string): ... here and ...
+	(dump_function_decl): ... here.  Updated to early-out with call to
+	dump_lambda_function after determining template bindings.
+
 2013-08-28  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR c++/58255
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c82a0ce..af71000 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1363,6 +1363,47 @@  find_typenames (tree t)
   return ft.typenames;
 }
 
+/* Output the "[with ...]" clause for a template instantiation T iff
+   TEMPLATE_PARMS, TEMPLATE_ARGS and FLAGS are suitable.  T may be NULL if
+   formatting a deduction/substitution diagnostic rather than an
+   instantiation.  */
+
+static void
+dump_substitution (cxx_pretty_printer *pp,
+                   tree t, tree template_parms, tree template_args,
+                   int flags)
+{
+  if (template_parms != NULL_TREE && template_args != NULL_TREE
+      && !(flags & TFF_NO_TEMPLATE_BINDINGS))
+    {
+      vec<tree, va_gc> *typenames = t ? find_typenames (t) : NULL;
+      pp_cxx_whitespace (pp);
+      pp_cxx_left_bracket (pp);
+      pp->translate_string ("with");
+      pp_cxx_whitespace (pp);
+      dump_template_bindings (pp, template_parms, template_args, typenames);
+      pp_cxx_right_bracket (pp);
+    }
+}
+
+/* Dump the lambda function FN including its 'mutable' qualifier and any
+   template bindings.  */
+
+static void
+dump_lambda_function (cxx_pretty_printer *pp,
+		      tree fn, tree template_parms, tree template_args,
+		      int flags)
+{
+  /* A lambda's signature is essentially its "type".  */
+  dump_type (pp, DECL_CONTEXT (fn), flags);
+  if (!(TYPE_QUALS (class_of_this_parm (TREE_TYPE (fn))) & TYPE_QUAL_CONST))
+    {
+      pp->padding = pp_before;
+      pp_c_ws_string (pp, "mutable");
+    }
+  dump_substitution (pp, fn, template_parms, template_args, flags);
+}
+
 /* Pretty print a function decl. There are several ways we want to print a
    function declaration. The TFF_ bits in FLAGS tells us how to behave.
    As error can only apply the '#' flag once to give 0 and 1 for V, there
@@ -1379,15 +1420,6 @@  dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
   int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
   int do_outer_scope = ! (flags & TFF_UNQUALIFIED_NAME);
   tree exceptions;
-  vec<tree, va_gc> *typenames = NULL;
-
-  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
-    {
-      /* A lambda's signature is essentially its "type", so defer.  */
-      gcc_assert (LAMBDA_TYPE_P (DECL_CONTEXT (t)));
-      dump_type (pp, DECL_CONTEXT (t), flags);
-      return;
-    }
 
   flags &= ~(TFF_UNQUALIFIED_NAME | TFF_TEMPLATE_NAME);
   if (TREE_CODE (t) == TEMPLATE_DECL)
@@ -1409,10 +1441,12 @@  dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
 	{
 	  template_parms = DECL_TEMPLATE_PARMS (tmpl);
 	  t = tmpl;
-	  typenames = find_typenames (t);
 	}
     }
 
+  if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
+    return dump_lambda_function (pp, t, template_parms, template_args, flags);
+
   fntype = TREE_TYPE (t);
   parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
 
@@ -1476,17 +1510,7 @@  dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
       if (show_return)
 	dump_type_suffix (pp, TREE_TYPE (fntype), flags);
 
-      /* If T is a template instantiation, dump the parameter binding.  */
-      if (template_parms != NULL_TREE && template_args != NULL_TREE
-	  && !(flags & TFF_NO_TEMPLATE_BINDINGS))
-	{
-	  pp_cxx_whitespace (pp);
-	  pp_cxx_left_bracket (pp);
-	  pp_cxx_ws_string (pp, M_("with"));
-	  pp_cxx_whitespace (pp);
-	  dump_template_bindings (pp, template_parms, template_args, typenames);
-	  pp_cxx_right_bracket (pp);
-	}
+      dump_substitution (pp, t, template_parms, template_args, flags);
     }
   else if (template_args)
     {
@@ -2950,12 +2974,7 @@  subst_to_string (tree p)
 
   reinit_cxx_pp ();
   dump_template_decl (cxx_pp, TREE_PURPOSE (p), flags);
-  pp_cxx_whitespace (cxx_pp);
-  pp_cxx_left_bracket (cxx_pp);
-  pp_cxx_ws_string (cxx_pp, M_("with"));
-  pp_cxx_whitespace (cxx_pp);
-  dump_template_bindings (cxx_pp, tparms, targs, NULL);
-  pp_cxx_right_bracket (cxx_pp);
+  dump_substitution (cxx_pp, NULL, tparms, targs, /*flags=*/0);
   return pp_ggc_formatted_text (cxx_pp);
 }