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.

> 
> 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.

> 
> Jason
> 
> 

Reply via email to