On 10/7/24 10:26 AM, Patrick Palka wrote:
On Mon, 7 Oct 2024, Jason Merrill wrote:

On 10/7/24 9:58 AM, Patrick Palka wrote:
On Sat, 5 Oct 2024, Jason Merrill wrote:

On 10/4/24 11:00 AM, Patrick Palka wrote:
On Thu, 3 Oct 2024, Jason Merrill wrote:

On 10/3/24 12:38 PM, Jason Merrill wrote:
On 10/2/24 7:50 AM, Richard Biener wrote:
This reduces peak memory usage by 20% for a specific testcase.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

It's very ugly so I'd appreciate suggestions on how to handle such
situations better?

I'm pushing this alternative patch, tested x86_64-pc-linux-gnu.

OK, apparently that was both too clever and not clever enough.
Replacing
it
with this one that's much closer to yours.

Jason

From: Jason Merrill <ja...@redhat.com>
Date: Thu, 3 Oct 2024 16:31:00 -0400
Subject: [PATCH] c++: free garbage vec in coerce_template_parms
To: gcc-patches@gcc.gnu.org

coerce_template_parms can create two different vecs for the inner
template
arguments, new_inner_args and (potentially) the result of
expand_template_argument_pack.  One or the other, or possibly both,
end up
being garbage: in the typical case, the expanded vec is garbage
because
it's
only used as the source for convert_template_argument.  In some
dependent
cases, the new vec is garbage because we decide to return the original
args
instead.  In these cases, ggc_free the garbage vec to reduce the
memory
overhead of overload resolution.

gcc/cp/ChangeLog:

        * pt.cc (coerce_template_parms): Free garbage vecs.

Co-authored-by: Richard Biener <rguent...@suse.de>
---
    gcc/cp/pt.cc | 10 +++++++++-
    1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 20affcd65a2..4ceae1d38de 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -9275,6 +9275,7 @@ coerce_template_parms (tree parms,
            {
              /* We don't know how many args we have yet, just use the
                 unconverted (and still packed) ones for now.  */
+             ggc_free (new_inner_args);
              new_inner_args = orig_inner_args;
              arg_idx = nargs;
              break;
@@ -9329,7 +9330,8 @@ coerce_template_parms (tree parms,
                  = make_pack_expansion (conv, complain);
                    /* We don't know how many args we have yet, just
-                 use the unconverted ones for now.  */
+                use the unconverted (but unpacked) ones for now.  */
+             ggc_free (new_inner_args);

I'm a bit worried about these ggc_frees.  If an earlier template
parameter is a constrained auto NTTP then new_inner_args/new_args could
have been captured by the satisfaction cache during coercion for that
argument, and so we'd be freeing a vector that's still live?

It seems like for e.g.

template <class T> concept NotInt = !__is_same (T, int);
template <NotInt auto NI, class U> struct A { };
template <class...Ts> using B = A<'x', Ts...>;

we don't check satisfaction until after we're done coercing, because of

    if (processing_template_decl && context == adc_unify)
      /* Constraints will be checked after deduction.  */;

in do_auto_deduction.

Ah, I wonder why we pass/use adc_unify from both unify and
convert_template_argument..  That early exit makes sense for unify
but not for convert_template_argument since it prevents us from
checking constrained auto NTTPs during ahead of time coercion:

    template<class T>
    concept C = T::value;

    template<C auto>
    struct A { };

    template<class T>
    void f() {
      A<0> a; // no constraint error
    }

    A<0> a; // constraint error

I guess we'd ideally want to fix/implement this?  At which point the
ggc_free's of new_inner_args would be unsafe I think..

I don't think that would be an improvement; the C constraint is an associated
constraint of A (https://eel.is/c++draft/temp#constr.decl-3.3.1).

I thought C in 'template<C X>' is an associated constraint but not in
'template<C auto X>'?  At least that's how GCC currently behaves.

I think that's wrong: https://eel.is/c++draft/temp#param-11

Why don't we check satisfaction of A<0> when parsing f?

We do but it's considered to have no associated constraints since C is
'attached' to the auto rather than to A currently.

Ah, yes, I think I've run into trouble from that before.

Jason

Reply via email to