* [PATCH] c++: improve template parameter level lowering
@ 2023-04-20 15:34 Patrick Palka
2023-04-20 15:44 ` Patrick Palka
0 siblings, 1 reply; 3+ messages in thread
From: Patrick Palka @ 2023-04-20 15:34 UTC (permalink / raw)
To: gcc-patches; +Cc: jason, Patrick Palka
1. Now that we no longer substitute the constraints of an auto, we can
get rid of the infinite recursion loop breaker during level lowering
of a constrained auto and we can also use the TEMPLATE_PARM_DESCENDANTS
cache in this case.
2. Don't bother recursing when level lowering a cv-qualified type template
parameter.
3. Use TEMPLATE_PARM_DESCENDANTS when level lowering a non-type template
parameter too.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?
gcc/cp/ChangeLog:
* pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Remove infinite
recursion loop breaker in the level lowering case for
constrained autos. Use the TEMPLATE_PARM_DESCENDANTS cache in
this case as well.
<case TEMPLATE_PARM_INDEX>: Use the TEMPLATE_PARM_INDEX cache
when level lowering a non-type template parameter.
---
gcc/cp/pt.cc | 42 ++++++++++++++++++++----------------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index f65f2d58b28..07e9736cdce 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* If we get here, we must have been looking at a parm for a
more deeply nested template. Make a new version of this
template parameter, but with a lower level. */
+ int quals;
switch (code)
{
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
- if (cp_type_quals (t))
+ quals = cp_type_quals (t);
+ if (quals)
{
- r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
- r = cp_build_qualified_type
- (r, cp_type_quals (t),
- complain | (code == TEMPLATE_TYPE_PARM
- ? tf_ignore_bad_quals : 0));
+ gcc_checking_assert (code == TEMPLATE_TYPE_PARM);
+ t = TYPE_MAIN_VARIANT (t);
}
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
- && (r = (TEMPLATE_PARM_DESCENDANTS
- (TEMPLATE_TYPE_PARM_INDEX (t))))
- && (r = TREE_TYPE (r))
- && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r))
- /* Break infinite recursion when substituting the constraints
- of a constrained placeholder. */;
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
- && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
- r = TEMPLATE_PARM_DESCENDANTS (arg))
- && (TEMPLATE_PARM_LEVEL (r)
- == TEMPLATE_PARM_LEVEL (arg) - levels))
- /* Cache the simple case of lowering a type parameter. */
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
+ r = TEMPLATE_PARM_DESCENDANTS (arg))
+ && (TEMPLATE_PARM_LEVEL (r)
+ == TEMPLATE_PARM_LEVEL (arg) - levels))
+ /* Cache the simple case of lowering a type parameter. */
r = TREE_TYPE (r);
else
{
@@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else
TYPE_CANONICAL (r) = canonical_type_parameter (r);
}
+ if (quals)
+ r = cp_build_qualified_type (r, quals,
+ complain | tf_ignore_bad_quals);
break;
case BOUND_TEMPLATE_TEMPLATE_PARM:
@@ -16307,7 +16300,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
type = tsubst (type, args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
- r = reduce_template_parm_level (t, type, levels, args, complain);
+ if ((r = TEMPLATE_PARM_DESCENDANTS (t))
+ && (TEMPLATE_PARM_LEVEL (r) == TEMPLATE_PARM_LEVEL (t) - levels)
+ && TREE_TYPE (r) == type)
+ /* Cache the simple case of lowering a non-type parameter. */;
+ else
+ r = reduce_template_parm_level (t, type, levels, args, complain);
break;
default:
--
2.40.0.352.g667fcf4e15
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] c++: improve template parameter level lowering
2023-04-20 15:34 [PATCH] c++: improve template parameter level lowering Patrick Palka
@ 2023-04-20 15:44 ` Patrick Palka
2023-04-20 17:07 ` Jason Merrill
0 siblings, 1 reply; 3+ messages in thread
From: Patrick Palka @ 2023-04-20 15:44 UTC (permalink / raw)
To: Patrick Palka; +Cc: gcc-patches, jason
On Thu, 20 Apr 2023, Patrick Palka wrote:
> 1. Now that we no longer substitute the constraints of an auto, we can
> get rid of the infinite recursion loop breaker during level lowering
> of a constrained auto and we can also use the TEMPLATE_PARM_DESCENDANTS
> cache in this case.
> 2. Don't bother recursing when level lowering a cv-qualified type template
> parameter.
> 3. Use TEMPLATE_PARM_DESCENDANTS when level lowering a non-type template
> parameter too.
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
>
> gcc/cp/ChangeLog:
>
> * pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Remove infinite
> recursion loop breaker in the level lowering case for
> constrained autos. Use the TEMPLATE_PARM_DESCENDANTS cache in
> this case as well.
> <case TEMPLATE_PARM_INDEX>: Use the TEMPLATE_PARM_INDEX cache
> when level lowering a non-type template parameter.
> ---
> gcc/cp/pt.cc | 42 ++++++++++++++++++++----------------------
> 1 file changed, 20 insertions(+), 22 deletions(-)
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index f65f2d58b28..07e9736cdce 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> /* If we get here, we must have been looking at a parm for a
> more deeply nested template. Make a new version of this
> template parameter, but with a lower level. */
> + int quals;
> switch (code)
> {
> case TEMPLATE_TYPE_PARM:
> case TEMPLATE_TEMPLATE_PARM:
> - if (cp_type_quals (t))
> + quals = cp_type_quals (t);
> + if (quals)
> {
> - r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
> - r = cp_build_qualified_type
> - (r, cp_type_quals (t),
> - complain | (code == TEMPLATE_TYPE_PARM
> - ? tf_ignore_bad_quals : 0));
> + gcc_checking_assert (code == TEMPLATE_TYPE_PARM);
> + t = TYPE_MAIN_VARIANT (t);
> }
> - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> - && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
> - && (r = (TEMPLATE_PARM_DESCENDANTS
> - (TEMPLATE_TYPE_PARM_INDEX (t))))
> - && (r = TREE_TYPE (r))
> - && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r))
> - /* Break infinite recursion when substituting the constraints
> - of a constrained placeholder. */;
> - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> - && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
> - && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
> - r = TEMPLATE_PARM_DESCENDANTS (arg))
> - && (TEMPLATE_PARM_LEVEL (r)
> - == TEMPLATE_PARM_LEVEL (arg) - levels))
> - /* Cache the simple case of lowering a type parameter. */
> + if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> + && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
> + r = TEMPLATE_PARM_DESCENDANTS (arg))
> + && (TEMPLATE_PARM_LEVEL (r)
> + == TEMPLATE_PARM_LEVEL (arg) - levels))
> + /* Cache the simple case of lowering a type parameter. */
> r = TREE_TYPE (r);
> else
> {
> @@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> else
> TYPE_CANONICAL (r) = canonical_type_parameter (r);
> }
> + if (quals)
> + r = cp_build_qualified_type (r, quals,
> + complain | tf_ignore_bad_quals);
> break;
>
> case BOUND_TEMPLATE_TEMPLATE_PARM:
> @@ -16307,7 +16300,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> type = tsubst (type, args, complain, in_decl);
> if (type == error_mark_node)
> return error_mark_node;
> - r = reduce_template_parm_level (t, type, levels, args, complain);
> + if ((r = TEMPLATE_PARM_DESCENDANTS (t))
> + && (TEMPLATE_PARM_LEVEL (r) == TEMPLATE_PARM_LEVEL (t) - levels)
> + && TREE_TYPE (r) == type)
> + /* Cache the simple case of lowering a non-type parameter. */;
> + else
> + r = reduce_template_parm_level (t, type, levels, args, complain);
D'oh, this hunk is totally redundant since reduce_template_parm_level
already checks TEMPLATE_PARM_DESCENDANTS, and so we've been caching
level-lowering of non-type template parameters this whole time.
Please consider this patch instead, which removes this hunk and
therefore only changes TEMPLATE_TYPE_PARM level lowering:
-- >8 --
Subject: [PATCH] c++: improve TEMPLATE_TYPE_PARM level lowering
1. Don't bother recursing when level lowering a cv-qualified type template
parameter.
2. Get rid of the infinite recursion loop breaker during level lowering of
a constrained auto and use the TEMPLATE_PARM_DESCENDANTS cache in this
case too, now that we no longer substitute its constraints.
gcc/cp/ChangeLog:
* pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Don't recurse when
level lowering a cv-qualified type template parameter. Remove
infinite recursion loop breaker in the level lowering case for
constrained autos. Use the TEMPLATE_PARM_DESCENDANTS cache in
this case as well.
---
gcc/cp/pt.cc | 35 ++++++++++++++---------------------
1 file changed, 14 insertions(+), 21 deletions(-)
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index f65f2d58b28..ed038b9ca24 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* If we get here, we must have been looking at a parm for a
more deeply nested template. Make a new version of this
template parameter, but with a lower level. */
+ int quals;
switch (code)
{
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
- if (cp_type_quals (t))
+ quals = cp_type_quals (t);
+ if (quals)
{
- r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
- r = cp_build_qualified_type
- (r, cp_type_quals (t),
- complain | (code == TEMPLATE_TYPE_PARM
- ? tf_ignore_bad_quals : 0));
+ gcc_checking_assert (code == TEMPLATE_TYPE_PARM);
+ t = TYPE_MAIN_VARIANT (t);
}
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
- && (r = (TEMPLATE_PARM_DESCENDANTS
- (TEMPLATE_TYPE_PARM_INDEX (t))))
- && (r = TREE_TYPE (r))
- && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r))
- /* Break infinite recursion when substituting the constraints
- of a constrained placeholder. */;
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
- && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
- && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
- r = TEMPLATE_PARM_DESCENDANTS (arg))
- && (TEMPLATE_PARM_LEVEL (r)
- == TEMPLATE_PARM_LEVEL (arg) - levels))
- /* Cache the simple case of lowering a type parameter. */
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
+ r = TEMPLATE_PARM_DESCENDANTS (arg))
+ && (TEMPLATE_PARM_LEVEL (r)
+ == TEMPLATE_PARM_LEVEL (arg) - levels))
+ /* Cache the simple case of lowering a type parameter. */
r = TREE_TYPE (r);
else
{
@@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else
TYPE_CANONICAL (r) = canonical_type_parameter (r);
}
+ if (quals)
+ r = cp_build_qualified_type (r, quals,
+ complain | tf_ignore_bad_quals);
break;
case BOUND_TEMPLATE_TEMPLATE_PARM:
--
2.40.0.352.g667fcf4e15
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] c++: improve template parameter level lowering
2023-04-20 15:44 ` Patrick Palka
@ 2023-04-20 17:07 ` Jason Merrill
0 siblings, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2023-04-20 17:07 UTC (permalink / raw)
To: Patrick Palka; +Cc: gcc-patches
On 4/20/23 11:44, Patrick Palka wrote:
> On Thu, 20 Apr 2023, Patrick Palka wrote:
>
>> 1. Now that we no longer substitute the constraints of an auto, we can
>> get rid of the infinite recursion loop breaker during level lowering
>> of a constrained auto and we can also use the TEMPLATE_PARM_DESCENDANTS
>> cache in this case.
>> 2. Don't bother recursing when level lowering a cv-qualified type template
>> parameter.
>> 3. Use TEMPLATE_PARM_DESCENDANTS when level lowering a non-type template
>> parameter too.
>>
>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
>> trunk?
>>
>> gcc/cp/ChangeLog:
>>
>> * pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Remove infinite
>> recursion loop breaker in the level lowering case for
>> constrained autos. Use the TEMPLATE_PARM_DESCENDANTS cache in
>> this case as well.
>> <case TEMPLATE_PARM_INDEX>: Use the TEMPLATE_PARM_INDEX cache
>> when level lowering a non-type template parameter.
>> ---
>> gcc/cp/pt.cc | 42 ++++++++++++++++++++----------------------
>> 1 file changed, 20 insertions(+), 22 deletions(-)
>>
>> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
>> index f65f2d58b28..07e9736cdce 100644
>> --- a/gcc/cp/pt.cc
>> +++ b/gcc/cp/pt.cc
>> @@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>> /* If we get here, we must have been looking at a parm for a
>> more deeply nested template. Make a new version of this
>> template parameter, but with a lower level. */
>> + int quals;
>> switch (code)
>> {
>> case TEMPLATE_TYPE_PARM:
>> case TEMPLATE_TEMPLATE_PARM:
>> - if (cp_type_quals (t))
>> + quals = cp_type_quals (t);
>> + if (quals)
>> {
>> - r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
>> - r = cp_build_qualified_type
>> - (r, cp_type_quals (t),
>> - complain | (code == TEMPLATE_TYPE_PARM
>> - ? tf_ignore_bad_quals : 0));
>> + gcc_checking_assert (code == TEMPLATE_TYPE_PARM);
>> + t = TYPE_MAIN_VARIANT (t);
>> }
>> - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
>> - && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
>> - && (r = (TEMPLATE_PARM_DESCENDANTS
>> - (TEMPLATE_TYPE_PARM_INDEX (t))))
>> - && (r = TREE_TYPE (r))
>> - && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r))
>> - /* Break infinite recursion when substituting the constraints
>> - of a constrained placeholder. */;
>> - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
>> - && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
>> - && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
>> - r = TEMPLATE_PARM_DESCENDANTS (arg))
>> - && (TEMPLATE_PARM_LEVEL (r)
>> - == TEMPLATE_PARM_LEVEL (arg) - levels))
>> - /* Cache the simple case of lowering a type parameter. */
>> + if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
>> + && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
>> + r = TEMPLATE_PARM_DESCENDANTS (arg))
>> + && (TEMPLATE_PARM_LEVEL (r)
>> + == TEMPLATE_PARM_LEVEL (arg) - levels))
>> + /* Cache the simple case of lowering a type parameter. */
>> r = TREE_TYPE (r);
>> else
>> {
>> @@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>> else
>> TYPE_CANONICAL (r) = canonical_type_parameter (r);
>> }
>> + if (quals)
>> + r = cp_build_qualified_type (r, quals,
>> + complain | tf_ignore_bad_quals);
>> break;
>>
>> case BOUND_TEMPLATE_TEMPLATE_PARM:
>> @@ -16307,7 +16300,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>> type = tsubst (type, args, complain, in_decl);
>> if (type == error_mark_node)
>> return error_mark_node;
>> - r = reduce_template_parm_level (t, type, levels, args, complain);
>> + if ((r = TEMPLATE_PARM_DESCENDANTS (t))
>> + && (TEMPLATE_PARM_LEVEL (r) == TEMPLATE_PARM_LEVEL (t) - levels)
>> + && TREE_TYPE (r) == type)
>> + /* Cache the simple case of lowering a non-type parameter. */;
>> + else
>> + r = reduce_template_parm_level (t, type, levels, args, complain);
>
> D'oh, this hunk is totally redundant since reduce_template_parm_level
> already checks TEMPLATE_PARM_DESCENDANTS, and so we've been caching
> level-lowering of non-type template parameters this whole time.
>
> Please consider this patch instead, which removes this hunk and
> therefore only changes TEMPLATE_TYPE_PARM level lowering:
OK.
> -- >8 --
>
> Subject: [PATCH] c++: improve TEMPLATE_TYPE_PARM level lowering
>
> 1. Don't bother recursing when level lowering a cv-qualified type template
> parameter.
> 2. Get rid of the infinite recursion loop breaker during level lowering of
> a constrained auto and use the TEMPLATE_PARM_DESCENDANTS cache in this
> case too, now that we no longer substitute its constraints.
>
> gcc/cp/ChangeLog:
>
> * pt.cc (tsubst) <case TEMPLATE_TYPE_PARM>: Don't recurse when
> level lowering a cv-qualified type template parameter. Remove
> infinite recursion loop breaker in the level lowering case for
> constrained autos. Use the TEMPLATE_PARM_DESCENDANTS cache in
> this case as well.
> ---
> gcc/cp/pt.cc | 35 ++++++++++++++---------------------
> 1 file changed, 14 insertions(+), 21 deletions(-)
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index f65f2d58b28..ed038b9ca24 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -16228,33 +16228,23 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> /* If we get here, we must have been looking at a parm for a
> more deeply nested template. Make a new version of this
> template parameter, but with a lower level. */
> + int quals;
> switch (code)
> {
> case TEMPLATE_TYPE_PARM:
> case TEMPLATE_TEMPLATE_PARM:
> - if (cp_type_quals (t))
> + quals = cp_type_quals (t);
> + if (quals)
> {
> - r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
> - r = cp_build_qualified_type
> - (r, cp_type_quals (t),
> - complain | (code == TEMPLATE_TYPE_PARM
> - ? tf_ignore_bad_quals : 0));
> + gcc_checking_assert (code == TEMPLATE_TYPE_PARM);
> + t = TYPE_MAIN_VARIANT (t);
> }
> - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> - && PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
> - && (r = (TEMPLATE_PARM_DESCENDANTS
> - (TEMPLATE_TYPE_PARM_INDEX (t))))
> - && (r = TREE_TYPE (r))
> - && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r))
> - /* Break infinite recursion when substituting the constraints
> - of a constrained placeholder. */;
> - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> - && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)
> - && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
> - r = TEMPLATE_PARM_DESCENDANTS (arg))
> - && (TEMPLATE_PARM_LEVEL (r)
> - == TEMPLATE_PARM_LEVEL (arg) - levels))
> - /* Cache the simple case of lowering a type parameter. */
> + if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
> + && (arg = TEMPLATE_TYPE_PARM_INDEX (t),
> + r = TEMPLATE_PARM_DESCENDANTS (arg))
> + && (TEMPLATE_PARM_LEVEL (r)
> + == TEMPLATE_PARM_LEVEL (arg) - levels))
> + /* Cache the simple case of lowering a type parameter. */
> r = TREE_TYPE (r);
> else
> {
> @@ -16278,6 +16268,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> else
> TYPE_CANONICAL (r) = canonical_type_parameter (r);
> }
> + if (quals)
> + r = cp_build_qualified_type (r, quals,
> + complain | tf_ignore_bad_quals);
> break;
>
> case BOUND_TEMPLATE_TEMPLATE_PARM:
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-04-20 17:07 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-20 15:34 [PATCH] c++: improve template parameter level lowering Patrick Palka
2023-04-20 15:44 ` Patrick Palka
2023-04-20 17:07 ` 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).