Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]

2021-03-01 Thread Jason Merrill via Gcc-patches

On 3/1/21 7:59 PM, Marek Polacek wrote:

On Mon, Mar 01, 2021 at 03:08:58PM -0500, Jason Merrill wrote:

On 3/1/21 2:54 PM, Marek Polacek wrote:

On Thu, Feb 25, 2021 at 10:45:29PM -0500, Jason Merrill via Gcc-patches wrote:

On 2/25/21 5:41 PM, Marek Polacek wrote:

On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote:

On 2/12/21 6:12 PM, Marek Polacek wrote:

We represent deduction guides with FUNCTION_DECLs, but they are built
without DECL_CONTEXT


Hmm, that seems wrong: "A deduction-guide shall be declared in the
same scope as the corresponding class template and, for a member class
template, with the same access."  But it probably isn't necessary to change
this:


leading to an ICE in type_dependent_expression_p
on the assert that the type of a function template with no dependent
(innermost!) template arguments must be non-dependent.  Consider the
attached class-deduction79.C: we create a deduction guide:

  template G(T)-> E::G

we deduce T and create a partial instantiation:

  G(T) -> E::G [with T = int]

And then do_class_deduction wants to create a CALL_EXPR from the above
using build_new_function_call -> build_over_call which calls mark_used
-> maybe_instantiate_noexcept -> type_dependent_expression_p.

There, the innermost template arguments are non-dependent (), but
the fntype is dependent -- the return type is a TYPENAME_TYPE, and
since we have no DECL_CONTEXT, this check holds:

  /* Otherwise, if the function decl isn't from a dependent scope, it can't 
be
 type-dependent.  Checking this is important for functions with auto 
return
 type, which looks like a dependent type.  */
  if (TREE_CODE (expression) == FUNCTION_DECL
  && !(DECL_CLASS_SCOPE_P (expression)
   && dependent_type_p (DECL_CONTEXT (expression)))

whereupon we ICE.

Experiments with setting DECL_CONTEXT didn't pan out.


In c8 of the PR it looks like you were using the class itself as
DECL_CONTEXT; the quote above says that the right context is the enclosing
scope of the class.


Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in
retrieve_specialization:

 /* There should be as many levels of arguments as there are
levels of parameters.  */
 gcc_assert (TMPL_ARGS_DEPTH (args)
 == (TREE_CODE (tmpl) == TEMPLATE_DECL
 ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
 : template_class_depth (DECL_CONTEXT (tmpl;


Yeah, probably simpler not to bother.


So perhaps we
just want to skip the assert for deduction guides, because they are
a little special.  Better ideas solicited.


In c3 you mention that one of the variants broke with r269093; this is
because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for the
template pattern itself (E).


And the original test started with my r11-1713 because using TREE_TYPE
directly instead of decltype (which is a non-deduced context) means we
can deduced from the argument.

But I think probably the right answer is to defer this deduction until the
enclosing scope is non-dependent, i.e. (untested)


Thanks.  That mostly works, except the new class-deduction-aggr[89].C
tests.  Consider 8:

namespace N {
template  struct S {
 template  S(T, U);
};
} // namespace N
template  struct E {
 template  struct G { T t; };
 void fn() { G{N::S{'a', 1}}; }
};

void
g ()
{
 E<1> e;
 e.fn ();
}

With your patch, when in do_class_deduction when processing_template_decl,
we just return.  When we call do_class_deduction again when p_t_d is 0,
maybe_aggr_guide returns early here:

 if (!CP_AGGREGATE_TYPE_P (type))
   return NULL_TREE

because G is not complete (and rightly so, we didn't instantiate it).  So
we aren't able to deduce the template parameters.  I'm not sure if I should
pursue this direction further.  :(


I think so; we just need to test CP_AGGREGATE_TYPE_P on the original
template pattern instead of the instantiation E<1>::G.


I'm sorry, I've got stuck again.

Yes, using the original template pattern helps us get past the
CP_AGGREGATE_TYPE_P check.

However, using TREE_TYPE (DECL_TI_TEMPLATE (tmpl)) as the type of the deduction 
guide
means the guide will be "template G(T)-> E< >::G" which
results in

class-deduction-aggr8.C:11:15: error: invalid use of dependent type 'typename 
E< >::G >'

which makes sense I guess: when we defer building up the guide until
we've instantiated E<1>, finding the dependent type E<> is not expected.


Yeah, I was only thinking to use the pattern for the aggregate check.


Ack.  Though I think I also have to use the pattern here:

   init = reshape_init (type, init, complain);

otherwise reshape_init returns a TARGET_EXPR and we immediately
crash in collect_ctor_idx_types because that only expects a CONSTRUCTOR.
And what we need to get is the type T -- of the constructor's index.
  

But creating the guide with "struct E<1>::G" as its type seems
wrong; I'm not even sure if a 

Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]

2021-03-01 Thread Marek Polacek via Gcc-patches
On Mon, Mar 01, 2021 at 03:08:58PM -0500, Jason Merrill wrote:
> On 3/1/21 2:54 PM, Marek Polacek wrote:
> > On Thu, Feb 25, 2021 at 10:45:29PM -0500, Jason Merrill via Gcc-patches 
> > wrote:
> > > On 2/25/21 5:41 PM, Marek Polacek wrote:
> > > > On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote:
> > > > > On 2/12/21 6:12 PM, Marek Polacek wrote:
> > > > > > We represent deduction guides with FUNCTION_DECLs, but they are 
> > > > > > built
> > > > > > without DECL_CONTEXT
> > > > > 
> > > > > Hmm, that seems wrong: "A deduction-guide shall be declared in the
> > > > > same scope as the corresponding class template and, for a member class
> > > > > template, with the same access."  But it probably isn't necessary to 
> > > > > change
> > > > > this:
> > > > > 
> > > > > > leading to an ICE in type_dependent_expression_p
> > > > > > on the assert that the type of a function template with no dependent
> > > > > > (innermost!) template arguments must be non-dependent.  Consider the
> > > > > > attached class-deduction79.C: we create a deduction guide:
> > > > > > 
> > > > > >  template G(T)-> E::G
> > > > > > 
> > > > > > we deduce T and create a partial instantiation:
> > > > > > 
> > > > > >  G(T) -> E::G [with T = int]
> > > > > > 
> > > > > > And then do_class_deduction wants to create a CALL_EXPR from the 
> > > > > > above
> > > > > > using build_new_function_call -> build_over_call which calls 
> > > > > > mark_used
> > > > > > -> maybe_instantiate_noexcept -> type_dependent_expression_p.
> > > > > > 
> > > > > > There, the innermost template arguments are non-dependent (), 
> > > > > > but
> > > > > > the fntype is dependent -- the return type is a TYPENAME_TYPE, and
> > > > > > since we have no DECL_CONTEXT, this check holds:
> > > > > > 
> > > > > >  /* Otherwise, if the function decl isn't from a dependent 
> > > > > > scope, it can't be
> > > > > > type-dependent.  Checking this is important for functions 
> > > > > > with auto return
> > > > > > type, which looks like a dependent type.  */
> > > > > >  if (TREE_CODE (expression) == FUNCTION_DECL
> > > > > >  && !(DECL_CLASS_SCOPE_P (expression)
> > > > > >   && dependent_type_p (DECL_CONTEXT (expression)))
> > > > > > 
> > > > > > whereupon we ICE.
> > > > > > 
> > > > > > Experiments with setting DECL_CONTEXT didn't pan out.
> > > > > 
> > > > > In c8 of the PR it looks like you were using the class itself as
> > > > > DECL_CONTEXT; the quote above says that the right context is the 
> > > > > enclosing
> > > > > scope of the class.
> > > > 
> > > > Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in
> > > > retrieve_specialization:
> > > > 
> > > > /* There should be as many levels of arguments as there are
> > > >levels of parameters.  */
> > > > gcc_assert (TMPL_ARGS_DEPTH (args)
> > > > == (TREE_CODE (tmpl) == TEMPLATE_DECL
> > > > ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
> > > > : template_class_depth (DECL_CONTEXT (tmpl;
> > > 
> > > Yeah, probably simpler not to bother.
> > > 
> > > > > > So perhaps we
> > > > > > just want to skip the assert for deduction guides, because they are
> > > > > > a little special.  Better ideas solicited.
> > > > > 
> > > > > In c3 you mention that one of the variants broke with r269093; this is
> > > > > because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false 
> > > > > for the
> > > > > template pattern itself (E).
> > > > 
> > > > And the original test started with my r11-1713 because using TREE_TYPE
> > > > directly instead of decltype (which is a non-deduced context) means we
> > > > can deduced from the argument.
> > > > > But I think probably the right answer is to defer this deduction 
> > > > > until the
> > > > > enclosing scope is non-dependent, i.e. (untested)
> > > > 
> > > > Thanks.  That mostly works, except the new class-deduction-aggr[89].C
> > > > tests.  Consider 8:
> > > > 
> > > > namespace N {
> > > > template  struct S {
> > > > template  S(T, U);
> > > > };
> > > > } // namespace N
> > > > template  struct E {
> > > > template  struct G { T t; };
> > > > void fn() { G{N::S{'a', 1}}; }
> > > > };
> > > > 
> > > > void
> > > > g ()
> > > > {
> > > > E<1> e;
> > > > e.fn ();
> > > > }
> > > > 
> > > > With your patch, when in do_class_deduction when 
> > > > processing_template_decl,
> > > > we just return.  When we call do_class_deduction again when p_t_d is 0,
> > > > maybe_aggr_guide returns early here:
> > > > 
> > > > if (!CP_AGGREGATE_TYPE_P (type))
> > > >   return NULL_TREE
> > > > 
> > > > because G is not complete (and rightly so, we didn't instantiate it).  
> > > > So
> > > > we aren't able to deduce the template parameters.  I'm not sure if I 
> > > > should
> > > > pursue this direction further.  :(
> > > 
> > > I think so; we just need to test CP_AGGREGATE_TYPE_P on the 

Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]

2021-03-01 Thread Jason Merrill via Gcc-patches

On 3/1/21 2:54 PM, Marek Polacek wrote:

On Thu, Feb 25, 2021 at 10:45:29PM -0500, Jason Merrill via Gcc-patches wrote:

On 2/25/21 5:41 PM, Marek Polacek wrote:

On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote:

On 2/12/21 6:12 PM, Marek Polacek wrote:

We represent deduction guides with FUNCTION_DECLs, but they are built
without DECL_CONTEXT


Hmm, that seems wrong: "A deduction-guide shall be declared in the
same scope as the corresponding class template and, for a member class
template, with the same access."  But it probably isn't necessary to change
this:


leading to an ICE in type_dependent_expression_p
on the assert that the type of a function template with no dependent
(innermost!) template arguments must be non-dependent.  Consider the
attached class-deduction79.C: we create a deduction guide:

 template G(T)-> E::G

we deduce T and create a partial instantiation:

 G(T) -> E::G [with T = int]

And then do_class_deduction wants to create a CALL_EXPR from the above
using build_new_function_call -> build_over_call which calls mark_used
-> maybe_instantiate_noexcept -> type_dependent_expression_p.

There, the innermost template arguments are non-dependent (), but
the fntype is dependent -- the return type is a TYPENAME_TYPE, and
since we have no DECL_CONTEXT, this check holds:

 /* Otherwise, if the function decl isn't from a dependent scope, it can't 
be
type-dependent.  Checking this is important for functions with auto 
return
type, which looks like a dependent type.  */
 if (TREE_CODE (expression) == FUNCTION_DECL
 && !(DECL_CLASS_SCOPE_P (expression)
  && dependent_type_p (DECL_CONTEXT (expression)))

whereupon we ICE.

Experiments with setting DECL_CONTEXT didn't pan out.


In c8 of the PR it looks like you were using the class itself as
DECL_CONTEXT; the quote above says that the right context is the enclosing
scope of the class.


Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in
retrieve_specialization:

/* There should be as many levels of arguments as there are
   levels of parameters.  */
gcc_assert (TMPL_ARGS_DEPTH (args)
== (TREE_CODE (tmpl) == TEMPLATE_DECL
? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
: template_class_depth (DECL_CONTEXT (tmpl;


Yeah, probably simpler not to bother.


So perhaps we
just want to skip the assert for deduction guides, because they are
a little special.  Better ideas solicited.


In c3 you mention that one of the variants broke with r269093; this is
because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for the
template pattern itself (E).


And the original test started with my r11-1713 because using TREE_TYPE
directly instead of decltype (which is a non-deduced context) means we
can deduced from the argument.

But I think probably the right answer is to defer this deduction until the
enclosing scope is non-dependent, i.e. (untested)


Thanks.  That mostly works, except the new class-deduction-aggr[89].C
tests.  Consider 8:

namespace N {
template  struct S {
template  S(T, U);
};
} // namespace N
template  struct E {
template  struct G { T t; };
void fn() { G{N::S{'a', 1}}; }
};

void
g ()
{
E<1> e;
e.fn ();
}

With your patch, when in do_class_deduction when processing_template_decl,
we just return.  When we call do_class_deduction again when p_t_d is 0,
maybe_aggr_guide returns early here:

if (!CP_AGGREGATE_TYPE_P (type))
  return NULL_TREE

because G is not complete (and rightly so, we didn't instantiate it).  So
we aren't able to deduce the template parameters.  I'm not sure if I should
pursue this direction further.  :(


I think so; we just need to test CP_AGGREGATE_TYPE_P on the original
template pattern instead of the instantiation E<1>::G.


I'm sorry, I've got stuck again.

Yes, using the original template pattern helps us get past the
CP_AGGREGATE_TYPE_P check.

However, using TREE_TYPE (DECL_TI_TEMPLATE (tmpl)) as the type of the deduction 
guide
means the guide will be "template G(T)-> E< >::G" which
results in

   class-deduction-aggr8.C:11:15: error: invalid use of dependent type 'typename E< 
>::G >'

which makes sense I guess: when we defer building up the guide until
we've instantiated E<1>, finding the dependent type E<> is not expected.


Yeah, I was only thinking to use the pattern for the aggregate check.


But creating the guide with "struct E<1>::G" as its type seems
wrong; I'm not even sure if a guide like

   template G(T)-> E<1>::G

makes sense.


It looks fine to me.


In any case the deduction fails (when we call
build_new_function_call in do_class_deduction), because we've got
a mismatch: the template parameter T has level 1, but the template
function parameter has level 2.


Sure, because E<1>::G has been partially instantiated, so the T has 
been reduced from level 2 to 1.


You'll need to do a similar partial instantiation 

Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]

2021-03-01 Thread Marek Polacek via Gcc-patches
On Thu, Feb 25, 2021 at 10:45:29PM -0500, Jason Merrill via Gcc-patches wrote:
> On 2/25/21 5:41 PM, Marek Polacek wrote:
> > On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote:
> > > On 2/12/21 6:12 PM, Marek Polacek wrote:
> > > > We represent deduction guides with FUNCTION_DECLs, but they are built
> > > > without DECL_CONTEXT
> > > 
> > > Hmm, that seems wrong: "A deduction-guide shall be declared in the
> > > same scope as the corresponding class template and, for a member class
> > > template, with the same access."  But it probably isn't necessary to 
> > > change
> > > this:
> > > 
> > > > leading to an ICE in type_dependent_expression_p
> > > > on the assert that the type of a function template with no dependent
> > > > (innermost!) template arguments must be non-dependent.  Consider the
> > > > attached class-deduction79.C: we create a deduction guide:
> > > > 
> > > > template G(T)-> E::G
> > > > 
> > > > we deduce T and create a partial instantiation:
> > > > 
> > > > G(T) -> E::G [with T = int]
> > > > 
> > > > And then do_class_deduction wants to create a CALL_EXPR from the above
> > > > using build_new_function_call -> build_over_call which calls mark_used
> > > > -> maybe_instantiate_noexcept -> type_dependent_expression_p.
> > > > 
> > > > There, the innermost template arguments are non-dependent (), but
> > > > the fntype is dependent -- the return type is a TYPENAME_TYPE, and
> > > > since we have no DECL_CONTEXT, this check holds:
> > > > 
> > > > /* Otherwise, if the function decl isn't from a dependent scope, it 
> > > > can't be
> > > >type-dependent.  Checking this is important for functions with 
> > > > auto return
> > > >type, which looks like a dependent type.  */
> > > > if (TREE_CODE (expression) == FUNCTION_DECL
> > > > && !(DECL_CLASS_SCOPE_P (expression)
> > > >  && dependent_type_p (DECL_CONTEXT (expression)))
> > > > 
> > > > whereupon we ICE.
> > > > 
> > > > Experiments with setting DECL_CONTEXT didn't pan out.
> > > 
> > > In c8 of the PR it looks like you were using the class itself as
> > > DECL_CONTEXT; the quote above says that the right context is the enclosing
> > > scope of the class.
> > 
> > Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in
> > retrieve_specialization:
> > 
> >/* There should be as many levels of arguments as there are
> >   levels of parameters.  */
> >gcc_assert (TMPL_ARGS_DEPTH (args)
> >== (TREE_CODE (tmpl) == TEMPLATE_DECL
> >? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
> >: template_class_depth (DECL_CONTEXT (tmpl;
> 
> Yeah, probably simpler not to bother.
> 
> > > > So perhaps we
> > > > just want to skip the assert for deduction guides, because they are
> > > > a little special.  Better ideas solicited.
> > > 
> > > In c3 you mention that one of the variants broke with r269093; this is
> > > because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for 
> > > the
> > > template pattern itself (E).
> > 
> > And the original test started with my r11-1713 because using TREE_TYPE
> > directly instead of decltype (which is a non-deduced context) means we
> > can deduced from the argument.
> > > But I think probably the right answer is to defer this deduction until the
> > > enclosing scope is non-dependent, i.e. (untested)
> > 
> > Thanks.  That mostly works, except the new class-deduction-aggr[89].C
> > tests.  Consider 8:
> > 
> > namespace N {
> > template  struct S {
> >template  S(T, U);
> > };
> > } // namespace N
> > template  struct E {
> >template  struct G { T t; };
> >void fn() { G{N::S{'a', 1}}; }
> > };
> > 
> > void
> > g ()
> > {
> >E<1> e;
> >e.fn ();
> > }
> > 
> > With your patch, when in do_class_deduction when processing_template_decl,
> > we just return.  When we call do_class_deduction again when p_t_d is 0,
> > maybe_aggr_guide returns early here:
> > 
> >if (!CP_AGGREGATE_TYPE_P (type))
> >  return NULL_TREE
> > 
> > because G is not complete (and rightly so, we didn't instantiate it).  So
> > we aren't able to deduce the template parameters.  I'm not sure if I should
> > pursue this direction further.  :(
> 
> I think so; we just need to test CP_AGGREGATE_TYPE_P on the original
> template pattern instead of the instantiation E<1>::G.

I'm sorry, I've got stuck again.

Yes, using the original template pattern helps us get past the
CP_AGGREGATE_TYPE_P check.

However, using TREE_TYPE (DECL_TI_TEMPLATE (tmpl)) as the type of the deduction 
guide
means the guide will be "template G(T)-> E< >::G" which
results in

  class-deduction-aggr8.C:11:15: error: invalid use of dependent type 'typename 
E< >::G >'

which makes sense I guess: when we defer building up the guide until
we've instantiated E<1>, finding the dependent type E<> is not expected.

But creating the guide with "struct E<1>::G" as its type seems
wrong; I'm not even sure 

Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]

2021-02-25 Thread Jason Merrill via Gcc-patches

On 2/25/21 5:41 PM, Marek Polacek wrote:

On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote:

On 2/12/21 6:12 PM, Marek Polacek wrote:

We represent deduction guides with FUNCTION_DECLs, but they are built
without DECL_CONTEXT


Hmm, that seems wrong: "A deduction-guide shall be declared in the
same scope as the corresponding class template and, for a member class
template, with the same access."  But it probably isn't necessary to change
this:


leading to an ICE in type_dependent_expression_p
on the assert that the type of a function template with no dependent
(innermost!) template arguments must be non-dependent.  Consider the
attached class-deduction79.C: we create a deduction guide:

template G(T)-> E::G

we deduce T and create a partial instantiation:

G(T) -> E::G [with T = int]

And then do_class_deduction wants to create a CALL_EXPR from the above
using build_new_function_call -> build_over_call which calls mark_used
-> maybe_instantiate_noexcept -> type_dependent_expression_p.

There, the innermost template arguments are non-dependent (), but
the fntype is dependent -- the return type is a TYPENAME_TYPE, and
since we have no DECL_CONTEXT, this check holds:

/* Otherwise, if the function decl isn't from a dependent scope, it can't be
   type-dependent.  Checking this is important for functions with auto 
return
   type, which looks like a dependent type.  */
if (TREE_CODE (expression) == FUNCTION_DECL
&& !(DECL_CLASS_SCOPE_P (expression)
 && dependent_type_p (DECL_CONTEXT (expression)))

whereupon we ICE.

Experiments with setting DECL_CONTEXT didn't pan out.


In c8 of the PR it looks like you were using the class itself as
DECL_CONTEXT; the quote above says that the right context is the enclosing
scope of the class.


Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in
retrieve_specialization:

   /* There should be as many levels of arguments as there are
  levels of parameters.  */
   gcc_assert (TMPL_ARGS_DEPTH (args)
   == (TREE_CODE (tmpl) == TEMPLATE_DECL
   ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
   : template_class_depth (DECL_CONTEXT (tmpl;


Yeah, probably simpler not to bother.


So perhaps we
just want to skip the assert for deduction guides, because they are
a little special.  Better ideas solicited.


In c3 you mention that one of the variants broke with r269093; this is
because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for the
template pattern itself (E).


And the original test started with my r11-1713 because using TREE_TYPE
directly instead of decltype (which is a non-deduced context) means we
can deduced from the argument.
  

But I think probably the right answer is to defer this deduction until the
enclosing scope is non-dependent, i.e. (untested)


Thanks.  That mostly works, except the new class-deduction-aggr[89].C
tests.  Consider 8:

namespace N {
template  struct S {
   template  S(T, U);
};
} // namespace N
template  struct E {
   template  struct G { T t; };
   void fn() { G{N::S{'a', 1}}; }
};

void
g ()
{
   E<1> e;
   e.fn ();
}

With your patch, when in do_class_deduction when processing_template_decl,
we just return.  When we call do_class_deduction again when p_t_d is 0,
maybe_aggr_guide returns early here:

   if (!CP_AGGREGATE_TYPE_P (type))
 return NULL_TREE

because G is not complete (and rightly so, we didn't instantiate it).  So
we aren't able to deduce the template parameters.  I'm not sure if I should
pursue this direction further.  :(


I think so; we just need to test CP_AGGREGATE_TYPE_P on the original 
template pattern instead of the instantiation E<1>::G.


Jason



Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]

2021-02-25 Thread Marek Polacek via Gcc-patches
On Thu, Feb 25, 2021 at 10:59:49AM -0500, Jason Merrill wrote:
> On 2/12/21 6:12 PM, Marek Polacek wrote:
> > We represent deduction guides with FUNCTION_DECLs, but they are built
> > without DECL_CONTEXT
> 
> Hmm, that seems wrong: "A deduction-guide shall be declared in the
> same scope as the corresponding class template and, for a member class
> template, with the same access."  But it probably isn't necessary to change
> this:
> 
> > leading to an ICE in type_dependent_expression_p
> > on the assert that the type of a function template with no dependent
> > (innermost!) template arguments must be non-dependent.  Consider the
> > attached class-deduction79.C: we create a deduction guide:
> > 
> >template G(T)-> E::G
> > 
> > we deduce T and create a partial instantiation:
> > 
> >G(T) -> E::G [with T = int]
> > 
> > And then do_class_deduction wants to create a CALL_EXPR from the above
> > using build_new_function_call -> build_over_call which calls mark_used
> > -> maybe_instantiate_noexcept -> type_dependent_expression_p.
> > 
> > There, the innermost template arguments are non-dependent (), but
> > the fntype is dependent -- the return type is a TYPENAME_TYPE, and
> > since we have no DECL_CONTEXT, this check holds:
> > 
> >/* Otherwise, if the function decl isn't from a dependent scope, it 
> > can't be
> >   type-dependent.  Checking this is important for functions with auto 
> > return
> >   type, which looks like a dependent type.  */
> >if (TREE_CODE (expression) == FUNCTION_DECL
> >&& !(DECL_CLASS_SCOPE_P (expression)
> > && dependent_type_p (DECL_CONTEXT (expression)))
> > 
> > whereupon we ICE.
> > 
> > Experiments with setting DECL_CONTEXT didn't pan out.
> 
> In c8 of the PR it looks like you were using the class itself as
> DECL_CONTEXT; the quote above says that the right context is the enclosing
> scope of the class.

Sadly, using CP_TYPE_CONTEXT (type) would result in a crash in
retrieve_specialization:

  /* There should be as many levels of arguments as there are
 levels of parameters.  */
  gcc_assert (TMPL_ARGS_DEPTH (args)
  == (TREE_CODE (tmpl) == TEMPLATE_DECL
  ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
  : template_class_depth (DECL_CONTEXT (tmpl;

> > So perhaps we
> > just want to skip the assert for deduction guides, because they are
> > a little special.  Better ideas solicited.
> 
> In c3 you mention that one of the variants broke with r269093; this is
> because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for the
> template pattern itself (E).

And the original test started with my r11-1713 because using TREE_TYPE
directly instead of decltype (which is a non-deduced context) means we
can deduced from the argument.
 
> But I think probably the right answer is to defer this deduction until the
> enclosing scope is non-dependent, i.e. (untested)

Thanks.  That mostly works, except the new class-deduction-aggr[89].C
tests.  Consider 8:

namespace N {
template  struct S {
  template  S(T, U);
};
} // namespace N
template  struct E {
  template  struct G { T t; };
  void fn() { G{N::S{'a', 1}}; }
};

void
g ()
{
  E<1> e;
  e.fn ();
}

With your patch, when in do_class_deduction when processing_template_decl,
we just return.  When we call do_class_deduction again when p_t_d is 0,
maybe_aggr_guide returns early here:

  if (!CP_AGGREGATE_TYPE_P (type))
return NULL_TREE

because G is not complete (and rightly so, we didn't instantiate it).  So
we aren't able to deduce the template parameters.  I'm not sure if I should
pursue this direction further.  :(

Marek



Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]

2021-02-25 Thread Jason Merrill via Gcc-patches

On 2/12/21 6:12 PM, Marek Polacek wrote:

We represent deduction guides with FUNCTION_DECLs, but they are built
without DECL_CONTEXT


Hmm, that seems wrong: "A deduction-guide shall be declared in the
same scope as the corresponding class template and, for a member class 
template, with the same access."  But it probably isn't necessary to 
change this:



leading to an ICE in type_dependent_expression_p
on the assert that the type of a function template with no dependent
(innermost!) template arguments must be non-dependent.  Consider the
attached class-deduction79.C: we create a deduction guide:

   template G(T)-> E::G

we deduce T and create a partial instantiation:

   G(T) -> E::G [with T = int]

And then do_class_deduction wants to create a CALL_EXPR from the above
using build_new_function_call -> build_over_call which calls mark_used
-> maybe_instantiate_noexcept -> type_dependent_expression_p.

There, the innermost template arguments are non-dependent (), but
the fntype is dependent -- the return type is a TYPENAME_TYPE, and
since we have no DECL_CONTEXT, this check holds:

   /* Otherwise, if the function decl isn't from a dependent scope, it can't be
  type-dependent.  Checking this is important for functions with auto return
  type, which looks like a dependent type.  */
   if (TREE_CODE (expression) == FUNCTION_DECL
   && !(DECL_CLASS_SCOPE_P (expression)
&& dependent_type_p (DECL_CONTEXT (expression)))

whereupon we ICE.

Experiments with setting DECL_CONTEXT didn't pan out.


In c8 of the PR it looks like you were using the class itself as 
DECL_CONTEXT; the quote above says that the right context is the 
enclosing scope of the class.



So perhaps we
just want to skip the assert for deduction guides, because they are
a little special.  Better ideas solicited.


In c3 you mention that one of the variants broke with r269093; this is 
because my change to check CLASSTYPE_TEMPLATE_INSTANTIATION is false for 
the template pattern itself (E).


But I think probably the right answer is to defer this deduction until 
the enclosing scope is non-dependent, i.e. (untested)


>From a0c19e712b8d8e6048d7371b237dc38cad2b9119 Mon Sep 17 00:00:00 2001
From: Jason Merrill 
Date: Thu, 25 Feb 2021 10:55:28 -0500
Subject: [PATCH] dep
To: gcc-patches@gcc.gnu.org

---
 gcc/cp/pt.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3576e0effb6..0e383d2434e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -29214,6 +29214,10 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
   if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
 return ptype;
 
+  if (DECL_CLASS_SCOPE_P (tmpl)
+  && dependent_type_p (DECL_CONTEXT (tmpl)))
+return ptype;
+
   /* Initializing one placeholder from another.  */
   if (init && TREE_CODE (init) == TEMPLATE_PARM_INDEX
   && is_auto (TREE_TYPE (init))
-- 
2.27.0



Re: [PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]

2021-02-24 Thread Marek Polacek via Gcc-patches
Ping.

On Fri, Feb 12, 2021 at 06:12:12PM -0500, Marek Polacek via Gcc-patches wrote:
> We represent deduction guides with FUNCTION_DECLs, but they are built
> without DECL_CONTEXT, leading to an ICE in type_dependent_expression_p
> on the assert that the type of a function template with no dependent
> (innermost!) template arguments must be non-dependent.  Consider the
> attached class-deduction79.C: we create a deduction guide:
> 
>   template G(T)-> E::G
> 
> we deduce T and create a partial instantiation:
> 
>   G(T) -> E::G [with T = int]
> 
> And then do_class_deduction wants to create a CALL_EXPR from the above
> using build_new_function_call -> build_over_call which calls mark_used
> -> maybe_instantiate_noexcept -> type_dependent_expression_p.
> 
> There, the innermost template arguments are non-dependent (), but
> the fntype is dependent -- the return type is a TYPENAME_TYPE, and
> since we have no DECL_CONTEXT, this check holds:
> 
>   /* Otherwise, if the function decl isn't from a dependent scope, it can't be
>  type-dependent.  Checking this is important for functions with auto 
> return
>  type, which looks like a dependent type.  */
>   if (TREE_CODE (expression) == FUNCTION_DECL
>   && !(DECL_CLASS_SCOPE_P (expression)
>&& dependent_type_p (DECL_CONTEXT (expression)))
> 
> whereupon we ICE.
> 
> Experiments with setting DECL_CONTEXT didn't pan out.  So perhaps we
> just want to skip the assert for deduction guides, because they are
> a little special.  Better ideas solicited.
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu.
> 
> gcc/cp/ChangeLog:
> 
>   PR c++/97034
>   PR c++/99009
>   * pt.c (type_dependent_expression_p): Don't assert that the type
>   of a deduction guide must non-dependent.
> 
> gcc/testsuite/ChangeLog:
> 
>   PR c++/97034
>   PR c++/99009
>   * g++.dg/cpp1z/class-deduction79.C: New test.
>   * g++.dg/cpp1z/class-deduction80.C: New test.
>   * g++.dg/cpp2a/class-deduction-aggr8.C: New test.
>   * g++.dg/cpp2a/class-deduction-aggr9.C: New test.
> ---
>  gcc/cp/pt.c   |  5 -
>  .../g++.dg/cpp1z/class-deduction79.C  | 20 +++
>  .../g++.dg/cpp1z/class-deduction80.C  | 12 +++
>  .../g++.dg/cpp2a/class-deduction-aggr8.C  | 19 ++
>  .../g++.dg/cpp2a/class-deduction-aggr9.C  | 18 +
>  5 files changed, 73 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction79.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction80.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 60de8e93ff7..3e6f3407d40 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -27282,7 +27282,10 @@ type_dependent_expression_p (tree expression)
>  && DECL_UNIQUE_FRIEND_P (expression)
>  && (!DECL_FRIEND_CONTEXT (expression)
>  || dependent_type_p (DECL_FRIEND_CONTEXT (expression
> -  && !DECL_LOCAL_DECL_P (expression))
> +  && !DECL_LOCAL_DECL_P (expression)
> +  /* We build deduction guides without any DECL_CONTEXT, but they can
> +  be type-dependent.  */
> +  && !deduction_guide_p (expression))
>  {
>gcc_assert (!dependent_type_p (TREE_TYPE (expression))
> || undeduced_auto_decl (expression));
> diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C 
> b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C
> new file mode 100644
> index 000..86a68248157
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C
> @@ -0,0 +1,20 @@
> +// PR c++/97034
> +// { dg-do compile { target c++17 } }
> +
> +template 
> +struct E {
> +  template 
> +  struct G {
> +T t;
> +G(T) { }
> +  };
> +
> +  void fn() { G{1}; }
> +};
> +
> +void
> +g ()
> +{
> +  E e;
> +  e.fn ();
> +}
> diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C 
> b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C
> new file mode 100644
> index 000..238024c508f
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C
> @@ -0,0 +1,12 @@
> +// PR c++/99009
> +// { dg-do compile { target c++17 } }
> +
> +template struct B {
> +  B(int = A()) {}
> +  template  struct A;
> +};
> +
> +template struct X {
> +  template  struct Y;
> +  X() { Y y; };
> +};
> diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C 
> b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C
> new file mode 100644
> index 000..399061100ae
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C
> @@ -0,0 +1,19 @@
> +// PR c++/97034
> +// { dg-do compile { target c++20 } }
> +
> +namespace N {
> +template  struct S {
> +  template  S(T, U);
> +};
> +} // namespace N
> +template  struct E {
> +  template  struct G { T t; };
> +  void fn() { 

[PATCH] c++: ICE with deduction guide in checking type-dep [PR99009, PR97034]

2021-02-12 Thread Marek Polacek via Gcc-patches
We represent deduction guides with FUNCTION_DECLs, but they are built
without DECL_CONTEXT, leading to an ICE in type_dependent_expression_p
on the assert that the type of a function template with no dependent
(innermost!) template arguments must be non-dependent.  Consider the
attached class-deduction79.C: we create a deduction guide:

  template G(T)-> E::G

we deduce T and create a partial instantiation:

  G(T) -> E::G [with T = int]

And then do_class_deduction wants to create a CALL_EXPR from the above
using build_new_function_call -> build_over_call which calls mark_used
-> maybe_instantiate_noexcept -> type_dependent_expression_p.

There, the innermost template arguments are non-dependent (), but
the fntype is dependent -- the return type is a TYPENAME_TYPE, and
since we have no DECL_CONTEXT, this check holds:

  /* Otherwise, if the function decl isn't from a dependent scope, it can't be
 type-dependent.  Checking this is important for functions with auto return
 type, which looks like a dependent type.  */
  if (TREE_CODE (expression) == FUNCTION_DECL
  && !(DECL_CLASS_SCOPE_P (expression)
   && dependent_type_p (DECL_CONTEXT (expression)))

whereupon we ICE.

Experiments with setting DECL_CONTEXT didn't pan out.  So perhaps we
just want to skip the assert for deduction guides, because they are
a little special.  Better ideas solicited.

Bootstrapped/regtested on x86_64-pc-linux-gnu.

gcc/cp/ChangeLog:

PR c++/97034
PR c++/99009
* pt.c (type_dependent_expression_p): Don't assert that the type
of a deduction guide must non-dependent.

gcc/testsuite/ChangeLog:

PR c++/97034
PR c++/99009
* g++.dg/cpp1z/class-deduction79.C: New test.
* g++.dg/cpp1z/class-deduction80.C: New test.
* g++.dg/cpp2a/class-deduction-aggr8.C: New test.
* g++.dg/cpp2a/class-deduction-aggr9.C: New test.
---
 gcc/cp/pt.c   |  5 -
 .../g++.dg/cpp1z/class-deduction79.C  | 20 +++
 .../g++.dg/cpp1z/class-deduction80.C  | 12 +++
 .../g++.dg/cpp2a/class-deduction-aggr8.C  | 19 ++
 .../g++.dg/cpp2a/class-deduction-aggr9.C  | 18 +
 5 files changed, 73 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction79.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction80.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 60de8e93ff7..3e6f3407d40 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -27282,7 +27282,10 @@ type_dependent_expression_p (tree expression)
   && DECL_UNIQUE_FRIEND_P (expression)
   && (!DECL_FRIEND_CONTEXT (expression)
   || dependent_type_p (DECL_FRIEND_CONTEXT (expression
-  && !DECL_LOCAL_DECL_P (expression))
+  && !DECL_LOCAL_DECL_P (expression)
+  /* We build deduction guides without any DECL_CONTEXT, but they can
+be type-dependent.  */
+  && !deduction_guide_p (expression))
 {
   gcc_assert (!dependent_type_p (TREE_TYPE (expression))
  || undeduced_auto_decl (expression));
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C 
b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C
new file mode 100644
index 000..86a68248157
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C
@@ -0,0 +1,20 @@
+// PR c++/97034
+// { dg-do compile { target c++17 } }
+
+template 
+struct E {
+  template 
+  struct G {
+T t;
+G(T) { }
+  };
+
+  void fn() { G{1}; }
+};
+
+void
+g ()
+{
+  E e;
+  e.fn ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C 
b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C
new file mode 100644
index 000..238024c508f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C
@@ -0,0 +1,12 @@
+// PR c++/99009
+// { dg-do compile { target c++17 } }
+
+template struct B {
+  B(int = A()) {}
+  template  struct A;
+};
+
+template struct X {
+  template  struct Y;
+  X() { Y y; };
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C
new file mode 100644
index 000..399061100ae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C
@@ -0,0 +1,19 @@
+// PR c++/97034
+// { dg-do compile { target c++20 } }
+
+namespace N {
+template  struct S {
+  template  S(T, U);
+};
+} // namespace N
+template  struct E {
+  template  struct G { T t; };
+  void fn() { G{N::S{'a', 1}}; }
+};
+
+void
+g ()
+{
+  E<1> e;
+  e.fn ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C
new file mode 100644
index 000..245a04cd5f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C
@@ -0,0 +1,18 @@
+// PR c++/97034
+// {